diff options
-rw-r--r-- | ext/com_dotnet/com_extension.c | 1 | ||||
-rw-r--r-- | ext/com_dotnet/com_handlers.c | 37 | ||||
-rw-r--r-- | ext/com_dotnet/com_misc.c | 2 | ||||
-rw-r--r-- | ext/com_dotnet/com_saproxy.c | 54 | ||||
-rw-r--r-- | ext/com_dotnet/com_variant.c | 10 | ||||
-rwxr-xr-x | ext/com_dotnet/tests/27974.phpt | 18 |
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! |