summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandy wharmby <wharmby@php.net>2007-02-02 15:27:35 +0000
committerandy wharmby <wharmby@php.net>2007-02-02 15:27:35 +0000
commitcda82bc0a3f06d0a5328071ba46a65fe7c8fbef9 (patch)
tree6eed6dbfc0ebf4d7707068967f5e5a57cbe1fbea
parenta8c006235cd48c06768cb835ba8b4313713a6f81 (diff)
downloadphp-git-cda82bc0a3f06d0a5328071ba46a65fe7c8fbef9.tar.gz
Fixed bug #34564 (COM extension not returning modified "out" argument)
-rw-r--r--NEWS1
-rw-r--r--ext/com_dotnet/com_misc.c1
-rw-r--r--ext/com_dotnet/com_variant.c136
-rw-r--r--ext/com_dotnet/com_wrapper.c11
-rw-r--r--ext/com_dotnet/php_com_dotnet_internal.h2
5 files changed, 151 insertions, 0 deletions
diff --git a/NEWS b/NEWS
index 8f7a4d0635..7128b54e90 100644
--- a/NEWS
+++ b/NEWS
@@ -349,6 +349,7 @@ PHP NEWS
error raised). (Carl P. Corliss, Dmitry)
- Fixed bug #35106 (nested foreach fails when array variable has a
reference). (Dmitry)
+- Fixed bug #34564 (COM extension not returning modified "out" argument) (Andy)
- Fixed bug #33734 (Something strange with COM Object). (Rob)
- Fixed bug #33386 (ScriptControl only sees last function of class). (Rob)
- Fixed bug #33282 (Re-assignment by reference does not clear the is_ref
diff --git a/ext/com_dotnet/com_misc.c b/ext/com_dotnet/com_misc.c
index 9008a14584..2eb1c4eb2c 100644
--- a/ext/com_dotnet/com_misc.c
+++ b/ext/com_dotnet/com_misc.c
@@ -78,6 +78,7 @@ PHPAPI void php_com_wrap_variant(zval *z, VARIANT *v,
VariantInit(&obj->v);
VariantCopyInd(&obj->v, v);
+ obj->modified = 0;
if (V_VT(&obj->v) == VT_DISPATCH) {
IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &obj->typeinfo);
diff --git a/ext/com_dotnet/com_variant.c b/ext/com_dotnet/com_variant.c
index 05b45822c5..45bebb6c63 100644
--- a/ext/com_dotnet/com_variant.c
+++ b/ext/com_dotnet/com_variant.c
@@ -257,6 +257,140 @@ PHPAPI int php_com_zval_from_variant(zval *z, VARIANT *v, int codepage TSRMLS_DC
return ret;
}
+
+PHPAPI int php_com_copy_variant(VARIANT *dstvar, VARIANT *srcvar TSRMLS_DC)
+{
+ int ret = SUCCESS;
+
+ switch (V_VT(dstvar) & ~VT_BYREF) {
+ case VT_EMPTY:
+ case VT_NULL:
+ case VT_VOID:
+ /* should not be possible */
+ break;
+
+ case VT_UI1:
+ if (V_VT(dstvar) & VT_BYREF) {
+ *V_UI1REF(dstvar) = V_UI1(srcvar);
+ } else {
+ V_UI1(dstvar) = V_UI1(srcvar);
+ }
+ break;
+
+ case VT_I1:
+ if (V_VT(dstvar) & VT_BYREF) {
+ *V_I1REF(dstvar) = V_I1(srcvar);
+ } else {
+ V_I1(dstvar) = V_I1(srcvar);
+ }
+ break;
+
+ case VT_UI2:
+ if (V_VT(dstvar) & VT_BYREF) {
+ *V_UI2REF(dstvar) = V_UI2(srcvar);
+ } else {
+ V_UI2(dstvar) = V_UI2(srcvar);
+ }
+ break;
+
+ case VT_I2:
+ if (V_VT(dstvar) & VT_BYREF) {
+ *V_I2REF(dstvar) = V_I2(srcvar);
+ } else {
+ V_I2(dstvar) = V_I2(srcvar);
+ }
+ break;
+
+ case VT_UI4:
+ if (V_VT(dstvar) & VT_BYREF) {
+ *V_UI4REF(dstvar) = V_UI4(srcvar);
+ } else {
+ V_UI4(dstvar) = V_UI4(srcvar);
+ }
+ break;
+
+ case VT_I4:
+ if (V_VT(dstvar) & VT_BYREF) {
+ *V_I4REF(dstvar) = V_I4(srcvar);
+ } else {
+ V_I4(dstvar) = V_I4(srcvar);
+ }
+ break;
+
+ case VT_INT:
+ if (V_VT(dstvar) & VT_BYREF) {
+ *V_INTREF(dstvar) = V_INT(srcvar);
+ } else {
+ V_INT(dstvar) = V_INT(srcvar);
+ }
+ break;
+
+ case VT_UINT:
+ if (V_VT(dstvar) & VT_BYREF) {
+ *V_UINTREF(dstvar) = V_UINT(srcvar);
+ } else {
+ V_UINT(dstvar) = V_UINT(srcvar);
+ }
+ break;
+
+ case VT_R4:
+ if (V_VT(dstvar) & VT_BYREF) {
+ *V_R4REF(dstvar) = V_R4(srcvar);
+ } else {
+ V_R4(dstvar) = V_R4(srcvar);
+ }
+ break;
+
+ case VT_R8:
+ if (V_VT(dstvar) & VT_BYREF) {
+ *V_R8REF(dstvar) = V_R8(srcvar);
+ } else {
+ V_R8(dstvar) = V_R8(srcvar);
+ }
+ break;
+
+ case VT_BOOL:
+ if (V_VT(dstvar) & VT_BYREF) {
+ *V_BOOLREF(dstvar) = V_BOOL(srcvar);
+ } else {
+ V_BOOL(dstvar) = V_BOOL(srcvar);
+ }
+ break;
+
+ case VT_BSTR:
+ if (V_VT(dstvar) & VT_BYREF) {
+ *V_BSTRREF(dstvar) = V_BSTR(srcvar);
+ } else {
+ V_BSTR(dstvar) = V_BSTR(srcvar);
+ }
+ break;
+
+ case VT_UNKNOWN:
+ if (V_VT(dstvar) & VT_BYREF) {
+ *V_UNKNOWNREF(dstvar) = V_UNKNOWN(srcvar);
+ } else {
+ V_UNKNOWN(dstvar) = V_UNKNOWN(srcvar);
+ }
+ break;
+
+ case VT_DISPATCH:
+ if (V_VT(dstvar) & VT_BYREF) {
+ *V_DISPATCHREF(dstvar) = V_DISPATCH(srcvar);
+ } else {
+ V_DISPATCH(dstvar) = V_DISPATCH(srcvar);
+ }
+ break;
+
+ case VT_VARIANT:
+ return php_com_copy_variant(V_VARIANTREF(dstvar), srcvar TSRMLS_CC);
+
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "variant->variant: failed to copy from 0x%x to 0x%x", V_VT(dstvar), V_VT(srcvar));
+ ret = FAILURE;
+ }
+ return ret;
+}
+
/* {{{ com_variant_create_instance - ctor for new VARIANT() */
PHP_FUNCTION(com_variant_create_instance)
{
@@ -357,6 +491,8 @@ PHP_FUNCTION(variant_set)
VariantClear(&obj->v);
php_com_variant_from_zval(&obj->v, zvalue, obj->code_page TSRMLS_CC);
+ /* remember we modified this variant */
+ obj->modified = 1;
}
/* }}} */
diff --git a/ext/com_dotnet/com_wrapper.c b/ext/com_dotnet/com_wrapper.c
index af8579c6bd..4cc81aa04b 100644
--- a/ext/com_dotnet/com_wrapper.c
+++ b/ext/com_dotnet/com_wrapper.c
@@ -298,6 +298,17 @@ static HRESULT STDMETHODCALLTYPE disp_invokeex(
&retval, pdp->cArgs, params, 1, NULL TSRMLS_CC)) {
ret = S_OK;
trace("function called ok\n");
+
+ /* Copy any modified values to callers copy of variant*/
+ for (i = 0; i < pdp->cArgs; i++) {
+ php_com_dotnet_object *obj = CDNO_FETCH(*params[i]);
+ VARIANT *srcvar = &obj->v;
+ VARIANT *dstvar = &pdp->rgvarg[ pdp->cArgs - 1 - i];
+ if ((V_VT(dstvar) & VT_BYREF) && obj->modified ) {
+ trace("percolate modified value for arg %d VT=%08x\n", i, V_VT(dstvar));
+ php_com_copy_variant(dstvar, srcvar TSRMLS_CC);
+ }
+ }
} else {
trace("failed to call func\n");
ret = DISP_E_EXCEPTION;
diff --git a/ext/com_dotnet/php_com_dotnet_internal.h b/ext/com_dotnet/php_com_dotnet_internal.h
index 3d3d8cfd85..75a52e7d8d 100644
--- a/ext/com_dotnet/php_com_dotnet_internal.h
+++ b/ext/com_dotnet/php_com_dotnet_internal.h
@@ -36,6 +36,7 @@ typedef struct _php_com_dotnet_object {
zend_object zo;
VARIANT v;
+ int modified;
ITypeInfo *typeinfo;
long code_page;
@@ -152,6 +153,7 @@ PHP_FUNCTION(variant_cast);
PHPAPI void php_com_variant_from_zval_with_type(VARIANT *v, zval *z, VARTYPE type, int codepage TSRMLS_DC);
PHPAPI void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage TSRMLS_DC);
PHPAPI int php_com_zval_from_variant(zval *z, VARIANT *v, int codepage TSRMLS_DC);
+PHPAPI int php_com_copy_variant(VARIANT *dst, VARIANT *src TSRMLS_DC);
/* com_dotnet.c */
PHP_FUNCTION(com_dotnet_create_instance);