This is a preliminary patch to add support for VT_DISPATCH as parameters to VarAdd and other arithmetic operations with variants. The tests still "pass" in the sense that null VT_DISPATCH as issued by the tests are still rejected. I post this in the hope that it will be reviewed while I prepare a test case.

Changelog:
* Add support for receiving of VT_DISPATCH parameters in several operator functions by fetching the result value, then reissuing the same operation on result data.

--
The following cryptic message was allegedly found in the inner edge of a Windows
XP installation CD:

4F6E65204F5320746F2072756C65207468656D20616C6C2C204F6E65204F5320746F2066696E6420
7468656D2C0D0A4F6E65204F5320746F206272696E67207468656D20616C6C20616E6420696E2074
6865206461726B6E6573732062696E64207468656D2E0A

It is rumored that only a true Unix Wizard can decypher this mysterious message,
which supposedly encodes the true nature and purpose of the software.

--- wine-0.9.25-cvs/dlls/oleaut32/variant.c	2006-11-08 15:27:23.000000000 -0500
+++ wine-0.9.25-cvs-patch/dlls/oleaut32/variant.c	2006-11-18 22:39:11.000000000 -0500
@@ -2856,6 +2856,40 @@
 #undef _VARCMP
 }
 
+static HRESULT VARIANT_InvokeDispatchOp(LPVARIANT left, LPVARIANT right, 
+    LPVARIANT result, HRESULT WINAPI (* pOperatorFunc)(LPVARIANT, LPVARIANT, LPVARIANT))    
+{
+    HRESULT hres;
+    VARIANT leftVar, rightVar;
+    LPVARIANT leftResult, rightResult;
+    static DISPPARAMS emptyParams = { NULL, NULL, 0, 0 };
+    
+    if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH) {
+        leftResult = &leftVar;
+        if (NULL == V_DISPATCH(left)) return DISP_E_TYPEMISMATCH;
+        hres = IDispatch_Invoke(V_DISPATCH(left), DISPID_VALUE, &IID_NULL, 
+            LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &emptyParams, leftResult, 
+            NULL, NULL);
+        if (!SUCCEEDED(hres)) return hres;
+    } else {
+        leftResult = left;
+    }
+    if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH) {
+        rightResult = &rightVar;
+        if (NULL == V_DISPATCH(right)) return DISP_E_TYPEMISMATCH;
+        hres = IDispatch_Invoke(V_DISPATCH(right), DISPID_VALUE, &IID_NULL, 
+            LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &emptyParams, rightResult, 
+            NULL, NULL);
+        if (!SUCCEEDED(hres)) return hres;
+    } else {
+        rightResult = right;
+    }
+    hres = pOperatorFunc(leftResult, rightResult, result);
+    if (leftResult != left) VariantClear(leftResult);
+    if (rightResult != right) VariantClear(rightResult);
+    return hres;
+}
+
 /**********************************************************************
  *              VarAnd [OLEAUT32.142]
  *
@@ -2884,6 +2918,13 @@
     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
 
+    /* Handle VT_DISPATCH by recursively calling op on result of IDispatch_Invoke */
+    if (((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH || 
+        (V_VT(right) & VT_TYPEMASK) == VT_DISPATCH) &&
+        (V_VT(left) & VT_TYPEMASK) != VT_NULL && 
+        (V_VT(right) & VT_TYPEMASK) != VT_NULL) 
+        return VARIANT_InvokeDispatchOp(left, right, result, VarAnd);
+
     leftvt = V_VT(left)&VT_TYPEMASK;
     rightvt = V_VT(right)&VT_TYPEMASK;
     leftExtraFlags = V_VT(left)&(~VT_TYPEMASK);
@@ -3114,6 +3155,13 @@
           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right),
           result);
 
+    /* Handle VT_DISPATCH by recursively calling op on result of IDispatch_Invoke */
+    if (((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH || 
+        (V_VT(right) & VT_TYPEMASK) == VT_DISPATCH) &&
+        (V_VT(left) & VT_TYPEMASK) != VT_NULL && 
+        (V_VT(right) & VT_TYPEMASK) != VT_NULL) 
+        return VARIANT_InvokeDispatchOp(left, right, result, VarAdd);
+
     VariantInit(&lv);
     VariantInit(&rv);
     VariantInit(&tv);
@@ -3304,6 +3352,13 @@
           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right),
           result);
 
