Annotation of embedaddon/php/ext/com_dotnet/com_persist.c, revision 1.1.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>