From 071e950344e7eee90e44aba54268b57fea8be0f9 Mon Sep 17 00:00:00 2001 From: Jon Griffiths Date: Wed, 17 Mar 2004 20:49:22 +0000 Subject: [PATCH] Implement VarEqv. --- dlls/oleaut32/oleaut32.spec | 2 +- dlls/oleaut32/variant.c | 198 +++++++++++++++++++++++++++++++++++- 2 files changed, 198 insertions(+), 2 deletions(-) diff --git a/dlls/oleaut32/oleaut32.spec b/dlls/oleaut32/oleaut32.spec index 6b6c39967ad..4516cfc3242 100644 --- a/dlls/oleaut32/oleaut32.spec +++ b/dlls/oleaut32/oleaut32.spec @@ -147,7 +147,7 @@ 148 stdcall SafeArrayPtrOfIndex(ptr ptr ptr) 149 stdcall SysStringByteLen(ptr) 150 stdcall SysAllocStringByteLen(ptr long) -152 stub VarEqv # stdcall (ptr ptr ptr) +152 stdcall VarEqv(ptr ptr ptr) 153 stub VarIdiv # stdcall (ptr ptr ptr) 154 stub VarImp # stdcall (ptr ptr ptr) 155 stdcall VarMod(ptr ptr ptr) diff --git a/dlls/oleaut32/variant.c b/dlls/oleaut32/variant.c index 8a2e43cccc4..76adf26df9a 100644 --- a/dlls/oleaut32/variant.c +++ b/dlls/oleaut32/variant.c @@ -3118,7 +3118,7 @@ HRESULT WINAPI VarOr(LPVARIANT left, LPVARIANT right, LPVARIANT result) rc = S_OK; } else { - FIXME("unimplemented part, V_VT(left) == 0x%X, V_VT(right) == 0x%X\n", + FIXME("unimplemented part, V_VT(left) == 0x%X, V_VT(right) == 0x%X\n", V_VT(left) & VT_TYPEMASK, V_VT(right) & VT_TYPEMASK); } } @@ -3369,6 +3369,202 @@ HRESULT WINAPI VarInt(LPVARIANT pVarIn, LPVARIANT pVarOut) return hRet; } +/********************************************************************** + * VarEqv [OLEAUT32.172] + * + * Determine if two variants contain the same value. + * + * PARAMS + * pVarLeft [I] First variant to compare + * pVarRight [I] Variant to compare to pVarLeft + * pVarOut [O] Destination for comparason result + * + * RETURNS + * Success: S_OK. pVarOut contains the result of the comparason (VARIANT_TRUE + * if equivalent or VARIANT_FALSE or -2 otherwise, with type from the + * table below). + * Failure: An HRESULT error code indicating the error. + * + * NOTES + * - Equvalence is defined as containing the same value if one variant is + * converted to the other. + * - Any value in pVarLeft or pVarRight that will not fit in a VT_I4 will + * cause overflow (This is compatable with the native implementation). + * - The result stored in pVarOut depends on the types of pVarLeft/pVarRight + * according to the following table: + *| Type 1 Type 2 Result Type + *| ------ ------ ----------- + *| VT_NULL All Others VT_NULL + *| VT_BOOL VT_BOOL VT_BOOL + *| VT_EMPTY VT_I2 + *| VT_UI1 VT_I2 + *| VT_I2 VT_I2 + *| VT_EMPTY VT_EMPTY VT_I2 + *| VT_UI1 VT_I2 + *| VT_BOOL VT_I2 + *| VT_I2 VT_I2 + *| VT_UI1 VT_UI1 VT_UI1 + *| VT_EMPTY VT_I2 + *| VT_BOOL VT_I2 + *| VT_I2 VT_I2 + *| VT_I2 VT_I2 VT_I2 + *| VT_EMPTY VT_I2 + *| VT_BOOL VT_I2 + *| All Other Combinations VT_UI4 + */ +HRESULT WINAPI VarEqv(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut) +{ + VARTYPE vt = VT_UI4; + VARIANT varLeft, varRight; + HRESULT hRet; + + TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", pVarLeft, debugstr_VT(pVarLeft), + debugstr_VF(pVarLeft), pVarRight, debugstr_VT(pVarRight), + debugstr_VF(pVarRight), pVarOut); + + 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 || + V_VT(pVarLeft) == VT_RECORD || V_VT(pVarRight) == VT_RECORD) + return DISP_E_BADVARTYPE; + + if (V_VT(pVarLeft) == VT_NULL || V_VT(pVarRight) == VT_NULL) + { + if (V_VT(pVarLeft) == VT_NULL) + pVarLeft = pVarRight; /* point to the non-NULL var */ + + switch (V_VT(pVarLeft)) + { + case VT_BSTR: + if (!V_BSTR(pVarLeft)) + return DISP_E_BADVARTYPE; + /* Fall Through ... */ + case VT_NULL: case VT_EMPTY: case VT_DATE: case VT_CY: + case VT_DECIMAL: case VT_R4: case VT_R8: case VT_BOOL: + case VT_I1: case VT_UI1: case VT_I2: case VT_UI2: + case VT_I4: case VT_UI4: case VT_I8: case VT_UI8: + case VT_INT: case VT_UINT: + V_VT(pVarOut) = VT_NULL; + return S_OK; + default: + return DISP_E_BADVARTYPE; + } + } + + if (V_VT(pVarLeft) == VT_EMPTY || V_VT(pVarRight) == VT_EMPTY) + { + if (V_VT(pVarLeft) == VT_EMPTY) + pVarLeft = pVarRight; /* point to the non-EMPTY var */ + + switch (V_VT(pVarLeft)) + { + case VT_EMPTY: case VT_UI1: case VT_BOOL: case VT_I2: + V_VT(pVarOut) = VT_I2; + V_I2(pVarOut) = VARIANT_FALSE; + return S_OK; + + case VT_BSTR: + if (!V_BSTR(pVarLeft)) + return DISP_E_BADVARTYPE; + /* Fall Through ... */ + case VT_DATE: case VT_CY: case VT_DECIMAL: case VT_R4: case VT_R8: + case VT_I1: case VT_UI2: case VT_I4: case VT_UI4: + case VT_INT: case VT_UINT: case VT_I8: case VT_UI8: + V_VT(pVarOut) = VT_I4; + V_I4(pVarOut) = VARIANT_FALSE; + return S_OK; + default: + return DISP_E_BADVARTYPE; + } + } + + if (V_VT(pVarLeft) == VT_BOOL && V_VT(pVarRight) == VT_BOOL) + { + V_VT(pVarOut) = VT_BOOL; + if (V_BOOL(pVarLeft) == V_BOOL(pVarRight)) + V_BOOL(pVarOut) = VARIANT_TRUE; + else if (V_BOOL(pVarLeft) == VARIANT_TRUE && V_BOOL(pVarRight) == VARIANT_FALSE) + { + V_BOOL(pVarOut) = VARIANT_FALSE; + } + else if (V_BOOL(pVarLeft) == VARIANT_FALSE && V_BOOL(pVarRight) == VARIANT_TRUE) + { + V_BOOL(pVarOut) = VARIANT_FALSE; + } + else + V_BOOL(pVarOut) = -2; /* Go Figure; this matches native */ + + return S_OK; + } + + if (V_VT(pVarLeft) == VT_UI1 && V_VT(pVarRight) == VT_UI1) + { + V_VT(pVarOut) = VT_UI1; + V_UI1(pVarOut) = V_UI1(pVarLeft) == V_UI1(pVarRight) ? 0xff : 0xfe; + return S_OK; + } + + if ((V_VT(pVarLeft) == VT_BOOL || V_VT(pVarLeft) == VT_UI1 || + V_VT(pVarLeft) == VT_I2) && + (V_VT(pVarRight) == VT_BOOL || V_VT(pVarRight) == VT_UI1 || + V_VT(pVarRight) == VT_I2)) + vt = VT_I2; + + V_VT(&varLeft) = V_VT(&varRight) = VT_EMPTY; + hRet = VariantCopy(&varLeft, pVarLeft); + if (FAILED(hRet)) + goto VarEqv_Exit; + + hRet = VariantCopy(&varRight, pVarRight); + if (FAILED(hRet)) + goto VarEqv_Exit; + + hRet = VariantChangeTypeEx(&varLeft, pVarLeft, LOCALE_USER_DEFAULT, 0, vt); + if (FAILED(hRet)) + goto VarEqv_Exit; + + hRet = VariantChangeTypeEx(&varRight, pVarRight, LOCALE_USER_DEFAULT, 0, vt); + if (FAILED(hRet)) + goto VarEqv_Exit; + + V_VT(pVarOut) = vt; + if (vt == VT_UI4) + { + if (V_UI4(&varLeft) == V_UI4(&varRight)) + V_UI4(pVarOut) = VARIANT_TRUE; + else if (V_UI4(&varLeft) == VARIANT_TRUE && V_UI4(&varRight) == VARIANT_FALSE) + { + V_UI4(pVarOut) = VARIANT_FALSE; + } + else if (V_UI4(&varLeft) == VARIANT_FALSE && V_UI4(&varRight) == VARIANT_TRUE) + { + V_UI4(pVarOut) = VARIANT_FALSE; + } + else + V_UI4(pVarOut) = -2; + } + else + { + if (V_I2(&varLeft) == V_I2(&varRight)) + V_I2(pVarOut) = VARIANT_TRUE; + else if (V_I2(&varLeft) == VARIANT_TRUE && V_I2(&varRight) == VARIANT_FALSE) + { + V_I2(pVarOut) = VARIANT_FALSE; + } + else if (V_I2(&varLeft) == VARIANT_FALSE && V_I2(&varRight) == VARIANT_TRUE) + { + V_I2(pVarOut) = VARIANT_FALSE; + } + else + V_I2(pVarOut) = -2; + } + +VarEqv_Exit: + VariantClear(&varLeft); + VariantClear(&varRight); + return hRet; +} + /********************************************************************** * VarNeg [OLEAUT32.173] *