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.
*/