xref: /PHP-8.0/ext/com_dotnet/com_extension.c (revision e6044d44)
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    | http://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 <intsafe.h>
22 
23 #include "php.h"
24 #include "php_ini.h"
25 #include "ext/standard/info.h"
26 #include "php_com_dotnet.h"
27 #include "php_com_dotnet_internal.h"
28 #include "Zend/zend_exceptions.h"
29 #include "Zend/zend_interfaces.h"
30 #include "com_extension_arginfo.h"
31 
32 ZEND_DECLARE_MODULE_GLOBALS(com_dotnet)
33 static PHP_GINIT_FUNCTION(com_dotnet);
34 
35 zend_class_entry
36 	*php_com_variant_class_entry,
37    	*php_com_exception_class_entry,
38 	*php_com_saproxy_class_entry;
39 
40 /* {{{ com_dotnet_module_entry */
41 zend_module_entry com_dotnet_module_entry = {
42 	STANDARD_MODULE_HEADER,
43 	"com_dotnet",
44 	ext_functions,
45 	PHP_MINIT(com_dotnet),
46 	PHP_MSHUTDOWN(com_dotnet),
47 	PHP_RINIT(com_dotnet),
48 	PHP_RSHUTDOWN(com_dotnet),
49 	PHP_MINFO(com_dotnet),
50 	PHP_COM_DOTNET_VERSION,
51 	PHP_MODULE_GLOBALS(com_dotnet),
52 	PHP_GINIT(com_dotnet),
53 	NULL,
54 	NULL,
55 	STANDARD_MODULE_PROPERTIES_EX
56 };
57 /* }}} */
58 
59 #ifdef COMPILE_DL_COM_DOTNET
60 #ifdef ZTS
61 ZEND_TSRMLS_CACHE_DEFINE()
62 #endif
ZEND_GET_MODULE(com_dotnet)63 ZEND_GET_MODULE(com_dotnet)
64 #endif
65 
66 /* {{{ PHP_INI */
67 
68 /* com.typelib_file is the path to a file containing a
69  * list of typelibraries to register *persistently*.
70  * lines starting with ; are comments
71  * append #cis to end of typelib name to cause its constants
72  * to be loaded case insensitively */
73 static PHP_INI_MH(OnTypeLibFileUpdate)
74 {
75 	FILE *typelib_file;
76 	char *typelib_name_buffer;
77 	char *strtok_buf = NULL;
78 
79 	if (NULL == new_value || !new_value->val[0] || (typelib_file = VCWD_FOPEN(new_value->val, "r"))==NULL) {
80 		return FAILURE;
81 	}
82 
83 	typelib_name_buffer = (char *) emalloc(sizeof(char)*1024);
84 
85 	while (fgets(typelib_name_buffer, 1024, typelib_file)) {
86 		ITypeLib *pTL;
87 		char *typelib_name;
88 		char *modifier, *ptr;
89 		int mode = CONST_CS | CONST_PERSISTENT;	/* CONST_PERSISTENT is ok here */
90 
91 		if (typelib_name_buffer[0]==';') {
92 			continue;
93 		}
94 		typelib_name = php_strtok_r(typelib_name_buffer, "\r\n", &strtok_buf); /* get rid of newlines */
95 		if (typelib_name == NULL) {
96 			continue;
97 		}
98 		typelib_name = php_strtok_r(typelib_name, "#", &strtok_buf);
99 		modifier = php_strtok_r(NULL, "#", &strtok_buf);
100 		if (modifier != NULL) {
101 			if (!strcmp(modifier, "cis") || !strcmp(modifier, "case_insensitive")) {
102 				php_error_docref("com.configuration", E_WARNING, "Declaration of case-insensitive constants is no longer supported; #cis modifier ignored");
103 			}
104 		}
105 
106 		/* Remove leading/training white spaces on search_string */
107 		while (isspace(*typelib_name)) {/* Ends on '\0' in worst case */
108 			typelib_name ++;
109 		}
110 		ptr = typelib_name + strlen(typelib_name) - 1;
111 		while ((ptr != typelib_name) && isspace(*ptr)) {
112 			*ptr = '\0';
113 			ptr--;
114 		}
115 
116 		if ((pTL = php_com_load_typelib_via_cache(typelib_name, COMG(code_page))) != NULL) {
117 			php_com_import_typelib(pTL, mode, COMG(code_page));
118 			ITypeLib_Release(pTL);
119 		}
120 	}
121 
122 	efree(typelib_name_buffer);
123 	fclose(typelib_file);
124 
125 	return SUCCESS;
126 }
127 
ZEND_INI_MH(OnAutoregisterCasesensitive)128 static ZEND_INI_MH(OnAutoregisterCasesensitive)
129 {
130 	if (!zend_ini_parse_bool(new_value)) {
131 		php_error_docref("com.configuration", E_WARNING, "Declaration of case-insensitive constants is no longer supported");
132 		return FAILURE;
133 	}
134 	return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
135 }
136 
137 PHP_INI_BEGIN()
138     STD_PHP_INI_BOOLEAN("com.allow_dcom",				"0", PHP_INI_SYSTEM, OnUpdateBool, allow_dcom, zend_com_dotnet_globals, com_dotnet_globals)
139     STD_PHP_INI_BOOLEAN("com.autoregister_verbose",	"0", PHP_INI_ALL, OnUpdateBool, autoreg_verbose, zend_com_dotnet_globals, com_dotnet_globals)
140     STD_PHP_INI_BOOLEAN("com.autoregister_typelib",	"0", PHP_INI_ALL, OnUpdateBool, autoreg_on, zend_com_dotnet_globals, com_dotnet_globals)
141     STD_PHP_INI_ENTRY("com.autoregister_casesensitive",	"1", PHP_INI_ALL, OnAutoregisterCasesensitive, autoreg_case_sensitive, zend_com_dotnet_globals, com_dotnet_globals)
142 	STD_PHP_INI_ENTRY("com.code_page", "", PHP_INI_ALL, OnUpdateLong, code_page, zend_com_dotnet_globals, com_dotnet_globals)
143 	PHP_INI_ENTRY("com.typelib_file", "", PHP_INI_SYSTEM, OnTypeLibFileUpdate)
144 	PHP_INI_ENTRY("com.dotnet_version", NULL, PHP_INI_SYSTEM, NULL)
PHP_INI_END()145 PHP_INI_END()
146 /* }}} */
147 
148 /* {{{ PHP_GINIT_FUNCTION */
149 static PHP_GINIT_FUNCTION(com_dotnet)
150 {
151 #if defined(COMPILE_DL_COM_DOTNET) && defined(ZTS)
152 	ZEND_TSRMLS_CACHE_UPDATE();
153 #endif
154 	memset(com_dotnet_globals, 0, sizeof(*com_dotnet_globals));
155 	com_dotnet_globals->code_page = CP_ACP;
156 }
157 /* }}} */
158 
159 /* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(com_dotnet)160 PHP_MINIT_FUNCTION(com_dotnet)
161 {
162 	zend_class_entry ce, *tmp;
163 
164 	php_com_wrapper_minit(INIT_FUNC_ARGS_PASSTHRU);
165 	php_com_persist_minit(INIT_FUNC_ARGS_PASSTHRU);
166 
167 	INIT_CLASS_ENTRY(ce, "com_exception", NULL);
168 	php_com_exception_class_entry = zend_register_internal_class_ex(&ce, zend_ce_exception);
169 	php_com_exception_class_entry->ce_flags |= ZEND_ACC_FINAL;
170 /*	php_com_exception_class_entry->constructor->common.fn_flags |= ZEND_ACC_PROTECTED; */
171 
172 	INIT_CLASS_ENTRY(ce, "com_safearray_proxy", NULL);
173 	php_com_saproxy_class_entry = zend_register_internal_class(&ce);
174 	php_com_saproxy_class_entry->ce_flags |= ZEND_ACC_FINAL;
175 /*	php_com_saproxy_class_entry->constructor->common.fn_flags |= ZEND_ACC_PROTECTED; */
176 	php_com_saproxy_class_entry->get_iterator = php_com_saproxy_iter_get;
177 
178 	INIT_CLASS_ENTRY(ce, "variant", class_variant_methods);
179 	ce.create_object = php_com_object_new;
180 	php_com_variant_class_entry = zend_register_internal_class(&ce);
181 	php_com_variant_class_entry->get_iterator = php_com_iter_get;
182 	php_com_variant_class_entry->serialize = zend_class_serialize_deny;
183 	php_com_variant_class_entry->unserialize = zend_class_unserialize_deny;
184 
185 	INIT_CLASS_ENTRY(ce, "com", class_com_methods);
186 	ce.create_object = php_com_object_new;
187 	tmp = zend_register_internal_class_ex(&ce, php_com_variant_class_entry);
188 	tmp->get_iterator = php_com_iter_get;
189 	tmp->serialize = zend_class_serialize_deny;
190 	tmp->unserialize = zend_class_unserialize_deny;
191 
192 #if HAVE_MSCOREE_H
193 	INIT_CLASS_ENTRY(ce, "dotnet", class_dotnet_methods);
194 	ce.create_object = php_com_object_new;
195 	tmp = zend_register_internal_class_ex(&ce, php_com_variant_class_entry);
196 	tmp->get_iterator = php_com_iter_get;
197 	tmp->serialize = zend_class_serialize_deny;
198 	tmp->unserialize = zend_class_unserialize_deny;
199 #endif
200 
201 	REGISTER_INI_ENTRIES();
202 
203 #define COM_CONST(x) REGISTER_LONG_CONSTANT(#x, x, CONST_CS|CONST_PERSISTENT)
204 
205 #if SIZEOF_ZEND_LONG == 8
206 # define COM_ERR_CONST(x) REGISTER_LONG_CONSTANT(#x, (zend_long) (ULONG) (x), CONST_CS|CONST_PERSISTENT)
207 #else
208 # define COM_ERR_CONST COM_CONST
209 #endif
210 
211 	COM_CONST(CLSCTX_INPROC_SERVER);
212 	COM_CONST(CLSCTX_INPROC_HANDLER);
213 	COM_CONST(CLSCTX_LOCAL_SERVER);
214 	COM_CONST(CLSCTX_REMOTE_SERVER);
215 	COM_CONST(CLSCTX_SERVER);
216 	COM_CONST(CLSCTX_ALL);
217 
218 #if 0
219 	COM_CONST(DISPATCH_METHOD);
220 	COM_CONST(DISPATCH_PROPERTYGET);
221 	COM_CONST(DISPATCH_PROPERTYPUT);
222 #endif
223 
224 	COM_CONST(VT_NULL);
225 	COM_CONST(VT_EMPTY);
226 	COM_CONST(VT_UI1);
227 	COM_CONST(VT_I1);
228 	COM_CONST(VT_UI2);
229 	COM_CONST(VT_I2);
230 	COM_CONST(VT_UI4);
231 	COM_CONST(VT_I4);
232 	COM_CONST(VT_R4);
233 	COM_CONST(VT_R8);
234 	COM_CONST(VT_BOOL);
235 	COM_CONST(VT_ERROR);
236 	COM_CONST(VT_CY);
237 	COM_CONST(VT_DATE);
238 	COM_CONST(VT_BSTR);
239 	COM_CONST(VT_DECIMAL);
240 	COM_CONST(VT_UNKNOWN);
241 	COM_CONST(VT_DISPATCH);
242 	COM_CONST(VT_VARIANT);
243 	COM_CONST(VT_INT);
244 	COM_CONST(VT_UINT);
245 	COM_CONST(VT_ARRAY);
246 	COM_CONST(VT_BYREF);
247 
248 	COM_CONST(CP_ACP);
249 	COM_CONST(CP_MACCP);
250 	COM_CONST(CP_OEMCP);
251 	COM_CONST(CP_UTF7);
252 	COM_CONST(CP_UTF8);
253 	COM_CONST(CP_SYMBOL);
254 	COM_CONST(CP_THREAD_ACP);
255 
256 	COM_CONST(VARCMP_LT);
257 	COM_CONST(VARCMP_EQ);
258 	COM_CONST(VARCMP_GT);
259 	COM_CONST(VARCMP_NULL);
260 	COM_CONST(LOCALE_SYSTEM_DEFAULT);
261 
262 	COM_CONST(NORM_IGNORECASE);
263 	COM_CONST(NORM_IGNORENONSPACE);
264 	COM_CONST(NORM_IGNORESYMBOLS);
265 	COM_CONST(NORM_IGNOREWIDTH);
266 	COM_CONST(NORM_IGNOREKANATYPE);
267 #ifdef NORM_IGNOREKASHIDA
268 	COM_CONST(NORM_IGNOREKASHIDA);
269 #endif
270 	COM_ERR_CONST(DISP_E_DIVBYZERO);
271 	COM_ERR_CONST(DISP_E_OVERFLOW);
272 	COM_ERR_CONST(DISP_E_BADINDEX);
273 	COM_ERR_CONST(MK_E_UNAVAILABLE);
274 
275 #if SIZEOF_ZEND_LONG == 8
276 	COM_CONST(VT_UI8);
277 	COM_CONST(VT_I8);
278 #endif
279 
280 	PHP_MINIT(com_typeinfo)(INIT_FUNC_ARGS_PASSTHRU);
281 
282 	return SUCCESS;
283 }
284 /* }}} */
285 
286 /* {{{ PHP_MSHUTDOWN_FUNCTION */
PHP_MSHUTDOWN_FUNCTION(com_dotnet)287 PHP_MSHUTDOWN_FUNCTION(com_dotnet)
288 {
289 	UNREGISTER_INI_ENTRIES();
290 #if HAVE_MSCOREE_H
291 	if (COMG(dotnet_runtime_stuff)) {
292 		php_com_dotnet_mshutdown();
293 	}
294 #endif
295 
296 	PHP_MSHUTDOWN(com_typeinfo)(INIT_FUNC_ARGS_PASSTHRU);
297 
298 	return SUCCESS;
299 }
300 /* }}} */
301 
302 /* {{{ PHP_RINIT_FUNCTION */
PHP_RINIT_FUNCTION(com_dotnet)303 PHP_RINIT_FUNCTION(com_dotnet)
304 {
305 	COMG(rshutdown_started) = 0;
306 	return SUCCESS;
307 }
308 /* }}} */
309 
310 /* {{{ PHP_RSHUTDOWN_FUNCTION */
PHP_RSHUTDOWN_FUNCTION(com_dotnet)311 PHP_RSHUTDOWN_FUNCTION(com_dotnet)
312 {
313 #if HAVE_MSCOREE_H
314 	if (COMG(dotnet_runtime_stuff)) {
315 		php_com_dotnet_rshutdown();
316 	}
317 #endif
318 	COMG(rshutdown_started) = 1;
319 	return SUCCESS;
320 }
321 /* }}} */
322 
323 /* {{{ PHP_MINFO_FUNCTION */
PHP_MINFO_FUNCTION(com_dotnet)324 PHP_MINFO_FUNCTION(com_dotnet)
325 {
326 	php_info_print_table_start();
327 
328 	php_info_print_table_header(2, "COM support", "enabled");
329 	php_info_print_table_header(2, "DCOM support", COMG(allow_dcom) ? "enabled" : "disabled");
330 
331 #if HAVE_MSCOREE_H
332 	php_info_print_table_header(2, ".Net support", "enabled");
333 #else
334 	php_info_print_table_header(2, ".Net support", "not present in this build");
335 #endif
336 
337 	php_info_print_table_end();
338 
339 	DISPLAY_INI_ENTRIES();
340 }
341 /* }}} */
342