[v2 PATCH] oleaut32: Improve support for IDispatch in VarCat

Alistair Leslie-Hughes leslie_alistair at hotmail.com
Thu May 25 21:35:45 CDT 2017


We cannot use VariantChangeTypeEx to convert the IDispatch type
since it always returns DISP_E_TYPEMISMATCH when the Invoke fails.

Fixes https://bugs.winehq.org/show_bug.cgi?id=27106

Signed-off-by: Alistair Leslie-Hughes <leslie_alistair at hotmail.com>
---
 dlls/oleaut32/tests/vartest.c | 20 ++++++++++--
 dlls/oleaut32/variant.c       | 71 +++++++++++++++++++++++++++----------------
 2 files changed, 61 insertions(+), 30 deletions(-)

diff --git a/dlls/oleaut32/tests/vartest.c b/dlls/oleaut32/tests/vartest.c
index a271c50..d8a6ebf 100644
--- a/dlls/oleaut32/tests/vartest.c
+++ b/dlls/oleaut32/tests/vartest.c
@@ -6093,7 +6093,7 @@ static void test_VarCat(void)
 
     SET_EXPECT(dispatch_invoke);
     hres = VarCat(&left, &right, &result);
-    todo_wine ok(hres == S_OK, "got 0x%08x\n", hres);
+    ok(hres == S_OK, "got 0x%08x\n", hres);
     ok(V_VT(&result) == VT_BSTR, "got %d\n", V_VT(&result));
     ok(SysStringLen(V_BSTR(&result)) == 0, "got %d\n", SysStringLen(V_BSTR(&result)));
     CHECK_CALLED(dispatch_invoke);
@@ -6108,7 +6108,7 @@ static void test_VarCat(void)
 
     SET_EXPECT(dispatch_invoke);
     hres = VarCat(&left, &right, &result);
-    todo_wine ok(hres == S_OK, "got 0x%08x\n", hres);
+    ok(hres == S_OK, "got 0x%08x\n", hres);
     ok(V_VT(&result) == VT_BSTR, "got %d\n", V_VT(&result));
     ok(SysStringLen(V_BSTR(&result)) == 0, "got %d\n", SysStringLen(V_BSTR(&result)));
     CHECK_CALLED(dispatch_invoke);
@@ -6140,7 +6140,21 @@ static void test_VarCat(void)
 
     SET_EXPECT(dispatch_invoke);
     hres = VarCat(&left, &right, &result);
-    todo_wine ok(hres == E_OUTOFMEMORY, "got 0x%08x\n", hres);
+    ok(hres == E_OUTOFMEMORY, "got 0x%08x\n", hres);
+    CHECK_CALLED(dispatch_invoke);
+
+    VariantClear(&left);
+    VariantClear(&right);
+    VariantClear(&result);
+
+    init_test_dispatch(VT_NULL, &dispatch);
+    dispatch.result = DISP_E_TYPEMISMATCH;
+    V_VT(&right) = VT_DISPATCH;
+    V_DISPATCH(&right) = &dispatch.IDispatch_iface;
+
+    SET_EXPECT(dispatch_invoke);
+    hres = VarCat(&left, &right, &result);
+    ok(hres == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hres);
     CHECK_CALLED(dispatch_invoke);
 
     VariantClear(&left);
