Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/oleaut32/tests/usrmarshal.c | 30 ++++++++++++++++++++++++++++++ dlls/oleaut32/usrmarshal.c | 3 +++ 2 files changed, 33 insertions(+)
diff --git a/dlls/oleaut32/tests/usrmarshal.c b/dlls/oleaut32/tests/usrmarshal.c index 5ea13e4..0185b6d 100644 --- a/dlls/oleaut32/tests/usrmarshal.c +++ b/dlls/oleaut32/tests/usrmarshal.c @@ -964,6 +964,36 @@ static void test_marshal_VARIANT(void) VARIANT_UserFree(&umcb.Flags, &v2); HeapFree(GetProcessHeap(), 0, oldbuffer);
+ /*** I8 ***/ + VariantInit(&v); + V_VT(&v) = VT_I8; + V_I8(&v) = (LONGLONG)1000000 * 1000000; + + rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); + ok(stubMsg.BufferLength == 32, "size %d\n", stubMsg.BufferLength); + + buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); + stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; + memset(buffer, 0xcc, stubMsg.BufferLength); + next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); + ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); + wirev = (DWORD*)buffer; + + wirev = check_variant_header(wirev, &v, stubMsg.BufferLength); + ok(*wirev == 0xcccccccc, "wv[5] %08x\n", *wirev); /* pad */ + wirev++; + ok(*(LONGLONG *)wirev == V_I8(&v), "wv[6] %s\n", wine_dbgstr_longlong(*(LONGLONG *)wirev)); + VariantInit(&v2); + stubMsg.Buffer = buffer; + next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); + ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); + ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2)); + ok(V_I8(&v) == V_I8(&v2), "got i8 %s expect %s\n", + wine_dbgstr_longlong(V_I8(&v)), wine_dbgstr_longlong(V_I8(&v2))); + + VARIANT_UserFree(&umcb.Flags, &v2); + HeapFree(GetProcessHeap(), 0, oldbuffer); + /*** R4 ***/ VariantInit(&v); V_VT(&v) = VT_R4; diff --git a/dlls/oleaut32/usrmarshal.c b/dlls/oleaut32/usrmarshal.c index da524c8..d3dc93a 100644 --- a/dlls/oleaut32/usrmarshal.c +++ b/dlls/oleaut32/usrmarshal.c @@ -227,6 +227,9 @@ unsigned int get_type_size(ULONG *pFlags, VARTYPE vt) case VT_INT: case VT_UINT: return sizeof(INT); + case VT_I8: + case VT_UI8: + return sizeof(LONGLONG); case VT_R4: return sizeof(FLOAT); case VT_R8:
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/oleaut32/tests/tmarshal.c | 129 ++++++++++++++++++++++++++++++++- dlls/oleaut32/tests/tmarshal.idl | 56 +++++++++++++- dlls/oleaut32/tests/tmarshal_dispids.h | 52 ------------- 3 files changed, 183 insertions(+), 54 deletions(-) delete mode 100644 dlls/oleaut32/tests/tmarshal_dispids.h
diff --git a/dlls/oleaut32/tests/tmarshal.c b/dlls/oleaut32/tests/tmarshal.c index b48b785..68547f7 100644 --- a/dlls/oleaut32/tests/tmarshal.c +++ b/dlls/oleaut32/tests/tmarshal.c @@ -17,6 +17,8 @@ * */
+#include <math.h> + #define COBJMACROS #define CONST_VTABLE
@@ -27,7 +29,6 @@ #include "wine/test.h"
#include "tmarshal.h" -#include "tmarshal_dispids.h"
static HRESULT (WINAPI *pVarAdd)(LPVARIANT,LPVARIANT,LPVARIANT);
@@ -923,6 +924,44 @@ static HRESULT WINAPI Widget_Coclass( return S_OK; }
+static HRESULT WINAPI Widget_basetypes_in(IWidget *iface, signed char c, short s, int i, hyper h, + unsigned char uc, unsigned short us, unsigned int ui, MIDL_uhyper uh, + float f, double d, STATE st) +{ + ok(c == 5, "Got char %d.\n", c); + ok(s == -123, "Got short %d.\n", s); + ok(i == -100000, "Got int %d.\n", i); + ok(h == (LONGLONG)-100000 * 1000000, "Got hyper %s.\n", wine_dbgstr_longlong(h)); + ok(uc == 0, "Got unsigned char %u.\n", uc); + ok(us == 456, "Got unsigned short %u.\n", us); + ok(ui == 0xdeadbeef, "Got unsigned int %i.\n", ui); + ok(uh == (ULONGLONG)1234567890 * 9876543210, "Got unsigned hyper %s.\n", wine_dbgstr_longlong(uh)); + ok(f == (float)M_PI, "Got float %f.\n", f); + ok(d == M_E, "Got double %f.\n", d); + ok(st == STATE_WIDGETIFIED, "Got state %u.\n", st); + + return S_OK; +} + +static HRESULT WINAPI Widget_basetypes_out(IWidget *iface, signed char *c, short *s, int *i, hyper *h, + unsigned char *uc, unsigned short *us, unsigned int *ui, MIDL_uhyper *uh, + float *f, double *d, STATE *st) +{ + *c = 10; + *s = -321; + *i = -200000; + *h = (LONGLONG)-200000 * 1000000; + *uc = 254; + *us = 256; + *ui = 0xf00dfade; + *uh = (((ULONGLONG)0xabcdef01) << 32) | (ULONGLONG)0x23456789; + *f = M_LN2; + *d = M_LN10; + *st = STATE_UNWIDGETIFIED; + + return S_OK; +} + static const struct IWidgetVtbl Widget_VTable = { Widget_QueryInterface, @@ -964,6 +1003,8 @@ static const struct IWidgetVtbl Widget_VTable = Widget_VarArg_Run, Widget_VarArg_Ref_Run, Widget_Coclass, + Widget_basetypes_in, + Widget_basetypes_out, };
static HRESULT WINAPI StaticWidget_QueryInterface(IStaticWidget *iface, REFIID riid, void **ppvObject) @@ -1277,6 +1318,90 @@ static ITypeInfo *NonOleAutomation_GetTypeInfo(void) return NULL; }
+static void test_marshal_basetypes(IWidget *widget, IDispatch *disp) +{ + VARIANTARG arg[11]; + DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0}; + HRESULT hr; + + signed char c; + short s; + int i; + hyper h; + unsigned char uc; + unsigned short us; + unsigned int ui; + MIDL_uhyper uh; + float f; + double d; + STATE st; + + V_VT(&arg[10]) = VT_I1; V_I1(&arg[10]) = 5; + V_VT(&arg[9]) = VT_I2; V_I2(&arg[9]) = -123; + V_VT(&arg[8]) = VT_I4; V_I4(&arg[8]) = -100000; + V_VT(&arg[7]) = VT_I8; V_I8(&arg[7]) = (LONGLONG)-100000 * 1000000; + V_VT(&arg[6]) = VT_UI1; V_UI1(&arg[6]) = 0; + V_VT(&arg[5]) = VT_UI2; V_UI2(&arg[5]) = 456; + V_VT(&arg[4]) = VT_UI4; V_UI4(&arg[4]) = 0xdeadbeef; + V_VT(&arg[3]) = VT_UI8; V_UI8(&arg[3]) = (ULONGLONG)1234567890 * 9876543210; + V_VT(&arg[2]) = VT_R4; V_R4(&arg[2]) = M_PI; + V_VT(&arg[1]) = VT_R8; V_R8(&arg[1]) = M_E; + V_VT(&arg[0]) = VT_I4; V_I4(&arg[0]) = STATE_WIDGETIFIED; + hr = IDispatch_Invoke(disp, DISPID_TM_BASETYPES_IN, &IID_NULL, LOCALE_NEUTRAL, + DISPATCH_METHOD, &dispparams, NULL, NULL, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IWidget_basetypes_in(widget, 5, -123, -100000, (LONGLONG)-100000 * 1000000, 0, 456, + 0xdeadbeef, (ULONGLONG)1234567890 * 9876543210, M_PI, M_E, STATE_WIDGETIFIED); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + c = s = i = h = uc = us = ui = uh = f = d = st = 0; + + V_VT(&arg[10]) = VT_BYREF|VT_I1; V_I1REF(&arg[10]) = &c; + V_VT(&arg[9]) = VT_BYREF|VT_I2; V_I2REF(&arg[9]) = &s; + V_VT(&arg[8]) = VT_BYREF|VT_I4; V_I4REF(&arg[8]) = &i; + V_VT(&arg[7]) = VT_BYREF|VT_I8; V_I8REF(&arg[7]) = &h; + V_VT(&arg[6]) = VT_BYREF|VT_UI1; V_UI1REF(&arg[6]) = &uc; + V_VT(&arg[5]) = VT_BYREF|VT_UI2; V_UI2REF(&arg[5]) = &us; + V_VT(&arg[4]) = VT_BYREF|VT_UI4; V_UI4REF(&arg[4]) = &ui; + V_VT(&arg[3]) = VT_BYREF|VT_UI8; V_UI8REF(&arg[3]) = &uh; + V_VT(&arg[2]) = VT_BYREF|VT_R4; V_R4REF(&arg[2]) = &f; + V_VT(&arg[1]) = VT_BYREF|VT_R8; V_R8REF(&arg[1]) = &d; + V_VT(&arg[0]) = VT_BYREF|VT_I4; V_I4REF(&arg[0]) = (int *)&st; + hr = IDispatch_Invoke(disp, DISPID_TM_BASETYPES_OUT, &IID_NULL, LOCALE_NEUTRAL, + DISPATCH_METHOD, &dispparams, NULL, NULL, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(c == 10, "Got char %d.\n", c); + ok(s == -321, "Got short %d.\n", s); + ok(i == -200000, "Got int %d.\n", i); + ok(h == (LONGLONG)-200000 * 1000000L, "Got hyper %s.\n", wine_dbgstr_longlong(h)); + ok(uc == 254, "Got unsigned char %u.\n", uc); + ok(us == 256, "Got unsigned short %u.\n", us); + ok(ui == 0xf00dfade, "Got unsigned int %i.\n", ui); + ok(uh == ((((ULONGLONG)0xabcdef01) << 32) | (ULONGLONG)0x23456789), + "Got unsigned hyper %s.\n", wine_dbgstr_longlong(uh)); + ok(f == (float)M_LN2, "Got float %f.\n", f); + ok(d == M_LN10, "Got double %f.\n", d); + ok(st == STATE_UNWIDGETIFIED, "Got state %u.\n", st); + + c = s = i = h = uc = us = ui = uh = f = d = st = 0; + + hr = IWidget_basetypes_out(widget, &c, &s, &i, &h, &uc, &us, &ui, &uh, &f, &d, &st); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(c == 10, "Got char %d.\n", c); + ok(s == -321, "Got short %d.\n", s); + ok(i == -200000, "Got int %d.\n", i); + ok(h == (LONGLONG)-200000 * 1000000L, "Got hyper %s.\n", wine_dbgstr_longlong(h)); + ok(uc == 254, "Got unsigned char %u.\n", uc); + ok(us == 256, "Got unsigned short %u.\n", us); + ok(ui == 0xf00dfade, "Got unsigned int %i.\n", ui); + ok(uh == ((((ULONGLONG)0xabcdef01) << 32) | (ULONGLONG)0x23456789), + "Got unsigned hyper %s.\n", wine_dbgstr_longlong(uh)); + ok(f == (float)M_LN2, "Got float %f.\n", f); + ok(d == M_LN10, "Got double %f.\n", d); + ok(st == STATE_UNWIDGETIFIED, "Got state %u.\n", st); +} + static void test_typelibmarshal(void) { static const WCHAR szCat[] = { 'C','a','t',0 }; @@ -1887,6 +2012,8 @@ static void test_typelibmarshal(void) ok(V_I4(&varresult) == DISPID_TM_NEG_RESTRICTED, "got %x\n", V_I4(&varresult)); VariantClear(&varresult);
+ test_marshal_basetypes(pWidget, pDispatch); + IDispatch_Release(pDispatch); IWidget_Release(pWidget);
diff --git a/dlls/oleaut32/tests/tmarshal.idl b/dlls/oleaut32/tests/tmarshal.idl index 996e948..2452f2d 100644 --- a/dlls/oleaut32/tests/tmarshal.idl +++ b/dlls/oleaut32/tests/tmarshal.idl @@ -20,9 +20,53 @@ #pragma makedep ident #pragma makedep typelib
-#include "tmarshal_dispids.h" import "ocidl.idl";
+enum IWidget_dispids +{ + DISPID_TM_NAME = 1, + DISPID_TM_DOSOMETHING, + DISPID_TM_STATE, + DISPID_TM_MAP, + DISPID_TM_SETOLECOLOR, + DISPID_TM_GETOLECOLOR, + DISPID_TM_CLONE, + DISPID_TM_CLONEDISPATCH, + DISPID_TM_CLONECOCLASS, + DISPID_TM_VALUE, + DISPID_TM_ARRAY, + DISPID_TM_VARARRAYPTR, + DISPID_TM_VARCARRAY, + DISPID_TM_VARIANT, + DISPID_TM_VARARG, + DISPID_TM_STRUCTARGS, + DISPID_TM_ERROR, + DISPID_TM_CLONEINTERFACE, + DISPID_TM_TESTDUAL, + DISPID_TM_PROP_WITH_LCID, + DISPID_TM_PROP_INT, + DISPID_TM_PROP_UINT, + DISPID_TM_BYREF_UINT, + DISPID_TM_PROP_OPT_ARG, + DISPID_TM_PROP_REQ_ARG, + DISPID_TM_RESTRICTED, + DISPID_TM_TESTSECONDIFACE, + DISPID_TM_VARARG_RUN, + DISPID_TM_VARARG_REF_RUN, + DISPID_TM_COCLASS, + + DISPID_TM_BASETYPES_IN, + DISPID_TM_BASETYPES_OUT, +}; + +static const int DISPID_TM_NEG_RESTRICTED = -26; + +enum INonOleAutomation_dispids +{ + DISPID_NOA_BSTRRET = 1, + DISPID_NOA_ERROR +}; + [ uuid(d96d8a3e-78b6-4c8d-8f27-059db959be8a), version(2.5), @@ -188,6 +232,16 @@ library TestTypelib
[id(DISPID_TM_COCLASS)] HRESULT Coclass([in] ApplicationObject2 *param); + + [id(DISPID_TM_BASETYPES_IN)] + HRESULT basetypes_in([in] signed char c, [in] short s, [in] int i, [in] hyper h, + [in] unsigned char uc, [in] unsigned short us, [in] unsigned int ui, + [in] unsigned hyper uh, [in] float f, [in] double d, [in] STATE st); + + [id(DISPID_TM_BASETYPES_OUT)] + HRESULT basetypes_out([out] signed char *c, [out] short *s, [out] int *i, [out] hyper *h, + [out] unsigned char *uc, [out] unsigned short *us, [out] unsigned int *ui, + [out] unsigned hyper *uh, [out] float *f, [out] double *d, [out] STATE *st); }
[ diff --git a/dlls/oleaut32/tests/tmarshal_dispids.h b/dlls/oleaut32/tests/tmarshal_dispids.h deleted file mode 100644 index 26f4027..0000000 --- a/dlls/oleaut32/tests/tmarshal_dispids.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2005-2006 Robert Shearman for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * - */ - -#define DISPID_TM_NAME 1 -#define DISPID_TM_DOSOMETHING 2 -#define DISPID_TM_STATE 3 -#define DISPID_TM_MAP 4 -#define DISPID_TM_SETOLECOLOR 5 -#define DISPID_TM_GETOLECOLOR 6 -#define DISPID_TM_CLONE 7 -#define DISPID_TM_CLONEDISPATCH 8 -#define DISPID_TM_CLONECOCLASS 9 -#define DISPID_TM_ARRAY 10 -#define DISPID_TM_VARARRAYPTR 11 -#define DISPID_TM_VARIANT 12 -#define DISPID_TM_VARARG 13 -#define DISPID_TM_ERROR 14 -#define DISPID_TM_CLONEINTERFACE 15 -#define DISPID_TM_TESTDUAL 16 -#define DISPID_TM_STRUCTARGS 17 -#define DISPID_TM_PROP_WITH_LCID 18 -#define DISPID_TM_PROP_INT 19 -#define DISPID_TM_PROP_UINT 20 -#define DISPID_TM_BYREF_UINT 21 -#define DISPID_TM_PROP_OPT_ARG 22 -#define DISPID_TM_PROP_REQ_ARG 23 -#define DISPID_TM_VARCARRAY 24 -#define DISPID_TM_RESTRICTED 25 -#define DISPID_TM_NEG_RESTRICTED -26 -#define DISPID_TM_TESTSECONDIFACE 27 -#define DISPID_TM_VARARG_RUN 28 -#define DISPID_TM_VARARG_REF_RUN 29 -#define DISPID_TM_COCLASS 30 - -#define DISPID_NOA_BSTRRET 1 -#define DISPID_NOA_ERROR 2
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/oleaut32/tests/tmarshal.c | 179 +++++++++++++++++++++++++++++++++++++++ dlls/oleaut32/tests/tmarshal.idl | 8 ++ 2 files changed, 187 insertions(+)
diff --git a/dlls/oleaut32/tests/tmarshal.c b/dlls/oleaut32/tests/tmarshal.c index 68547f7..4914eba 100644 --- a/dlls/oleaut32/tests/tmarshal.c +++ b/dlls/oleaut32/tests/tmarshal.c @@ -376,6 +376,8 @@ static ItestDualVtbl TestDualVtbl = { static ItestDual TestDual = { &TestDualVtbl }; static ItestDual TestDualDisp = { &TestDualVtbl };
+static int testmode; + typedef struct Widget { IWidget IWidget_iface; @@ -962,6 +964,61 @@ static HRESULT WINAPI Widget_basetypes_out(IWidget *iface, signed char *c, short return S_OK; }
+static HRESULT WINAPI Widget_int_ptr(IWidget *iface, int *in, int *out, int *in_out) +{ + ok(*in == 123, "Got [in] %d.\n", *in); + if (testmode == 0) /* Invoke() */ + ok(*out == 456, "Got [out] %d.\n", *out); + else if (testmode == 1) +todo_wine + ok(!*out, "Got [out] %d.\n", *out); + ok(*in_out == 789, "Got [in, out] %d.\n", *in_out); + + *in = 987; + *out = 654; + *in_out = 321; + + return S_OK; +} + +static HRESULT WINAPI Widget_int_ptr_ptr(IWidget *iface, int **in, int **out, int **in_out) +{ +todo_wine_if(testmode == 2) + ok(!*out, "Got [out] %p.\n", *out); + if (testmode == 0) + { + ok(!*in, "Got [in] %p.\n", *in); + ok(!*in_out, "Got [in, out] %p.\n", *in_out); + } + else if (testmode == 1) + { + ok(!*in, "Got [in] %p.\n", *in); + ok(!*in_out, "Got [in, out] %p.\n", *in_out); + + *out = CoTaskMemAlloc(sizeof(int)); + **out = 654; + *in_out = CoTaskMemAlloc(sizeof(int)); + **in_out = 321; + } + else if (testmode == 2) + { + ok(**in == 123, "Got [in] %d.\n", **in); + ok(**in_out == 789, "Got [in, out] %d.\n", **in_out); + + *out = CoTaskMemAlloc(sizeof(int)); + **out = 654; + **in_out = 321; + } + else if (testmode == 3) + { + ok(**in_out == 789, "Got [in, out] %d.\n", **in_out); + CoTaskMemFree(*in_out); + *in_out = NULL; + } + + return S_OK; +} + static const struct IWidgetVtbl Widget_VTable = { Widget_QueryInterface, @@ -1005,6 +1062,8 @@ static const struct IWidgetVtbl Widget_VTable = Widget_Coclass, Widget_basetypes_in, Widget_basetypes_out, + Widget_int_ptr, + Widget_int_ptr_ptr, };
static HRESULT WINAPI StaticWidget_QueryInterface(IStaticWidget *iface, REFIID riid, void **ppvObject) @@ -1402,6 +1461,125 @@ static void test_marshal_basetypes(IWidget *widget, IDispatch *disp) ok(st == STATE_UNWIDGETIFIED, "Got state %u.\n", st); }
+static void test_marshal_pointer(IWidget *widget, IDispatch *disp) +{ + VARIANTARG arg[3]; + DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0}; + int in, out, in_out, *in_ptr, *out_ptr, *in_out_ptr; + HRESULT hr; + + testmode = 0; + + in = 123; + out = 456; + in_out = 789; + V_VT(&arg[2]) = VT_BYREF|VT_I4; V_I4REF(&arg[2]) = ∈ + V_VT(&arg[1]) = VT_BYREF|VT_I4; V_I4REF(&arg[1]) = &out; + V_VT(&arg[0]) = VT_BYREF|VT_I4; V_I4REF(&arg[0]) = &in_out; + hr = IDispatch_Invoke(disp, DISPID_TM_INT_PTR, &IID_NULL, LOCALE_NEUTRAL, + DISPATCH_METHOD, &dispparams, NULL, NULL, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(in == 987, "Got [in] %d.\n", in); + ok(out == 654, "Got [out] %d.\n", out); + ok(in_out == 321, "Got [in, out] %d.\n", in_out); + + testmode = 1; + + in = 123; + out = 456; + in_out = 789; + hr = IWidget_int_ptr(widget, &in, &out, &in_out); + ok(hr == S_OK, "Got hr %#x.\n", hr); +todo_wine + ok(in == 123, "Got [in] %d.\n", in); + ok(out == 654, "Got [out] %d.\n", out); + ok(in_out == 321, "Got [in, out] %d.\n", in_out); + +if (0) { + out = in_out = -1; + hr = IWidget_int_ptr(widget, NULL, &out, &in_out); + ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr); + ok(!out, "[out] parameter should have been cleared.\n"); + ok(in_out == -1, "[in, out] parameter should not have been cleared.\n"); + + in = in_out = -1; + hr = IWidget_int_ptr(widget, &in, NULL, &in_out); + ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr); + ok(in == -1, "[in] parameter should not have been cleared.\n"); + ok(in_out == -1, "[in, out] parameter should not have been cleared.\n"); + + in = out = -1; + hr = IWidget_int_ptr(widget, &in, &out, NULL); + ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr); + ok(in == -1, "[in] parameter should not have been cleared.\n"); + ok(!out, "[out] parameter should have been cleared.\n"); +} + + /* We can't test Invoke() with double pointers, as it is not possible to fit + * more than one level of indirection into a VARIANTARG. */ + + testmode = 0; + in_ptr = out_ptr = in_out_ptr = NULL; + hr = IWidget_int_ptr_ptr(widget, &in_ptr, &out_ptr, &in_out_ptr); + ok(hr == S_OK, "Got hr %#x\n", hr); + ok(!in_ptr, "Got [in] %p.\n", in_ptr); + ok(!out_ptr, "Got [out] %p.\n", out_ptr); + ok(!in_out_ptr, "Got [in, out] %p.\n", in_out_ptr); + + testmode = 1; + hr = IWidget_int_ptr_ptr(widget, &in_ptr, &out_ptr, &in_out_ptr); + ok(hr == S_OK, "Got hr %#x\n", hr); + ok(*out_ptr == 654, "Got [out] %d.\n", *out_ptr); + ok(*in_out_ptr == 321, "Got [in, out] %d.\n", *in_out_ptr); + CoTaskMemFree(out_ptr); + CoTaskMemFree(in_out_ptr); + + testmode = 2; + in = 123; + out = 456; + in_out = 789; + in_ptr = ∈ + out_ptr = &out; + in_out_ptr = &in_out; + hr = IWidget_int_ptr_ptr(widget, &in_ptr, &out_ptr, &in_out_ptr); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(out_ptr != &out, "[out] ptr should have changed.\n"); + ok(in_out_ptr == &in_out, "[in, out] ptr should not have changed.\n"); + ok(*out_ptr == 654, "Got [out] %d.\n", *out_ptr); + ok(*in_out_ptr == 321, "Got [in, out] %d.\n", *in_out_ptr); + + testmode = 3; + in_ptr = out_ptr = NULL; + in_out = 789; + in_out_ptr = &in_out; + hr = IWidget_int_ptr_ptr(widget, &in_ptr, &out_ptr, &in_out_ptr); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!in_out_ptr, "Got [in, out] %p.\n", in_out_ptr); + +if (0) { + out_ptr = &out; + in_out_ptr = &in_out; + hr = IWidget_int_ptr_ptr(widget, NULL, &out_ptr, &in_out_ptr); + ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr); + ok(!out_ptr, "[out] parameter should have been cleared.\n"); + ok(in_out_ptr == &in_out, "[in, out] parameter should not have been cleared.\n"); + + in_ptr = ∈ + in_out_ptr = &in_out; + hr = IWidget_int_ptr_ptr(widget, &in_ptr, NULL, &in_out_ptr); + ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr); + ok(in_ptr == &in, "[in] parameter should not have been cleared.\n"); + ok(in_out_ptr == &in_out, "[in, out] parameter should not have been cleared.\n"); + + in_ptr = ∈ + out_ptr = &out; + hr = IWidget_int_ptr_ptr(widget, &in_ptr, &out_ptr, NULL); + ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr); + ok(in_ptr == &in, "[in] parameter should not have been cleared.\n"); + ok(!out_ptr, "[out] parameter should have been cleared.\n"); +} +} + static void test_typelibmarshal(void) { static const WCHAR szCat[] = { 'C','a','t',0 }; @@ -2013,6 +2191,7 @@ static void test_typelibmarshal(void) VariantClear(&varresult);
test_marshal_basetypes(pWidget, pDispatch); + test_marshal_pointer(pWidget, pDispatch);
IDispatch_Release(pDispatch); IWidget_Release(pWidget); diff --git a/dlls/oleaut32/tests/tmarshal.idl b/dlls/oleaut32/tests/tmarshal.idl index 2452f2d..3cbad57 100644 --- a/dlls/oleaut32/tests/tmarshal.idl +++ b/dlls/oleaut32/tests/tmarshal.idl @@ -57,6 +57,8 @@ enum IWidget_dispids
DISPID_TM_BASETYPES_IN, DISPID_TM_BASETYPES_OUT, + DISPID_TM_INT_PTR, + DISPID_TM_INT_PTR_PTR, };
static const int DISPID_TM_NEG_RESTRICTED = -26; @@ -242,6 +244,12 @@ library TestTypelib HRESULT basetypes_out([out] signed char *c, [out] short *s, [out] int *i, [out] hyper *h, [out] unsigned char *uc, [out] unsigned short *us, [out] unsigned int *ui, [out] unsigned hyper *uh, [out] float *f, [out] double *d, [out] STATE *st); + + [id(DISPID_TM_INT_PTR)] + HRESULT int_ptr([in] int *in, [out] int *out, [in, out] int *in_out); + + [id(DISPID_TM_INT_PTR_PTR)] + HRESULT int_ptr_ptr([in] int **in, [out] int **out, [in, out] int **in_out); }
[
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=43136
Your paranoid android.
=== wvistau64 (64 bit Windows report) ===
Report errors: oleaut32:tmarshal crashed (c0000374)
=== w2008s64 (64 bit Windows report) ===
Report errors: oleaut32:tmarshal crashed (c0000374)
=== w7pro64 (64 bit Windows report) ===
Report errors: oleaut32:tmarshal crashed (c0000374)
=== w864 (64 bit Windows report) ===
Report errors: oleaut32:tmarshal crashed (c0000374)
=== w1064 (64 bit Windows report) ===
Report errors: oleaut32:tmarshal crashed (c0000374)
=== debian9 (32 bit Wine report) ===
oleaut32: tmarshal.c:974: Test succeeded inside todo block: Got [out] 0. tmarshal.c:1494: Test succeeded inside todo block: Got [in] 123. Unhandled exception: page fault on write access to 0x00000000 in 32-bit code (0x7eb91d06). typelib.c:5688: Test failed: got 0x00000000
Report errors: oleaut32:tmarshal crashed (c0000005)
=== debian9 (build log) ===
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/oleaut32/tests/usrmarshal.c | 27 +++++++++++++++++++++++++++ dlls/oleaut32/usrmarshal.c | 3 ++- 2 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/dlls/oleaut32/tests/usrmarshal.c b/dlls/oleaut32/tests/usrmarshal.c index 0185b6d..97c0502 100644 --- a/dlls/oleaut32/tests/usrmarshal.c +++ b/dlls/oleaut32/tests/usrmarshal.c @@ -777,6 +777,7 @@ static void test_marshal_VARIANT(void) HRESULT hr; LONG bound, bound2; VARTYPE vt, vt2; + IUnknown *unk;
stubMsg.RpcMsg = &rpcMsg;
@@ -1579,6 +1580,32 @@ todo_wine ok(heap_unknown->refs == 1, "%d refcounts of IUnknown leaked\n", heap_unknown->refs - 1); IUnknown_Release(&heap_unknown->IUnknown_iface); HeapFree(GetProcessHeap(), 0, oldbuffer); + + unk = NULL; + VariantInit(&v); + V_VT(&v) = VT_UNKNOWN | VT_BYREF; + V_UNKNOWNREF(&v) = &unk; + + rpcMsg.BufferLength = stubMsg.BufferLength = VARIANT_UserSize(&umcb.Flags, 0, &v); + ok(stubMsg.BufferLength >= 28, "size %d\n", stubMsg.BufferLength); + buffer = rpcMsg.Buffer = stubMsg.Buffer = stubMsg.BufferStart = alloc_aligned(stubMsg.BufferLength, &oldbuffer); + stubMsg.BufferEnd = stubMsg.Buffer + stubMsg.BufferLength; + memset(buffer, 0xcc, stubMsg.BufferLength); + next = VARIANT_UserMarshal(&umcb.Flags, buffer, &v); + ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); + wirev = (DWORD*)buffer; + wirev = check_variant_header(wirev, &v, stubMsg.BufferLength); + + ok(*wirev == 4, "wv[5] %08x\n", *wirev); + + VariantInit(&v2); + stubMsg.Buffer = buffer; + next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2); + ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength); + ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v2), V_VT(&v)); + ok(!*V_UNKNOWNREF(&v2), "got %p expect NULL\n", *V_UNKNOWNREF(&v2)); + VARIANT_UserFree(&umcb.Flags, &v2); + HeapFree(GetProcessHeap(), 0, oldbuffer); }
diff --git a/dlls/oleaut32/usrmarshal.c b/dlls/oleaut32/usrmarshal.c index d3dc93a..163b48f 100644 --- a/dlls/oleaut32/usrmarshal.c +++ b/dlls/oleaut32/usrmarshal.c @@ -647,7 +647,8 @@ void WINAPI VARIANT_UserFree(ULONG *pFlags, VARIANT *pvar) break; case VT_UNKNOWN | VT_BYREF: case VT_DISPATCH | VT_BYREF: - IUnknown_Release(*V_UNKNOWNREF(pvar)); + if (*V_UNKNOWNREF(pvar)) + IUnknown_Release(*V_UNKNOWNREF(pvar)); break; } }
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=43137
Your paranoid android.
=== wvistau64 (64 bit Windows report) ===
Report errors: oleaut32:tmarshal crashed (c0000374)
=== w2008s64 (64 bit Windows report) ===
Report errors: oleaut32:tmarshal crashed (c0000374)
=== w7pro64 (64 bit Windows report) ===
Report errors: oleaut32:tmarshal crashed (c0000374)
=== w864 (64 bit Windows report) ===
Report errors: oleaut32:tmarshal crashed (c0000374)
=== w1064 (64 bit Windows report) ===
Report errors: oleaut32:tmarshal crashed (c0000374)
=== debian9 (32 bit Wine report) ===
oleaut32: tmarshal.c:974: Test succeeded inside todo block: Got [out] 0. tmarshal.c:1494: Test succeeded inside todo block: Got [in] 123. Unhandled exception: page fault on write access to 0x00000000 in 32-bit code (0x7eb7ad06). typelib.c:5688: Test failed: got 0x00000000
Report errors: oleaut32:tmarshal crashed (c0000005)
=== debian9 (build log) ===
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/oleaut32/tests/tmarshal.c | 428 +++++++++++++++++++++++++++++++++++++++ dlls/oleaut32/tests/tmarshal.idl | 13 ++ 2 files changed, 441 insertions(+)
diff --git a/dlls/oleaut32/tests/tmarshal.c b/dlls/oleaut32/tests/tmarshal.c index 4914eba..eaf34a8 100644 --- a/dlls/oleaut32/tests/tmarshal.c +++ b/dlls/oleaut32/tests/tmarshal.c @@ -34,6 +34,12 @@ static HRESULT (WINAPI *pVarAdd)(LPVARIANT,LPVARIANT,LPVARIANT);
#define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr) +static inline void release_iface_(unsigned int line, void *iface) +{ + ULONG ref = IUnknown_Release((IUnknown *)iface); + ok_(__FILE__, line)(!ref, "Got outstanding refcount %d.\n", ref); +} +#define release_iface(a) release_iface_(__LINE__, a)
#ifdef __i386__ static const int tmarshal_todo = 0; @@ -376,6 +382,98 @@ static ItestDualVtbl TestDualVtbl = { static ItestDual TestDual = { &TestDualVtbl }; static ItestDual TestDualDisp = { &TestDualVtbl };
+struct disp_obj +{ + ISomethingFromDispatch ISomethingFromDispatch_iface; + LONG ref; +}; + +static inline struct disp_obj *impl_from_ISomethingFromDispatch(ISomethingFromDispatch *iface) +{ + return CONTAINING_RECORD(iface, struct disp_obj, ISomethingFromDispatch_iface); +} + +static HRESULT WINAPI disp_obj_QueryInterface(ISomethingFromDispatch *iface, REFIID iid, void **out) +{ + if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IDispatch) + || IsEqualGUID(iid, &IID_ISomethingFromDispatch)) + { + *out = iface; + ISomethingFromDispatch_AddRef(iface); + return S_OK; + } + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI disp_obj_AddRef(ISomethingFromDispatch *iface) +{ + struct disp_obj *obj = impl_from_ISomethingFromDispatch(iface); + return ++obj->ref; +} + +static ULONG WINAPI disp_obj_Release(ISomethingFromDispatch *iface) +{ + struct disp_obj *obj = impl_from_ISomethingFromDispatch(iface); + LONG ref = --obj->ref; + if (!ref) + CoTaskMemFree(obj); + return ref; +} + +static HRESULT WINAPI disp_obj_GetTypeInfoCount(ISomethingFromDispatch *iface, UINT *count) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI disp_obj_GetTypeInfo(ISomethingFromDispatch *iface, + UINT index, LCID lcid, ITypeInfo **typeinfo) +{ + ok(index == 0xdeadbeef, "Got unexpected index %#x.\n", index); + return 0xbeefdead; +} + +static HRESULT WINAPI disp_obj_GetIDsOfNames(ISomethingFromDispatch *iface, + REFIID iid, LPOLESTR *names, UINT count, LCID lcid, DISPID *ids) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI disp_obj_Invoke(ISomethingFromDispatch *iface, DISPID id, REFIID iid, LCID lcid, + WORD flags, DISPPARAMS *dispparams, VARIANT *result, EXCEPINFO *excepinfo, UINT *errarg) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI disp_obj_anotherfn(ISomethingFromDispatch *iface) +{ + return 0x01234567; +} + +static const ISomethingFromDispatchVtbl disp_obj_vtbl = +{ + disp_obj_QueryInterface, + disp_obj_AddRef, + disp_obj_Release, + disp_obj_GetTypeInfoCount, + disp_obj_GetTypeInfo, + disp_obj_GetIDsOfNames, + disp_obj_Invoke, + disp_obj_anotherfn, +}; + +static ISomethingFromDispatch *create_disp_obj(void) +{ + struct disp_obj *obj = CoTaskMemAlloc(sizeof(*obj)); + obj->ISomethingFromDispatch_iface.lpVtbl = &disp_obj_vtbl; + obj->ref = 1; + return &obj->ISomethingFromDispatch_iface; +} + static int testmode;
typedef struct Widget @@ -1019,6 +1117,92 @@ todo_wine_if(testmode == 2) return S_OK; }
+/* Call methods to check that we have valid proxies to each interface. */ +static void check_iface_marshal(IUnknown *unk, IDispatch *disp, ISomethingFromDispatch *sfd) +{ + ISomethingFromDispatch *sfd2; + ITypeInfo *typeinfo; + HRESULT hr; + + hr = IUnknown_QueryInterface(unk, &IID_ISomethingFromDispatch, (void **)&sfd2); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ISomethingFromDispatch_Release(sfd2); + + hr = IDispatch_GetTypeInfo(disp, 0xdeadbeef, 0, &typeinfo); + ok(hr == 0xbeefdead, "Got hr %#x.\n", hr); + + hr = ISomethingFromDispatch_anotherfn(sfd); + ok(hr == 0x01234567, "Got hr %#x.\n", hr); +} + +static HRESULT WINAPI Widget_iface_in(IWidget *iface, IUnknown *unk, IDispatch *disp, ISomethingFromDispatch *sfd) +{ + if (testmode == 0) + check_iface_marshal(unk, disp, sfd); + else if (testmode == 1) + { + ok(!unk, "Got iface %p.\n", unk); + ok(!disp, "Got iface %p.\n", disp); + ok(!sfd, "Got iface %p.\n", sfd); + } + return S_OK; +} + +static HRESULT WINAPI Widget_iface_out(IWidget *iface, IUnknown **unk, IDispatch **disp, ISomethingFromDispatch **sfd) +{ +todo_wine { + ok(!*unk, "Got iface %p.\n", *unk); + ok(!*disp, "Got iface %p.\n", *disp); + ok(!*sfd, "Got iface %p.\n", *sfd); +} + + if (testmode == 0) + { + *unk = (IUnknown *)create_disp_obj(); + *disp = (IDispatch *)create_disp_obj(); + *sfd = create_disp_obj(); + } + return S_OK; +} + +static HRESULT WINAPI Widget_iface_ptr(IWidget *iface, ISomethingFromDispatch **in, + ISomethingFromDispatch **out, ISomethingFromDispatch **in_out) +{ + HRESULT hr; + +todo_wine_if(testmode == 0 || testmode == 1) + ok(!*out, "Got [out] %p.\n", *out); + if (testmode == 0 || testmode == 1) + { + hr = ISomethingFromDispatch_anotherfn(*in); + ok(hr == 0x01234567, "Got hr %#x.\n", hr); + hr = ISomethingFromDispatch_anotherfn(*in_out); + ok(hr == 0x01234567, "Got hr %#x.\n", hr); + } + + if (testmode == 1) + { + *out = create_disp_obj(); + ISomethingFromDispatch_Release(*in_out); + *in_out = create_disp_obj(); + } + else if (testmode == 2) + { + ok(!*in, "Got [in] %p.\n", *in); + ok(!*in_out, "Got [in, out] %p.\n", *in_out); + *in_out = create_disp_obj(); + } + else if (testmode == 3) + { + hr = ISomethingFromDispatch_anotherfn(*in_out); + ok(hr == 0x01234567, "Got hr %#x.\n", hr); + ISomethingFromDispatch_Release(*in_out); + *in_out = NULL; + } + + return S_OK; +} + static const struct IWidgetVtbl Widget_VTable = { Widget_QueryInterface, @@ -1064,6 +1248,9 @@ static const struct IWidgetVtbl Widget_VTable = Widget_basetypes_out, Widget_int_ptr, Widget_int_ptr_ptr, + Widget_iface_in, + Widget_iface_out, + Widget_iface_ptr, };
static HRESULT WINAPI StaticWidget_QueryInterface(IStaticWidget *iface, REFIID riid, void **ppvObject) @@ -1580,6 +1767,246 @@ if (0) { } }
+static void test_marshal_iface(IWidget *widget, IDispatch *disp) +{ + VARIANTARG arg[3]; + DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0}; + ISomethingFromDispatch *sfd1, *sfd2, *sfd3, *proxy_sfd, *sfd_in, *sfd_out, *sfd_in_out; + IUnknown *proxy_unk, *proxy_unk2, *unk_in, *unk_out, *unk_in_out; + IDispatch *proxy_disp; + HRESULT hr; + + testmode = 0; + sfd1 = create_disp_obj(); + sfd2 = create_disp_obj(); + sfd3 = create_disp_obj(); + hr = IWidget_iface_in(widget, (IUnknown *)create_disp_obj(), + (IDispatch *)create_disp_obj(), create_disp_obj()); + ok(hr == S_OK, "Got hr %#x.\n", hr); + release_iface(sfd1); + release_iface(sfd2); + release_iface(sfd3); + + testmode = 1; + hr = IWidget_iface_in(widget, NULL, NULL, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + testmode = 0; + proxy_unk = (IUnknown *)0xdeadbeef; + proxy_disp = (IDispatch *)0xdeadbeef; + proxy_sfd = (ISomethingFromDispatch *)0xdeadbeef; + hr = IWidget_iface_out(widget, &proxy_unk, &proxy_disp, &proxy_sfd); + ok(hr == S_OK, "Got hr %#x.\n", hr); + check_iface_marshal(proxy_unk, proxy_disp, proxy_sfd); + release_iface(proxy_unk); + release_iface(proxy_disp); + release_iface(proxy_sfd); + + testmode = 1; + hr = IWidget_iface_out(widget, &proxy_unk, &proxy_disp, &proxy_sfd); + ok(hr == S_OK, "Got hr %#x.\n", hr); +todo_wine { + ok(!proxy_unk, "Got unexpected proxy %p.\n", proxy_unk); + ok(!proxy_disp, "Got unexpected proxy %p.\n", proxy_disp); + ok(!proxy_sfd, "Got unexpected proxy %p.\n", proxy_sfd); +} + + testmode = 0; + sfd_in = sfd1 = create_disp_obj(); + sfd_out = sfd2 = create_disp_obj(); + sfd_in_out = sfd3 = create_disp_obj(); + hr = IWidget_iface_ptr(widget, &sfd_in, &sfd_out, &sfd_in_out); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(sfd_in == sfd1, "[in] parameter should not have changed.\n"); +todo_wine + ok(!sfd_out, "[out] parameter should have been cleared.\n"); + ok(sfd_in_out == sfd3, "[in, out] parameter should not have changed.\n"); + release_iface(sfd1); + release_iface(sfd2); + release_iface(sfd3); + + testmode = 1; + sfd_in = sfd1 = create_disp_obj(); + sfd_in_out = sfd3 = create_disp_obj(); + ISomethingFromDispatch_AddRef(sfd_in_out); + hr = IWidget_iface_ptr(widget, &sfd_in, &sfd_out, &sfd_in_out); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = ISomethingFromDispatch_anotherfn(sfd_out); + ok(hr == 0x01234567, "Got hr %#x.\n", hr); + ok(sfd_in_out != sfd3, "[in, out] parameter should have changed.\n"); + hr = ISomethingFromDispatch_anotherfn(sfd_in_out); + ok(hr == 0x01234567, "Got hr %#x.\n", hr); + release_iface(sfd_out); + release_iface(sfd_in_out); + release_iface(sfd1); + release_iface(sfd3); + + testmode = 2; + sfd_in = sfd_out = sfd_in_out = NULL; + hr = IWidget_iface_ptr(widget, &sfd_in, &sfd_out, &sfd_in_out); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!sfd_out, "[out] parameter should not have been set.\n"); + hr = ISomethingFromDispatch_anotherfn(sfd_in_out); + ok(hr == 0x01234567, "Got hr %#x.\n", hr); + release_iface(sfd_in_out); + + testmode = 3; + sfd_in = sfd_out = NULL; + sfd_in_out = sfd3 = create_disp_obj(); + ISomethingFromDispatch_AddRef(sfd_in_out); + hr = IWidget_iface_ptr(widget, &sfd_in, &sfd_out, &sfd_in_out); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!sfd_in_out, "Got [in, out] %p.\n", sfd_in_out); + release_iface(sfd3); + + /* Test with Invoke(). Note that since we pass VT_UNKNOWN, we don't get our + * interface back, but rather an IUnknown. */ + + testmode = 0; + sfd1 = create_disp_obj(); + sfd2 = create_disp_obj(); + sfd3 = create_disp_obj(); + + V_VT(&arg[2]) = VT_UNKNOWN; V_UNKNOWN(&arg[2]) = (IUnknown *)sfd1; + V_VT(&arg[1]) = VT_UNKNOWN; V_UNKNOWN(&arg[1]) = (IUnknown *)sfd2; + V_VT(&arg[0]) = VT_UNKNOWN; V_UNKNOWN(&arg[0]) = (IUnknown *)sfd3; + hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_IN, &IID_NULL, LOCALE_NEUTRAL, + DISPATCH_METHOD, &dispparams, NULL, NULL, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + V_VT(&arg[2]) = VT_DISPATCH; V_DISPATCH(&arg[2]) = (IDispatch *)sfd1; + V_VT(&arg[1]) = VT_DISPATCH; V_DISPATCH(&arg[1]) = (IDispatch *)sfd2; + V_VT(&arg[0]) = VT_DISPATCH; V_DISPATCH(&arg[0]) = (IDispatch *)sfd3; + hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_IN, &IID_NULL, LOCALE_NEUTRAL, + DISPATCH_METHOD, &dispparams, NULL, NULL, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + release_iface(sfd1); + release_iface(sfd2); + release_iface(sfd3); + + testmode = 1; + V_VT(&arg[2]) = VT_UNKNOWN; V_UNKNOWN(&arg[2]) = NULL; + V_VT(&arg[1]) = VT_UNKNOWN; V_UNKNOWN(&arg[1]) = NULL; + V_VT(&arg[0]) = VT_UNKNOWN; V_UNKNOWN(&arg[0]) = NULL; + hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_IN, &IID_NULL, LOCALE_NEUTRAL, + DISPATCH_METHOD, &dispparams, NULL, NULL, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + testmode = 0; + proxy_unk = proxy_unk2 = NULL; + proxy_disp = NULL; + V_VT(&arg[2]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[2]) = &proxy_unk; + V_VT(&arg[1]) = VT_DISPATCH|VT_BYREF; V_DISPATCHREF(&arg[1]) = &proxy_disp; + V_VT(&arg[0]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[0]) = &proxy_unk2; + hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_OUT, &IID_NULL, LOCALE_NEUTRAL, + DISPATCH_METHOD, &dispparams, NULL, NULL, NULL); +todo_wine + ok(hr == S_OK, "Got hr %#x.\n", hr); +if (hr == S_OK) { + hr = IUnknown_QueryInterface(proxy_unk2, &IID_ISomethingFromDispatch, (void **)&proxy_sfd); + ok(hr == S_OK, "Got hr %#x.\n", hr); + check_iface_marshal(proxy_unk, proxy_disp, proxy_sfd); + ISomethingFromDispatch_Release(proxy_sfd); + release_iface(proxy_unk); + release_iface(proxy_disp); + release_iface(proxy_unk2); +} + + testmode = 1; + proxy_unk = proxy_unk2 = NULL; + proxy_disp = NULL; + hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_OUT, &IID_NULL, LOCALE_NEUTRAL, + DISPATCH_METHOD, &dispparams, NULL, NULL, NULL); +todo_wine + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!proxy_unk, "Got unexpected proxy %p.\n", proxy_unk); + ok(!proxy_disp, "Got unexpected proxy %p.\n", proxy_disp); + ok(!proxy_unk2, "Got unexpected proxy %p.\n", proxy_unk2); + + testmode = 0; + sfd1 = create_disp_obj(); + sfd3 = create_disp_obj(); + unk_in = (IUnknown *)sfd1; + unk_out = NULL; + unk_in_out = (IUnknown *)sfd3; + V_VT(&arg[2]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[2]) = &unk_in; + V_VT(&arg[1]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[1]) = &unk_out; + V_VT(&arg[0]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[0]) = &unk_in_out; + hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_PTR, &IID_NULL, LOCALE_NEUTRAL, + DISPATCH_METHOD, &dispparams, NULL, NULL, NULL); +todo_wine + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(unk_in == (IUnknown *)sfd1, "[in] parameter should not have changed.\n"); + ok(!unk_out, "[out] parameter should have been cleared.\n"); + ok(unk_in_out == (IUnknown *)sfd3, "[in, out] parameter should not have changed.\n"); + release_iface(sfd1); + release_iface(sfd3); + + testmode = 1; + sfd1 = create_disp_obj(); + sfd3 = create_disp_obj(); + unk_in = (IUnknown *)sfd1; + unk_out = NULL; + unk_in_out = (IUnknown *)sfd3; + IUnknown_AddRef(unk_in_out); + hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_PTR, &IID_NULL, LOCALE_NEUTRAL, + DISPATCH_METHOD, &dispparams, NULL, NULL, NULL); +todo_wine + ok(hr == S_OK, "Got hr %#x.\n", hr); + +if (hr == S_OK) { + hr = IUnknown_QueryInterface(unk_out, &IID_ISomethingFromDispatch, (void **)&sfd_out); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = ISomethingFromDispatch_anotherfn(sfd_out); + ok(hr == 0x01234567, "Got hr %#x.\n", hr); + ISomethingFromDispatch_Release(sfd_out); + + ok(unk_in_out != (IUnknown *)sfd3, "[in, out] parameter should have changed.\n"); + hr = IUnknown_QueryInterface(unk_in_out, &IID_ISomethingFromDispatch, (void **)&sfd_in_out); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = ISomethingFromDispatch_anotherfn(sfd_in_out); + ok(hr == 0x01234567, "Got hr %#x.\n", hr); + ISomethingFromDispatch_Release(sfd_in_out); + + release_iface(unk_out); + release_iface(unk_in_out); + release_iface(sfd1); + release_iface(sfd3); +} + + testmode = 2; + unk_in = unk_out = unk_in_out = NULL; + hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_PTR, &IID_NULL, LOCALE_NEUTRAL, + DISPATCH_METHOD, &dispparams, NULL, NULL, NULL); +todo_wine + ok(hr == S_OK, "Got hr %#x.\n", hr); + + ok(!unk_out, "[out] parameter should not have been set.\n"); +if (hr == S_OK) { + hr = IUnknown_QueryInterface(unk_in_out, &IID_ISomethingFromDispatch, (void **)&sfd_in_out); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = ISomethingFromDispatch_anotherfn(sfd_in_out); + ok(hr == 0x01234567, "Got hr %#x.\n", hr); + ISomethingFromDispatch_Release(sfd_in_out); + + release_iface(unk_in_out); +} + + testmode = 3; + unk_in = unk_out = NULL; + sfd3 = create_disp_obj(); + unk_in_out = (IUnknown *)sfd3; + IUnknown_AddRef(unk_in_out); + hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_PTR, &IID_NULL, LOCALE_NEUTRAL, + DISPATCH_METHOD, &dispparams, NULL, NULL, NULL); +todo_wine { + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!unk_in_out, "[in, out] parameter should have been cleared.\n"); + release_iface(sfd3); +} +} + static void test_typelibmarshal(void) { static const WCHAR szCat[] = { 'C','a','t',0 }; @@ -2192,6 +2619,7 @@ static void test_typelibmarshal(void)
test_marshal_basetypes(pWidget, pDispatch); test_marshal_pointer(pWidget, pDispatch); + test_marshal_iface(pWidget, pDispatch);
IDispatch_Release(pDispatch); IWidget_Release(pWidget); diff --git a/dlls/oleaut32/tests/tmarshal.idl b/dlls/oleaut32/tests/tmarshal.idl index 3cbad57..7e02453 100644 --- a/dlls/oleaut32/tests/tmarshal.idl +++ b/dlls/oleaut32/tests/tmarshal.idl @@ -59,6 +59,9 @@ enum IWidget_dispids DISPID_TM_BASETYPES_OUT, DISPID_TM_INT_PTR, DISPID_TM_INT_PTR_PTR, + DISPID_TM_IFACE_IN, + DISPID_TM_IFACE_OUT, + DISPID_TM_IFACE_PTR, };
static const int DISPID_TM_NEG_RESTRICTED = -26; @@ -95,6 +98,7 @@ library TestTypelib
[ odl, + oleautomation, uuid(12345678-1234-4321-1234-121212121212) ] interface ISomethingFromDispatch : IDispatch @@ -250,6 +254,15 @@ library TestTypelib
[id(DISPID_TM_INT_PTR_PTR)] HRESULT int_ptr_ptr([in] int **in, [out] int **out, [in, out] int **in_out); + + [id(DISPID_TM_IFACE_IN)] + HRESULT iface_in([in] IUnknown *unk, [in] IDispatch *disp, [in] ISomethingFromDispatch *sfd); + + [id(DISPID_TM_IFACE_OUT)] + HRESULT iface_out([out] IUnknown **unk, [out] IDispatch **disp, [out] ISomethingFromDispatch **sfd); + + [id(DISPID_TM_IFACE_PTR)] + HRESULT iface_ptr([in] ISomethingFromDispatch **in, [out] ISomethingFromDispatch **out, [in, out] ISomethingFromDispatch **in_out); }
[
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=43139
Your paranoid android.
=== wxppro (32 bit Windows report) ===
oleaut32: tmarshal.c:1743: Test failed: Got hr 0x80010105. tmarshal.c:1744: Test failed: Got [in, out] 0022FB00.
=== wvistau64 (64 bit Windows report) ===
Report errors: oleaut32:tmarshal crashed (c0000374)
=== w2008s64 (64 bit Windows report) ===
Report errors: oleaut32:tmarshal crashed (c0000374)
=== w7pro64 (64 bit Windows report) ===
Report errors: oleaut32:tmarshal crashed (c0000374)
=== w864 (64 bit Windows report) ===
Report errors: oleaut32:tmarshal crashed (c0000374)
=== w1064 (64 bit Windows report) ===
Report errors: oleaut32:tmarshal crashed (c0000374)
=== debian9 (32 bit Wine report) ===
oleaut32: tmarshal.c:1072: Test succeeded inside todo block: Got [out] 0. tmarshal.c:1681: Test succeeded inside todo block: Got [in] 123. Unhandled exception: page fault on write access to 0x00000000 in 32-bit code (0x7eb78d06). typelib.c:5688: Test failed: got 0x00000000
Report errors: oleaut32:tmarshal crashed (c0000005)
=== debian9 (build log) ===