Commit 03a59001 authored by Alexandre Julliard's avatar Alexandre Julliard

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

parent cf1c9d88
...@@ -1201,17 +1201,37 @@ static HRESULT WINAPI ret_false_func(void) ...@@ -1201,17 +1201,37 @@ static HRESULT WINAPI ret_false_func(void)
static const WCHAR testW[] = { 'T','e','s','t',0 }; 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_VT(&v1) == VT_I4, "unexpected %d\n", V_VT(&v1));
ok(V_I4(&v1) == 2, "unexpected %d\n", V_I4(&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(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))); ok(lstrcmpW(V_BSTR(&v2), testW) == 0, "unexpected %s\n", wine_dbgstr_w(V_BSTR(&v2)));
V_VT(ret) = VT_UI4; V_VT(&ret) = VT_UI4;
V_I4(ret) = 4321; 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) 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( (*(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) ...@@ -1227,6 +1247,7 @@ static void WINAPI inst_func2(void *inst, VARIANT *ret, VARIANT v1, VARIANT v2)
V_VT(ret) = VT_UI4; V_VT(ret) = VT_UI4;
V_I4(ret) = 4321; V_I4(ret) = 4321;
} }
#endif
static void *vtable[] = { NULL, NULL, NULL, inst_func }; static void *vtable[] = { NULL, NULL, NULL, inst_func };
static void *vtable2[] = { NULL, NULL, NULL, inst_func2 }; static void *vtable2[] = { NULL, NULL, NULL, inst_func2 };
......
...@@ -6882,23 +6882,8 @@ HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VART ...@@ -6882,23 +6882,8 @@ HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VART
} }
else func = (void *)offset; else func = (void *)offset;
/* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */ /* maximum size for an argument is 16 */
/* first as it will need to be in the 'x' registers: */ args = heap_alloc( 16 * count );
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 );
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
...@@ -6906,8 +6891,6 @@ HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VART ...@@ -6906,8 +6891,6 @@ HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VART
switch (types[i]) switch (types[i])
{ {
case VT_EMPTY:
break;
case VT_R4: case VT_R4:
if (fpcount < 8) regs.fp[fpcount++].f = V_R4(arg); if (fpcount < 8) regs.fp[fpcount++].f = V_R4(arg);
else *(float *)&args[argspos++] = 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 ...@@ -6918,7 +6901,6 @@ HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VART
else *(double *)&args[argspos++] = V_R8(arg); else *(double *)&args[argspos++] = V_R8(arg);
break; break;
case VT_DECIMAL: case VT_DECIMAL:
case VT_VARIANT:
if (rcount < 7) if (rcount < 7)
{ {
memcpy( &regs.x[rcount], arg, sizeof(*arg) ); memcpy( &regs.x[rcount], arg, sizeof(*arg) );
...@@ -6930,6 +6912,10 @@ HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VART ...@@ -6930,6 +6912,10 @@ HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VART
argspos += 2; argspos += 2;
} }
break; 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 */ 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); if (rcount < 8) regs.x[rcount++] = V_BOOL(arg);
else args[argspos++] = V_BOOL(arg); else args[argspos++] = V_BOOL(arg);
...@@ -6946,9 +6932,12 @@ HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VART ...@@ -6946,9 +6932,12 @@ HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VART
switch (ret_type) switch (ret_type)
{ {
case VT_EMPTY: /* EMPTY = no return value */ case VT_HRESULT:
case VT_DECIMAL: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */ heap_free( args );
return E_INVALIDARG;
case VT_DECIMAL:
case VT_VARIANT: case VT_VARIANT:
regs.x[8] = (DWORD_PTR)result; /* x8 is a pointer to the result */
call_method( func, argspos, args, (DWORD_PTR *)&regs ); call_method( func, argspos, args, (DWORD_PTR *)&regs );
break; break;
case VT_R4: case VT_R4:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment