1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2018 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 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include <intsafe.h>
24
25 #include "php.h"
26 #include "php_ini.h"
27 #include "ext/standard/info.h"
28 #include "php_com_dotnet.h"
29 #include "php_com_dotnet_internal.h"
30 #include "Zend/zend_exceptions.h"
31 #include "Zend/zend_interfaces.h"
32
33 ZEND_DECLARE_MODULE_GLOBALS(com_dotnet)
34 static PHP_GINIT_FUNCTION(com_dotnet);
35
36 TsHashTable php_com_typelibraries;
37
38 zend_class_entry
39 *php_com_variant_class_entry,
40 *php_com_exception_class_entry,
41 *php_com_saproxy_class_entry;
42
43 /* {{{ arginfo */
44 ZEND_BEGIN_ARG_INFO_EX(arginfo_variant_set, 0, 0, 2)
45 ZEND_ARG_INFO(0, variant)
46 ZEND_ARG_INFO(0, value)
47 ZEND_END_ARG_INFO()
48
49 ZEND_BEGIN_ARG_INFO_EX(arginfo_left_right, 0, 0, 2)
50 ZEND_ARG_INFO(0, left)
51 ZEND_ARG_INFO(0, right)
52 ZEND_END_ARG_INFO()
53
54 ZEND_BEGIN_ARG_INFO_EX(arginfo_variant_abs, 0, 0, 1)
55 ZEND_ARG_INFO(0, left)
56 ZEND_END_ARG_INFO()
57
58 ZEND_BEGIN_ARG_INFO_EX(arginfo_variant_fix, 0, 0, 1)
59 ZEND_ARG_INFO(0, left)
60 ZEND_END_ARG_INFO()
61
62 ZEND_BEGIN_ARG_INFO_EX(arginfo_variant_int, 0, 0, 1)
63 ZEND_ARG_INFO(0, left)
64 ZEND_END_ARG_INFO()
65
66 ZEND_BEGIN_ARG_INFO_EX(arginfo_variant_neg, 0, 0, 1)
67 ZEND_ARG_INFO(0, left)
68 ZEND_END_ARG_INFO()
69
70 ZEND_BEGIN_ARG_INFO_EX(arginfo_variant_not, 0, 0, 1)
71 ZEND_ARG_INFO(0, left)
72 ZEND_END_ARG_INFO()
73
74 ZEND_BEGIN_ARG_INFO_EX(arginfo_variant_round, 0, 0, 2)
75 ZEND_ARG_INFO(0, left)
76 ZEND_ARG_INFO(0, decimals)
77 ZEND_END_ARG_INFO()
78
79 ZEND_BEGIN_ARG_INFO_EX(arginfo_variant_cmp, 0, 0, 2)
80 ZEND_ARG_INFO(0, left)
81 ZEND_ARG_INFO(0, right)
82 ZEND_ARG_INFO(0, lcid)
83 ZEND_ARG_INFO(0, flags)
84 ZEND_END_ARG_INFO()
85
86 ZEND_BEGIN_ARG_INFO_EX(arginfo_variant_date_to_timestamp, 0, 0, 1)
87 ZEND_ARG_INFO(0, variant)
88 ZEND_END_ARG_INFO()
89
90 ZEND_BEGIN_ARG_INFO_EX(arginfo_variant_date_from_timestamp, 0, 0, 1)
91 ZEND_ARG_INFO(0, timestamp)
92 ZEND_END_ARG_INFO()
93
94 ZEND_BEGIN_ARG_INFO_EX(arginfo_variant_get_type, 0, 0, 1)
95 ZEND_ARG_INFO(0, variant)
96 ZEND_END_ARG_INFO()
97
98 ZEND_BEGIN_ARG_INFO_EX(arginfo_variant_set_type, 0, 0, 2)
99 ZEND_ARG_INFO(0, variant)
100 ZEND_ARG_INFO(0, type)
101 ZEND_END_ARG_INFO()
102
103 ZEND_BEGIN_ARG_INFO_EX(arginfo_variant_cast, 0, 0, 2)
104 ZEND_ARG_INFO(0, variant)
105 ZEND_ARG_INFO(0, type)
106 ZEND_END_ARG_INFO()
107
108 ZEND_BEGIN_ARG_INFO_EX(arginfo_com_get_active_object, 0, 0, 1)
109 ZEND_ARG_INFO(0, progid)
110 ZEND_ARG_INFO(0, code_page)
111 ZEND_END_ARG_INFO()
112
113 ZEND_BEGIN_ARG_INFO(arginfo_com_create_guid, 0)
114 ZEND_END_ARG_INFO()
115
116 ZEND_BEGIN_ARG_INFO_EX(arginfo_com_event_sink, 0, 0, 2)
117 ZEND_ARG_INFO(0, comobject)
118 ZEND_ARG_INFO(0, sinkobject)
119 ZEND_ARG_INFO(0, sinkinterface)
120 ZEND_END_ARG_INFO()
121
122 ZEND_BEGIN_ARG_INFO_EX(arginfo_com_print_typeinfo, 0, 0, 1)
123 ZEND_ARG_INFO(0, comobject)
124 ZEND_ARG_INFO(0, dispinterface)
125 ZEND_ARG_INFO(0, wantsink)
126 ZEND_END_ARG_INFO()
127
128 ZEND_BEGIN_ARG_INFO_EX(arginfo_com_message_pump, 0, 0, 0)
129 ZEND_ARG_INFO(0, timeoutms)
130 ZEND_END_ARG_INFO()
131
132 ZEND_BEGIN_ARG_INFO_EX(arginfo_com_load_typelib, 0, 0, 1)
133 ZEND_ARG_INFO(0, typelib_name)
134 ZEND_ARG_INFO(0, case_insensitive)
135 ZEND_END_ARG_INFO()
136 /* }}} */
137
138 static const zend_function_entry com_dotnet_functions[] = {
139 PHP_FE(variant_set, arginfo_variant_set)
140 PHP_FE(variant_add, arginfo_left_right)
141 PHP_FE(variant_cat, arginfo_left_right)
142 PHP_FE(variant_sub, arginfo_left_right)
143 PHP_FE(variant_mul, arginfo_left_right)
144 PHP_FE(variant_and, arginfo_left_right)
145 PHP_FE(variant_div, arginfo_left_right)
146 PHP_FE(variant_eqv, arginfo_left_right)
147 PHP_FE(variant_idiv, arginfo_left_right)
148 PHP_FE(variant_imp, arginfo_left_right)
149 PHP_FE(variant_mod, arginfo_left_right)
150 PHP_FE(variant_or, arginfo_left_right)
151 PHP_FE(variant_pow, arginfo_left_right)
152 PHP_FE(variant_xor, arginfo_left_right)
153 PHP_FE(variant_abs, arginfo_variant_abs)
154 PHP_FE(variant_fix, arginfo_variant_fix)
155 PHP_FE(variant_int, arginfo_variant_int)
156 PHP_FE(variant_neg, arginfo_variant_neg)
157 PHP_FE(variant_not, arginfo_variant_not)
158 PHP_FE(variant_round, arginfo_variant_round)
159 PHP_FE(variant_cmp, arginfo_variant_cmp)
160 PHP_FE(variant_date_to_timestamp, arginfo_variant_date_to_timestamp)
161 PHP_FE(variant_date_from_timestamp, arginfo_variant_date_from_timestamp)
162 PHP_FE(variant_get_type, arginfo_variant_get_type)
163 PHP_FE(variant_set_type, arginfo_variant_set_type)
164 PHP_FE(variant_cast, arginfo_variant_cast)
165 /* com_com.c */
166 PHP_FE(com_create_guid, arginfo_com_create_guid)
167 PHP_FE(com_event_sink, arginfo_com_event_sink)
168 PHP_FE(com_print_typeinfo, arginfo_com_print_typeinfo)
169 PHP_FE(com_message_pump, arginfo_com_message_pump)
170 PHP_FE(com_load_typelib, arginfo_com_load_typelib)
171 PHP_FE(com_get_active_object, arginfo_com_get_active_object)
172 PHP_FE_END
173 };
174
175 /* {{{ com_dotnet_module_entry
176 */
177 zend_module_entry com_dotnet_module_entry = {
178 STANDARD_MODULE_HEADER,
179 "com_dotnet",
180 com_dotnet_functions,
181 PHP_MINIT(com_dotnet),
182 PHP_MSHUTDOWN(com_dotnet),
183 PHP_RINIT(com_dotnet),
184 PHP_RSHUTDOWN(com_dotnet),
185 PHP_MINFO(com_dotnet),
186 PHP_COM_DOTNET_VERSION,
187 PHP_MODULE_GLOBALS(com_dotnet),
188 PHP_GINIT(com_dotnet),
189 NULL,
190 NULL,
191 STANDARD_MODULE_PROPERTIES_EX
192 };
193 /* }}} */
194
195 #ifdef COMPILE_DL_COM_DOTNET
196 #ifdef ZTS
197 ZEND_TSRMLS_CACHE_DEFINE()
198 #endif
ZEND_GET_MODULE(com_dotnet)199 ZEND_GET_MODULE(com_dotnet)
200 #endif
201
202 /* {{{ PHP_INI
203 */
204
205 /* com.typelib_file is the path to a file containing a
206 * list of typelibraries to register *persistently*.
207 * lines starting with ; are comments
208 * append #cis to end of typelib name to cause its constants
209 * to be loaded case insensitively */
210 static PHP_INI_MH(OnTypeLibFileUpdate)
211 {
212 FILE *typelib_file;
213 char *typelib_name_buffer;
214 char *strtok_buf = NULL;
215 int cached;
216
217 if (NULL == new_value || !new_value->val[0] || (typelib_file = VCWD_FOPEN(new_value->val, "r"))==NULL) {
218 return FAILURE;
219 }
220
221 typelib_name_buffer = (char *) emalloc(sizeof(char)*1024);
222
223 while (fgets(typelib_name_buffer, 1024, typelib_file)) {
224 ITypeLib *pTL;
225 char *typelib_name;
226 char *modifier, *ptr;
227 int mode = CONST_CS | CONST_PERSISTENT; /* CONST_PERSISTENT is ok here */
228
229 if (typelib_name_buffer[0]==';') {
230 continue;
231 }
232 typelib_name = php_strtok_r(typelib_name_buffer, "\r\n", &strtok_buf); /* get rid of newlines */
233 if (typelib_name == NULL) {
234 continue;
235 }
236 typelib_name = php_strtok_r(typelib_name, "#", &strtok_buf);
237 modifier = php_strtok_r(NULL, "#", &strtok_buf);
238 if (modifier != NULL) {
239 if (!strcmp(modifier, "cis") || !strcmp(modifier, "case_insensitive")) {
240 mode &= ~CONST_CS;
241 }
242 }
243
244 /* Remove leading/training white spaces on search_string */
245 while (isspace(*typelib_name)) {/* Ends on '\0' in worst case */
246 typelib_name ++;
247 }
248 ptr = typelib_name + strlen(typelib_name) - 1;
249 while ((ptr != typelib_name) && isspace(*ptr)) {
250 *ptr = '\0';
251 ptr--;
252 }
253
254 if ((pTL = php_com_load_typelib_via_cache(typelib_name, COMG(code_page), &cached)) != NULL) {
255 php_com_import_typelib(pTL, mode, COMG(code_page));
256 ITypeLib_Release(pTL);
257 }
258 }
259
260 efree(typelib_name_buffer);
261 fclose(typelib_file);
262
263 return SUCCESS;
264 }
265
266 PHP_INI_BEGIN()
267 STD_PHP_INI_ENTRY("com.allow_dcom", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_dcom, zend_com_dotnet_globals, com_dotnet_globals)
268 STD_PHP_INI_ENTRY("com.autoregister_verbose", "0", PHP_INI_ALL, OnUpdateBool, autoreg_verbose, zend_com_dotnet_globals, com_dotnet_globals)
269 STD_PHP_INI_ENTRY("com.autoregister_typelib", "0", PHP_INI_ALL, OnUpdateBool, autoreg_on, zend_com_dotnet_globals, com_dotnet_globals)
270 STD_PHP_INI_ENTRY("com.autoregister_casesensitive", "1", PHP_INI_ALL, OnUpdateBool, autoreg_case_sensitive, zend_com_dotnet_globals, com_dotnet_globals)
271 STD_PHP_INI_ENTRY("com.code_page", "", PHP_INI_ALL, OnUpdateLong, code_page, zend_com_dotnet_globals, com_dotnet_globals)
272 PHP_INI_ENTRY("com.typelib_file", "", PHP_INI_SYSTEM, OnTypeLibFileUpdate)
PHP_INI_END()273 PHP_INI_END()
274 /* }}} */
275
276 /* {{{ PHP_GINIT_FUNCTION
277 */
278 static PHP_GINIT_FUNCTION(com_dotnet)
279 {
280 #if defined(COMPILE_DL_COM_DOTNET) && defined(ZTS)
281 ZEND_TSRMLS_CACHE_UPDATE();
282 #endif
283 memset(com_dotnet_globals, 0, sizeof(*com_dotnet_globals));
284 com_dotnet_globals->code_page = CP_ACP;
285 }
286 /* }}} */
287
288 /* {{{ PHP_MINIT_FUNCTION
289 */
PHP_MINIT_FUNCTION(com_dotnet)290 PHP_MINIT_FUNCTION(com_dotnet)
291 {
292 zend_class_entry ce, *tmp;
293
294 php_com_wrapper_minit(INIT_FUNC_ARGS_PASSTHRU);
295 php_com_persist_minit(INIT_FUNC_ARGS_PASSTHRU);
296
297 INIT_CLASS_ENTRY(ce, "com_exception", NULL);
298 php_com_exception_class_entry = zend_register_internal_class_ex(&ce, zend_ce_exception);
299 php_com_exception_class_entry->ce_flags |= ZEND_ACC_FINAL;
300 /* php_com_exception_class_entry->constructor->common.fn_flags |= ZEND_ACC_PROTECTED; */
301
302 INIT_CLASS_ENTRY(ce, "com_safearray_proxy", NULL);
303 php_com_saproxy_class_entry = zend_register_internal_class(&ce);
304 php_com_saproxy_class_entry->ce_flags |= ZEND_ACC_FINAL;
305 /* php_com_saproxy_class_entry->constructor->common.fn_flags |= ZEND_ACC_PROTECTED; */
306 php_com_saproxy_class_entry->get_iterator = php_com_saproxy_iter_get;
307
308 INIT_CLASS_ENTRY(ce, "variant", NULL);
309 ce.create_object = php_com_object_new;
310 php_com_variant_class_entry = zend_register_internal_class(&ce);
311 php_com_variant_class_entry->get_iterator = php_com_iter_get;
312 php_com_variant_class_entry->serialize = zend_class_serialize_deny;
313 php_com_variant_class_entry->unserialize = zend_class_unserialize_deny;
314
315 INIT_CLASS_ENTRY(ce, "com", NULL);
316 ce.create_object = php_com_object_new;
317 tmp = zend_register_internal_class_ex(&ce, php_com_variant_class_entry);
318 tmp->get_iterator = php_com_iter_get;
319 tmp->serialize = zend_class_serialize_deny;
320 tmp->unserialize = zend_class_unserialize_deny;
321
322 zend_ts_hash_init(&php_com_typelibraries, 0, NULL, php_com_typelibrary_dtor, 1);
323
324 #if HAVE_MSCOREE_H
325 INIT_CLASS_ENTRY(ce, "dotnet", NULL);
326 ce.create_object = php_com_object_new;
327 tmp = zend_register_internal_class_ex(&ce, php_com_variant_class_entry);
328 tmp->get_iterator = php_com_iter_get;
329 tmp->serialize = zend_class_serialize_deny;
330 tmp->unserialize = zend_class_unserialize_deny;
331 #endif
332
333 REGISTER_INI_ENTRIES();
334
335 #define COM_CONST(x) REGISTER_LONG_CONSTANT(#x, x, CONST_CS|CONST_PERSISTENT)
336
337 #if SIZEOF_ZEND_LONG == 8
338 # define COM_ERR_CONST(x) { \
339 zend_long __tmp; \
340 ULongToIntPtr(x, &__tmp); \
341 REGISTER_LONG_CONSTANT(#x, __tmp, CONST_CS|CONST_PERSISTENT); \
342 }
343 #else
344 # define COM_ERR_CONST COM_CONST
345 #endif
346
347 COM_CONST(CLSCTX_INPROC_SERVER);
348 COM_CONST(CLSCTX_INPROC_HANDLER);
349 COM_CONST(CLSCTX_LOCAL_SERVER);
350 COM_CONST(CLSCTX_REMOTE_SERVER);
351 COM_CONST(CLSCTX_SERVER);
352 COM_CONST(CLSCTX_ALL);
353
354 #if 0
355 COM_CONST(DISPATCH_METHOD);
356 COM_CONST(DISPATCH_PROPERTYGET);
357 COM_CONST(DISPATCH_PROPERTYPUT);
358 #endif
359
360 COM_CONST(VT_NULL);
361 COM_CONST(VT_EMPTY);
362 COM_CONST(VT_UI1);
363 COM_CONST(VT_I1);
364 COM_CONST(VT_UI2);
365 COM_CONST(VT_I2);
366 COM_CONST(VT_UI4);
367 COM_CONST(VT_I4);
368 COM_CONST(VT_R4);
369 COM_CONST(VT_R8);
370 COM_CONST(VT_BOOL);
371 COM_CONST(VT_ERROR);
372 COM_CONST(VT_CY);
373 COM_CONST(VT_DATE);
374 COM_CONST(VT_BSTR);
375 COM_CONST(VT_DECIMAL);
376 COM_CONST(VT_UNKNOWN);
377 COM_CONST(VT_DISPATCH);
378 COM_CONST(VT_VARIANT);
379 COM_CONST(VT_INT);
380 COM_CONST(VT_UINT);
381 COM_CONST(VT_ARRAY);
382 COM_CONST(VT_BYREF);
383
384 COM_CONST(CP_ACP);
385 COM_CONST(CP_MACCP);
386 COM_CONST(CP_OEMCP);
387 COM_CONST(CP_UTF7);
388 COM_CONST(CP_UTF8);
389 COM_CONST(CP_SYMBOL);
390 COM_CONST(CP_THREAD_ACP);
391
392 COM_CONST(VARCMP_LT);
393 COM_CONST(VARCMP_EQ);
394 COM_CONST(VARCMP_GT);
395 COM_CONST(VARCMP_NULL);
396
397 COM_CONST(NORM_IGNORECASE);
398 COM_CONST(NORM_IGNORENONSPACE);
399 COM_CONST(NORM_IGNORESYMBOLS);
400 COM_CONST(NORM_IGNOREWIDTH);
401 COM_CONST(NORM_IGNOREKANATYPE);
402 #ifdef NORM_IGNOREKASHIDA
403 COM_CONST(NORM_IGNOREKASHIDA);
404 #endif
405 COM_ERR_CONST(DISP_E_DIVBYZERO);
406 COM_ERR_CONST(DISP_E_OVERFLOW);
407 COM_ERR_CONST(DISP_E_BADINDEX);
408 COM_ERR_CONST(MK_E_UNAVAILABLE);
409
410 #if SIZEOF_ZEND_LONG == 8
411 COM_CONST(VT_UI8);
412 COM_CONST(VT_I8);
413 #endif
414 return SUCCESS;
415 }
416 /* }}} */
417
418 /* {{{ PHP_MSHUTDOWN_FUNCTION
419 */
PHP_MSHUTDOWN_FUNCTION(com_dotnet)420 PHP_MSHUTDOWN_FUNCTION(com_dotnet)
421 {
422 UNREGISTER_INI_ENTRIES();
423 #if HAVE_MSCOREE_H
424 if (COMG(dotnet_runtime_stuff)) {
425 php_com_dotnet_mshutdown();
426 }
427 #endif
428
429 zend_ts_hash_destroy(&php_com_typelibraries);
430 return SUCCESS;
431 }
432 /* }}} */
433
434 /* {{{ PHP_RINIT_FUNCTION
435 */
PHP_RINIT_FUNCTION(com_dotnet)436 PHP_RINIT_FUNCTION(com_dotnet)
437 {
438 COMG(rshutdown_started) = 0;
439 return SUCCESS;
440 }
441 /* }}} */
442
443 /* {{{ PHP_RSHUTDOWN_FUNCTION
444 */
PHP_RSHUTDOWN_FUNCTION(com_dotnet)445 PHP_RSHUTDOWN_FUNCTION(com_dotnet)
446 {
447 #if HAVE_MSCOREE_H
448 if (COMG(dotnet_runtime_stuff)) {
449 php_com_dotnet_rshutdown();
450 }
451 #endif
452 COMG(rshutdown_started) = 1;
453 return SUCCESS;
454 }
455 /* }}} */
456
457 /* {{{ PHP_MINFO_FUNCTION
458 */
PHP_MINFO_FUNCTION(com_dotnet)459 PHP_MINFO_FUNCTION(com_dotnet)
460 {
461 php_info_print_table_start();
462
463 php_info_print_table_header(2, "COM support", "enabled");
464 php_info_print_table_header(2, "DCOM support", COMG(allow_dcom) ? "enabled" : "disabled");
465
466 #if HAVE_MSCOREE_H
467 php_info_print_table_header(2, ".Net support", "enabled");
468 #else
469 php_info_print_table_header(2, ".Net support", "not present in this build");
470 #endif
471
472 php_info_print_table_end();
473
474 DISPLAY_INI_ENTRIES();
475 }
476 /* }}} */
477
478 /*
479 * Local variables:
480 * tab-width: 4
481 * c-basic-offset: 4
482 * End:
483 * vim600: noet sw=4 ts=4 fdm=marker
484 * vim<600: noet sw=4 ts=4
485 */
486