Module: wine Branch: oldstable Commit: b141e816d73b80c330d625aaa572ccbac87f564e URL: https://source.winehq.org/git/wine.git/?a=commit;h=b141e816d73b80c330d625aaa...
Author: Alexandre Julliard julliard@winehq.org Date: Tue Nov 13 19:08:10 2018 +0100
oleaut32: Fix argument order with instance and VARIANT return type.
Spotted by Dmitry Timoshkov.
Signed-off-by: Alexandre Julliard julliard@winehq.org (cherry picked from commit b73972b9df0e26ebfe07c0d7fbc5b2b9583c556c) Signed-off-by: Michael Stefaniuc mstefani@winehq.org
---
dlls/oleaut32/typelib.c | 84 ++++++++++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 36 deletions(-)
diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c index 49366ae..4a57162 100644 --- a/dlls/oleaut32/typelib.c +++ b/dlls/oleaut32/typelib.c @@ -6676,7 +6676,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; @@ -6694,8 +6694,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; @@ -6704,6 +6702,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]; @@ -6738,31 +6750,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 ); @@ -6776,7 +6781,7 @@ DispCallFunc( return S_OK;
#elif defined(__x86_64__) - int argspos; + int argspos = 0; UINT i; DWORD_PTR *args; void *func; @@ -6794,8 +6799,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; @@ -6804,6 +6807,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]; @@ -6827,23 +6844,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 ); @@ -6883,6 +6895,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) @@ -6898,14 +6918,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 );