Annotation of embedaddon/php/ext/com_dotnet/com_persist.c, revision 1.1

1.1     ! misho       1: /*
        !             2:    +----------------------------------------------------------------------+
        !             3:    | PHP Version 5                                                        |
        !             4:    +----------------------------------------------------------------------+
        !             5:    | Copyright (c) 1997-2012 The PHP Group                                |
        !             6:    +----------------------------------------------------------------------+
        !             7:    | This source file is subject to version 3.01 of the PHP license,      |
        !             8:    | that is bundled with this package in the file LICENSE, and is        |
        !             9:    | available through the world-wide-web at the following url:           |
        !            10:    | http://www.php.net/license/3_01.txt                                  |
        !            11:    | If you did not receive a copy of the PHP license and are unable to   |
        !            12:    | obtain it through the world-wide-web, please send a note to          |
        !            13:    | license@php.net so we can mail you a copy immediately.               |
        !            14:    +----------------------------------------------------------------------+
        !            15:    | Author: Wez Furlong  <wez@thebrainroom.com>                          |
        !            16:    +----------------------------------------------------------------------+
        !            17:  */
        !            18: 
        !            19: /* $Id: com_persist.c 321634 2012-01-01 13:15:04Z felipe $ */
        !            20: 
        !            21: /* Infrastructure for working with persistent COM objects.
        !            22:  * Implements: IStream* wrapper for PHP streams.
        !            23:  * TODO: Magic __wakeup and __sleep handlers for serialization 
        !            24:  * (can wait till 5.1) */
        !            25: 
        !            26: #ifdef HAVE_CONFIG_H
        !            27: #include "config.h"
        !            28: #endif
        !            29: 
        !            30: #include "php.h"
        !            31: #include "php_ini.h"
        !            32: #include "ext/standard/info.h"
        !            33: #include "php_com_dotnet.h"
        !            34: #include "php_com_dotnet_internal.h"
        !            35: #include "Zend/zend_exceptions.h"
        !            36: 
        !            37: /* {{{ expose php_stream as a COM IStream */
        !            38: 
        !            39: typedef struct {
        !            40:        CONST_VTBL struct IStreamVtbl *lpVtbl;
        !            41:        DWORD engine_thread;
        !            42:        LONG refcount;
        !            43:        php_stream *stream;
        !            44:        int id;
        !            45: } php_istream;
        !            46: 
        !            47: static int le_istream;
        !            48: static void istream_destructor(php_istream *stm);
        !            49: 
        !            50: static void istream_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
        !            51: {
        !            52:        php_istream *stm = (php_istream *)rsrc->ptr;
        !            53:        istream_destructor(stm);
        !            54: }
        !            55: 
        !            56: #ifdef ZTS
        !            57: # define TSRMLS_FIXED()        TSRMLS_FETCH();
        !            58: #else
        !            59: # define TSRMLS_FIXED()
        !            60: #endif
        !            61: 
        !            62: #define FETCH_STM()    \
        !            63:        TSRMLS_FIXED() \
        !            64:        php_istream *stm = (php_istream*)This; \
        !            65:        if (GetCurrentThreadId() != stm->engine_thread) \
        !            66:                return RPC_E_WRONG_THREAD;
        !            67: 
        !            68: static HRESULT STDMETHODCALLTYPE stm_queryinterface(
        !            69:        IStream *This,
        !            70:        /* [in] */ REFIID riid,
        !            71:        /* [iid_is][out] */ void **ppvObject)
        !            72: {
        !            73:        FETCH_STM();
        !            74: 
        !            75:        if (IsEqualGUID(&IID_IUnknown, riid) ||
        !            76:                        IsEqualGUID(&IID_IStream, riid)) {
        !            77:                *ppvObject = This;
        !            78:                InterlockedIncrement(&stm->refcount);
        !            79:                return S_OK;
        !            80:        }
        !            81: 
        !            82:        *ppvObject = NULL;
        !            83:        return E_NOINTERFACE;
        !            84: }
        !            85: 
        !            86: static ULONG STDMETHODCALLTYPE stm_addref(IStream *This)
        !            87: {
        !            88:        FETCH_STM();
        !            89: 
        !            90:        return InterlockedIncrement(&stm->refcount);
        !            91: }
        !            92:         
        !            93: static ULONG STDMETHODCALLTYPE stm_release(IStream *This)
        !            94: {
        !            95:        ULONG ret;
        !            96:        FETCH_STM();
        !            97: 
        !            98:        ret = InterlockedDecrement(&stm->refcount);
        !            99:        if (ret == 0) {
        !           100:                /* destroy it */
        !           101:                if (stm->id)
        !           102:                        zend_list_delete(stm->id);
        !           103:        }
        !           104:        return ret;
        !           105: }
        !           106: 
        !           107: static HRESULT STDMETHODCALLTYPE stm_read(IStream *This, void *pv, ULONG cb, ULONG *pcbRead)
        !           108: {
        !           109:        int nread;
        !           110:        FETCH_STM();
        !           111: 
        !           112:        nread = php_stream_read(stm->stream, pv, cb);
        !           113: 
        !           114:        if (pcbRead) {
        !           115:                *pcbRead = nread > 0 ? nread : 0;
        !           116:        }
        !           117:        if (nread > 0) {
        !           118:                return S_OK;
        !           119:        }
        !           120:        return S_FALSE;
        !           121: }
        !           122: 
        !           123: static HRESULT STDMETHODCALLTYPE stm_write(IStream *This, void const *pv, ULONG cb, ULONG *pcbWritten)
        !           124: {
        !           125:        int nwrote;
        !           126:        FETCH_STM();
        !           127: 
        !           128:        nwrote = php_stream_write(stm->stream, pv, cb);
        !           129: 
        !           130:        if (pcbWritten) {
        !           131:                *pcbWritten = nwrote > 0 ? nwrote : 0;
        !           132:        }
        !           133:        if (nwrote > 0) {
        !           134:                return S_OK;
        !           135:        }
        !           136:        return S_FALSE;
        !           137: }
        !           138: 
        !           139: static HRESULT STDMETHODCALLTYPE stm_seek(IStream *This, LARGE_INTEGER dlibMove,
        !           140:                DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
        !           141: {
        !           142:        off_t offset;
        !           143:        int whence;
        !           144:        int ret;
        !           145:        FETCH_STM();
        !           146: 
        !           147:        switch (dwOrigin) {
        !           148:                case STREAM_SEEK_SET:   whence = SEEK_SET;      break;
        !           149:                case STREAM_SEEK_CUR:   whence = SEEK_CUR;      break;
        !           150:                case STREAM_SEEK_END:   whence = SEEK_END;      break;
        !           151:                default:
        !           152:                        return STG_E_INVALIDFUNCTION;
        !           153:        }
        !           154:        
        !           155:        if (dlibMove.HighPart) {
        !           156:                /* we don't support 64-bit offsets */
        !           157:                return STG_E_INVALIDFUNCTION;
        !           158:        }
        !           159:        
        !           160:        offset = (off_t) dlibMove.QuadPart;
        !           161: 
        !           162:        ret = php_stream_seek(stm->stream, offset, whence);
        !           163: 
        !           164:        if (plibNewPosition) {
        !           165:                plibNewPosition->QuadPart = (ULONGLONG)(ret >= 0 ? ret : 0);
        !           166:        }
        !           167: 
        !           168:        return ret >= 0 ? S_OK : STG_E_INVALIDFUNCTION;
        !           169: }
        !           170: 
        !           171: static HRESULT STDMETHODCALLTYPE stm_set_size(IStream *This, ULARGE_INTEGER libNewSize)
        !           172: {
        !           173:        FETCH_STM();
        !           174: 
        !           175:        if (libNewSize.HighPart) {
        !           176:                return STG_E_INVALIDFUNCTION;
        !           177:        }
        !           178:        
        !           179:        if (php_stream_truncate_supported(stm->stream)) {
        !           180:                int ret = php_stream_truncate_set_size(stm->stream, (size_t)libNewSize.QuadPart);
        !           181: 
        !           182:                if (ret == 0) {
        !           183:                        return S_OK;
        !           184:                }
        !           185:        }
        !           186: 
        !           187:        return STG_E_INVALIDFUNCTION;
        !           188: }
        !           189: 
        !           190: static HRESULT STDMETHODCALLTYPE stm_copy_to(IStream *This, IStream *pstm, ULARGE_INTEGER cb,
        !           191:                ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
        !           192: {
        !           193:        FETCH_STM();
        !           194: 
        !           195:        return E_NOTIMPL;
        !           196: }
        !           197: 
        !           198: static HRESULT STDMETHODCALLTYPE stm_commit(IStream *This, DWORD grfCommitFlags)
        !           199: {
        !           200:        FETCH_STM();
        !           201: 
        !           202:        php_stream_flush(stm->stream);
        !           203: 
        !           204:        return S_OK;
        !           205: }
        !           206: 
        !           207: static HRESULT STDMETHODCALLTYPE stm_revert(IStream *This)
        !           208: {
        !           209:        /* NOP */
        !           210:        return S_OK;
        !           211: }
        !           212: 
        !           213: static HRESULT STDMETHODCALLTYPE stm_lock_region(IStream *This,
        !           214:        ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD lockType)
        !           215: {
        !           216:        return STG_E_INVALIDFUNCTION;
        !           217: }
        !           218: 
        !           219: static HRESULT STDMETHODCALLTYPE stm_unlock_region(IStream *This,
        !           220:                ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD lockType)
        !           221: {
        !           222:        return STG_E_INVALIDFUNCTION;
        !           223: }
        !           224: 
        !           225: static HRESULT STDMETHODCALLTYPE stm_stat(IStream *This,
        !           226:                STATSTG *pstatstg, DWORD grfStatFlag)
        !           227: {
        !           228:        return STG_E_INVALIDFUNCTION;
        !           229: }
        !           230: 
        !           231: static HRESULT STDMETHODCALLTYPE stm_clone(IStream *This, IStream **ppstm)
        !           232: {
        !           233:        return STG_E_INVALIDFUNCTION;
        !           234: }
        !           235: 
        !           236: static struct IStreamVtbl php_istream_vtbl = {
        !           237:        stm_queryinterface,
        !           238:        stm_addref,
        !           239:        stm_release,
        !           240:        stm_read,
        !           241:        stm_write,
        !           242:        stm_seek,
        !           243:        stm_set_size,
        !           244:        stm_copy_to,
        !           245:        stm_commit,
        !           246:        stm_revert,
        !           247:        stm_lock_region,
        !           248:        stm_unlock_region,
        !           249:        stm_stat,
        !           250:        stm_clone
        !           251: };
        !           252: 
        !           253: static void istream_destructor(php_istream *stm)
        !           254: {
        !           255:        TSRMLS_FETCH();
        !           256: 
        !           257:        if (stm->id) {
        !           258:                int id = stm->id;
        !           259:                stm->id = 0;
        !           260:                zend_list_delete(id);
        !           261:                return;
        !           262:        }
        !           263: 
        !           264:        if (stm->refcount > 0) {
        !           265:                CoDisconnectObject((IUnknown*)stm, 0);
        !           266:        }
        !           267: 
        !           268:        zend_list_delete(stm->stream->rsrc_id);
        !           269: 
        !           270:        CoTaskMemFree(stm);
        !           271: }
        !           272: /* }}} */
        !           273: 
        !           274: PHPAPI IStream *php_com_wrapper_export_stream(php_stream *stream TSRMLS_DC)
        !           275: {
        !           276:        php_istream *stm = (php_istream*)CoTaskMemAlloc(sizeof(*stm));
        !           277: 
        !           278:        if (stm == NULL)
        !           279:                return NULL;
        !           280: 
        !           281:        memset(stm, 0, sizeof(*stm));
        !           282:        stm->engine_thread = GetCurrentThreadId();
        !           283:        stm->lpVtbl = &php_istream_vtbl;
        !           284:        stm->refcount = 1;
        !           285:        stm->stream = stream;
        !           286: 
        !           287:        zend_list_addref(stream->rsrc_id);
        !           288:        stm->id = zend_list_insert(stm, le_istream);
        !           289: 
        !           290:        return (IStream*)stm;
        !           291: }
        !           292: 
        !           293: #define CPH_ME(fname, arginfo) PHP_ME(com_persist, fname, arginfo, ZEND_ACC_PUBLIC)
        !           294: #define CPH_SME(fname, arginfo)        PHP_ME(com_persist, fname, arginfo, ZEND_ACC_ALLOW_STATIC|ZEND_ACC_PUBLIC)
        !           295: #define CPH_METHOD(fname)              static PHP_METHOD(com_persist, fname)
        !           296:        
        !           297: #define CPH_FETCH()                            php_com_persist_helper *helper = (php_com_persist_helper*)zend_object_store_get_object(getThis() TSRMLS_CC);
        !           298: 
        !           299: #define CPH_NO_OBJ()                   if (helper->unk == NULL) { php_com_throw_exception(E_INVALIDARG, "No COM object is associated with this helper instance" TSRMLS_CC); return; }
        !           300: 
        !           301: typedef struct {
        !           302:        zend_object                     std;
        !           303:        long codepage;
        !           304:        IUnknown                        *unk;
        !           305:        IPersistStream          *ips;
        !           306:        IPersistStreamInit      *ipsi;
        !           307:        IPersistFile            *ipf;
        !           308: } php_com_persist_helper;
        !           309: 
        !           310: static zend_object_handlers helper_handlers;
        !           311: static zend_class_entry *helper_ce;
        !           312: 
        !           313: static inline HRESULT get_persist_stream(php_com_persist_helper *helper)
        !           314: {
        !           315:        if (!helper->ips && helper->unk) {
        !           316:                return IUnknown_QueryInterface(helper->unk, &IID_IPersistStream, &helper->ips);
        !           317:        }
        !           318:        return helper->ips ? S_OK : E_NOTIMPL;
        !           319: }
        !           320: 
        !           321: static inline HRESULT get_persist_stream_init(php_com_persist_helper *helper)
        !           322: {
        !           323:        if (!helper->ipsi && helper->unk) {
        !           324:                return IUnknown_QueryInterface(helper->unk, &IID_IPersistStreamInit, &helper->ipsi);
        !           325:        }
        !           326:        return helper->ipsi ? S_OK : E_NOTIMPL;
        !           327: }
        !           328: 
        !           329: static inline HRESULT get_persist_file(php_com_persist_helper *helper)
        !           330: {
        !           331:        if (!helper->ipf && helper->unk) {
        !           332:                return IUnknown_QueryInterface(helper->unk, &IID_IPersistFile, &helper->ipf);
        !           333:        }
        !           334:        return helper->ipf ? S_OK : E_NOTIMPL;
        !           335: }
        !           336: 
        !           337: 
        !           338: /* {{{ proto string COMPersistHelper::GetCurFile()
        !           339:    Determines the filename into which an object will be saved, or false if none is set, via IPersistFile::GetCurFile */
        !           340: CPH_METHOD(GetCurFileName)
        !           341: {
        !           342:        HRESULT res;
        !           343:        OLECHAR *olename = NULL;
        !           344:        CPH_FETCH();
        !           345: 
        !           346:        CPH_NO_OBJ();
        !           347:        
        !           348:        res = get_persist_file(helper);
        !           349:        if (helper->ipf) {
        !           350:                res = IPersistFile_GetCurFile(helper->ipf, &olename);
        !           351: 
        !           352:                if (res == S_OK) {
        !           353:                        Z_TYPE_P(return_value) = IS_STRING;
        !           354:                        Z_STRVAL_P(return_value) = php_com_olestring_to_string(olename,
        !           355:                                   &Z_STRLEN_P(return_value), helper->codepage TSRMLS_CC);
        !           356:                        CoTaskMemFree(olename);
        !           357:                        return;
        !           358:                } else if (res == S_FALSE) {
        !           359:                        CoTaskMemFree(olename);
        !           360:                        RETURN_FALSE;
        !           361:                }
        !           362:                php_com_throw_exception(res, NULL TSRMLS_CC);
        !           363:        } else {
        !           364:                php_com_throw_exception(res, NULL TSRMLS_CC);
        !           365:        }
        !           366: }
        !           367: /* }}} */
        !           368: 
        !           369: 
        !           370: /* {{{ proto bool COMPersistHelper::SaveToFile(string filename [, bool remember])
        !           371:    Persist object data to file, via IPersistFile::Save */
        !           372: CPH_METHOD(SaveToFile)
        !           373: {
        !           374:        HRESULT res;
        !           375:        char *filename, *fullpath = NULL;
        !           376:        int filename_len;
        !           377:        zend_bool remember = TRUE;
        !           378:        OLECHAR *olefilename = NULL;
        !           379:        CPH_FETCH();
        !           380:        
        !           381:        CPH_NO_OBJ();
        !           382: 
        !           383:        res = get_persist_file(helper);
        !           384:        if (helper->ipf) {
        !           385:                if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!|b",
        !           386:                                        &filename, &filename_len, &remember)) {
        !           387:                        php_com_throw_exception(E_INVALIDARG, "Invalid arguments" TSRMLS_CC);
        !           388:                        return;
        !           389:                }
        !           390: 
        !           391:                if (filename) {
        !           392:                        if (strlen(filename) != filename_len) {
        !           393:                                RETURN_FALSE;
        !           394:                        }
        !           395:                        fullpath = expand_filepath(filename, NULL TSRMLS_CC);
        !           396:                        if (!fullpath) {
        !           397:                                RETURN_FALSE;
        !           398:                        }
        !           399:        
        !           400:                        if ((PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || 
        !           401:                                        php_check_open_basedir(fullpath TSRMLS_CC)) {
        !           402:                                efree(fullpath);
        !           403:                                RETURN_FALSE;
        !           404:                        }
        !           405: 
        !           406:                        olefilename = php_com_string_to_olestring(filename, strlen(fullpath), helper->codepage TSRMLS_CC);
        !           407:                        efree(fullpath);
        !           408:                }
        !           409:                res = IPersistFile_Save(helper->ipf, olefilename, remember);
        !           410:                if (SUCCEEDED(res)) {
        !           411:                        if (!olefilename) {
        !           412:                                res = IPersistFile_GetCurFile(helper->ipf, &olefilename);
        !           413:                                if (S_OK == res) {
        !           414:                                        IPersistFile_SaveCompleted(helper->ipf, olefilename);
        !           415:                                        CoTaskMemFree(olefilename);
        !           416:                                        olefilename = NULL;
        !           417:                                }
        !           418:                        } else if (remember) {
        !           419:                                IPersistFile_SaveCompleted(helper->ipf, olefilename);
        !           420:                        }
        !           421:                }
        !           422:                        
        !           423:                if (olefilename) {
        !           424:                        efree(olefilename);
        !           425:                }
        !           426: 
        !           427:                if (FAILED(res)) {
        !           428:                        php_com_throw_exception(res, NULL TSRMLS_CC);
        !           429:                }
        !           430: 
        !           431:        } else {
        !           432:                php_com_throw_exception(res, NULL TSRMLS_CC);
        !           433:        }
        !           434: }
        !           435: /* }}} */
        !           436: 
        !           437: /* {{{ proto bool COMPersistHelper::LoadFromFile(string filename [, int flags])
        !           438:    Load object data from file, via IPersistFile::Load */
        !           439: CPH_METHOD(LoadFromFile)
        !           440: {
        !           441:        HRESULT res;
        !           442:        char *filename, *fullpath;
        !           443:        int filename_len;
        !           444:        long flags = 0;
        !           445:        OLECHAR *olefilename;
        !           446:        CPH_FETCH();
        !           447:        
        !           448:        CPH_NO_OBJ();
        !           449: 
        !           450:        res = get_persist_file(helper);
        !           451:        if (helper->ipf) {
        !           452: 
        !           453:                if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l",
        !           454:                                        &filename, &filename_len, &flags)) {
        !           455:                        php_com_throw_exception(E_INVALIDARG, "Invalid arguments" TSRMLS_CC);
        !           456:                        return;
        !           457:                }
        !           458: 
        !           459:                if (strlen(filename) != filename_len) {
        !           460:                        RETURN_FALSE;
        !           461:                }
        !           462: 
        !           463:                if (!(fullpath = expand_filepath(filename, NULL TSRMLS_CC))) {
        !           464:                        RETURN_FALSE;
        !           465:                }
        !           466: 
        !           467:                if ((PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) ||
        !           468:                                php_check_open_basedir(fullpath TSRMLS_CC)) {
        !           469:                        efree(fullpath);
        !           470:                        RETURN_FALSE;
        !           471:                }
        !           472: 
        !           473:                olefilename = php_com_string_to_olestring(fullpath, strlen(fullpath), helper->codepage TSRMLS_CC);
        !           474:                efree(fullpath);
        !           475:                        
        !           476:                res = IPersistFile_Load(helper->ipf, olefilename, flags);
        !           477:                efree(olefilename);
        !           478: 
        !           479:                if (FAILED(res)) {
        !           480:                        php_com_throw_exception(res, NULL TSRMLS_CC);
        !           481:                }
        !           482:                
        !           483:        } else {
        !           484:                php_com_throw_exception(res, NULL TSRMLS_CC);
        !           485:        }
        !           486: }
        !           487: /* }}} */
        !           488: 
        !           489: /* {{{ proto int COMPersistHelper::GetMaxStreamSize()
        !           490:    Gets maximum stream size required to store the object data, via IPersistStream::GetSizeMax (or IPersistStreamInit::GetSizeMax) */
        !           491: CPH_METHOD(GetMaxStreamSize)
        !           492: {
        !           493:        HRESULT res;
        !           494:        ULARGE_INTEGER size;
        !           495:        CPH_FETCH();
        !           496:        
        !           497:        CPH_NO_OBJ();
        !           498:        
        !           499:        res = get_persist_stream_init(helper);
        !           500:        if (helper->ipsi) {
        !           501:                res = IPersistStreamInit_GetSizeMax(helper->ipsi, &size);
        !           502:        } else {
        !           503:                res = get_persist_stream(helper);
        !           504:                if (helper->ips) {
        !           505:                        res = IPersistStream_GetSizeMax(helper->ips, &size);
        !           506:                } else {
        !           507:                        php_com_throw_exception(res, NULL TSRMLS_CC);
        !           508:                        return;
        !           509:                }
        !           510:        }
        !           511: 
        !           512:        if (res != S_OK) {
        !           513:                php_com_throw_exception(res, NULL TSRMLS_CC);
        !           514:        } else {
        !           515:                /* TODO: handle 64 bit properly */
        !           516:                RETURN_LONG((LONG)size.QuadPart);
        !           517:        }
        !           518: }
        !           519: /* }}} */
        !           520: 
        !           521: /* {{{ proto int COMPersistHelper::InitNew()
        !           522:    Initializes the object to a default state, via IPersistStreamInit::InitNew */
        !           523: CPH_METHOD(InitNew)
        !           524: {
        !           525:        HRESULT res;
        !           526:        CPH_FETCH();
        !           527:        
        !           528:        CPH_NO_OBJ();
        !           529: 
        !           530:        res = get_persist_stream_init(helper);
        !           531:        if (helper->ipsi) {
        !           532:                res = IPersistStreamInit_InitNew(helper->ipsi);
        !           533: 
        !           534:                if (res != S_OK) {
        !           535:                        php_com_throw_exception(res, NULL TSRMLS_CC);
        !           536:                } else {
        !           537:                        RETURN_TRUE;
        !           538:                }
        !           539:        } else {
        !           540:                php_com_throw_exception(res, NULL TSRMLS_CC);
        !           541:        }
        !           542: }
        !           543: /* }}} */
        !           544: 
        !           545: /* {{{ proto mixed COMPersistHelper::LoadFromStream(resource stream)
        !           546:    Initializes an object from the stream where it was previously saved, via IPersistStream::Load or OleLoadFromStream */
        !           547: CPH_METHOD(LoadFromStream)
        !           548: {
        !           549:        zval *zstm;
        !           550:        php_stream *stream;
        !           551:        IStream *stm = NULL;
        !           552:        HRESULT res;
        !           553:        CPH_FETCH();
        !           554:        
        !           555:        if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zstm)) {
        !           556:                php_com_throw_exception(E_INVALIDARG, "invalid arguments" TSRMLS_CC);
        !           557:                return;
        !           558:        }
        !           559: 
        !           560:        php_stream_from_zval_no_verify(stream, &zstm);
        !           561:        
        !           562:        if (stream == NULL) {
        !           563:                php_com_throw_exception(E_INVALIDARG, "expected a stream" TSRMLS_CC);
        !           564:                return;
        !           565:        }
        !           566: 
        !           567:        stm = php_com_wrapper_export_stream(stream TSRMLS_CC);
        !           568:        if (stm == NULL) {
        !           569:                php_com_throw_exception(E_UNEXPECTED, "failed to wrap stream" TSRMLS_CC);
        !           570:                return;
        !           571:        }
        !           572:        
        !           573:        res = S_OK;
        !           574:        RETVAL_TRUE;
        !           575: 
        !           576:        if (helper->unk == NULL) {
        !           577:                IDispatch *disp = NULL;
        !           578: 
        !           579:                /* we need to create an object and load using OleLoadFromStream */
        !           580:                res = OleLoadFromStream(stm, &IID_IDispatch, &disp);
        !           581: 
        !           582:                if (SUCCEEDED(res)) {
        !           583:                        php_com_wrap_dispatch(return_value, disp, COMG(code_page) TSRMLS_CC);   
        !           584:                }
        !           585:        } else {
        !           586:                res = get_persist_stream_init(helper);
        !           587:                if (helper->ipsi) {
        !           588:                        res = IPersistStreamInit_Load(helper->ipsi, stm);
        !           589:                } else {
        !           590:                        res = get_persist_stream(helper);
        !           591:                        if (helper->ips) {
        !           592:                                res = IPersistStreamInit_Load(helper->ipsi, stm);
        !           593:                        }
        !           594:                }
        !           595:        }
        !           596:        IStream_Release(stm);
        !           597: 
        !           598:        if (FAILED(res)) {
        !           599:                php_com_throw_exception(res, NULL TSRMLS_CC);
        !           600:                RETURN_NULL();
        !           601:        }
        !           602: }
        !           603: /* }}} */
        !           604: 
        !           605: /* {{{ proto int COMPersistHelper::SaveToStream(resource stream)
        !           606:    Saves the object to a stream, via IPersistStream::Save */
        !           607: CPH_METHOD(SaveToStream)
        !           608: {
        !           609:        zval *zstm;
        !           610:        php_stream *stream;
        !           611:        IStream *stm = NULL;
        !           612:        HRESULT res;
        !           613:        CPH_FETCH();
        !           614:        
        !           615:        CPH_NO_OBJ();
        !           616:        
        !           617:        if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zstm)) {
        !           618:                php_com_throw_exception(E_INVALIDARG, "invalid arguments" TSRMLS_CC);
        !           619:                return;
        !           620:        }
        !           621: 
        !           622:        php_stream_from_zval_no_verify(stream, &zstm);
        !           623:        
        !           624:        if (stream == NULL) {
        !           625:                php_com_throw_exception(E_INVALIDARG, "expected a stream" TSRMLS_CC);
        !           626:                return;
        !           627:        }
        !           628: 
        !           629:        stm = php_com_wrapper_export_stream(stream TSRMLS_CC);
        !           630:        if (stm == NULL) {
        !           631:                php_com_throw_exception(E_UNEXPECTED, "failed to wrap stream" TSRMLS_CC);
        !           632:                return;
        !           633:        }
        !           634:        
        !           635:        res = get_persist_stream_init(helper);
        !           636:        if (helper->ipsi) {
        !           637:                res = IPersistStreamInit_Save(helper->ipsi, stm, TRUE);
        !           638:        } else {
        !           639:                res = get_persist_stream(helper);
        !           640:                if (helper->ips) {
        !           641:                        res = IPersistStream_Save(helper->ips, stm, TRUE);
        !           642:                }
        !           643:        }
        !           644:        
        !           645:        IStream_Release(stm);
        !           646: 
        !           647:        if (FAILED(res)) {
        !           648:                php_com_throw_exception(res, NULL TSRMLS_CC);
        !           649:                return;
        !           650:        }
        !           651: 
        !           652:        RETURN_TRUE;
        !           653: }
        !           654: /* }}} */
        !           655: 
        !           656: /* {{{ proto int COMPersistHelper::__construct([object com_object])
        !           657:    Creates a persistence helper object, usually associated with a com_object */
        !           658: CPH_METHOD(__construct)
        !           659: {
        !           660:        php_com_dotnet_object *obj = NULL;
        !           661:        zval *zobj = NULL;
        !           662:        CPH_FETCH();
        !           663: 
        !           664:        if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|O!",
        !           665:                                &zobj, php_com_variant_class_entry)) {
        !           666:                php_com_throw_exception(E_INVALIDARG, "invalid arguments" TSRMLS_CC);
        !           667:                return;
        !           668:        }
        !           669: 
        !           670:        if (!zobj) {
        !           671:                return;
        !           672:        }
        !           673:        
        !           674:        obj = CDNO_FETCH(zobj);
        !           675: 
        !           676:        if (V_VT(&obj->v) != VT_DISPATCH || V_DISPATCH(&obj->v) == NULL) {
        !           677:                php_com_throw_exception(E_INVALIDARG, "parameter must represent an IDispatch COM object" TSRMLS_CC);
        !           678:                return;
        !           679:        }
        !           680: 
        !           681:        /* it is always safe to cast an interface to IUnknown */
        !           682:        helper->unk = (IUnknown*)V_DISPATCH(&obj->v);
        !           683:        IUnknown_AddRef(helper->unk);
        !           684:        helper->codepage = obj->code_page;
        !           685: }
        !           686: /* }}} */
        !           687: 
        !           688: 
        !           689: 
        !           690: 
        !           691: static const zend_function_entry com_persist_helper_methods[] = {
        !           692:        CPH_ME(__construct, NULL)
        !           693:        CPH_ME(GetCurFileName, NULL)
        !           694:        CPH_ME(SaveToFile, NULL)
        !           695:        CPH_ME(LoadFromFile, NULL)
        !           696:        CPH_ME(GetMaxStreamSize, NULL)
        !           697:        CPH_ME(InitNew, NULL)
        !           698:        CPH_ME(LoadFromStream, NULL)
        !           699:        CPH_ME(SaveToStream, NULL)
        !           700:        PHP_FE_END
        !           701: };
        !           702: 
        !           703: static void helper_free_storage(void *obj TSRMLS_DC)
        !           704: {
        !           705:        php_com_persist_helper *object = (php_com_persist_helper*)obj;
        !           706: 
        !           707:        if (object->ipf) {
        !           708:                IPersistFile_Release(object->ipf);
        !           709:        }
        !           710:        if (object->ips) {
        !           711:                IPersistStream_Release(object->ips);
        !           712:        }
        !           713:        if (object->ipsi) {
        !           714:                IPersistStreamInit_Release(object->ipsi);
        !           715:        }
        !           716:        if (object->unk) {
        !           717:                IUnknown_Release(object->unk);
        !           718:        }
        !           719:        zend_object_std_dtor(&object->std TSRMLS_CC);
        !           720:        efree(object);
        !           721: }
        !           722: 
        !           723: 
        !           724: static void helper_clone(void *obj, void **clone_ptr TSRMLS_DC)
        !           725: {
        !           726:        php_com_persist_helper *clone, *object = (php_com_persist_helper*)obj;
        !           727: 
        !           728:        clone = emalloc(sizeof(*object));
        !           729:        memcpy(clone, object, sizeof(*object));
        !           730:        *clone_ptr = clone;
        !           731: 
        !           732:        zend_object_std_init(&clone->std, object->std.ce TSRMLS_CC);
        !           733: 
        !           734:        if (clone->ipf) {
        !           735:                IPersistFile_AddRef(clone->ipf);
        !           736:        }
        !           737:        if (clone->ips) {
        !           738:                IPersistStream_AddRef(clone->ips);
        !           739:        }
        !           740:        if (clone->ipsi) {
        !           741:                IPersistStreamInit_AddRef(clone->ipsi);
        !           742:        }
        !           743:        if (clone->unk) {
        !           744:                IUnknown_AddRef(clone->unk);
        !           745:        }
        !           746: }
        !           747: 
        !           748: static zend_object_value helper_new(zend_class_entry *ce TSRMLS_DC)
        !           749: {
        !           750:        php_com_persist_helper *helper;
        !           751:        zend_object_value retval;
        !           752: 
        !           753:        helper = emalloc(sizeof(*helper));
        !           754:        memset(helper, 0, sizeof(*helper));
        !           755: 
        !           756:        zend_object_std_init(&helper->std, helper_ce TSRMLS_CC);
        !           757:        
        !           758:        retval.handle = zend_objects_store_put(helper, NULL, helper_free_storage, helper_clone TSRMLS_CC);
        !           759:        retval.handlers = &helper_handlers;
        !           760: 
        !           761:        return retval;
        !           762: }
        !           763: 
        !           764: int php_com_persist_minit(INIT_FUNC_ARGS)
        !           765: {
        !           766:        zend_class_entry ce;
        !           767: 
        !           768:        memcpy(&helper_handlers, zend_get_std_object_handlers(), sizeof(helper_handlers));
        !           769:        helper_handlers.clone_obj = NULL;
        !           770: 
        !           771:        INIT_CLASS_ENTRY(ce, "COMPersistHelper", com_persist_helper_methods);
        !           772:        ce.create_object = helper_new;
        !           773:        helper_ce = zend_register_internal_class(&ce TSRMLS_CC);
        !           774:        helper_ce->ce_flags |= ZEND_ACC_FINAL;
        !           775: 
        !           776:        le_istream = zend_register_list_destructors_ex(istream_dtor,
        !           777:                        NULL, "com_dotnet_istream_wrapper", module_number);
        !           778:        
        !           779:        return SUCCESS;
        !           780: }
        !           781: 
        !           782: /*
        !           783:  * Local variables:
        !           784:  * tab-width: 4
        !           785:  * c-basic-offset: 4
        !           786:  * End:
        !           787:  * vim600: noet sw=4 ts=4 fdm=marker
        !           788:  * vim<600: noet sw=4 ts=4
        !           789:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>