xref: /php-src/ext/com_dotnet/com_extension.c (revision 77ee92a5)
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 
105 		if (typelib_name_buffer[0]==';') {
106 			continue;
107 		}
108 		typelib_name = php_strtok_r(typelib_name_buffer, "\r\n", &strtok_buf); /* get rid of newlines */
109 		if (typelib_name == NULL) {
110 			continue;
111 		}
112 		typelib_name = php_strtok_r(typelib_name, "#", &strtok_buf);
113 		modifier = php_strtok_r(NULL, "#", &strtok_buf);
114 		if (modifier != NULL) {
115 			if (!strcmp(modifier, "cis") || !strcmp(modifier, "case_insensitive")) {
116 				php_error_docref("com.configuration", E_WARNING, "Declaration of case-insensitive constants is no longer supported; #cis modifier ignored");
117 			}
118 		}
119 
120 		/* Remove leading/training white spaces on search_string */
121 		while (isspace(*typelib_name)) {/* Ends on '\0' in worst case */
122 			typelib_name ++;
123 		}
124 		ptr = typelib_name + strlen(typelib_name) - 1;
125 		while ((ptr != typelib_name) && isspace(*ptr)) {
126 			*ptr = '\0';
127 			ptr--;
128 		}
129 
130 		if ((pTL = php_com_load_typelib_via_cache(typelib_name, COMG(code_page))) != NULL) {
131 			php_com_import_typelib(pTL, CONST_PERSISTENT, COMG(code_page));
132 			ITypeLib_Release(pTL);
133 		}
134 	}
135 
136 	efree(typelib_name_buffer);
137 	fclose(typelib_file);
138 
139 	return SUCCESS;
140 }
141 
ZEND_INI_MH(OnAutoregisterCasesensitive)142 static ZEND_INI_MH(OnAutoregisterCasesensitive)
143 {
144 	if (!zend_ini_parse_bool(new_value)) {
145 		php_error_docref("com.configuration", E_WARNING, "Declaration of case-insensitive constants is no longer supported");
146 		return FAILURE;
147 	}
148 	return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
149 }
150 
151 PHP_INI_BEGIN()
152 	STD_PHP_INI_BOOLEAN("com.allow_dcom",				"0", PHP_INI_SYSTEM, OnUpdateBool, allow_dcom, zend_com_dotnet_globals, com_dotnet_globals)
153 	STD_PHP_INI_BOOLEAN("com.autoregister_verbose",	"0", PHP_INI_ALL, OnUpdateBool, autoreg_verbose, zend_com_dotnet_globals, com_dotnet_globals)
154 	STD_PHP_INI_BOOLEAN("com.autoregister_typelib",	"0", PHP_INI_ALL, OnUpdateBool, autoreg_on, zend_com_dotnet_globals, com_dotnet_globals)
155 	STD_PHP_INI_ENTRY("com.autoregister_casesensitive",	"1", PHP_INI_ALL, OnAutoregisterCasesensitive, autoreg_case_sensitive, zend_com_dotnet_globals, com_dotnet_globals)
156 	STD_PHP_INI_ENTRY("com.code_page", "", PHP_INI_ALL, OnUpdateLong, code_page, zend_com_dotnet_globals, com_dotnet_globals)
157 	PHP_INI_ENTRY("com.typelib_file", "", PHP_INI_SYSTEM, OnTypeLibFileUpdate)
158 	PHP_INI_ENTRY("com.dotnet_version", NULL, PHP_INI_SYSTEM, NULL)
PHP_INI_END()159 PHP_INI_END()
160 /* }}} */
161 
162 /* {{{ PHP_GINIT_FUNCTION */
163 static PHP_GINIT_FUNCTION(com_dotnet)
164 {
165 #if defined(COMPILE_DL_COM_DOTNET) && defined(ZTS)
166 	ZEND_TSRMLS_CACHE_UPDATE();
167 #endif
168 	memset(com_dotnet_globals, 0, sizeof(*com_dotnet_globals));
169 	com_dotnet_globals->code_page = CP_ACP;
170 }
171 /* }}} */
172 
173 /* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(com_dotnet)174 PHP_MINIT_FUNCTION(com_dotnet)
175 {
176 	zend_class_entry *tmp;
177 
178 	php_com_wrapper_minit(INIT_FUNC_ARGS_PASSTHRU);
179 	php_com_persist_minit(INIT_FUNC_ARGS_PASSTHRU);
180 
181 	php_com_exception_class_entry = register_class_com_exception(zend_ce_exception);
182 /*	php_com_exception_class_entry->constructor->common.fn_flags |= ZEND_ACC_PROTECTED; */
183 
184 	php_com_saproxy_class_entry = register_class_com_safearray_proxy();
185 /*	php_com_saproxy_class_entry->constructor->common.fn_flags |= ZEND_ACC_PROTECTED; */
186 	php_com_saproxy_class_entry->default_object_handlers = &php_com_saproxy_handlers;
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->default_object_handlers = &php_com_object_handlers;
191 	php_com_variant_class_entry->create_object = php_com_object_new;
192 	php_com_variant_class_entry->get_iterator = php_com_iter_get;
193 
194 	tmp = register_class_com(php_com_variant_class_entry);
195 	tmp->default_object_handlers = &php_com_object_handlers;
196 	tmp->create_object = php_com_object_new;
197 	tmp->get_iterator = php_com_iter_get;
198 
199 #if HAVE_MSCOREE_H
200 	tmp = register_class_dotnet(php_com_variant_class_entry);
201 	tmp->default_object_handlers = &php_com_object_handlers;
202 	tmp->create_object = php_com_object_new;
203 	tmp->get_iterator = php_com_iter_get;
204 #endif
205 
206 	REGISTER_INI_ENTRIES();
207 
208 	register_com_extension_symbols(module_number);
209 
210 	PHP_MINIT(com_typeinfo)(INIT_FUNC_ARGS_PASSTHRU);
211 
212 	return SUCCESS;
213 }
214 /* }}} */
215 
216 /* {{{ PHP_MSHUTDOWN_FUNCTION */
PHP_MSHUTDOWN_FUNCTION(com_dotnet)217 PHP_MSHUTDOWN_FUNCTION(com_dotnet)
218 {
219 	UNREGISTER_INI_ENTRIES();
220 #if HAVE_MSCOREE_H
221 	if (COMG(dotnet_runtime_stuff)) {
222 		php_com_dotnet_mshutdown();
223 	}
224 #endif
225 
226 	PHP_MSHUTDOWN(com_typeinfo)(INIT_FUNC_ARGS_PASSTHRU);
227 
228 	return SUCCESS;
229 }
230 /* }}} */
231 
232 /* {{{ PHP_RINIT_FUNCTION */
PHP_RINIT_FUNCTION(com_dotnet)233 PHP_RINIT_FUNCTION(com_dotnet)
234 {
235 	COMG(rshutdown_started) = 0;
236 	return SUCCESS;
237 }
238 /* }}} */
239 
240 /* {{{ PHP_RSHUTDOWN_FUNCTION */
PHP_RSHUTDOWN_FUNCTION(com_dotnet)241 PHP_RSHUTDOWN_FUNCTION(com_dotnet)
242 {
243 #if HAVE_MSCOREE_H
244 	if (COMG(dotnet_runtime_stuff)) {
245 		php_com_dotnet_rshutdown();
246 	}
247 #endif
248 	COMG(rshutdown_started) = 1;
249 	return SUCCESS;
250 }
251 /* }}} */
252 
253 /* {{{ PHP_MINFO_FUNCTION */
PHP_MINFO_FUNCTION(com_dotnet)254 PHP_MINFO_FUNCTION(com_dotnet)
255 {
256 	php_info_print_table_start();
257 
258 	php_info_print_table_row(2, "COM support", "enabled");
259 	php_info_print_table_row(2, "DCOM support", COMG(allow_dcom) ? "enabled" : "disabled");
260 
261 #if HAVE_MSCOREE_H
262 	php_info_print_table_row(2, ".Net support", "enabled");
263 #else
264 	php_info_print_table_row(2, ".Net support", "not present in this build");
265 #endif
266 
267 	php_info_print_table_end();
268 
269 	DISPLAY_INI_ENTRIES();
270 }
271 /* }}} */
272