Benjamin Arai : oleaut32: Fixes for function variant:VarAnd.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Sep 8 10:24:36 CDT 2006


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

Author: Benjamin Arai <me at benjaminarai.com>
Date:   Thu Sep  7 17:50:03 2006 -0700

oleaut32: Fixes for function variant:VarAnd.

---

 dlls/oleaut32/variant.c |  232 ++++++++++++++++++++++++++++++++++-------------
 1 files changed, 170 insertions(+), 62 deletions(-)

diff --git a/dlls/oleaut32/variant.c b/dlls/oleaut32/variant.c
index 60bb807..b800770 100644
--- a/dlls/oleaut32/variant.c
+++ b/dlls/oleaut32/variant.c
@@ -2872,80 +2872,188 @@ #undef _VARCMP
  */
 HRESULT WINAPI VarAnd(LPVARIANT left, LPVARIANT right, LPVARIANT result)
 {
-    HRESULT rc = E_FAIL;
+    HRESULT hres = S_OK;
+    VARTYPE resvt = VT_EMPTY;
+    VARTYPE leftvt,rightvt;
+    VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags;
+    VARIANT varLeft, varRight;
+
+    VariantInit(&varLeft);
+    VariantInit(&varRight);
 
     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_BOOL &&
-        (V_VT(right)&VT_TYPEMASK) == VT_BOOL) {
+    leftvt = V_VT(left)&VT_TYPEMASK;
+    rightvt = V_VT(right)&VT_TYPEMASK;
+    leftExtraFlags = V_VT(left)&(~VT_TYPEMASK);
+    rightExtraFlags = V_VT(right)&(~VT_TYPEMASK);
 
-        V_VT(result) = VT_BOOL;
-        if (V_BOOL(left) && V_BOOL(right)) {
-            V_BOOL(result) = VARIANT_TRUE;
-        } else {
-            V_BOOL(result) = VARIANT_FALSE;
-        }
-        rc = S_OK;
+    if (leftExtraFlags != rightExtraFlags)
+        return DISP_E_BADVARTYPE;
+    ExtraFlags = leftExtraFlags;
 
-    } else {
-        /* Integers */
-        BOOL         lOk        = TRUE;
-        BOOL         rOk        = TRUE;
-        LONGLONG     lVal = -1;
-        LONGLONG     rVal = -1;
-        LONGLONG     res  = -1;
-        int          resT = 0; /* Testing has shown I2 & I2 == I2, all else
-                                  becomes I4, even unsigned ints (incl. UI2) */
-
-        lOk = TRUE;
-        switch (V_VT(left)&VT_TYPEMASK) {
-        case VT_I1   : lVal = V_I1(left);  resT=VT_I4; break;
-        case VT_I2   : lVal = V_I2(left);  resT=VT_I2; break;
-        case VT_I4   :
-        case VT_INT  : lVal = V_I4(left);  resT=VT_I4; break;
-        case VT_UI1  : lVal = V_UI1(left);  resT=VT_I4; break;
-        case VT_UI2  : lVal = V_UI2(left); resT=VT_I4; break;
-        case VT_UI4  :
-        case VT_UINT : lVal = V_UI4(left); resT=VT_I4; break;
-        case VT_BOOL : rVal = V_BOOL(left); resT=VT_I4; break;
-        default: lOk = FALSE;
-        }
+    /* Native VarAnd always returns a error when using any extra
+     * flags or if the variant combination is I8 and INT.
+     */
+    if ((leftvt == VT_I8 && rightvt == VT_INT) ||
+        (leftvt == VT_INT && rightvt == VT_I8) ||
+        ExtraFlags != 0)
+        return DISP_E_BADVARTYPE;
 
-        rOk = TRUE;
-        switch (V_VT(right)&VT_TYPEMASK) {
-        case VT_I1   : rVal = V_I1(right);  resT=VT_I4; break;
-        case VT_I2   : rVal = V_I2(right);  resT=max(VT_I2, resT); break;
-        case VT_I4   :
-        case VT_INT  : rVal = V_I4(right);  resT=VT_I4; break;
-        case VT_UI1  : rVal = V_UI1(right);  resT=VT_I4; break;
-        case VT_UI2  : rVal = V_UI2(right); resT=VT_I4; break;
-        case VT_UI4  :
-        case VT_UINT : rVal = V_UI4(right); resT=VT_I4; break;
-        case VT_BOOL : rVal = V_BOOL(right); resT=VT_I4; break;
-        default: rOk = FALSE;
-        }
+    /* Determine return type */
+    else if (leftvt == VT_I8 || rightvt == VT_I8)
+        resvt = VT_I8;
+    else if (leftvt == VT_I4 || rightvt == VT_I4 ||
+        leftvt == VT_UINT || rightvt == VT_UINT ||
+        leftvt == VT_INT || rightvt == VT_INT ||
+        leftvt == VT_UINT || rightvt == VT_UINT ||
+        leftvt == VT_R4 || rightvt == VT_R4 ||
+        leftvt == VT_R8 || rightvt == VT_R8 ||
+        leftvt == VT_CY || rightvt == VT_CY ||
+        leftvt == VT_DATE || rightvt == VT_DATE ||
+        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_DECIMAL || rightvt == VT_DECIMAL)
+        resvt = VT_I4;
+    else if (leftvt == VT_UI1 || rightvt == VT_UI1 ||
+        leftvt == VT_I2 || rightvt == VT_I2 ||
+        leftvt == VT_EMPTY || rightvt == VT_EMPTY)
+        if ((leftvt == VT_NULL && rightvt == VT_UI1) ||
+            (leftvt == VT_UI1 && rightvt == VT_NULL) ||
+            (leftvt == VT_UI1 && rightvt == VT_UI1))
+            resvt = VT_UI1;
+        else
+            resvt = VT_I2;
+    else if (leftvt == VT_BOOL || rightvt == VT_BOOL ||
+        (leftvt == VT_BSTR && rightvt == VT_BSTR))
+        resvt = VT_BOOL;
+    else if (leftvt == VT_NULL || rightvt == VT_NULL ||
+        leftvt == VT_BSTR || rightvt == VT_BSTR)
+        resvt = VT_NULL;
+    else
+        return DISP_E_BADVARTYPE;
 
-        if (lOk && rOk) {
-            res = (lVal & rVal);
-            V_VT(result) = resT;
-            switch (resT) {
-            case VT_I2   : V_I2(result)  = res; break;
-            case VT_I4   : V_I4(result)  = res; break;
-            default:
-                FIXME("Unexpected result variant type %x\n", resT);
-                V_I4(result)  = res;
+    if (leftvt == VT_NULL || rightvt == VT_NULL)
+    {
+        /*
+         * Special cases for when left variant is VT_NULL
+         * (NULL & 0 = NULL, NULL & value = value)
+         */
+        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_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))
+                    return hres;
+                else if (b)
+                    V_VT(result) = VT_NULL;
+                else
+                {
+                    V_VT(result) = VT_BOOL;
+                    V_BOOL(result) = b;
+                }
+                goto VarAnd_Exit;
             }
-            rc = S_OK;
-
-        } else {
-            FIXME("VarAnd stub\n");
         }
