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>