[PATCH] oleaut32: Fix calling function with instance and VARIANT return type.

Dmitry Timoshkov dmitry at baikal.ru
Tue Nov 13 07:15:30 CST 2018


Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
---
 dlls/oleaut32/tests/typelib.c | 59 +++++++++++++++++++++++++++++++++--
 dlls/oleaut32/typelib.c       | 16 ++++++++--
 2 files changed, 71 insertions(+), 4 deletions(-)

diff --git a/dlls/oleaut32/tests/typelib.c b/dlls/oleaut32/tests/typelib.c
index 03031743df..90f0cb256e 100644
--- a/dlls/oleaut32/tests/typelib.c
+++ b/dlls/oleaut32/tests/typelib.c
@@ -1199,11 +1199,41 @@ static HRESULT WINAPI ret_false_func(void)
     return S_FALSE;
 }
 
-static const void *vtable[] = { NULL, NULL, NULL, inst_func };
+static const WCHAR testW[] = { 'T','e','s','t',0 };
+
+static void WINAPI variant_func2(VARIANT *ret, VARIANT v1, VARIANT v2)
+{
+    ok(V_VT(&v1) == VT_I4, "unexpected %d\n", V_VT(&v1));
+    ok(V_I4(&v1) == 2, "unexpected %d\n", V_I4(&v1));
+    ok(V_VT(&v2) == VT_BSTR, "unexpected %d\n", V_VT(&v2));
+    ok(lstrcmpW(V_BSTR(&v2), testW) == 0, "unexpected %s\n", wine_dbgstr_w(V_BSTR(&v2)));
+
+    V_VT(ret) = VT_UI4;
+    V_I4(ret) = 4321;
+}
+
+static void WINAPI inst_func2(void *inst, VARIANT *ret, VARIANT v1, VARIANT v2)
+{
+    ok( (*(void ***)inst)[3] == inst_func2, "wrong ptr %p\n", inst );
+
+    ok(V_VT(ret) == VT_I4 || broken(V_VT(ret) == VT_VARIANT) /* win64 */, "unexpected %d\n", V_VT(ret));
+    ok(V_I4(ret) == 1234, "unexpected %d\n", V_I4(ret));
+
+    ok(V_VT(&v1) == VT_I4, "unexpected %d\n", V_VT(&v1));
+    ok(V_I4(&v1) == 2, "unexpected %d\n", V_I4(&v1));
+    ok(V_VT(&v2) == VT_BSTR, "unexpected %d\n", V_VT(&v2));
+    ok(lstrcmpW(V_BSTR(&v2), testW) == 0, "unexpected %s\n", wine_dbgstr_w(V_BSTR(&v2)));
+
+    V_VT(ret) = VT_UI4;
+    V_I4(ret) = 4321;
+}
+
+static void *vtable[] = { NULL, NULL, NULL, inst_func };
+static void *vtable2[] = { NULL, NULL, NULL, inst_func2 };
 
 static void test_DispCallFunc(void)
 {
-    const void **inst = vtable;
+    void **inst;
     HRESULT res;
     VARIANT result, args[5];
     VARIANTARG *pargs[5];
@@ -1212,6 +1242,30 @@ static void test_DispCallFunc(void)
 
     for (i = 0; i < 5; i++) pargs[i] = &args[i];
 
+    memset( args, 0x55, sizeof(args) );
+
+    types[0] = VT_VARIANT;
+    V_VT(&args[0]) = VT_I4;
+    V_I4(&args[0]) = 2;
+    types[1] = VT_VARIANT;
+    V_VT(&args[1]) = VT_BSTR;
+    V_BSTR(&args[1]) = SysAllocString(testW);
+    memset( &result, 0xcc, sizeof(result) );
+    res = DispCallFunc(NULL, (ULONG_PTR)variant_func2, CC_STDCALL, VT_VARIANT, 2, types, pargs, &result);
+    ok(res == S_OK, "DispCallFunc error %#x\n", res);
+    ok(V_VT(&result) == VT_UI4, "wrong result type %d\n", V_VT(&result));
+    ok(V_UI4(&result) == 4321, "wrong result %u\n", V_UI4(&result));
+
+    V_VT(&result) = VT_I4;
+    V_UI4(&result) = 1234;
+    inst = vtable2;
+    res = DispCallFunc(&inst, 3 * sizeof(void *), CC_STDCALL, VT_VARIANT, 2, types, pargs, &result);
+    ok(res == S_OK, "DispCallFunc error %#x\n", res);
+    ok(V_VT(&result) == VT_UI4, "wrong result type %d\n", V_VT(&result));
+    ok(V_UI4(&result) == 4321, "wrong result %u\n", V_UI4(&result));
+
+    VariantClear(&args[1]);
+
     memset( args, 0x55, sizeof(args) );
     types[0] = VT_UI4;
     V_UI4(&args[0]) = 1;
@@ -1310,6 +1364,7 @@ static void test_DispCallFunc(void)
     types[0] = VT_I4;
     V_I4(&args[0]) = 3;
     memset( &result, 0xcc, sizeof(result) );
+    inst = vtable;
     res = DispCallFunc( &inst, 3 * sizeof(void*), CC_STDCALL, VT_I4, 1, types, pargs, &result );
     ok( res == S_OK, "DispCallFunc failed %x\n", res );
     ok( V_VT(&result) == VT_I4, "wrong result type %d\n", V_VT(&result) );
diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c
index 4555802a61..52d335fe47 100644
--- a/dlls/oleaut32/typelib.c
+++ b/dlls/oleaut32/typelib.c
@@ -6720,7 +6720,13 @@ DispCallFunc(
         break;
     case VT_DECIMAL:
     case VT_VARIANT:
-        args[0] = (DWORD)pvargResult;  /* arg 0 is a pointer to the result */
+        if (pvInstance)
+        {
+            args[0] = (DWORD)pvInstance;  /* arg 0 is a pointer to the instance */
+            args[1] = (DWORD)pvargResult; /* arg 1 is a pointer to the result */
+        }
+        else
+            args[0] = (DWORD)pvargResult;  /* arg 0 is a pointer to the result */
         call_method( func, argspos, args, &stack_offset );
         break;
     case VT_I8:
@@ -6806,7 +6812,13 @@ DispCallFunc(
         break;
     case VT_DECIMAL:
     case VT_VARIANT:
-        args[0] = (DWORD_PTR)pvargResult;  /* arg 0 is a pointer to the result */
+        if (pvInstance)
+        {
+            args[0] = (DWORD_PTR)pvInstance;  /* arg 0 is a pointer to the instance */
+            args[1] = (DWORD_PTR)pvargResult; /* arg 1 is a pointer to the result */
+        }
+        else
+            args[0] = (DWORD_PTR)pvargResult;  /* arg 0 is a pointer to the result */
         call_method( func, argspos, args );
         break;
     case VT_HRESULT:
-- 
2.17.1




More information about the wine-devel mailing list