php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
com_com.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Wez Furlong <wez@thebrainroom.com> |
14 +----------------------------------------------------------------------+
15 */
16
17#ifdef HAVE_CONFIG_H
18#include <config.h>
19#endif
20
21#include "php.h"
22#include "php_ini.h"
23#include "ext/standard/info.h"
24#include "php_com_dotnet.h"
27
28/* {{{ com_create_instance - ctor for COM class */
29PHP_METHOD(com, __construct)
30{
31 zval *object = ZEND_THIS;
32 zend_string *server_name = NULL;
33 HashTable *server_params = NULL;
35 char *module_name, *typelib_name = NULL;
36 size_t module_name_len = 0, typelib_name_len = 0;
37 zend_string *user_name = NULL, *password = NULL, *domain_name = NULL;
38 OLECHAR *moniker;
39 CLSID clsid;
40 CLSCTX ctx = CLSCTX_SERVER;
41 HRESULT res = E_FAIL;
42 ITypeLib *TL = NULL;
43 COSERVERINFO info;
44 COAUTHIDENTITY authid = {0};
45 COAUTHINFO authinfo = {
46 RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
47 RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE,
48 &authid, EOAC_NONE
49 };
50 zend_long cp = GetACP();
51 const struct php_win32_cp *cp_it;
52
54 Z_PARAM_STRING(module_name, module_name_len)
56 Z_PARAM_ARRAY_HT_OR_STR_OR_NULL(server_params, server_name)
58 Z_PARAM_STRING(typelib_name, typelib_name_len)
60
62 obj = CDNO_FETCH(object);
63
65 if (!cp_it) {
66 php_com_throw_exception(E_INVALIDARG, "Could not create COM object - invalid codepage!");
68 }
69 obj->code_page = (int)cp;
70
71 if (server_name) {
73 } else if (server_params) {
74 zval *tmp;
75
76 /* decode the data from the array */
77
78 if (NULL != (tmp = zend_hash_str_find(server_params,
79 "Server", sizeof("Server")-1))) {
80 server_name = zval_get_string(tmp);
82 }
83
84 if (NULL != (tmp = zend_hash_str_find(server_params,
85 "Username", sizeof("Username")-1))) {
86 user_name = zval_get_string(tmp);
87 }
88
89 if (NULL != (tmp = zend_hash_str_find(server_params,
90 "Password", sizeof("Password")-1))) {
91 password = zval_get_string(tmp);
92 }
93
94 if (NULL != (tmp = zend_hash_str_find(server_params,
95 "Domain", sizeof("Domain")-1))) {
96 domain_name = zval_get_string(tmp);
97 }
98
99 if (NULL != (tmp = zend_hash_str_find(server_params,
100 "Flags", sizeof("Flags")-1))) {
101 ctx = (CLSCTX)zval_get_long(tmp);
102 }
103 }
104
105 if (server_name && !COMG(allow_dcom)) {
106 php_com_throw_exception(E_ERROR, "DCOM has been disabled by your administrator [com.allow_dcom=0]");
108 }
109
110 moniker = php_com_string_to_olestring(module_name, module_name_len, obj->code_page);
111
112 /* if instantiating a remote object, either directly, or via
113 * a moniker, fill in the relevant info */
114 if (server_name) {
115 info.dwReserved1 = 0;
116 info.dwReserved2 = 0;
117 info.pwszName = php_com_string_to_olestring(ZSTR_VAL(server_name), ZSTR_LEN(server_name), obj->code_page);
118
119 if (user_name) {
120 authid.User = (OLECHAR*) ZSTR_VAL(user_name);
121 authid.UserLength = (ULONG) ZSTR_LEN(user_name);
122
123 if (password) {
124 authid.Password = (OLECHAR*) ZSTR_VAL(password);
125 authid.PasswordLength = (ULONG) ZSTR_LEN(password);
126 } else {
127 authid.Password = (OLECHAR*) "";
128 authid.PasswordLength = 0;
129 }
130
131 if (domain_name) {
132 authid.Domain = (OLECHAR*) ZSTR_VAL(domain_name);
133 authid.DomainLength = (ULONG) ZSTR_LEN(domain_name);
134 } else {
135 authid.Domain = (OLECHAR*) "";
136 authid.DomainLength = 0;
137 }
138 authid.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
139 info.pAuthInfo = &authinfo;
140 } else {
141 info.pAuthInfo = NULL;
142 }
143 }
144
145 if (FAILED(CLSIDFromString(moniker, &clsid))) {
146 /* try to use it as a moniker */
147 IBindCtx *pBindCtx = NULL;
148 IMoniker *pMoniker = NULL;
149 ULONG ulEaten;
150 BIND_OPTS2 bopt = {0};
151
152 if (SUCCEEDED(res = CreateBindCtx(0, &pBindCtx))) {
153 if (server_name) {
154 /* fill in the remote server info.
155 * MSDN docs indicate that this might be ignored in
156 * current win32 implementations, but at least we are
157 * doing the right thing in readiness for the day that
158 * it does work */
159 bopt.cbStruct = sizeof(bopt);
160 IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS*)&bopt);
161 bopt.pServerInfo = &info;
162 /* apparently, GetBindOptions will only ever return
163 * a regular BIND_OPTS structure. My gut feeling is
164 * that it will modify the size field to reflect that
165 * so lets be safe and set it to the BIND_OPTS2 size
166 * again */
167 bopt.cbStruct = sizeof(bopt);
168 IBindCtx_SetBindOptions(pBindCtx, (BIND_OPTS*)&bopt);
169 }
170
171 if (SUCCEEDED(res = MkParseDisplayName(pBindCtx, moniker, &ulEaten, &pMoniker))) {
172 res = IMoniker_BindToObject(pMoniker, pBindCtx,
173 NULL, &IID_IDispatch, (LPVOID*)&V_DISPATCH(&obj->v));
174
175 if (SUCCEEDED(res)) {
176 V_VT(&obj->v) = VT_DISPATCH;
177 }
178
179 IMoniker_Release(pMoniker);
180 }
181 }
182 if (pBindCtx) {
183 IBindCtx_Release(pBindCtx);
184 }
185 } else if (server_name) {
186 MULTI_QI qi;
187
188 qi.pIID = &IID_IDispatch;
189 qi.pItf = NULL;
190 qi.hr = S_OK;
191
192 res = CoCreateInstanceEx(&clsid, NULL, ctx, &info, 1, &qi);
193
194 if (SUCCEEDED(res)) {
195 res = qi.hr;
196 V_DISPATCH(&obj->v) = (IDispatch*)qi.pItf;
197 V_VT(&obj->v) = VT_DISPATCH;
198 }
199 } else {
200 res = CoCreateInstance(&clsid, NULL, CLSCTX_SERVER, &IID_IDispatch, (LPVOID*)&V_DISPATCH(&obj->v));
201 if (SUCCEEDED(res)) {
202 V_VT(&obj->v) = VT_DISPATCH;
203 }
204 }
205
206 if (server_name) {
207 if (info.pwszName) efree(info.pwszName);
208 if (server_params) zend_string_release(server_name);
209 }
210 if (user_name) zend_string_release(user_name);
211 if (password) zend_string_release(password);
212 if (domain_name) zend_string_release(domain_name);
213
214 efree(moniker);
215
216 if (FAILED(res)) {
217 char *werr, *msg;
218
220 spprintf(&msg, 0, "Failed to create COM object `%s': %s", module_name, werr);
222
224 efree(msg);
226 }
227
228 /* we got the object and it lives ! */
229
230 /* see if it has TypeInfo available */
231 if (FAILED(IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), &obj->typeinfo)) && typelib_name) {
232 /* load up the library from the named file */
233 TL = php_com_load_typelib_via_cache(typelib_name, obj->code_page);
234
235 if (TL) {
236 if (COMG(autoreg_on)) {
238 }
239
240 /* cross your fingers... there is no guarantee that this ITypeInfo
241 * instance has any relation to this IDispatch instance... */
242 ITypeLib_GetTypeInfo(TL, 0, &obj->typeinfo);
243 ITypeLib_Release(TL);
244 }
245 } else if (obj->typeinfo && COMG(autoreg_on)) {
246 UINT idx;
247
248 if (SUCCEEDED(ITypeInfo_GetContainingTypeLib(obj->typeinfo, &TL, &idx))) {
249 /* check if the library is already in the cache by getting its name */
250 BSTR name;
251
252 if (SUCCEEDED(ITypeLib_GetDocumentation(TL, -1, &name, NULL, NULL, NULL))) {
254
255 if (NULL != php_com_cache_typelib(TL, ZSTR_VAL(typelib_str), ZSTR_LEN(typelib_str))) {
257
258 /* add a reference for the hash */
259 ITypeLib_AddRef(TL);
260 }
261 zend_string_release_ex(typelib_str, /* persistent */ false);
262 } else {
263 /* try it anyway */
265 }
266
267 ITypeLib_Release(TL);
268 }
269 }
270
271}
272/* }}} */
273
274/* {{{ Returns a handle to an already running instance of a COM object */
276{
277 CLSID clsid;
278 char *module_name;
279 size_t module_name_len;
281 bool code_page_is_null = 1;
282 IUnknown *unk = NULL;
283 IDispatch *obj = NULL;
284 HRESULT res;
285 OLECHAR *module = NULL;
286
289 &module_name, &module_name_len, &code_page, &code_page_is_null)) {
291 }
292
293 if (code_page_is_null) {
295 }
296
297 module = php_com_string_to_olestring(module_name, module_name_len, (int)code_page);
298
299 res = CLSIDFromString(module, &clsid);
300
301 if (FAILED(res)) {
303 } else {
304 res = GetActiveObject(&clsid, NULL, &unk);
305
306 if (FAILED(res)) {
308 } else {
309 res = IUnknown_QueryInterface(unk, &IID_IDispatch, &obj);
310
311 if (FAILED(res)) {
313 } else if (obj) {
314 /* we got our dispatchable object */
316 }
317 }
318 }
319
320 if (obj) {
321 IDispatch_Release(obj);
322 }
323 if (unk) {
324 IUnknown_Release(obj);
325 }
326 efree(module);
327}
328/* }}} */
329
330/* Performs an Invoke on the given com object.
331 * returns a failure code and creates an exception if there was an error */
332HRESULT php_com_invoke_helper(php_com_dotnet_object *obj, DISPID id_member,
333 WORD flags, DISPPARAMS *disp_params, VARIANT *v, bool silent, bool allow_noarg)
334{
335 HRESULT hr;
336 unsigned int arg_err;
337 EXCEPINFO e = {0};
338
339 hr = IDispatch_Invoke(V_DISPATCH(&obj->v), id_member,
340 &IID_NULL, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), flags, disp_params, v, &e, &arg_err);
341
342 if (!silent && FAILED(hr)) {
343 char *desc = NULL, *msg = NULL;
344
345 switch (hr) {
346 case DISP_E_EXCEPTION: {
347 zend_string *source = NULL, *desc_str = NULL;
348 if (e.bstrSource) {
349 source = php_com_olestring_to_string(e.bstrSource, obj->code_page);
350 SysFreeString(e.bstrSource);
351 }
352 if (e.bstrDescription) {
353 desc_str = php_com_olestring_to_string(e.bstrDescription, obj->code_page);
354 SysFreeString(e.bstrDescription);
355 }
356 if (PG(html_errors)) {
357 spprintf(&msg, 0, "<b>Source:</b> %s<br/><b>Description:</b> %s",
358 source ? ZSTR_VAL(source) : "Unknown",
359 desc_str ? ZSTR_VAL(desc_str) : "Unknown");
360 } else {
361 spprintf(&msg, 0, "Source: %s\nDescription: %s",
362 source ? ZSTR_VAL(source) : "Unknown",
363 desc_str ? ZSTR_VAL(desc_str) : "Unknown");
364 }
365 if (desc_str) {
366 zend_string_release_ex(desc_str, /* persistent */ false);
367 }
368 if (source) {
369 zend_string_release_ex(source, /* persistent */ false);
370 }
371 if (e.bstrHelpFile) {
372 SysFreeString(e.bstrHelpFile);
373 }
374 break;
375 }
377 case DISP_E_TYPEMISMATCH:
379 spprintf(&msg, 0, "Parameter %d: %s", arg_err, desc);
381 break;
382
383 case DISP_E_BADPARAMCOUNT:
384 if ((disp_params->cArgs + disp_params->cNamedArgs == 0) && allow_noarg) {
385 /* if getting a property and they are missing all parameters,
386 * we want to create a proxy object for them; so lets not create an
387 * exception here */
388 msg = NULL;
389 break;
390 }
391 /* else fall through */
392
393 default:
395 spprintf(&msg, 0, "Error [0x%08lx] %s", hr, desc);
397 break;
398 }
399
400 if (msg) {
402 efree(msg);
403 }
404 }
405
406 return hr;
407}
408
409/* map an ID to a name */
411 DISPID *dispid)
412{
413 OLECHAR *olename;
414 HRESULT hr;
415 zval *tmp;
416
417 if (obj->id_of_name_cache && NULL != (tmp = zend_hash_find(obj->id_of_name_cache, name))) {
418 *dispid = (DISPID)Z_LVAL_P(tmp);
419 return S_OK;
420 }
421
423
424 if (obj->typeinfo) {
425 hr = ITypeInfo_GetIDsOfNames(obj->typeinfo, &olename, 1, dispid);
426 if (FAILED(hr)) {
427 HRESULT hr1 = hr;
428 hr = IDispatch_GetIDsOfNames(V_DISPATCH(&obj->v), &IID_NULL, &olename, 1, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), dispid);
429 if (SUCCEEDED(hr) && hr1 != E_NOTIMPL) {
430 /* fall back on IDispatch direct */
431 ITypeInfo_Release(obj->typeinfo);
432 obj->typeinfo = NULL;
433 }
434 }
435 } else {
436 hr = IDispatch_GetIDsOfNames(V_DISPATCH(&obj->v), &IID_NULL, &olename, 1, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), dispid);
437 }
438 efree(olename);
439
440 if (SUCCEEDED(hr)) {
441 zval tmp;
442
443 /* cache the mapping */
444 if (!obj->id_of_name_cache) {
447 }
448 ZVAL_LONG(&tmp, *dispid);
450 }
451
452 return hr;
453}
454
455/* the core of COM */
457 WORD flags, VARIANT *v, int nargs, zval *args)
458{
459 DISPID dispid, altdispid;
460 DISPPARAMS disp_params;
461 HRESULT hr;
462 VARIANT *vargs = NULL, *byref_vals = NULL;
463 int i, byref_count = 0, j;
464
465 /* assumption: that the active function (f) is the function we generated for the engine */
466 if (!f) {
467 return FAILURE;
468 }
469
470 hr = php_com_get_id_of_name(obj, f->function_name, &dispid);
471
472 if (FAILED(hr)) {
473 char *msg = NULL;
474 char *winerr = php_win32_error_to_msg(hr);
475 spprintf(&msg, 0, "Unable to lookup `%s': %s", f->function_name->val, winerr);
478 efree(msg);
479 return FAILURE;
480 }
481
482
483 if (nargs) {
484 vargs = (VARIANT*)safe_emalloc(sizeof(VARIANT), nargs, 0);
485 }
486
487 if (f->arg_info) {
488 for (i = 0; i < nargs; i++) {
489 if (ZEND_ARG_SEND_MODE(&f->arg_info[nargs - i - 1])) {
490 byref_count++;
491 }
492 }
493 }
494
495 if (byref_count) {
496 byref_vals = (VARIANT*)safe_emalloc(sizeof(VARIANT), byref_count, 0);
497 for (j = 0, i = 0; i < nargs; i++) {
498 if (ZEND_ARG_SEND_MODE(&f->arg_info[nargs - i - 1])) {
499 /* put the value into byref_vals instead */
500 php_com_variant_from_zval(&byref_vals[j], &args[nargs - i - 1], obj->code_page);
501
502 /* if it is already byref, "move" it into the vargs array, otherwise
503 * make vargs a reference to this value */
504 if (V_VT(&byref_vals[j]) & VT_BYREF) {
505 memcpy(&vargs[i], &byref_vals[j], sizeof(vargs[i]));
506 VariantInit(&byref_vals[j]); /* leave the variant slot empty to simplify cleanup */
507 } else {
508 VariantInit(&vargs[i]);
509 V_VT(&vargs[i]) = V_VT(&byref_vals[j]) | VT_BYREF;
510 /* union magic ensures that this works out */
511 vargs[i].byref = &V_UINT(&byref_vals[j]);
512 }
513 j++;
514 } else {
515 php_com_variant_from_zval(&vargs[i], &args[nargs - i - 1], obj->code_page);
516 }
517 }
518
519 } else {
520 /* Invoke'd args are in reverse order */
521 for (i = 0; i < nargs; i++) {
522 php_com_variant_from_zval(&vargs[i], &args[nargs - i - 1], obj->code_page);
523 }
524 }
525
526 disp_params.cArgs = nargs;
527 disp_params.cNamedArgs = 0;
528 disp_params.rgvarg = vargs;
529 disp_params.rgdispidNamedArgs = NULL;
530
531 if (flags & DISPATCH_PROPERTYPUT) {
532 altdispid = DISPID_PROPERTYPUT;
533 disp_params.rgdispidNamedArgs = &altdispid;
534 disp_params.cNamedArgs = 1;
535 }
536
537 /* this will create an exception if needed */
538 hr = php_com_invoke_helper(obj, dispid, flags, &disp_params, v, 0, 0);
539
540 /* release variants */
541 if (vargs) {
542 if (f && f->arg_info) {
543 for (i = 0, j = 0; i < nargs; i++) {
544 /* if this was byref, update the zval */
545 if (ZEND_ARG_SEND_MODE(&f->arg_info[nargs - i - 1])) {
546 zval *arg = &args[nargs - i - 1];
547
550 ZVAL_NULL(arg);
551
552 /* if the variant is pointing at the byref_vals, we need to map
553 * the pointee value as a zval; otherwise, the value is pointing
554 * into an existing PHP variant record */
555 if (V_VT(&vargs[i]) & VT_BYREF) {
556 if (vargs[i].byref == &V_UINT(&byref_vals[j])) {
557 /* copy that value */
558 php_com_zval_from_variant(arg, &byref_vals[j], obj->code_page);
559 }
560 } else {
561 /* not sure if this can ever happen; the variant we marked as BYREF
562 * is no longer BYREF - copy its value */
563 php_com_zval_from_variant(arg, &vargs[i], obj->code_page);
564 }
565 VariantClear(&byref_vals[j]);
566 j++;
567 }
568 VariantClear(&vargs[i]);
569 }
570 } else {
571 for (i = 0, j = 0; i < nargs; i++) {
572 VariantClear(&vargs[i]);
573 }
574 }
575 efree(vargs);
576 if (byref_vals) efree(byref_vals);
577 }
578
579 return SUCCEEDED(hr) ? SUCCESS : FAILURE;
580}
581
582
583
585 WORD flags, VARIANT *v, int nargs, zval *args, bool silent, bool allow_noarg)
586{
587 DISPID altdispid;
588 DISPPARAMS disp_params;
589 HRESULT hr;
590 VARIANT *vargs = NULL;
591 int i;
592
593 if (nargs) {
594 vargs = (VARIANT*)safe_emalloc(sizeof(VARIANT), nargs, 0);
595 }
596
597 /* Invoke'd args are in reverse order */
598 for (i = 0; i < nargs; i++) {
599 php_com_variant_from_zval(&vargs[i], &args[nargs - i - 1], obj->code_page);
600 }
601
602 disp_params.cArgs = nargs;
603 disp_params.cNamedArgs = 0;
604 disp_params.rgvarg = vargs;
605 disp_params.rgdispidNamedArgs = NULL;
606
607 if (flags & DISPATCH_PROPERTYPUT) {
608 altdispid = DISPID_PROPERTYPUT;
609 disp_params.rgdispidNamedArgs = &altdispid;
610 disp_params.cNamedArgs = 1;
611 }
612
613 /* this will create an exception if needed */
614 hr = php_com_invoke_helper(obj, dispid, flags, &disp_params, v, silent, allow_noarg);
615
616 /* release variants */
617 if (vargs) {
618 for (i = 0; i < nargs; i++) {
619 VariantClear(&vargs[i]);
620 }
621 efree(vargs);
622 }
623
624 /* a bit of a hack this, but it's needed for COM array access. */
625 if (hr == DISP_E_BADPARAMCOUNT)
626 return hr;
627
628 return SUCCEEDED(hr) ? SUCCESS : FAILURE;
629}
630
632 WORD flags, VARIANT *v, int nargs, zval *args, bool allow_noarg)
633{
634 DISPID dispid;
635 HRESULT hr;
636 char *msg = NULL;
637
638 hr = php_com_get_id_of_name(obj, name, &dispid);
639
640 if (FAILED(hr)) {
641 char *winerr = php_win32_error_to_msg(hr);
642 spprintf(&msg, 0, "Unable to lookup `%s': %s", ZSTR_VAL(name), winerr);
645 efree(msg);
646 return FAILURE;
647 }
648
649 return php_com_do_invoke_by_id(obj, dispid, flags, v, nargs, args, 0, allow_noarg);
650}
651
652/* {{{ Generate a globally unique identifier (GUID) */
654{
655 GUID retval;
656 OLECHAR *guid_string;
657
660 }
661
663 if (CoCreateGuid(&retval) == S_OK && StringFromCLSID(&retval, &guid_string) == S_OK) {
665
666 CoTaskMemFree(guid_string);
667 } else {
669 }
670}
671/* }}} */
672
673/* {{{ Connect events from a COM object to a PHP object */
675{
676 zval *object, *sinkobject;
677 zend_string *sink_str = NULL;
678 HashTable *sink_ht = NULL;
679 zend_string *type_lib_name = NULL;
680 zend_string *dispatch_name = NULL;
682 ITypeInfo *typeinfo = NULL;
683
686 Z_PARAM_OBJECT(sinkobject)
688 Z_PARAM_ARRAY_HT_OR_STR_OR_NULL(sink_ht, sink_str)
690
692
694 obj = CDNO_FETCH(object);
695
696 if (sink_ht) {
697 /* 0 => typelibname, 1 => dispname */
698 zval *tmp;
699
700 if ((tmp = zend_hash_index_find(sink_ht, 0)) != NULL && Z_TYPE_P(tmp) == IS_STRING)
701 type_lib_name = Z_STR_P(tmp);
702 if ((tmp = zend_hash_index_find(sink_ht, 1)) != NULL && Z_TYPE_P(tmp) == IS_STRING)
703 dispatch_name = Z_STR_P(tmp);
704 } else if (sink_str) {
705 dispatch_name = sink_str;
706 }
707
708 typeinfo = php_com_locate_typeinfo(type_lib_name, obj, dispatch_name, /* sink */ true);
709
710 if (typeinfo) {
711 HashTable *id_to_name;
712
713 ALLOC_HASHTABLE(id_to_name);
714
715 if (php_com_process_typeinfo(typeinfo, id_to_name, 0, &obj->sink_id, obj->code_page)) {
716
717 /* Create the COM wrapper for this sink */
718 obj->sink_dispatch = php_com_wrapper_export_as_sink(sinkobject, &obj->sink_id, id_to_name);
719
720 /* Now hook it up to the source */
721 php_com_object_enable_event_sink(obj, /* enable */ true);
723
724 } else {
725 FREE_HASHTABLE(id_to_name);
726 }
727 }
728
729 if (typeinfo) {
730 ITypeInfo_Release(typeinfo);
731 }
732
733}
734/* }}} */
735
736/* {{{ Print out a PHP class definition for a dispatchable interface */
738{
739 zend_object *object_zpp;
740 zend_string *type_lib_name = NULL;
741 zend_string *interface_name = NULL;
742 bool want_sink = false;
744 ITypeInfo *typeinfo;
745
749 Z_PARAM_STR_OR_NULL(interface_name)
750 Z_PARAM_BOOL(want_sink)
752
754 if (object_zpp) {
755 obj = (php_com_dotnet_object*)object_zpp;
756 }
757
758 typeinfo = php_com_locate_typeinfo(type_lib_name, obj, interface_name, want_sink);
759 if (typeinfo) {
760 php_com_process_typeinfo(typeinfo, NULL, 1, NULL, obj ? obj->code_page : COMG(code_page));
761 ITypeInfo_Release(typeinfo);
763 }
764
765 php_error_docref(NULL, E_WARNING, "Unable to find typeinfo using the parameters supplied");
767}
768/* }}} */
769
770/* {{{ Process COM messages, sleeping for up to timeoutms milliseconds */
772{
773 zend_long timeoutms = 0;
774 MSG msg;
776
777 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &timeoutms) == FAILURE)
779
781 result = MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD)timeoutms, QS_ALLINPUT);
782
783 if (result == WAIT_OBJECT_0) {
784 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
785 TranslateMessage(&msg);
786 DispatchMessage(&msg);
787 }
788 /* we processed messages */
790 } else {
791 /* we did not process messages (timed out) */
793 }
794}
795/* }}} */
796
797/* {{{ Loads a Typelibrary and registers its constants */
799{
800 char *name;
801 size_t namelen;
802 ITypeLib *pTL = NULL;
803 bool cs = TRUE;
804 int codepage = COMG(code_page);
805
806 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "s|b", &name, &namelen, &cs)) {
808 }
809
810 if (!cs) {
811 php_error_docref(NULL, E_WARNING, "com_load_typelib(): Argument #2 ($case_insensitive) is ignored since declaration of case-insensitive constants is no longer supported");
812 }
813
815
817 pTL = php_com_load_typelib_via_cache(name, codepage);
818 if (pTL) {
819 if (php_com_import_typelib(pTL, 0, codepage) == SUCCESS) {
821 }
822
823 ITypeLib_Release(pTL);
824 pTL = NULL;
825 }
826}
827/* }}} */
uint32_t v
Definition cdf.c:1237
PW32CP const struct php_win32_cp * php_win32_cp_get_by_id(DWORD id)
Definition codepage.c:338
zend_result php_com_do_invoke(php_com_dotnet_object *obj, zend_string *name, WORD flags, VARIANT *v, int nargs, zval *args, bool allow_noarg)
Definition com_com.c:631
zend_result php_com_do_invoke_by_id(php_com_dotnet_object *obj, DISPID dispid, WORD flags, VARIANT *v, int nargs, zval *args, bool silent, bool allow_noarg)
Definition com_com.c:584
HRESULT php_com_get_id_of_name(php_com_dotnet_object *obj, zend_string *name, DISPID *dispid)
Definition com_com.c:410
HRESULT php_com_invoke_helper(php_com_dotnet_object *obj, DISPID id_member, WORD flags, DISPPARAMS *disp_params, VARIANT *v, bool silent, bool allow_noarg)
Definition com_com.c:332
zend_result php_com_do_invoke_byref(php_com_dotnet_object *obj, zend_internal_function *f, WORD flags, VARIANT *v, int nargs, zval *args)
Definition com_com.c:456
zend_class_entry * php_com_variant_class_entry
const VT_BYREF
com_message_pump(int $timeout_milliseconds=0)
com_create_guid()
const VT_DISPATCH
com_get_active_object(string $prog_id, ?int $codepage=null)
const CP_ACP
com_event_sink(variant $variant, object $sink_object, array|string|null $sink_interface=null)
const CLSCTX_SERVER
com_load_typelib(string $typelib, bool $case_insensitive=true)
const DISP_E_PARAMNOTFOUND
const CLSCTX_REMOTE_SERVER
com_print_typeinfo(variant|string $variant, ?string $dispatch_interface=null, bool $display_sink=false)
void php_com_object_enable_event_sink(php_com_dotnet_object *obj, bool enable)
void php_com_throw_exception(HRESULT code, char *message)
Definition com_misc.c:28
PHP_COM_DOTNET_API void php_com_wrap_dispatch(zval *z, IDispatch *disp, int codepage)
Definition com_misc.c:45
PHP_COM_DOTNET_API zend_string * php_com_olestring_to_string(OLECHAR *olestring, int codepage)
Definition com_olechar.c:70
PHP_COM_DOTNET_API OLECHAR * php_com_string_to_olestring(const char *string, size_t string_len, int codepage)
Definition com_olechar.c:29
ITypeLib * php_com_cache_typelib(ITypeLib *TL, char *cache_key, zend_long cache_key_len)
ITypeInfo * php_com_locate_typeinfo(zend_string *type_lib_name, php_com_dotnet_object *obj, zend_string *dispatch_name, bool sink)
PHP_COM_DOTNET_API ITypeLib * php_com_load_typelib_via_cache(const char *search_string, int codepage)
PHP_COM_DOTNET_API zend_result php_com_import_typelib(ITypeLib *TL, int mode, int codepage)
bool php_com_process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, bool printdef, GUID *guid, int codepage)
PHP_COM_DOTNET_API zend_result php_com_zval_from_variant(zval *z, VARIANT *v, int codepage)
PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage)
PHP_COM_DOTNET_API IDispatch * php_com_wrapper_export_as_sink(zval *val, GUID *sinkid, HashTable *id_to_name)
#define WORD
Definition exif.c:1759
#define DWORD
Definition exif.c:1762
zend_string * res
Definition ffi.c:4692
memcpy(ptr1, ptr2, size)
zval * arg
Definition ffi.c:3975
#define TRUE
Definition gd_gd.c:7
#define FALSE
Definition gd_gd.c:8
#define NULL
Definition gdcache.h:45
#define SUCCESS
Definition hash_sha3.c:261
again j
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
Definition main.c:1173
PHPAPI void php_com_initialize(void)
Definition main.c:2005
#define PHP_FUNCTION
Definition php.h:364
#define PHP_METHOD
Definition php.h:365
#define COMG(v)
int code_page
bool autoreg_on
bool allow_dcom
#define CDNO_FETCH(zv)
struct _php_com_dotnet_object php_com_dotnet_object
#define PG(v)
Definition php_globals.h:31
char * msg
Definition phpdbg.h:289
ptrdiff_t namelen
Definition session.c:1097
#define spprintf
Definition spprintf.h:29
zend_string * function_name
zend_internal_arg_info * arg_info
char val[1]
Definition zend_types.h:377
char * desc
Definition codepage.h:40
PHP_WINUTIL_API char * php_win32_error_to_msg(HRESULT error)
Definition winutil.c:25
PHP_WINUTIL_API void php_win32_error_msg_free(char *msg)
Definition winutil.c:50
ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec,...)
Definition zend_API.c:1300
#define ZEND_NUM_ARGS()
Definition zend_API.h:530
#define Z_PARAM_ARRAY_HT_OR_STR_OR_NULL(dest_ht, dest_str)
Definition zend_API.h:2154
#define Z_PARAM_OBJ_OF_CLASS_OR_STR(destination_object, base_ce, destination_string)
Definition zend_API.h:1788
#define ZEND_PARSE_PARAMETERS_END()
Definition zend_API.h:1641
#define RETURN_FALSE
Definition zend_API.h:1058
#define Z_PARAM_OBJECT(dest)
Definition zend_API.h:1940
#define Z_PARAM_STR_OR_NULL(dest)
Definition zend_API.h:2089
#define Z_PARAM_OPTIONAL
Definition zend_API.h:1667
#define zend_parse_parameters_none()
Definition zend_API.h:353
#define Z_PARAM_STRING(dest, dest_len)
Definition zend_API.h:2071
#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args)
Definition zend_API.h:1620
#define Z_PARAM_LONG(dest)
Definition zend_API.h:1896
#define RETURN_THROWS()
Definition zend_API.h:1060
#define RETVAL_TRUE
Definition zend_API.h:1033
#define ZEND_THIS
Definition zend_API.h:523
#define Z_PARAM_BOOL(dest)
Definition zend_API.h:1726
#define Z_PARAM_OBJECT_OF_CLASS(dest, _ce)
Definition zend_API.h:1976
#define RETVAL_STR(s)
Definition zend_API.h:1013
#define RETVAL_FALSE
Definition zend_API.h:1032
#define RETURN_TRUE
Definition zend_API.h:1059
#define efree(ptr)
Definition zend_alloc.h:155
#define FREE_HASHTABLE(ht)
Definition zend_alloc.h:234
#define safe_emalloc(nmemb, size, offset)
Definition zend_alloc.h:154
#define ALLOC_HASHTABLE(ht)
Definition zend_alloc.h:231
struct _zval_struct zval
zend_string_release_ex(func->internal_function.function_name, 0)
zval * args
#define ZEND_ARG_SEND_MODE(arg_info)
struct _zend_internal_function zend_internal_function
#define E_ERROR
Definition zend_errors.h:23
#define E_WARNING
Definition zend_errors.h:24
ZEND_API zval *ZEND_FASTCALL zend_hash_str_find(const HashTable *ht, const char *str, size_t len)
Definition zend_hash.c:2689
ZEND_API zval *ZEND_FASTCALL zend_hash_update(HashTable *ht, zend_string *key, zval *pData)
Definition zend_hash.c:997
ZEND_API zval *ZEND_FASTCALL zend_hash_find(const HashTable *ht, zend_string *key)
Definition zend_hash.c:2668
ZEND_API zval *ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulong h)
Definition zend_hash.c:2701
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent)
Definition zend_hash.h:108
int32_t zend_long
Definition zend_long.h:42
struct _zend_string zend_string
struct _zend_object zend_object
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define ZVAL_NULL(z)
#define ZVAL_DEREF(z)
#define ZVAL_LONG(z, l)
#define IS_STRING
Definition zend_types.h:606
struct _zend_array HashTable
Definition zend_types.h:386
#define Z_STR_P(zval_p)
Definition zend_types.h:972
@ FAILURE
Definition zend_types.h:61
ZEND_RESULT_CODE zend_result
Definition zend_types.h:64
#define Z_LVAL_P(zval_p)
Definition zend_types.h:966
ZEND_API void zval_ptr_dtor(zval *zval_ptr)
zval retval
zval * return_value
zend_string * name
bool result
object