Return to com_persist.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / com_dotnet |
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: */