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