+        V_VT(result) = resvt;
+        goto VarAnd_Exit;
     }
 
-    TRACE("returning 0x%8lx (%s%s),%ld\n", rc, debugstr_VT(result),
-          debugstr_VF(result), V_VT(result) == VT_I4 ? V_I4(result) : V_I2(result));
-    return rc;
+    hres = VariantCopy(&varLeft, left);
+    if (FAILED(hres)) goto VarAnd_Exit;
+
+    hres = VariantCopy(&varRight, right);
+    if (FAILED(hres)) goto VarAnd_Exit;
+
+    if (resvt == VT_I4 && V_VT(&varLeft) == VT_UI4)
+        V_VT(&varLeft) = VT_I4; /* Don't overflow */
+    else
+    {
+        double d;
+
+        if (V_VT(&varLeft) == VT_BSTR &&
+            FAILED(VarR8FromStr(V_BSTR(&varLeft),
+            LOCALE_USER_DEFAULT, 0, &d)))
+            hres = VariantChangeType(&varLeft,&varLeft,
+            VARIANT_LOCALBOOL, VT_BOOL);
+            if (SUCCEEDED(hres) && V_VT(&varLeft) != resvt)
+                hres = VariantChangeType(&varLeft,&varLeft,0,resvt);
+            if (FAILED(hres)) goto VarAnd_Exit;
+    }
+
+    if (resvt == VT_I4 && V_VT(&varRight) == VT_UI4)
+        V_VT(&varRight) = VT_I4; /* Don't overflow */
+    else
+    {
+        double d;
+
+        if (V_VT(&varRight) == VT_BSTR &&
+            FAILED(VarR8FromStr(V_BSTR(&varRight),
+            LOCALE_USER_DEFAULT, 0, &d)))
+            hres = VariantChangeType(&varRight, &varRight,
+                VARIANT_LOCALBOOL, VT_BOOL);
+        if (SUCCEEDED(hres) && V_VT(&varRight) != resvt)
+            hres = VariantChangeType(&varRight, &varRight, 0, resvt);
+        if (FAILED(hres)) goto VarAnd_Exit;
+    }
+
+    V_VT(result) = resvt;
+    switch(resvt)
+    {
+    case VT_I8:
+        V_I8(result) = V_I8(&varLeft) & V_I8(&varRight);
+        break;
+    case VT_I4:
+        V_I4(result) = V_I4(&varLeft) & V_I4(&varRight);
+        break;
+    case VT_I2:
+        V_I2(result) = V_I2(&varLeft) & V_I2(&varRight);
+        break;
+    case VT_UI1:
+        V_UI1(result) = V_UI1(&varLeft) & V_UI1(&varRight);
+        break;
+    case VT_BOOL:
+        V_BOOL(result) = V_BOOL(&varLeft) & V_BOOL(&varRight);
+        break;
+    default:
+        FIXME("Couldn't bitwise AND variant types %d,%d\n",
+            leftvt,rightvt);
+    }
+
+VarAnd_Exit:
+    VariantClear(&varLeft);
+    VariantClear(&varRight);
+
+    return hres;
 }
 
 /**********************************************************************




More information about the wine-cvs mailing list