summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/com_dotnet/com_extension.c1
-rw-r--r--ext/com_dotnet/com_handlers.c37
-rw-r--r--ext/com_dotnet/com_misc.c2
-rw-r--r--ext/com_dotnet/com_saproxy.c54
-rw-r--r--ext/com_dotnet/com_variant.c10
-rwxr-xr-xext/com_dotnet/tests/27974.phpt18
6 files changed, 103 insertions, 19 deletions
diff --git a/ext/com_dotnet/com_extension.c b/ext/com_dotnet/com_extension.c
index 354cbcd1cc..10763aebec 100644
--- a/ext/com_dotnet/com_extension.c
+++ b/ext/com_dotnet/com_extension.c
@@ -281,6 +281,7 @@ PHP_MINIT_FUNCTION(com_dotnet)
#endif
COM_CONST(DISP_E_DIVBYZERO);
COM_CONST(DISP_E_OVERFLOW);
+ COM_CONST(DISP_E_BADINDEX);
return SUCCESS;
}
diff --git a/ext/com_dotnet/com_handlers.c b/ext/com_dotnet/com_handlers.c
index 6e6003babd..9c80d9f4f9 100644
--- a/ext/com_dotnet/com_handlers.c
+++ b/ext/com_dotnet/com_handlers.c
@@ -158,6 +158,7 @@ static void com_write_dimension(zval *object, zval *offset, zval *value TSRMLS_D
php_com_dotnet_object *obj;
zval *args[2];
VARIANT v;
+ HRESULT res;
obj = CDNO_FETCH(object);
@@ -176,8 +177,42 @@ static void com_write_dimension(zval *object, zval *offset, zval *value TSRMLS_D
DISPATCH_METHOD|DISPATCH_PROPERTYPUT, &v, 2, args TSRMLS_CC)) {
VariantClear(&v);
}
+ } else if (V_ISARRAY(&obj->v)) {
+ LONG indices = 0;
+ VARTYPE vt;
+
+ if (SafeArrayGetDim(V_ARRAY(&obj->v)) == 1) {
+ if (FAILED(SafeArrayGetVartype(V_ARRAY(&obj->v), &vt)) || vt == VT_EMPTY) {
+ vt = V_VT(&obj->v) & ~VT_ARRAY;
+ }
+
+ convert_to_long(offset);
+ indices = Z_LVAL_P(offset);
+
+ VariantInit(&v);
+ php_com_variant_from_zval(&v, value, obj->code_page TSRMLS_CC);
+
+ if (V_VT(&v) != vt) {
+ VariantChangeType(&v, &v, 0, vt);
+ }
+
+ if (vt == VT_VARIANT) {
+ res = SafeArrayPutElement(V_ARRAY(&obj->v), &indices, &v);
+ } else {
+ res = SafeArrayPutElement(V_ARRAY(&obj->v), &indices, &v.lVal);
+ }
+
+ VariantClear(&v);
+
+ if (FAILED(res)) {
+ php_com_throw_exception(res, NULL TSRMLS_CC);
+ }
+
+ } else {
+ php_com_throw_exception(DISP_E_BADINDEX, "this variant has multiple dimensions; you can't set a new value without specifying *all* dimensions" TSRMLS_CC);
+ }
+
} else {
- /* TODO: check for safearray */
php_com_throw_exception(E_INVALIDARG, "this variant is not an array type" TSRMLS_CC);
}
}
diff --git a/ext/com_dotnet/com_misc.c b/ext/com_dotnet/com_misc.c
index 641935ff25..f46c606713 100644
--- a/ext/com_dotnet/com_misc.c
+++ b/ext/com_dotnet/com_misc.c
@@ -118,7 +118,7 @@ PHPAPI int php_com_safearray_get_elem(VARIANT *array, VARIANT *dest, LONG dim1 T
/* check bounds */
if (dim1 < lbound || dim1 > ubound) {
- php_com_throw_exception(E_INVALIDARG, "index out of bounds" TSRMLS_CC);
+ php_com_throw_exception(DISP_E_BADINDEX, "index out of bounds" TSRMLS_CC);
return 0;
}
diff --git a/ext/com_dotnet/com_saproxy.c b/ext/com_dotnet/com_saproxy.c
index 1187f51150..85d9b978a5 100644
--- a/ext/com_dotnet/com_saproxy.c
+++ b/ext/com_dotnet/com_saproxy.c
@@ -156,7 +156,7 @@ static zval *saproxy_read_dimension(zval *object, zval *offset, int type TSRMLS_
SafeArrayGetUBound(sa, proxy->dimensions, &ubound);
if (Z_LVAL_P(offset) < lbound || Z_LVAL_P(offset) > ubound) {
- php_com_throw_exception(E_INVALIDARG, "index out of bounds" TSRMLS_CC);
+ php_com_throw_exception(DISP_E_BADINDEX, "index out of bounds" TSRMLS_CC);
return return_value;
}
@@ -185,15 +185,19 @@ static zval *saproxy_read_dimension(zval *object, zval *offset, int type TSRMLS_
}
if (vt == VT_VARIANT) {
- SafeArrayGetElement(sa, indices, &v);
+ res = SafeArrayGetElement(sa, indices, &v);
} else {
V_VT(&v) = vt;
- SafeArrayGetElement(sa, indices, &v.lVal);
+ res = SafeArrayGetElement(sa, indices, &v.lVal);
}
free_alloca(indices);
- php_com_wrap_variant(return_value, &v, proxy->obj->code_page TSRMLS_CC);
+ if (SUCCEEDED(res)) {
+ php_com_wrap_variant(return_value, &v, proxy->obj->code_page TSRMLS_CC);
+ } else {
+ php_com_throw_exception(res, NULL TSRMLS_CC);
+ }
VariantClear(&v);
@@ -209,8 +213,6 @@ static void saproxy_write_dimension(zval *object, zval *offset, zval *value TSRM
{
php_com_saproxy *proxy = SA_FETCH(object);
UINT dims;
- SAFEARRAY *sa;
- LONG ubound, lbound;
int i;
HRESULT res;
VARIANT v;
@@ -238,7 +240,44 @@ static void saproxy_write_dimension(zval *object, zval *offset, zval *value TSRM
efree(args);
} else if (V_ISARRAY(&proxy->obj->v)) {
- php_com_throw_exception(E_NOTIMPL, "writing to safearray not yet implemented" TSRMLS_CC);
+ LONG *indices;
+ VARTYPE vt;
+
+ dims = SafeArrayGetDim(V_ARRAY(&proxy->obj->v));
+ indices = do_alloca(dims * sizeof(LONG));
+ /* copy indices from proxy */
+ for (i = 0; i < dims; i++) {
+ convert_to_long(proxy->indices[i]);
+ indices[i] = Z_LVAL_P(proxy->indices[i]);
+ }
+
+ /* add user-supplied index */
+ convert_to_long(offset);
+ indices[dims-1] = Z_LVAL_P(offset);
+
+ if (FAILED(SafeArrayGetVartype(V_ARRAY(&proxy->obj->v), &vt)) || vt == VT_EMPTY) {
+ vt = V_VT(&proxy->obj->v) & ~VT_ARRAY;
+ }
+
+ VariantInit(&v);
+ php_com_variant_from_zval(&v, value, proxy->obj->code_page TSRMLS_CC);
+
+ if (V_VT(&v) != vt) {
+ VariantChangeType(&v, &v, 0, vt);
+ }
+
+ if (vt == VT_VARIANT) {
+ res = SafeArrayPutElement(V_ARRAY(&proxy->obj->v), indices, &v);
+ } else {
+ res = SafeArrayPutElement(V_ARRAY(&proxy->obj->v), indices, &v.lVal);
+ }
+
+ free_alloca(indices);
+ VariantClear(&v);
+
+ if (FAILED(res)) {
+ php_com_throw_exception(res, NULL TSRMLS_CC);
+ }
} else {
php_com_throw_exception(E_NOTIMPL, "invalid write to com proxy object" TSRMLS_CC);
}
@@ -366,7 +405,6 @@ static void saproxy_clone(void *object, void **clone_ptr TSRMLS_DC)
{
php_com_saproxy *proxy = (php_com_saproxy *)object;
php_com_saproxy *cloneproxy;
- int i;
cloneproxy = emalloc(sizeof(*cloneproxy));
memcpy(cloneproxy, proxy, sizeof(*cloneproxy));
diff --git a/ext/com_dotnet/com_variant.c b/ext/com_dotnet/com_variant.c
index ccb8c18321..347a015c52 100644
--- a/ext/com_dotnet/com_variant.c
+++ b/ext/com_dotnet/com_variant.c
@@ -444,10 +444,7 @@ static void variant_binary_operation(enum variant_binary_opcode op, INTERNAL_FUN
if (SUCCEEDED(result)) {
php_com_wrap_variant(return_value, &vres, codepage TSRMLS_CC);
} else {
- char *werr;
- werr = php_win_err(result);
- php_com_throw_exception(result, werr TSRMLS_CC);
- LocalFree(werr);
+ php_com_throw_exception(result, NULL TSRMLS_CC);
}
VariantClear(&vres);
@@ -606,10 +603,7 @@ static void variant_unary_operation(enum variant_unary_opcode op, INTERNAL_FUNCT
if (SUCCEEDED(result)) {
php_com_wrap_variant(return_value, &vres, codepage TSRMLS_CC);
} else {
- char *werr;
- werr = php_win_err(result);
- php_com_throw_exception(result, werr TSRMLS_CC);
- LocalFree(werr);
+ php_com_throw_exception(result, NULL TSRMLS_CC);
}
VariantClear(&vres);
diff --git a/ext/com_dotnet/tests/27974.phpt b/ext/com_dotnet/tests/27974.phpt
index 5956d2b4aa..30c42b6cf6 100755
--- a/ext/com_dotnet/tests/27974.phpt
+++ b/ext/com_dotnet/tests/27974.phpt
@@ -8,11 +8,23 @@ if (!extension_loaded("com_dotnet")) print "skip COM/.Net support not present";
error_reporting(E_ALL);
try {
-$v = new VARIANT(array("123", "456", "789"));
+ $v = new VARIANT(array("123", "456", "789"));
var_dump($v);
print $v[0] . "\n";
print $v[1] . "\n";
print $v[2] . "\n";
+ $v[1] = "hello";
+ foreach ($v as $item) {
+ var_dump($item);
+ }
+ try {
+ $v[3] = "shouldn't work";
+ } catch (com_exception $e) {
+ if ($e->getCode() != DISP_E_BADINDEX) {
+ throw $e;
+ }
+ echo "Got BADINDEX exception OK!\n";
+ }
echo "OK!";
} catch (Exception $e) {
print $e;
@@ -24,4 +36,8 @@ object(variant)#1 (0) {
123
456
789
+string(3) "123"
+string(5) "hello"
+string(3) "789"
+Got BADINDEX exception OK!
OK!