xref: /PHP-7.4/ext/com_dotnet/com_misc.c (revision 0cf7de1c)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 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 
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
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 
php_com_throw_exception(HRESULT code,char * message)30 void php_com_throw_exception(HRESULT code, char *message)
31 {
32 	int free_msg = 0;
33 	if (message == NULL) {
34 		message = php_win32_error_to_msg(code);
35 		free_msg = 1;
36 	}
37 #if SIZEOF_ZEND_LONG == 8
38 	zend_throw_exception(php_com_exception_class_entry, message, (zend_long)(uint32_t)code);
39 #else
40 	zend_throw_exception(php_com_exception_class_entry, message, (zend_long)code);
41 #endif
42 	if (free_msg) {
43 		php_win32_error_msg_free(message);
44 	}
45 }
46 
php_com_wrap_dispatch(zval * z,IDispatch * disp,int codepage)47 PHP_COM_DOTNET_API void php_com_wrap_dispatch(zval *z, IDispatch *disp,
48 		int codepage)
49 {
50 	php_com_dotnet_object *obj;
51 
52 	obj = emalloc(sizeof(*obj));
53 	memset(obj, 0, sizeof(*obj));
54 	obj->code_page = codepage;
55 	obj->ce = php_com_variant_class_entry;
56 	obj->zo.ce = php_com_variant_class_entry;
57 
58 	VariantInit(&obj->v);
59 	V_VT(&obj->v) = VT_DISPATCH;
60 	V_DISPATCH(&obj->v) = disp;
61 
62 	IDispatch_AddRef(V_DISPATCH(&obj->v));
63 	IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &obj->typeinfo);
64 
65 	zend_object_std_init(&obj->zo, php_com_variant_class_entry);
66 	obj->zo.handlers = &php_com_object_handlers;
67 	ZVAL_OBJ(z, &obj->zo);
68 }
69 
php_com_wrap_variant(zval * z,VARIANT * v,int codepage)70 PHP_COM_DOTNET_API void php_com_wrap_variant(zval *z, VARIANT *v,
71 		int codepage)
72 {
73 	php_com_dotnet_object *obj;
74 
75 	obj = emalloc(sizeof(*obj));
76 	memset(obj, 0, sizeof(*obj));
77 	obj->code_page = codepage;
78 	obj->ce = php_com_variant_class_entry;
79 	obj->zo.ce = php_com_variant_class_entry;
80 
81 	VariantInit(&obj->v);
82 	VariantCopyInd(&obj->v, v);
83 	obj->modified = 0;
84 
85 	if ((V_VT(&obj->v) == VT_DISPATCH) && (V_DISPATCH(&obj->v) != NULL)) {
86 		IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &obj->typeinfo);
87 	}
88 
89 	zend_object_std_init(&obj->zo, php_com_variant_class_entry);
90 	obj->zo.handlers = &php_com_object_handlers;
91 	ZVAL_OBJ(z, &obj->zo);
92 }
93 
94 /* this is a convenience function for fetching a particular
95  * element from a (possibly multi-dimensional) safe array */
php_com_safearray_get_elem(VARIANT * array,VARIANT * dest,LONG dim1)96 PHP_COM_DOTNET_API int php_com_safearray_get_elem(VARIANT *array, VARIANT *dest, LONG dim1)
97 {
98 	UINT dims;
99 	LONG lbound, ubound;
100 	LONG indices[1];
101 	VARTYPE vt;
102 
103 	if (!V_ISARRAY(array)) {
104 		return 0;
105 	}
106 
107 	dims = SafeArrayGetDim(V_ARRAY(array));
108 
109 	if (dims != 1) {
110 		php_error_docref(NULL, E_WARNING,
111 			   "Can only handle single dimension variant arrays (this array has %d)", dims);
112 		return 0;
113 	}
114 
115 	if (FAILED(SafeArrayGetVartype(V_ARRAY(array), &vt)) || vt == VT_EMPTY) {
116 		vt = V_VT(array) & ~VT_ARRAY;
117 	}
118 
119 	/* determine the bounds */
120 	SafeArrayGetLBound(V_ARRAY(array), 1, &lbound);
121 	SafeArrayGetUBound(V_ARRAY(array), 1, &ubound);
122 
123 	/* check bounds */
124 	if (dim1 < lbound || dim1 > ubound) {
125 		php_com_throw_exception(DISP_E_BADINDEX, "index out of bounds");
126 		return 0;
127 	}
128 
129 	/* now fetch that element */
130 	VariantInit(dest);
131 
132 	indices[0] = dim1;
133 
134 	if (vt == VT_VARIANT) {
135 		SafeArrayGetElement(V_ARRAY(array), indices, dest);
136 	} else {
137 		V_VT(dest) = vt;
138 		/* store the value into "lVal" member of the variant.
139 		 * This works because it is a union; since we know the variant
140 		 * type, we end up with a working variant */
141 		SafeArrayGetElement(V_ARRAY(array), indices, &dest->lVal);
142 	}
143 
144 	return 1;
145 }
146