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