+    /* Handle VT_DISPATCH by recursively calling op on result of IDispatch_Invoke */
+    if (((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH || 
+        (V_VT(right) & VT_TYPEMASK) == VT_DISPATCH) &&
+        (V_VT(left) & VT_TYPEMASK) != VT_NULL && 
+        (V_VT(right) & VT_TYPEMASK) != VT_NULL) 
+        return VARIANT_InvokeDispatchOp(left, right, result, VarMul);
+
     VariantInit(&lv);
     VariantInit(&rv);
     VariantInit(&tv);
@@ -3453,6 +3508,13 @@
     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
 
+    /* Handle VT_DISPATCH by recursively calling op on result of IDispatch_Invoke */
+    if (((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH || 
+        (V_VT(right) & VT_TYPEMASK) == VT_DISPATCH) &&
+        (V_VT(left) & VT_TYPEMASK) != VT_NULL && 
+        (V_VT(right) & VT_TYPEMASK) != VT_NULL) 
+        return VARIANT_InvokeDispatchOp(left, right, result, VarDiv);
+
     /* Native VarPow always returns a error when using any extra flags */
     if (ExtraFlags != 0)
         return DISP_E_BADVARTYPE;
@@ -3646,6 +3708,10 @@
     else if ((leftvt == VT_NULL && rightvt == VT_DISPATCH) ||
         (leftvt == VT_DISPATCH && rightvt == VT_NULL))
         resvt = VT_NULL;
+    /* Handle VT_DISPATCH by recursively calling op on result of IDispatch_Invoke */
+    else if (((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH || 
+        (V_VT(right) & VT_TYPEMASK) == VT_DISPATCH))
+        return VARIANT_InvokeDispatchOp(left, right, result, VarSub);
     else if (leftvt == VT_DISPATCH || rightvt == VT_DISPATCH ||
         leftvt == VT_ERROR || rightvt == VT_ERROR)
         return DISP_E_TYPEMISMATCH;
@@ -3785,6 +3851,13 @@
           debugstr_VF(pVarLeft), pVarRight, debugstr_VT(pVarRight),
           debugstr_VF(pVarRight), pVarOut);
 
+    /* Handle VT_DISPATCH by recursively calling op on result of IDispatch_Invoke */
+    if (((V_VT(pVarLeft) & VT_TYPEMASK) == VT_DISPATCH || 
+        (V_VT(pVarRight) & VT_TYPEMASK) == VT_DISPATCH) &&
+        (V_VT(pVarLeft) & VT_TYPEMASK) != VT_NULL && 
+        (V_VT(pVarRight) & VT_TYPEMASK) != VT_NULL) 
+        return VARIANT_InvokeDispatchOp(pVarLeft, pVarRight, pVarOut, VarOr);
+
     if (V_EXTRA_TYPE(pVarLeft) || V_EXTRA_TYPE(pVarRight) ||
         V_VT(pVarLeft) == VT_UNKNOWN || V_VT(pVarRight) == VT_UNKNOWN ||
         V_VT(pVarLeft) == VT_DISPATCH || V_VT(pVarRight) == VT_DISPATCH ||
@@ -4297,6 +4370,13 @@
           debugstr_VF(pVarLeft), pVarRight, debugstr_VT(pVarRight),
           debugstr_VF(pVarRight), pVarOut);
 
+    /* Handle VT_DISPATCH by recursively calling op on result of IDispatch_Invoke */
+    if (((V_VT(pVarLeft) & VT_TYPEMASK) == VT_DISPATCH || 
+        (V_VT(pVarRight) & VT_TYPEMASK) == VT_DISPATCH) &&
+        (V_VT(pVarLeft) & VT_TYPEMASK) != VT_NULL && 
+        (V_VT(pVarRight) & VT_TYPEMASK) != VT_NULL) 
+        return VARIANT_InvokeDispatchOp(pVarLeft, pVarRight, pVarOut, VarXor);
+
     if (V_EXTRA_TYPE(pVarLeft) || V_EXTRA_TYPE(pVarRight) ||
         V_VT(pVarLeft) > VT_UINT || V_VT(pVarRight) > VT_UINT ||
         V_VT(pVarLeft) == VT_VARIANT || V_VT(pVarRight) == VT_VARIANT ||
@@ -4869,6 +4949,13 @@
     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
 
+    /* Handle VT_DISPATCH by recursively calling op on result of IDispatch_Invoke */
+    if (((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH || 
+        (V_VT(right) & VT_TYPEMASK) == VT_DISPATCH) &&
+        (V_VT(left) & VT_TYPEMASK) != VT_NULL && 
+        (V_VT(right) & VT_TYPEMASK) != VT_NULL) 
+        return VARIANT_InvokeDispatchOp(left, right, result, VarIdiv);
+
     /* Native VarIdiv always returns a error when using any extra
      * flags or if the variant combination is I8 and INT.
      */
@@ -5012,6 +5099,13 @@
     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
 		  debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
 
+    /* Handle VT_DISPATCH by recursively calling op on result of IDispatch_Invoke */
+    if (((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH || 
+        (V_VT(right) & VT_TYPEMASK) == VT_DISPATCH) &&
+        (V_VT(left) & VT_TYPEMASK) != VT_NULL && 
+        (V_VT(right) & VT_TYPEMASK) != VT_NULL) 
+        return VARIANT_InvokeDispatchOp(left, right, result, VarMod);
+
     /* check for invalid inputs */
     lOk = TRUE;
     switch (V_VT(left) & VT_TYPEMASK) {
@@ -5220,6 +5314,13 @@
     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left), debugstr_VF(left),
           right, debugstr_VT(right), debugstr_VF(right), result);
 
+    /* Handle VT_DISPATCH by recursively calling op on result of IDispatch_Invoke */
+    if (((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH || 
+        (V_VT(right) & VT_TYPEMASK) == VT_DISPATCH) &&
+        (V_VT(left) & VT_TYPEMASK) != VT_NULL && 
+        (V_VT(right) & VT_TYPEMASK) != VT_NULL) 
+        return VARIANT_InvokeDispatchOp(left, right, result, VarPow);
+
     VariantInit(&dl);
     VariantInit(&dr);
 
@@ -5316,6 +5417,13 @@
     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
 
+    /* Handle VT_DISPATCH by recursively calling op on result of IDispatch_Invoke */
+    if (((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH || 
+        (V_VT(right) & VT_TYPEMASK) == VT_DISPATCH) &&
+        (V_VT(left) & VT_TYPEMASK) != VT_NULL && 
+        (V_VT(right) & VT_TYPEMASK) != VT_NULL) 
+        return VARIANT_InvokeDispatchOp(left, right, result, VarImp);
+
     /* Native VarImp always returns a error when using any extra
      * flags or if the variants are I8 and INT.
      */


Reply via email to