oleaut32: Fix argument order with instance and VARIANT return type.

Spotted by Dmitry Timoshkov.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2018-11-13 19:08:10 +01:00
parent c518813e1e
commit b73972b9df
1 changed files with 48 additions and 36 deletions

View File

@ -6647,7 +6647,7 @@ DispCallFunc(
VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
{
#ifdef __i386__
int argspos, stack_offset;
int argspos = 0, stack_offset;
void *func;
UINT i;
DWORD *args;
@ -6665,8 +6665,6 @@ DispCallFunc(
/* maximum size for an argument is sizeof(VARIANT) */
args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
/* start at 1 in case we need to pass a pointer to the return value as arg 0 */
argspos = 1;
if (pvInstance)
{
const FARPROC *vtable = *(FARPROC **)pvInstance;
@ -6675,6 +6673,20 @@ DispCallFunc(
}
else func = (void *)oVft;
switch (vtReturn)
{
case VT_DECIMAL:
case VT_VARIANT:
args[argspos++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
break;
case VT_HRESULT:
WARN("invalid return type %u\n", vtReturn);
heap_free( args );
return E_INVALIDARG;
default:
break;
}
for (i = 0; i < cActuals; i++)
{
VARIANT *arg = prgpvarg[i];
@ -6709,31 +6721,24 @@ DispCallFunc(
switch (vtReturn)
{
case VT_EMPTY:
call_method( func, argspos - 1, args + 1, &stack_offset );
case VT_DECIMAL:
case VT_VARIANT:
call_method( func, argspos, args, &stack_offset );
break;
case VT_R4:
V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
V_R4(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
break;
case VT_R8:
case VT_DATE:
V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
break;
case VT_DECIMAL:
case VT_VARIANT:
args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
call_method( func, argspos, args, &stack_offset );
V_R8(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
break;
case VT_I8:
case VT_UI8:
case VT_CY:
V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
V_UI8(pvargResult) = call_method( func, argspos, args, &stack_offset );
break;
case VT_HRESULT:
WARN("invalid return type %u\n", vtReturn);
heap_free( args );
return E_INVALIDARG;
default:
V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
V_UI4(pvargResult) = call_method( func, argspos, args, &stack_offset );
break;
}
heap_free( args );
@ -6747,7 +6752,7 @@ DispCallFunc(
return S_OK;
#elif defined(__x86_64__)
int argspos;
int argspos = 0;
UINT i;
DWORD_PTR *args;
void *func;
@ -6765,8 +6770,6 @@ DispCallFunc(
/* maximum size for an argument is sizeof(DWORD_PTR) */
args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
/* start at 1 in case we need to pass a pointer to the return value as arg 0 */
argspos = 1;
if (pvInstance)
{
const FARPROC *vtable = *(FARPROC **)pvInstance;
@ -6775,6 +6778,20 @@ DispCallFunc(
}
else func = (void *)oVft;
switch (vtReturn)
{
case VT_DECIMAL:
case VT_VARIANT:
args[argspos++] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
break;
case VT_HRESULT:
WARN("invalid return type %u\n", vtReturn);
heap_free( args );
return E_INVALIDARG;
default:
break;
}
for (i = 0; i < cActuals; i++)
{
VARIANT *arg = prgpvarg[i];
@ -6798,23 +6815,18 @@ DispCallFunc(
switch (vtReturn)
{
case VT_R4:
V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
V_R4(pvargResult) = call_double_method( func, argspos, args );
break;
case VT_R8:
case VT_DATE:
V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
V_R8(pvargResult) = call_double_method( func, argspos, args );
break;
case VT_DECIMAL:
case VT_VARIANT:
args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
call_method( func, argspos, args );
break;
case VT_HRESULT:
WARN("invalid return type %u\n", vtReturn);
heap_free( args );
return E_INVALIDARG;
default:
V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
V_UI8(pvargResult) = call_method( func, argspos, args );
break;
}
heap_free( args );
@ -6854,6 +6866,14 @@ DispCallFunc(
argspos = 0;
rcount = 0;
if (pvInstance)
{
const FARPROC *vtable = *(FARPROC **)pvInstance;
func = vtable[oVft/sizeof(void *)];
regs.r[rcount++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
}
else func = (void *)oVft;
/* 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 'r' registers: */
switch (vtReturn)
@ -6869,14 +6889,6 @@ DispCallFunc(
break;
}
if (pvInstance)
{
const FARPROC *vtable = *(FARPROC **)pvInstance;
func = vtable[oVft/sizeof(void *)];
regs.r[rcount++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
}
else func = (void *)oVft;
/* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
args = heap_alloc( sizeof(VARIANT) * cActuals + sizeof(DWORD) * 4 );