From d197d40295067e0737de5ed54632d43d197a4ef6 Mon Sep 17 00:00:00 2001
From: Jason Edmeades <us@the-edmeades.demon.co.uk>
Date: Tue, 10 Dec 2002 19:06:28 +0000
Subject: [PATCH] VarAdd support for integers.

---
 dlls/oleaut32/oleaut32.spec |  2 +-
 dlls/oleaut32/variant.c     | 84 +++++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/dlls/oleaut32/oleaut32.spec b/dlls/oleaut32/oleaut32.spec
index e6bd1b3d467..e372ceee73a 100644
--- a/dlls/oleaut32/oleaut32.spec
+++ b/dlls/oleaut32/oleaut32.spec
@@ -138,7 +138,7 @@
 138 stdcall VarUI1FromBool(long ptr) VarUI1FromBool
 139 stdcall VarFormatFromTokens (ptr ptr ptr long ptr long) VarFormatFromTokens
 140 stdcall VarTokenizeFormatString (ptr ptr long long long long ptr) VarTokenizeFormatString
-141 stub VarAdd # stdcall (ptr ptr ptr)
+141 stdcall VarAdd(ptr ptr ptr) VarAdd
 142 stdcall VarAnd(ptr ptr ptr) VarAnd
 143 stub VarDiv # stdcall (ptr ptr ptr)
 144 stub OACreateTypeLib2
diff --git a/dlls/oleaut32/variant.c b/dlls/oleaut32/variant.c
index 8c8d75ffead..351872d944f 100644
--- a/dlls/oleaut32/variant.c
+++ b/dlls/oleaut32/variant.c
@@ -5153,6 +5153,90 @@ HRESULT WINAPI VarAnd(LPVARIANT left, LPVARIANT right, LPVARIANT result)
     return rc;
 }
 
+/**********************************************************************
+ *              VarAdd [OLEAUT32.141]
+ * FIXME: From MSDN: If ... Then 
+ * Both expressions are of the string type Concatenated. 
+ * One expression is a string type and the other a character Addition. 
+ * One expression is numeric and the other is a string Addition. 
+ * Both expressions are numeric Addition. 
+ * Either expression is NULL NULL is returned. 
+ * Both expressions are empty  Integer subtype is returned. 
+ *
+ */
+HRESULT WINAPI VarAdd(LPVARIANT left, LPVARIANT right, LPVARIANT result)
+{
+    HRESULT rc = E_FAIL;
+
+    TRACE("Left Var:\n");
+    dump_Variant(left);
+    TRACE("Right Var:\n");
+    dump_Variant(right);
+
+    /* Handle strings as concat */
+    if ((V_VT(left)&VT_TYPEMASK) == VT_BSTR &&
+        (V_VT(right)&VT_TYPEMASK) == VT_BSTR) {
+        V_VT(result) = VT_BSTR;
+        VarBstrCat(V_BSTR(left), V_BSTR(right), &V_BSTR(result));
+    } 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                                */
+
+        lOk = TRUE;
+        switch (V_VT(left)&VT_TYPEMASK) {
+        case VT_I1   : lVal = V_UNION(left,cVal);  resT=VT_I4; break;
+        case VT_I2   : lVal = V_UNION(left,iVal);  resT=VT_I2; break;
+        case VT_I4   : lVal = V_UNION(left,lVal);  resT=VT_I4; break;
+        case VT_INT  : lVal = V_UNION(left,lVal);  resT=VT_I4; break;
+        case VT_UI1  : lVal = V_UNION(left,bVal);  resT=VT_I4; break;
+        case VT_UI2  : lVal = V_UNION(left,uiVal); resT=VT_I4; break;
+        case VT_UI4  : lVal = V_UNION(left,ulVal); resT=VT_I4; break;
+        case VT_UINT : lVal = V_UNION(left,ulVal); resT=VT_I4; break;
+        default: lOk = FALSE;
+        }
+
+        rOk = TRUE;
+        switch (V_VT(right)&VT_TYPEMASK) {
+        case VT_I1   : rVal = V_UNION(right,cVal);  resT=VT_I4; break;
+        case VT_I2   : rVal = V_UNION(right,iVal);  resT=max(VT_I2, resT); break;
+        case VT_I4   : rVal = V_UNION(right,lVal);  resT=VT_I4; break;
+        case VT_INT  : rVal = V_UNION(right,lVal);  resT=VT_I4; break;
+        case VT_UI1  : rVal = V_UNION(right,bVal);  resT=VT_I4; break;
+        case VT_UI2  : rVal = V_UNION(right,uiVal); resT=VT_I4; break;
+        case VT_UI4  : rVal = V_UNION(right,ulVal); resT=VT_I4; break;
+        case VT_UINT : rVal = V_UNION(right,ulVal); resT=VT_I4; break;
+        default: rOk = FALSE;
+        }
+
+        if (lOk && rOk) {
+            res = (lVal + rVal);
+            V_VT(result) = resT;
+            switch (resT) {
+            case VT_I2   : V_UNION(result,iVal)  = res; break;
+            case VT_I4   : V_UNION(result,lVal)  = res; break;
+            default:
+                FIXME("Unexpected result variant type %x\n", resT);
+                V_UNION(result,lVal)  = res;
+            }
+            rc = S_OK;
+
+        } else {
+            FIXME("VarAdd stub\n");
+        }
+    }
+
+    TRACE("rc=%d, Result:\n", (int) rc);
+    dump_Variant(result);
+    return rc;
+}
+
 /**********************************************************************
  *              VarNot [OLEAUT32.174]
  *
-- 
GitLab