xref: /PHP-8.2/ext/com_dotnet/com_extension.c (revision a01dd9fe)
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 <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 
31 #if SIZEOF_ZEND_LONG == 8
32 #define PHP_DISP_E_DIVBYZERO ((zend_long) (ULONG) DISP_E_DIVBYZERO)
33 #define PHP_DISP_E_OVERFLOW ((zend_long) (ULONG) DISP_E_OVERFLOW)
34 #define PHP_DISP_E_BADINDEX ((zend_long) (ULONG) DISP_E_BADINDEX)
35 #define PHP_DISP_E_PARAMNOTFOUND ((zend_long) (ULONG) DISP_E_PARAMNOTFOUND)
36 #define PHP_MK_E_UNAVAILABLE ((zend_long) (ULONG) MK_E_UNAVAILABLE)
37 #else
38 #define PHP_DISP_E_DIVBYZERO DISP_E_DIVBYZERO
39 #define PHP_DISP_E_OVERFLOW DISP_E_OVERFLOW
40 #define PHP_DISP_E_BADINDEX DISP_E_BADINDEX
41 #define PHP_DISP_E_PARAMNOTFOUND DISP_E_PARAMNOTFOUND
42 #define PHP_MK_E_UNAVAILABLE MK_E_UNAVAILABLE
43 #endif
44 
45 #include "com_extension_arginfo.h"
46 
47 ZEND_DECLARE_MODULE_GLOBALS(com_dotnet)
48 static PHP_GINIT_FUNCTION(com_dotnet);
49 
50 zend_class_entry
51 	*php_com_variant_class_entry,
52    	*php_com_exception_class_entry,
53 	*php_com_saproxy_class_entry;
54 
55 /* {{{ com_dotnet_module_entry */
56 zend_module_entry com_dotnet_module_entry = {
57 	STANDARD_MODULE_HEADER,
58 	"com_dotnet",
59 	ext_functions,
60 	PHP_MINIT(com_dotnet),
61 	PHP_MSHUTDOWN(com_dotnet),
62 	PHP_RINIT(com_dotnet),
63 	PHP_RSHUTDOWN(com_dotnet),
64 	PHP_MINFO(com_dotnet),
65 	PHP_COM_DOTNET_VERSION,
66 	PHP_MODULE_GLOBALS(com_dotnet),
67 	PHP_GINIT(com_dotnet),
68 	NULL,
69 	NULL,
70 	STANDARD_MODULE_PROPERTIES_EX
71 };
72 /* }}} */
73 
74 #ifdef COMPILE_DL_COM_DOTNET
75 #ifdef ZTS
76 ZEND_TSRMLS_CACHE_DEFINE()
77 #endif
ZEND_GET_MODULE(com_dotnet)78 ZEND_GET_MODULE(com_dotnet)
79 #endif
80 
81 /* {{{ PHP_INI */
82 
83 /* com.typelib_file is the path to a file containing a
84  * list of typelibraries to register *persistently*.
85  * lines starting with ; are comments
86  * append #cis to end of typelib name to cause its constants
87  * to be loaded case insensitively */
88 static PHP_INI_MH(OnTypeLibFileUpdate)
89 {
90 	FILE *typelib_file;
91 	char *typelib_name_buffer;
92 	char *strtok_buf = NULL;
93 
94 	if (NULL == new_value || !new_value->val[0] || (typelib_file = VCWD_FOPEN(new_value->val, "r"))==NULL) {
95 		return FAILURE;
96 	}
97 
98 	typelib_name_buffer = (char *) emalloc(sizeof(char)*1024);
99 
100 	while (fgets(typelib_name_buffer, 1024, typelib_file)) {
101 		ITypeLib *pTL;
102 		char *typelib_name;
103 		char *modifier, *ptr;
104 		int mode = CONST_CS | CONST_PERSISTENT;	/* CONST_PERSISTENT is ok here */
105 
106 		if (typelib_name_buffer[0]==';') {
107 			continue;
108 		}
109 		typelib_name = php_strtok_r(typelib_name_buffer, "\r\n", &strtok_buf); /* get rid of newlines */
110 		if (typelib_name == NULL) {
111 			continue;
112 		}
113 		typelib_name = php_strtok_r(typelib_name, "#", &strtok_buf);
114 		modifier = php_strtok_r(NULL, "#", &strtok_buf);
115 		if (modifier != NULL) {
116 			if (!strcmp(modifier, "cis") || !strcmp(modifier, "case_insensitive")) {
117 				php_error_docref("com.configuration", E_WARNING, "Declaration of case-insensitive constants is no longer supported; #cis modifier ignored");
118 			}
119 		}
120 
121 		/* Remove leading/training white spaces on search_string */
122 		while (isspace(*typelib_name)) {/* Ends on '\0' in worst case */
123 			typelib_name ++;
124 		}
125 		ptr = typelib_name + strlen(typelib_name) - 1;
126 		while ((ptr != typelib_name) && isspace(*ptr)) {
127 			*ptr = '\0';
128 			ptr--;
129 		}
130 
131 		if ((pTL = php_com_load_typelib_via_cache(typelib_name, COMG(code_page))) != NULL) {
132 			php_com_import_typelib(pTL, mode, COMG(code_page));
133 			ITypeLib_Release(pTL);
134 		}
135 	}
136 
137 	efree(typelib_name_buffer);
138 	fclose(typelib_file);
139 
140 	return SUCCESS;
141 }
142 
ZEND_INI_MH(OnAutoregisterCasesensitive)143 static ZEND_INI_MH(OnAutoregisterCasesensitive)
144 {
145 	if (!zend_ini_parse_bool(new_value)) {
146 		php_error_docref("com.configuration", E_WARNING, "Declaration of case-insensitive constants is no longer supported");
147 		return FAILURE;
148 	}
149 	return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
150 }
151 
152 PHP_INI_BEGIN()
153 	STD_PHP_INI_BOOLEAN("com.allow_dcom",				"0", PHP_INI_SYSTEM, OnUpdateBool, allow_dcom, zend_com_dotnet_globals, com_dotnet_globals)
154 	STD_PHP_INI_BOOLEAN("com.autoregister_verbose",	"0", PHP_INI_ALL, OnUpdateBool, autoreg_verbose, zend_com_dotnet_globals, com_dotnet_globals)
155 	STD_PHP_INI_BOOLEAN("com.autoregister_typelib",	"0", PHP_INI_ALL, OnUpdateBool, autoreg_on, zend_com_dotnet_globals, com_dotnet_globals)
156 	STD_PHP_INI_ENTRY("com.autoregister_casesensitive",	"1", PHP_INI_ALL, OnAutoregisterCasesensitive, autoreg_case_sensitive, zend_com_dotnet_globals, com_dotnet_globals)
157 	STD_PHP_INI_ENTRY("com.code_page", "", PHP_INI_ALL, OnUpdateLong, code_page, zend_com_dotnet_globals, com_dotnet_globals)
158 	PHP_INI_ENTRY("com.typelib_file", "", PHP_INI_SYSTEM, OnTypeLibFileUpdate)
159 	PHP_INI_ENTRY("com.dotnet_version", NULL, PHP_INI_SYSTEM, NULL)
PHP_INI_END()160 PHP_INI_END()
161 /* }}} */
162 
163 /* {{{ PHP_GINIT_FUNCTION */
164 static PHP_GINIT_FUNCTION(com_dotnet)
165 {
166 #if defined(COMPILE_DL_COM_DOTNET) && defined(ZTS)
167 	ZEND_TSRMLS_CACHE_UPDATE();
168 #endif
169 	memset(com_dotnet_globals, 0, sizeof(*com_dotnet_globals));
170 	com_dotnet_globals->code_page = CP_ACP;
171 }
172 /* }}} */
173 
174 /* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(com_dotnet)175 PHP_MINIT_FUNCTION(com_dotnet)
176 {
177 	zend_class_entry *tmp;
178 
179 	php_com_wrapper_minit(INIT_FUNC_ARGS_PASSTHRU);
180 	php_com_persist_minit(INIT_FUNC_ARGS_PASSTHRU);
181 
182 	php_com_exception_class_entry = register_class_com_exception(zend_ce_exception);
183 /*	php_com_exception_class_entry->constructor->common.fn_flags |= ZEND_ACC_PROTECTED; */
184 
185 	php_com_saproxy_class_entry = register_class_com_safearray_proxy();
186 /*	php_com_saproxy_class_entry->constructor->common.fn_flags |= ZEND_ACC_PROTECTED; */
187 	php_com_saproxy_class_entry->get_iterator = php_com_saproxy_iter_get;
188 
189 	php_com_variant_class_entry = register_class_variant();
190 	php_com_variant_class_entry->create_object = php_com_object_new;
191 	php_com_variant_class_entry->get_iterator = php_com_iter_get;
192 
193 	tmp = register_class_com(php_com_variant_class_entry);
194 	tmp->create_object = php_com_object_new;
195 	tmp->get_iterator = php_com_iter_get;
196 
197 #if HAVE_MSCOREE_H
198 	tmp = register_class_dotnet(php_com_variant_class_entry);
199 	tmp->create_object = php_com_object_new;
200 	tmp->get_iterator = php_com_iter_get;
201 #endif
202 
203 	REGISTER_INI_ENTRIES();
204 
205 	register_com_extension_symbols(module_number);
206 
207 	PHP_MINIT(com_typeinfo)(INIT_FUNC_ARGS_PASSTHRU);
208 
209 	return SUCCESS;
210 }
211 /* }}} */
212 
213 /* {{{ PHP_MSHUTDOWN_FUNCTION */
PHP_MSHUTDOWN_FUNCTION(com_dotnet)214 PHP_MSHUTDOWN_FUNCTION(com_dotnet)
215 {
216 	UNREGISTER_INI_ENTRIES();
217 #if HAVE_MSCOREE_H
218 	if (COMG(dotnet_runtime_stuff)) {
219 		php_com_dotnet_mshutdown();
220 	}
221 #endif
222 
223 	PHP_MSHUTDOWN(com_typeinfo)(INIT_FUNC_ARGS_PASSTHRU);
224 
225 	return SUCCESS;
226 }
227 /* }}} */
228 
229 /* {{{ PHP_RINIT_FUNCTION */
PHP_RINIT_FUNCTION(com_dotnet)230 PHP_RINIT_FUNCTION(com_dotnet)
231 {
232 	COMG(rshutdown_started) = 0;
233 	return SUCCESS;
234 }
235 /* }}} */
236 
237 /* {{{ PHP_RSHUTDOWN_FUNCTION */
PHP_RSHUTDOWN_FUNCTION(com_dotnet)238 PHP_RSHUTDOWN_FUNCTION(com_dotnet)
239 {
240 #if HAVE_MSCOREE_H
241 	if (COMG(dotnet_runtime_stuff)) {
242 		php_com_dotnet_rshutdown();
243 	}
244 #endif
245 	COMG(rshutdown_started) = 1;
246 	return SUCCESS;
247 }
248 /* }}} */
249 
250 /* {{{ PHP_MINFO_FUNCTION */
PHP_MINFO_FUNCTION(com_dotnet)251 PHP_MINFO_FUNCTION(com_dotnet)
252 {
253 	php_info_print_table_start();
254 
255 	php_info_print_table_header(2, "COM support", "enabled");
256 	php_info_print_table_header(2, "DCOM support", COMG(allow_dcom) ? "enabled" : "disabled");
257 
258 #if HAVE_MSCOREE_H
259 	php_info_print_table_header(2, ".Net support", "enabled");
260 #else
261 	php_info_print_table_header(2, ".Net support", "not present in this build");
262 #endif
263 
264 	php_info_print_table_end();
265 
266 	DISPLAY_INI_ENTRIES();
267 }
268 /* }}} */
269