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

Alistair Leslie-Hughes leslie_alistair at hotmail.com
Fri May 26 00:13:46 CDT 2017


v3: Use worker function to get the value from Dispatch.

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       | 100 ++++++++++++++++++++++++------------------
 2 files changed, 74 insertions(+), 46 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..56ee83f 100644
--- a/dlls/oleaut32/variant.c
+++ b/dlls/oleaut32/variant.c
@@ -515,6 +515,22 @@ static inline HRESULT VARIANT_CoerceArray(VARIANTARG* pd, VARIANTARG* ps, VARTYP
   return DISP_E_TYPEMISMATCH;
 }
 
+static HRESULT VARIANT_FetchDispatchValue(LPVARIANT pvDispatch, LPVARIANT pValue)
+{
+    HRESULT hres;
+    static DISPPARAMS emptyParams = { NULL, NULL, 0, 0 };
+
+    if ((V_VT(pvDispatch) & VT_TYPEMASK) == VT_DISPATCH) {
+        if (NULL == V_DISPATCH(pvDispatch)) return DISP_E_TYPEMISMATCH;
+        hres = IDispatch_Invoke(V_DISPATCH(pvDispatch), DISPID_VALUE, &IID_NULL,
+            LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &emptyParams, pValue,
+            NULL, NULL);
+    } else {
+        hres = DISP_E_TYPEMISMATCH;
+    }
+    return hres;
+}
+
 /******************************************************************************
  * Check if a variants type is valid.
  */
@@ -2581,64 +2597,78 @@ HRESULT WINAPI VarCat(LPVARIANT left, LPVARIANT right, LPVARIANT out)
     else
     {
         VARIANT bstrvar_left, bstrvar_right;
+        VARIANT *tmp;
+        VARIANT fetched;
+
         V_VT(out) = VT_BSTR;
 
         VariantInit(&bstrvar_left);
         VariantInit(&bstrvar_right);
+        VariantInit(&fetched);
 
         /* 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 = VARIANT_FetchDispatchValue(left, &fetched);
+                if(FAILED(hres))
+                    goto failed;
+
+                tmp = &fetched;
             }
-            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 = VARIANT_FetchDispatchValue(right, &fetched);
+                if(FAILED(hres))
+                    goto failed;
+
+                tmp = &fetched;
             }
-            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(&fetched);
+        return hres;
     }
 }
 
@@ -2865,22 +2895,6 @@ HRESULT WINAPI VarCmp(LPVARIANT left, LPVARIANT right, LCID lcid, DWORD flags)
 #undef _VARCMP
 }
 
-static HRESULT VARIANT_FetchDispatchValue(LPVARIANT pvDispatch, LPVARIANT pValue)
-{
-    HRESULT hres;
-    static DISPPARAMS emptyParams = { NULL, NULL, 0, 0 };
-
-    if ((V_VT(pvDispatch) & VT_TYPEMASK) == VT_DISPATCH) {
-        if (NULL == V_DISPATCH(pvDispatch)) return DISP_E_TYPEMISMATCH;
-        hres = IDispatch_Invoke(V_DISPATCH(pvDispatch), DISPID_VALUE, &IID_NULL,
-            LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &emptyParams, pValue,
-            NULL, NULL);
-    } else {
-        hres = DISP_E_TYPEMISMATCH;
-    }
-    return hres;
-}
-
 /**********************************************************************
  *              VarAnd [OLEAUT32.142]
  *
-- 
1.9.1




More information about the wine-patches mailing list