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 #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 LocalFree(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