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