Commit a5e3a999 authored by Alex Villacís Lasso's avatar Alex Villacís Lasso Committed by Alexandre Julliard

oleaut32: Support for VT_DISPATCH in VarSub.

parent 67c9b7cb
...@@ -3690,17 +3690,80 @@ HRESULT WINAPI VarSub(LPVARIANT left, LPVARIANT right, LPVARIANT result) ...@@ -3690,17 +3690,80 @@ HRESULT WINAPI VarSub(LPVARIANT left, LPVARIANT right, LPVARIANT result)
VARTYPE leftvt,rightvt; VARTYPE leftvt,rightvt;
VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags; VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags;
VARIANT lv,rv; VARIANT lv,rv;
VARIANT tempLeft, tempRight;
VariantInit(&lv);
VariantInit(&rv);
VariantInit(&tempLeft);
VariantInit(&tempRight);
TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left), TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result); debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH &&
(V_VT(left)&(~VT_TYPEMASK)) == 0 &&
(V_VT(right) & VT_TYPEMASK) != VT_NULL)
{
if (NULL == V_DISPATCH(left)) {
if ((V_VT(right) & VT_TYPEMASK) >= VT_INT_PTR)
hres = DISP_E_BADVARTYPE;
else if ((V_VT(right) & VT_TYPEMASK) >= VT_UI8 &&
(V_VT(right) & VT_TYPEMASK) < VT_RECORD)
hres = DISP_E_BADVARTYPE;
else switch (V_VT(right) & VT_TYPEMASK)
{
case VT_VARIANT:
case VT_UNKNOWN:
case 15:
case VT_I1:
case VT_UI2:
case VT_UI4:
hres = DISP_E_BADVARTYPE;
}
if (FAILED(hres)) goto end;
}
hres = VARIANT_FetchDispatchValue(left, &tempLeft);
if (FAILED(hres)) goto end;
left = &tempLeft;
}
if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH &&
(V_VT(right)&(~VT_TYPEMASK)) == 0 &&
(V_VT(left) & VT_TYPEMASK) != VT_NULL)
{
if (NULL == V_DISPATCH(right))
{
if ((V_VT(left) & VT_TYPEMASK) >= VT_INT_PTR)
hres = DISP_E_BADVARTYPE;
else if ((V_VT(left) & VT_TYPEMASK) >= VT_UI8 &&
(V_VT(left) & VT_TYPEMASK) < VT_RECORD)
hres = DISP_E_BADVARTYPE;
else switch (V_VT(left) & VT_TYPEMASK)
{
case VT_VARIANT:
case VT_UNKNOWN:
case 15:
case VT_I1:
case VT_UI2:
case VT_UI4:
hres = DISP_E_BADVARTYPE;
}
if (FAILED(hres)) goto end;
}
hres = VARIANT_FetchDispatchValue(right, &tempRight);
if (FAILED(hres)) goto end;
right = &tempRight;
}
leftvt = V_VT(left)&VT_TYPEMASK; leftvt = V_VT(left)&VT_TYPEMASK;
rightvt = V_VT(right)&VT_TYPEMASK; rightvt = V_VT(right)&VT_TYPEMASK;
leftExtraFlags = V_VT(left)&(~VT_TYPEMASK); leftExtraFlags = V_VT(left)&(~VT_TYPEMASK);
rightExtraFlags = V_VT(right)&(~VT_TYPEMASK); rightExtraFlags = V_VT(right)&(~VT_TYPEMASK);
if (leftExtraFlags != rightExtraFlags) if (leftExtraFlags != rightExtraFlags)
return DISP_E_BADVARTYPE; {
hres = DISP_E_BADVARTYPE;
goto end;
}
ExtraFlags = leftExtraFlags; ExtraFlags = leftExtraFlags;
/* determine return type and return code */ /* determine return type and return code */
...@@ -3712,9 +3775,15 @@ HRESULT WINAPI VarSub(LPVARIANT left, LPVARIANT right, LPVARIANT result) ...@@ -3712,9 +3775,15 @@ HRESULT WINAPI VarSub(LPVARIANT left, LPVARIANT right, LPVARIANT result)
ExtraFlags == VT_VECTOR || ExtraFlags == VT_VECTOR ||
ExtraFlags == VT_BYREF || ExtraFlags == VT_BYREF ||
ExtraFlags == VT_RESERVED) ExtraFlags == VT_RESERVED)
return DISP_E_BADVARTYPE; {
hres = DISP_E_BADVARTYPE;
goto end;
}
else if (ExtraFlags >= VT_ARRAY) else if (ExtraFlags >= VT_ARRAY)
return DISP_E_TYPEMISMATCH; {
hres = DISP_E_TYPEMISMATCH;
goto end;
}
/* Native VarSub cannot handle: VT_I1, VT_UI2, VT_UI4, /* Native VarSub cannot handle: VT_I1, VT_UI2, VT_UI4,
VT_INT, VT_UINT and VT_UI8. Tested with WinXP */ VT_INT, VT_UINT and VT_UI8. Tested with WinXP */
else if (leftvt == VT_CLSID || rightvt == VT_CLSID || else if (leftvt == VT_CLSID || rightvt == VT_CLSID ||
...@@ -3729,34 +3798,44 @@ HRESULT WINAPI VarSub(LPVARIANT left, LPVARIANT right, LPVARIANT result) ...@@ -3729,34 +3798,44 @@ HRESULT WINAPI VarSub(LPVARIANT left, LPVARIANT right, LPVARIANT result)
leftvt == VT_RECORD || rightvt == VT_RECORD) leftvt == VT_RECORD || rightvt == VT_RECORD)
{ {
if (leftvt == VT_RECORD && rightvt == VT_I8) if (leftvt == VT_RECORD && rightvt == VT_I8)
return DISP_E_TYPEMISMATCH; hres = DISP_E_TYPEMISMATCH;
else if (leftvt < VT_UI1 && rightvt == VT_RECORD) else if (leftvt < VT_UI1 && rightvt == VT_RECORD)
return DISP_E_TYPEMISMATCH; hres = DISP_E_TYPEMISMATCH;
else if (leftvt >= VT_UI1 && rightvt == VT_RECORD) else if (leftvt >= VT_UI1 && rightvt == VT_RECORD)
return DISP_E_TYPEMISMATCH; hres = DISP_E_TYPEMISMATCH;
else if (leftvt == VT_RECORD && rightvt <= VT_UI1) else if (leftvt == VT_RECORD && rightvt <= VT_UI1)
return DISP_E_TYPEMISMATCH; hres = DISP_E_TYPEMISMATCH;
else if (leftvt == VT_RECORD && rightvt > VT_UI1) else if (leftvt == VT_RECORD && rightvt > VT_UI1)
return DISP_E_BADVARTYPE; hres = DISP_E_BADVARTYPE;
else else
return DISP_E_BADVARTYPE; hres = DISP_E_BADVARTYPE;
goto end;
} }
/* The following flags/types are invalid for left variant */ /* The following flags/types are invalid for left variant */
else if (!((leftvt <= VT_LPWSTR || leftvt == VT_RECORD || else if (!((leftvt <= VT_LPWSTR || leftvt == VT_RECORD ||
leftvt == VT_CLSID) && leftvt != (VARTYPE)15 /* undefined vt */ && leftvt == VT_CLSID) && leftvt != (VARTYPE)15 /* undefined vt */ &&
(leftvt < VT_VOID || leftvt > VT_LPWSTR))) (leftvt < VT_VOID || leftvt > VT_LPWSTR)))
return DISP_E_BADVARTYPE; {
hres = DISP_E_BADVARTYPE;
goto end;
}
/* The following flags/types are invalid for right variant */ /* The following flags/types are invalid for right variant */
else if (!((rightvt <= VT_LPWSTR || rightvt == VT_RECORD || else if (!((rightvt <= VT_LPWSTR || rightvt == VT_RECORD ||
rightvt == VT_CLSID) && rightvt != (VARTYPE)15 /* undefined vt */ && rightvt == VT_CLSID) && rightvt != (VARTYPE)15 /* undefined vt */ &&
(rightvt < VT_VOID || rightvt > VT_LPWSTR))) (rightvt < VT_VOID || rightvt > VT_LPWSTR)))
return DISP_E_BADVARTYPE; {
hres = DISP_E_BADVARTYPE;
goto end;
}
else if ((leftvt == VT_NULL && rightvt == VT_DISPATCH) || else if ((leftvt == VT_NULL && rightvt == VT_DISPATCH) ||
(leftvt == VT_DISPATCH && rightvt == VT_NULL)) (leftvt == VT_DISPATCH && rightvt == VT_NULL))
resvt = VT_NULL; resvt = VT_NULL;
else if (leftvt == VT_DISPATCH || rightvt == VT_DISPATCH || else if (leftvt == VT_DISPATCH || rightvt == VT_DISPATCH ||
leftvt == VT_ERROR || rightvt == VT_ERROR) leftvt == VT_ERROR || rightvt == VT_ERROR)
return DISP_E_TYPEMISMATCH; {
hres = DISP_E_TYPEMISMATCH;
goto end;
}
else if (leftvt == VT_NULL || rightvt == VT_NULL) else if (leftvt == VT_NULL || rightvt == VT_NULL)
resvt = VT_NULL; resvt = VT_NULL;
else if ((leftvt == VT_EMPTY && rightvt == VT_BSTR) || else if ((leftvt == VT_EMPTY && rightvt == VT_BSTR) ||
...@@ -3793,32 +3872,22 @@ HRESULT WINAPI VarSub(LPVARIANT left, LPVARIANT right, LPVARIANT result) ...@@ -3793,32 +3872,22 @@ HRESULT WINAPI VarSub(LPVARIANT left, LPVARIANT right, LPVARIANT result)
else if (leftvt == VT_UI1 || rightvt == VT_UI1) else if (leftvt == VT_UI1 || rightvt == VT_UI1)
resvt = VT_UI1; resvt = VT_UI1;
else else
return DISP_E_TYPEMISMATCH; {
hres = DISP_E_TYPEMISMATCH;
VariantInit(&lv); goto end;
VariantInit(&rv); }
/* coerce to the result type */ /* coerce to the result type */
if (leftvt == VT_BSTR && rightvt == VT_DATE) if (leftvt == VT_BSTR && rightvt == VT_DATE)
hres = VariantChangeType(&lv, left, 0, VT_R8); hres = VariantChangeType(&lv, left, 0, VT_R8);
else else
hres = VariantChangeType(&lv, left, 0, resvt); hres = VariantChangeType(&lv, left, 0, resvt);
if (hres != S_OK) if (hres != S_OK) goto end;
{
VariantClear(&lv);
VariantClear(&rv);
return hres;
}
if (leftvt == VT_DATE && rightvt == VT_BSTR) if (leftvt == VT_DATE && rightvt == VT_BSTR)
hres = VariantChangeType(&rv, right, 0, VT_R8); hres = VariantChangeType(&rv, right, 0, VT_R8);
else else
hres = VariantChangeType(&rv, right, 0, resvt); hres = VariantChangeType(&rv, right, 0, resvt);
if (hres != S_OK) if (hres != S_OK) goto end;
{
VariantClear(&lv);
VariantClear(&rv);
return hres;
}
/* do the math */ /* do the math */
V_VT(result) = resvt; V_VT(result) = resvt;
...@@ -3858,9 +3927,12 @@ HRESULT WINAPI VarSub(LPVARIANT left, LPVARIANT right, LPVARIANT result) ...@@ -3858,9 +3927,12 @@ HRESULT WINAPI VarSub(LPVARIANT left, LPVARIANT right, LPVARIANT result)
break; break;
} }
end:
VariantClear(&lv); VariantClear(&lv);
VariantClear(&rv); VariantClear(&rv);
VariantClear(&tempLeft);
VariantClear(&tempRight);
TRACE("returning 0x%8x (variant type %s)\n", hres, debugstr_VT(result));
return hres; return hres;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment