Alexandre Julliard : oleaut32: Fix handling of VARIANT parameters in DispCallFunc() on ARM64.

Alexandre Julliard julliard at winehq.org
Tue Oct 29 17:41:46 CDT 2019


Module: wine
Branch: master
Commit: 03a590017e901b9473cc40afbc851eca218c96c4
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=03a590017e901b9473cc40afbc851eca218c96c4

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Oct 29 14:10:45 2019 +0100

oleaut32: Fix handling of VARIANT parameters in DispCallFunc() on ARM64.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/oleaut32/tests/typelib.c | 27 ++++++++++++++++++++++++---
 dlls/oleaut32/typelib.c       | 33 +++++++++++----------------------
 2 files changed, 35 insertions(+), 25 deletions(-)

diff --git a/dlls/oleaut32/tests/typelib.c b/dlls/oleaut32/tests/typelib.c
index a706481042..47faad7763 100644
--- a/dlls/oleaut32/tests/typelib.c
+++ b/dlls/oleaut32/tests/typelib.c
@@ -1201,17 +1201,37 @@ static HRESULT WINAPI ret_false_func(void)
 
 static const WCHAR testW[] = { 'T','e','s','t',0 };
 
-static void WINAPI variant_func2(VARIANT *ret, VARIANT v1, VARIANT v2)
+static VARIANT WINAPI variant_func2(VARIANT v1, VARIANT v2)
 {
+    VARIANT 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;
+    V_VT(&ret) = VT_UI4;
+    V_I4(&ret) = 4321;
+    return ret;
 }
 
+#ifdef __aarch64__
+static VARIANT WINAPI inst_func2(void *inst, VARIANT v1, VARIANT v2)
+{
+    VARIANT ret;
+
+    ok( (*(void ***)inst)[3] == inst_func2, "wrong ptr %p\n", inst );
+
+    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;
+    return ret;
+}
+#else
 static void WINAPI inst_func2(void *inst, VARIANT *ret, VARIANT v1, VARIANT v2)
 {
     ok( (*(void ***)inst)[3] == inst_func2, "wrong ptr %p\n", inst );
@@ -1227,6 +1247,7 @@ static void WINAPI inst_func2(void *inst, VARIANT *ret, VARIANT v1, VARIANT v2)
     V_VT(ret) = VT_UI4;
     V_I4(ret) = 4321;
 }
+#endif
 
 static void *vtable[] = { NULL, NULL, NULL, inst_func };
 static void *vtable2[] = { NULL, NULL, NULL, inst_func2 };
diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c
index 7ad92837da..d652edc7ee 100644
--- a/dlls/oleaut32/typelib.c
+++ b/dlls/oleaut32/typelib.c
@@ -6882,23 +6882,8 @@ HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VART
     }
     else func = (void *)offset;
 
-    /* Determine if we need to pass a pointer for the return value as arg 0.  If so, do that */
-    /*  first as it will need to be in the 'x' registers:                                    */
-    switch (ret_type)
-    {
-    case VT_DECIMAL:
-    case VT_VARIANT:
-        regs.x[8] = (DWORD_PTR)result;  /* x8 is a pointer to the result */
-        break;
-    case VT_HRESULT:
-        WARN("invalid return type %u\n", ret_type);
-        return E_INVALIDARG;
-    default:
-        break;
-    }
-
-    /* maximum size for an argument is sizeof(VARIANT).  Also allow for return pointer and stack alignment. */
-    args = heap_alloc( sizeof(VARIANT) * count + sizeof(DWORD_PTR) * 4 );
+    /* maximum size for an argument is 16 */
+    args = heap_alloc( 16 * count );
 
     for (i = 0; i < count; i++)
     {
@@ -6906,8 +6891,6 @@ HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VART
 
         switch (types[i])
         {
-        case VT_EMPTY:
-            break;
         case VT_R4:
             if (fpcount < 8) regs.fp[fpcount++].f = V_R4(arg);
             else *(float *)&args[argspos++] = V_R4(arg);
@@ -6918,7 +6901,6 @@ HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VART
             else *(double *)&args[argspos++] = V_R8(arg);
             break;
         case VT_DECIMAL:
-        case VT_VARIANT:
             if (rcount < 7)
             {
                 memcpy( &regs.x[rcount], arg, sizeof(*arg) );
@@ -6930,6 +6912,10 @@ HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VART
                 argspos += 2;
             }
             break;
+        case VT_VARIANT:
+            if (rcount < 8) regs.x[rcount++] = (DWORD_PTR)arg;
+            else args[argspos++] = (DWORD_PTR)arg;
+            break;
         case VT_BOOL:  /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
             if (rcount < 8) regs.x[rcount++] = V_BOOL(arg);
             else args[argspos++] = V_BOOL(arg);
@@ -6946,9 +6932,12 @@ HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VART
 
     switch (ret_type)
     {
-    case VT_EMPTY:      /* EMPTY = no return value */
-    case VT_DECIMAL:    /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
+    case VT_HRESULT:
+        heap_free( args );
+        return E_INVALIDARG;
+    case VT_DECIMAL:
     case VT_VARIANT:
+        regs.x[8] = (DWORD_PTR)result;  /* x8 is a pointer to the result */
         call_method( func, argspos, args, (DWORD_PTR *)&regs );
         break;
     case VT_R4:




More information about the wine-cvs mailing list