com_extension.c 14 KB

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