diff --git a/dlls/oleaut32/variant.c b/dlls/oleaut32/variant.c index ae3043ad8b2..46d31e9b1ea 100644 --- a/dlls/oleaut32/variant.c +++ b/dlls/oleaut32/variant.c @@ -3404,65 +3404,186 @@ HRESULT WINAPI VarDiv(LPVARIANT left, LPVARIANT right, LPVARIANT result) */ HRESULT WINAPI VarSub(LPVARIANT left, LPVARIANT right, LPVARIANT result) { - HRESULT rc = E_FAIL; - VARTYPE lvt,rvt,resvt; + HRESULT hres = S_OK; + VARTYPE resvt = VT_EMPTY; + VARTYPE leftvt,rightvt; + VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags; VARIANT lv,rv; - BOOL found; TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left), debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result); - VariantInit(&lv);VariantInit(&rv); - lvt = V_VT(left)&VT_TYPEMASK; - rvt = V_VT(right)&VT_TYPEMASK; - found = FALSE;resvt = VT_VOID; - if (((1<= VT_ARRAY) + return DISP_E_TYPEMISMATCH; + /* 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 || + leftvt == VT_VARIANT || rightvt == VT_VARIANT || + leftvt == VT_I1 || rightvt == VT_I1 || + leftvt == VT_UI2 || rightvt == VT_UI2 || + leftvt == VT_UI4 || rightvt == VT_UI4 || + leftvt == VT_UI8 || rightvt == VT_UI8 || + leftvt == VT_INT || rightvt == VT_INT || + leftvt == VT_UINT || rightvt == VT_UINT || + leftvt == VT_UNKNOWN || rightvt == VT_UNKNOWN || + leftvt == VT_RECORD || rightvt == VT_RECORD) + { + if (leftvt == VT_RECORD && rightvt == VT_I8) + return DISP_E_TYPEMISMATCH; + else if (leftvt < VT_UI1 && rightvt == VT_RECORD) + return DISP_E_TYPEMISMATCH; + else if (leftvt >= VT_UI1 && rightvt == VT_RECORD) + return DISP_E_TYPEMISMATCH; + else if (leftvt == VT_RECORD && rightvt <= VT_UI1) + return DISP_E_TYPEMISMATCH; + else if (leftvt == VT_RECORD && rightvt > VT_UI1) + return DISP_E_BADVARTYPE; + else + return DISP_E_BADVARTYPE; } - if (!found && (((1< VT_LPWSTR))) + return DISP_E_BADVARTYPE; + /* 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; + 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; + else if (leftvt == VT_NULL || rightvt == VT_NULL) + resvt = VT_NULL; + else if ((leftvt == VT_EMPTY && rightvt == VT_BSTR) || + (leftvt == VT_DATE && rightvt == VT_DATE) || + (leftvt == VT_BSTR && rightvt == VT_EMPTY) || + (leftvt == VT_BSTR && rightvt == VT_BSTR)) + resvt = VT_R8; + else if (leftvt == VT_DECIMAL || rightvt == VT_DECIMAL) + resvt = VT_DECIMAL; + else if (leftvt == VT_DATE || rightvt == VT_DATE) + resvt = VT_DATE; + else if (leftvt == VT_CY || rightvt == VT_CY) + resvt = VT_CY; + else if (leftvt == VT_R8 || rightvt == VT_R8) + resvt = VT_R8; + else if (leftvt == VT_BSTR || rightvt == VT_BSTR) + resvt = VT_R8; + else if (leftvt == VT_R4 || rightvt == VT_R4) + { + if (leftvt == VT_I4 || rightvt == VT_I4 || + leftvt == VT_I8 || rightvt == VT_I8) + resvt = VT_R8; + else + resvt = VT_R4; } - if (!found && (((1<