diff --git a/dlls/oleaut32/variant.c b/dlls/oleaut32/variant.c
index 2dcded5..e700cf0 100644
--- a/dlls/oleaut32/variant.c
+++ b/dlls/oleaut32/variant.c
@@ -2580,65 +2580,82 @@ HRESULT WINAPI VarCat(LPVARIANT left, LPVARIANT right, LPVARIANT out)
     /* Else proceed with formatting inputs to strings */
     else
     {
+        static DISPPARAMS emptyParams = { NULL, NULL, 0, 0 };
         VARIANT bstrvar_left, bstrvar_right;
+        VARIANT *tmp;
+        VARIANT src;
+
         V_VT(out) = VT_BSTR;
 
         VariantInit(&bstrvar_left);
         VariantInit(&bstrvar_right);
+        VariantInit(&src);
 
         /* Convert left side variant to string */
         if (leftvt != VT_BSTR)
         {
-            /* Fill with empty string for later concat with right side */
-            if (leftvt == VT_NULL)
+            tmp = left;
+
+            if(leftvt == VT_DISPATCH)
             {
-                V_VT(&bstrvar_left) = VT_BSTR;
-                V_BSTR(&bstrvar_left) = SysAllocString(sz_empty);
+                hres = IDispatch_Invoke(V_DISPATCH(left), DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET,
+                                      &emptyParams, &src, NULL, NULL);
+                if(FAILED(hres))
+                    goto failed;
+
+                tmp = &src;
             }
-            else
+
+            hres = VariantChangeTypeEx(&bstrvar_left,tmp,0,VARIANT_ALPHABOOL|VARIANT_LOCALBOOL,VT_BSTR);
+            if (hres == DISP_E_TYPEMISMATCH)
             {
-                hres = VariantChangeTypeEx(&bstrvar_left,left,0,VARIANT_ALPHABOOL|VARIANT_LOCALBOOL,VT_BSTR);
-                if (hres != S_OK) {
-                    VariantClear(&bstrvar_left);
-                    VariantClear(&bstrvar_right);
-                    return hres;
-                }
+                V_VT(&bstrvar_left) = VT_BSTR;
+                V_BSTR(&bstrvar_left) = SysAllocString(sz_empty);
             }
+            else if(hres != S_OK)
+                goto failed;
         }
 
         /* convert right side variant to string */
         if (rightvt != VT_BSTR)
         {
-            /* Fill with empty string for later concat with right side */
-            if (rightvt == VT_NULL)
+            tmp = right;
+
+            if(rightvt == VT_DISPATCH)
             {
-                V_VT(&bstrvar_right) = VT_BSTR;
-                V_BSTR(&bstrvar_right) = SysAllocString(sz_empty);
+                hres = IDispatch_Invoke(V_DISPATCH(right), DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET,
+                                      &emptyParams, &src, NULL, NULL);
+                if(FAILED(hres))
+                    goto failed;
+
+                tmp = &src;
             }
-            else
+
+            hres = VariantChangeTypeEx(&bstrvar_right,tmp,0,VARIANT_ALPHABOOL|VARIANT_LOCALBOOL,VT_BSTR);
+            if (hres == DISP_E_TYPEMISMATCH)
             {
-                hres = VariantChangeTypeEx(&bstrvar_right,right,0,VARIANT_ALPHABOOL|VARIANT_LOCALBOOL,VT_BSTR);
-                if (hres != S_OK) {
-                    VariantClear(&bstrvar_left);
-                    VariantClear(&bstrvar_right);
-                    return hres;
-                }
+                V_VT(&bstrvar_right) = VT_BSTR;
+                V_BSTR(&bstrvar_right) = SysAllocString(sz_empty);
             }
+            else if(hres != S_OK)
+                goto failed;
         }
 
         /* Concat the resulting strings together */
         if (leftvt == VT_BSTR && rightvt == VT_BSTR)
-            VarBstrCat (V_BSTR(left), V_BSTR(right), &V_BSTR(out));
+            hres = VarBstrCat (V_BSTR(left), V_BSTR(right), &V_BSTR(out));
         else if (leftvt != VT_BSTR && rightvt != VT_BSTR)
-            VarBstrCat (V_BSTR(&bstrvar_left), V_BSTR(&bstrvar_right), &V_BSTR(out));
+            hres = VarBstrCat (V_BSTR(&bstrvar_left), V_BSTR(&bstrvar_right), &V_BSTR(out));
         else if (leftvt != VT_BSTR && rightvt == VT_BSTR)
-            VarBstrCat (V_BSTR(&bstrvar_left), V_BSTR(right), &V_BSTR(out));
+            hres = VarBstrCat (V_BSTR(&bstrvar_left), V_BSTR(right), &V_BSTR(out));
         else if (leftvt == VT_BSTR && rightvt != VT_BSTR)
-            VarBstrCat (V_BSTR(left), V_BSTR(&bstrvar_right), &V_BSTR(out));
+            hres = VarBstrCat (V_BSTR(left), V_BSTR(&bstrvar_right), &V_BSTR(out));
 
+failed:
         VariantClear(&bstrvar_left);
         VariantClear(&bstrvar_right);
-        return S_OK;
+        VariantClear(&src);
+        return hres;
     }
 }
 
-- 
1.9.1




More information about the wine-patches mailing list