Benjamin Arai : oleaut32: Implementation for function variant:VarImp.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Sep 25 09:46:34 CDT 2006


Module: wine
Branch: master
Commit: 4cb6c9184b24f9be421306f15f9d1a05515c90a3
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=4cb6c9184b24f9be421306f15f9d1a05515c90a3

Author: Benjamin Arai <me at benjaminarai.com>
Date:   Wed Sep 20 13:17:58 2006 -0700

oleaut32: Implementation for function variant:VarImp.

---

 dlls/oleaut32/oleaut32.spec |    2 
 dlls/oleaut32/variant.c     |  227 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 228 insertions(+), 1 deletions(-)

diff --git a/dlls/oleaut32/oleaut32.spec b/dlls/oleaut32/oleaut32.spec
index ad110c7..abffbd2 100644
--- a/dlls/oleaut32/oleaut32.spec
+++ b/dlls/oleaut32/oleaut32.spec
@@ -148,7 +148,7 @@
 150 stdcall SysAllocStringByteLen(ptr long)
 152 stdcall VarEqv(ptr ptr ptr)
 153 stdcall VarIdiv(ptr ptr ptr)
-154 stub VarImp # stdcall (ptr ptr ptr)
+154 stdcall VarImp(ptr ptr ptr)
 155 stdcall VarMod(ptr ptr ptr)
 156 stdcall VarMul(ptr ptr ptr)
 157 stdcall VarOr(ptr ptr ptr)
diff --git a/dlls/oleaut32/variant.c b/dlls/oleaut32/variant.c
index ae27ad0..c8044a9 100644
--- a/dlls/oleaut32/variant.c
+++ b/dlls/oleaut32/variant.c
@@ -5280,3 +5280,230 @@ HRESULT WINAPI VarPow(LPVARIANT left, LP
 
     return S_OK;
 }
