Signed-off-by: Dmitry Timoshkov dmitry@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:
On Tue, Nov 13, 2018 at 04:15:30PM +0300, Dmitry Timoshkov wrote:
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
case VT_I8:args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */ call_method( func, argspos, args, &stack_offset ); break;
Hi Dmitry,
While this looks good, it would be better to add pvargResult to the args array before the other args are processed (just after pvInstance is added). That would mean we could avoid all the args + 1 hacks in the various call_method() calls. I realise that would increase the patch size somewhat, but we'd end up with a much cleaner function.
What do you think?
Huw.
Hi Huw,
Huw Davies huw@codeweavers.com wrote:
While this looks good, it would be better to add pvargResult to the args array before the other args are processed (just after pvInstance is added). That would mean we could avoid all the args + 1 hacks in the various call_method() calls. I realise that would increase the patch size somewhat, but we'd end up with a much cleaner function.
What do you think?
Could that be done as a separate patch? Frankly, since this is a patch from staging, and it's a pretty old one, I'd prefer to not try to go over it once again.
On Tue, Nov 13, 2018 at 06:59:13PM +0300, Dmitry Timoshkov wrote:
Hi Huw,
Huw Davies huw@codeweavers.com wrote:
While this looks good, it would be better to add pvargResult to the args array before the other args are processed (just after pvInstance is added). That would mean we could avoid all the args + 1 hacks in the various call_method() calls. I realise that would increase the patch size somewhat, but we'd end up with a much cleaner function.
What do you think?
Could that be done as a separate patch? Frankly, since this is a patch from staging, and it's a pretty old one, I'd prefer to not try to go over it once again.
Sure.
Signed-off-by: Huw Davies huw@codeweavers.com
Huw Davies huw@codeweavers.com wrote:
While this looks good, it would be better to add pvargResult to the args array before the other args are processed (just after pvInstance is added). That would mean we could avoid all the args + 1 hacks in the various call_method() calls. I realise that would increase the patch size somewhat, but we'd end up with a much cleaner function.
What do you think?
Could that be done as a separate patch? Frankly, since this is a patch from staging, and it's a pretty old one, I'd prefer to not try to go over it once again.
Sure.
Thanks. Feel free to send a follow up patch with the proposed restructuring.