Module: wine Branch: master Commit: a5e3a999eafe78f2973bc732748756981b044795 URL: http://source.winehq.org/git/wine.git/?a=commit;h=a5e3a999eafe78f2973bc73274...
Author: Alex Villacís Lasso a_villacis@palosanto.com Date: Tue Jan 2 18:52:11 2007 -0500
oleaut32: Support for VT_DISPATCH in VarSub.
---
dlls/oleaut32/variant.c | 130 ++++++++++++++++++++++++++++++++++++---------- 1 files changed, 101 insertions(+), 29 deletions(-)
diff --git a/dlls/oleaut32/variant.c b/dlls/oleaut32/variant.c index 60af75d..7a7909e 100644 --- a/dlls/oleaut32/variant.c +++ b/dlls/oleaut32/variant.c @@ -3690,17 +3690,80 @@ HRESULT WINAPI VarSub(LPVARIANT left, LP VARTYPE leftvt,rightvt; VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags; 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), 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; rightvt = V_VT(right)&VT_TYPEMASK; leftExtraFlags = V_VT(left)&(~VT_TYPEMASK); rightExtraFlags = V_VT(right)&(~VT_TYPEMASK);
if (leftExtraFlags != rightExtraFlags) - return DISP_E_BADVARTYPE; + { + hres = DISP_E_BADVARTYPE; + goto end; + } ExtraFlags = leftExtraFlags;
/* determine return type and return code */ @@ -3712,9 +3775,15 @@ HRESULT WINAPI VarSub(LPVARIANT left, LP ExtraFlags == VT_VECTOR || ExtraFlags == VT_BYREF || ExtraFlags == VT_RESERVED) - return DISP_E_BADVARTYPE; + { + hres = DISP_E_BADVARTYPE; + goto end; + } 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, VT_INT, VT_UINT and VT_UI8. Tested with WinXP */ else if (leftvt == VT_CLSID || rightvt == VT_CLSID || @@ -3729,34 +3798,44 @@ HRESULT WINAPI VarSub(LPVARIANT left, LP leftvt == VT_RECORD || rightvt == VT_RECORD) { if (leftvt == VT_RECORD && rightvt == VT_I8) - return DISP_E_TYPEMISMATCH; + hres = DISP_E_TYPEMISMATCH; else if (leftvt < VT_UI1 && rightvt == VT_RECORD) - return DISP_E_TYPEMISMATCH; + hres = DISP_E_TYPEMISMATCH; else if (leftvt >= VT_UI1 && rightvt == VT_RECORD) - return DISP_E_TYPEMISMATCH; + hres = DISP_E_TYPEMISMATCH; else if (leftvt == VT_RECORD && rightvt <= VT_UI1) - return DISP_E_TYPEMISMATCH; + hres = DISP_E_TYPEMISMATCH; else if (leftvt == VT_RECORD && rightvt > VT_UI1) - return DISP_E_BADVARTYPE; + hres = DISP_E_BADVARTYPE; else - return DISP_E_BADVARTYPE; + hres = DISP_E_BADVARTYPE; + goto end; } /* The following flags/types are invalid for left variant */ else if (!((leftvt <= VT_LPWSTR || leftvt == VT_RECORD || leftvt == VT_CLSID) && leftvt != (VARTYPE)15 /* undefined vt */ && (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 */ else if (!((rightvt <= VT_LPWSTR || rightvt == VT_RECORD || rightvt == VT_CLSID) && rightvt != (VARTYPE)15 /* undefined vt */ && (rightvt < VT_VOID || rightvt > VT_LPWSTR))) - return DISP_E_BADVARTYPE; + { + hres = DISP_E_BADVARTYPE; + goto end; + } else if ((leftvt == VT_NULL && rightvt == VT_DISPATCH) || (leftvt == VT_DISPATCH && rightvt == VT_NULL)) resvt = VT_NULL; else if (leftvt == VT_DISPATCH || rightvt == VT_DISPATCH || leftvt == VT_ERROR || rightvt == VT_ERROR) - return DISP_E_TYPEMISMATCH; + { + hres = DISP_E_TYPEMISMATCH; + goto end; + } else if (leftvt == VT_NULL || rightvt == VT_NULL) resvt = VT_NULL; else if ((leftvt == VT_EMPTY && rightvt == VT_BSTR) || @@ -3793,32 +3872,22 @@ HRESULT WINAPI VarSub(LPVARIANT left, LP else if (leftvt == VT_UI1 || rightvt == VT_UI1) resvt = VT_UI1; else - return DISP_E_TYPEMISMATCH; - - VariantInit(&lv); - VariantInit(&rv); + { + hres = DISP_E_TYPEMISMATCH; + goto end; + }
/* coerce to the result type */ if (leftvt == VT_BSTR && rightvt == VT_DATE) hres = VariantChangeType(&lv, left, 0, VT_R8); else hres = VariantChangeType(&lv, left, 0, resvt); - if (hres != S_OK) - { - VariantClear(&lv); - VariantClear(&rv); - return hres; - } + if (hres != S_OK) goto end; if (leftvt == VT_DATE && rightvt == VT_BSTR) hres = VariantChangeType(&rv, right, 0, VT_R8); else hres = VariantChangeType(&rv, right, 0, resvt); - if (hres != S_OK) - { - VariantClear(&lv); - VariantClear(&rv); - return hres; - } + if (hres != S_OK) goto end;
/* do the math */ V_VT(result) = resvt; @@ -3858,9 +3927,12 @@ HRESULT WINAPI VarSub(LPVARIANT left, LP break; }
+end: VariantClear(&lv); VariantClear(&rv); - + VariantClear(&tempLeft); + VariantClear(&tempRight); + TRACE("returning 0x%8x (variant type %s)\n", hres, debugstr_VT(result)); return hres; }