+
+/**********************************************************************
+ *              VarImp [OLEAUT32.154]
+ *
+ * Bitwise implication of two variants.
+ *
+ * PARAMS
+ *  left    [I] First variant
+ *  right   [I] Second variant
+ *  result  [O] Result variant
+ *
+ * RETURNS
+ *  Success: S_OK.
+ *  Failure: An HRESULT error code indicating the error.
+ */
+HRESULT WINAPI VarImp(LPVARIANT left, LPVARIANT right, LPVARIANT result)
+{
+    HRESULT hres = S_OK;
+    VARTYPE resvt = VT_EMPTY;
+    VARTYPE leftvt,rightvt;
+    VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags;
+    VARIANT lv,rv;
+    double d;
+
+    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;
+    ExtraFlags = leftExtraFlags;
+
+    TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
+          debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
+
+    /* Native VarImp always returns a error when using any extra
+     * flags or if the variants are I8 and INT.
+     */
+    if ((leftvt == VT_I8 && rightvt == VT_INT) ||
+        ExtraFlags != 0)
+        return DISP_E_BADVARTYPE;
+
+    /* Determine result type */
+    else if ((leftvt == VT_NULL && rightvt == VT_NULL) ||
+        (leftvt == VT_NULL && rightvt == VT_EMPTY))
+    {
+        V_VT(result) = VT_NULL;
+        return S_OK;
+    }
+    else if (leftvt == VT_I8 || rightvt == VT_I8)
+        resvt = VT_I8;
+    else if (leftvt == VT_I4 || rightvt == VT_I4 ||
+        leftvt == VT_INT || rightvt == VT_INT ||
+        leftvt == VT_UINT || rightvt == VT_UINT ||
+        leftvt == VT_UI4 || rightvt == VT_UI4 ||
+        leftvt == VT_UI8 || rightvt == VT_UI8 ||
+        leftvt == VT_UI2 || rightvt == VT_UI2 ||
+        leftvt == VT_DECIMAL || rightvt == VT_DECIMAL ||
+        leftvt == VT_DATE || rightvt == VT_DATE ||
+        leftvt == VT_CY || rightvt == VT_CY ||
+        leftvt == VT_R8 || rightvt == VT_R8 ||
+        leftvt == VT_R4 || rightvt == VT_R4 ||
+        leftvt == VT_I1 || rightvt == VT_I1)
+        resvt = VT_I4;
+    else if ((leftvt == VT_UI1 && rightvt == VT_UI1) ||
+        (leftvt == VT_UI1 && rightvt == VT_NULL) ||
+        (leftvt == VT_NULL && rightvt == VT_UI1))
+        resvt = VT_UI1;
+    else if (leftvt == VT_EMPTY || rightvt == VT_EMPTY ||
+        leftvt == VT_I2 || rightvt == VT_I2 ||
+        leftvt == VT_UI1 || rightvt == VT_UI1)
+        resvt = VT_I2;
+    else if (leftvt == VT_BOOL || rightvt == VT_BOOL ||
+        leftvt == VT_BSTR || rightvt == VT_BSTR)
+        resvt = VT_BOOL;
+
+    VariantInit(&lv);
+    VariantInit(&rv);
+
+    /* VT_NULL requires special handling for when the opposite
+     * variant is equal to something other than -1.
+     * (NULL Imp 0 = NULL, NULL Imp n = n)
+     */
+    if (leftvt == VT_NULL)
+    {
+        VARIANT_BOOL b;
+        switch(rightvt)
+        {
+        case VT_I1:   if (!V_I1(right)) resvt = VT_NULL; break;
+        case VT_UI1:  if (!V_UI1(right)) resvt = VT_NULL; break;
+        case VT_I2:   if (!V_I2(right)) resvt = VT_NULL; break;
+        case VT_UI2:  if (!V_UI2(right)) resvt = VT_NULL; break;
+        case VT_I4:   if (!V_I4(right)) resvt = VT_NULL; break;
+        case VT_UI4:  if (!V_UI4(right)) resvt = VT_NULL; break;
+        case VT_I8:   if (!V_I8(right)) resvt = VT_NULL; break;
+        case VT_UI8:  if (!V_UI8(right)) resvt = VT_NULL; break;
+        case VT_INT:  if (!V_INT(right)) resvt = VT_NULL; break;
+        case VT_UINT: if (!V_UINT(right)) resvt = VT_NULL; break;
+        case VT_BOOL: if (!V_BOOL(right)) resvt = VT_NULL; break;
+        case VT_R4:   if (!V_R4(right)) resvt = VT_NULL; break;
+        case VT_R8:   if (!V_R8(right)) resvt = VT_NULL; break;
+        case VT_DATE: if (!V_DATE(right)) resvt = VT_NULL; break;
+        case VT_CY:   if (!V_CY(right).int64) resvt = VT_NULL; break;
+        case VT_DECIMAL:
+            if (!(DEC_HI32(&V_DECIMAL(right)) || DEC_LO64(&V_DECIMAL(right))))
+                resvt = VT_NULL;
+            break;
+        case VT_BSTR:
+            hres = VarBoolFromStr(V_BSTR(right),LOCALE_USER_DEFAULT, VAR_LOCALBOOL, &b);
+            if (FAILED(hres)) goto VarImp_Exit;
+            else if (!b)
+                V_VT(result) = VT_NULL;
+            else
+            {
+                V_VT(result) = VT_BOOL;
+                V_BOOL(result) = b;
+            }
+            goto VarImp_Exit;
+        }
+        if (resvt == VT_NULL)
+        {
+            V_VT(result) = resvt;
+            goto VarImp_Exit;
+        }
+        else
+        {
+            hres = VariantChangeType(result,right,0,resvt);
+            goto VarImp_Exit;
+        }
+    }
+
+    /* Special handling is required when NULL is the right variant.
+     * (-1 Imp NULL = NULL, n Imp NULL = n Imp 0)
+     */
+    else if (rightvt == VT_NULL)
+    {
+        VARIANT_BOOL b;
+        switch(leftvt)
+        {
+        case VT_I1:     if (V_I1(left) == -1) resvt = VT_NULL; break;
+        case VT_UI1:    if (V_UI1(left) == 0xff) resvt = VT_NULL; break;
+        case VT_I2:     if (V_I2(left) == -1) resvt = VT_NULL; break;
+        case VT_UI2:    if (V_UI2(left) == 0xffff) resvt = VT_NULL; break;
+        case VT_INT:    if (V_INT(left) == -1) resvt = VT_NULL; break;
+        case VT_UINT:   if (V_UINT(left) == ~0u) resvt = VT_NULL; break;
+        case VT_I4:     if (V_I4(left) == -1) resvt = VT_NULL; break;
+        case VT_UI4:    if (V_UI4(left) == ~0u) resvt = VT_NULL; break;
+        case VT_I8:     if (V_I8(left) == -1) resvt = VT_NULL; break;
+        case VT_UI8:    if (V_UI8(left) == ~(ULONGLONG)0) resvt = VT_NULL; break;
+        case VT_BOOL:   if (V_BOOL(left) == VARIANT_TRUE) resvt = VT_NULL; break;
+        case VT_R4:     if (V_R4(left) == -1.0) resvt = VT_NULL; break;
+        case VT_R8:     if (V_R8(left) == -1.0) resvt = VT_NULL; break;
+        case VT_CY:     if (V_CY(left).int64 == -1) resvt = VT_NULL; break;
+        case VT_DECIMAL:
+            if (DEC_HI32(&V_DECIMAL(left)) == 0xffffffff)
+                resvt = VT_NULL;
+            break;
+        case VT_BSTR:
+            hres = VarBoolFromStr(V_BSTR(left),LOCALE_USER_DEFAULT, VAR_LOCALBOOL, &b);
+            if (FAILED(hres)) goto VarImp_Exit;
+            else if (b == VARIANT_TRUE)
+                resvt = VT_NULL;
+        }
+        if (resvt == VT_NULL)
+        {
+            V_VT(result) = resvt;
+            goto VarImp_Exit;
+        }
+    }
+
+    hres = VariantCopy(&lv, left);
+    if (FAILED(hres)) goto VarImp_Exit;
+
+    if (rightvt == VT_NULL)
+        V_VT(&rv) = resvt;
+    else
+    {
+        hres = VariantCopy(&rv, right);
+        if (FAILED(hres)) goto VarImp_Exit;
+    }
+
+    if (V_VT(&lv) == VT_BSTR &&
+        FAILED(VarR8FromStr(V_BSTR(&lv),LOCALE_USER_DEFAULT, 0, &d)))
+        hres = VariantChangeType(&lv,&lv,VARIANT_LOCALBOOL, VT_BOOL);
+    if (SUCCEEDED(hres) && V_VT(&lv) != resvt)
+        hres = VariantChangeType(&lv,&lv,0,resvt);
+    if (FAILED(hres)) goto VarImp_Exit;
+
+    if (V_VT(&rv) == VT_BSTR &&
+        FAILED(VarR8FromStr(V_BSTR(&rv),LOCALE_USER_DEFAULT, 0, &d)))
+        hres = VariantChangeType(&rv, &rv,VARIANT_LOCALBOOL, VT_BOOL);
+    if (SUCCEEDED(hres) && V_VT(&rv) != resvt)
+        hres = VariantChangeType(&rv, &rv, 0, resvt);
+    if (FAILED(hres)) goto VarImp_Exit;
+
+    /* do the math */
+    V_VT(result) = resvt;
+    switch (resvt)
+    {
+    case VT_I8:
+    V_I8(result) = (~V_I8(&lv)) | V_I8(&rv);
+    break;
+    case VT_I4:
+    V_I4(result) = (~V_I4(&lv)) | V_I4(&rv);
+    break;
+    case VT_I2:
+    V_I2(result) = (~V_I2(&lv)) | V_I2(&rv);
+    break;
+    case VT_UI1:
+    V_UI1(result) = (~V_UI1(&lv)) | V_UI1(&rv);
+    break;
+    case VT_BOOL:
+    V_BOOL(result) = (~V_BOOL(&lv)) | V_BOOL(&rv);
+    break;
+    default:
+    FIXME("Couldn't perform bitwise implication on variant types %d,%d\n",
+        leftvt,rightvt);
+    }
+
+VarImp_Exit:
+
+    VariantClear(&lv);
+    VariantClear(&rv);
+
+    return hres;
+}




More information about the wine-cvs mailing list