Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/oleaut32/tests/tmarshal.c | 178 +++++++++++++++++++++++++++++++ dlls/oleaut32/tests/tmarshal.idl | 8 ++ 2 files changed, 186 insertions(+)
diff --git a/dlls/oleaut32/tests/tmarshal.c b/dlls/oleaut32/tests/tmarshal.c index 68547f7e98..01df9efe3a 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,60 @@ 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); + *in_out = NULL; + } + + return S_OK; +} + static const struct IWidgetVtbl Widget_VTable = { Widget_QueryInterface, @@ -1005,6 +1061,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 +1460,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 +2190,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 2452f2d185..3cbad57085 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); }
[
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 0185b6d155..97c05024e5 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 d3dc93a206..163b48f6f4 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; } }
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 01df9efe3a..8581ec9e10 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 @@ -1018,6 +1116,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, @@ -1063,6 +1247,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) @@ -1579,6 +1766,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 }; @@ -2191,6 +2618,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 3cbad57085..7e02453c41 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=43600
Your paranoid android.
=== debian9 (32 bit Wine report) ===
oleaut32: tmarshal.c:1072: Test succeeded inside todo block: Got [out] 0. tmarshal.c:1680: Test succeeded inside todo block: Got [in] 123. Unhandled exception: page fault on write access to 0x00000000 in 32-bit code (0x7eb8fd06). typelib.c:5688: Test failed: got 0x00000000
Report errors: oleaut32:tmarshal crashed (c0000005)
=== debian9 (build log) ===
=== debian9 (32 bit WoW Wine report) ===
oleaut32: tmarshal.c:1072: Test succeeded inside todo block: Got [out] 0. tmarshal.c:1680: Test succeeded inside todo block: Got [in] 123. Unhandled exception: page fault on write access to 0x00000000 in 32-bit code (0x7eb82d06). 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 | 93 ++++++++++++++++++++++++++++++++ dlls/oleaut32/tests/tmarshal.idl | 4 ++ 2 files changed, 97 insertions(+)
diff --git a/dlls/oleaut32/tests/tmarshal.c b/dlls/oleaut32/tests/tmarshal.c index 8581ec9e10..b705f40a40 100644 --- a/dlls/oleaut32/tests/tmarshal.c +++ b/dlls/oleaut32/tests/tmarshal.c @@ -50,6 +50,11 @@ static const int tmarshal_todo = 1; /* ULL suffix is not portable */ #define ULL_CONST(dw1, dw2) ((((ULONGLONG)dw1) << 32) | (ULONGLONG)dw2)
+static const WCHAR test_bstr1[] = {'f','o','o',0,'b','a','r'}; +static const WCHAR test_bstr2[] = {'t','e','s','t',0}; +static const WCHAR test_bstr3[] = {'q','u','x',0}; +static const WCHAR test_bstr4[] = {'a','b','c',0}; + const MYSTRUCT MYSTRUCT_BYVAL = {0x12345678, ULL_CONST(0xdeadbeef, 0x98765432), {0,1,2,3,4,5,6,7}}; const MYSTRUCT MYSTRUCT_BYPTR = {0x91827364, ULL_CONST(0x88776655, 0x44332211), {0,1,2,3,4,5,6,7}}; const MYSTRUCT MYSTRUCT_ARRAY[5] = { @@ -1202,6 +1207,37 @@ todo_wine_if(testmode == 0 || testmode == 1) return S_OK; }
+static HRESULT WINAPI Widget_bstr(IWidget *iface, BSTR in, BSTR *out, BSTR *in_ptr, BSTR *in_out) +{ + UINT len; + + if (testmode == 0) + { + len = SysStringByteLen(in); + ok(len == sizeof(test_bstr1), "Got wrong length %u.\n", len); + ok(!memcmp(in, test_bstr1, len), "Got string %s.\n", wine_dbgstr_wn(in, len / sizeof(WCHAR))); +todo_wine_if(*out) + ok(!*out, "Got unexpected output %p.\n", *out); + len = SysStringLen(*in_ptr); + ok(len == lstrlenW(test_bstr2), "Got wrong length %u.\n", len); + ok(!memcmp(*in_ptr, test_bstr2, len), "Got string %s.\n", wine_dbgstr_w(*in_ptr)); + len = SysStringLen(*in_out); + ok(len == lstrlenW(test_bstr3), "Got wrong length %u.\n", len); + ok(!memcmp(*in_out, test_bstr3, len), "Got string %s.\n", wine_dbgstr_w(*in_out)); + + *out = SysAllocString(test_bstr4); + in[1] = (*in_ptr)[1] = (*in_out)[1] = 'X'; + } + else if (testmode == 1) + { + ok(!in, "Got string %s.\n", wine_dbgstr_w(in)); + ok(!*out, "Got string %s.\n", wine_dbgstr_w(*out)); + ok(!*in_ptr, "Got string %s.\n", wine_dbgstr_w(*in_ptr)); + ok(!*in_out, "Got string %s.\n", wine_dbgstr_w(*in_out)); + } + return S_OK; +} + static const struct IWidgetVtbl Widget_VTable = { Widget_QueryInterface, @@ -1250,6 +1286,7 @@ static const struct IWidgetVtbl Widget_VTable = Widget_iface_in, Widget_iface_out, Widget_iface_ptr, + Widget_bstr, };
static HRESULT WINAPI StaticWidget_QueryInterface(IStaticWidget *iface, REFIID riid, void **ppvObject) @@ -2006,6 +2043,61 @@ todo_wine { } }
+static void test_marshal_bstr(IWidget *widget, IDispatch *disp) +{ + VARIANTARG arg[4]; + DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0}; + BSTR in, out, in_ptr, in_out; + HRESULT hr; + UINT len; + + testmode = 0; + in = SysAllocStringLen(test_bstr1, ARRAY_SIZE(test_bstr1)); + out = NULL; + in_ptr = SysAllocString(test_bstr2); + in_out = SysAllocString(test_bstr3); + + V_VT(&arg[3]) = VT_BSTR; V_BSTR(&arg[3]) = in; + V_VT(&arg[2]) = VT_BSTR|VT_BYREF; V_BSTRREF(&arg[2]) = &out; + V_VT(&arg[1]) = VT_BSTR|VT_BYREF; V_BSTRREF(&arg[1]) = &in_ptr; + V_VT(&arg[0]) = VT_BSTR|VT_BYREF; V_BSTRREF(&arg[0]) = &in_out; + hr = IDispatch_Invoke(disp, DISPID_TM_BSTR, &IID_NULL, LOCALE_NEUTRAL, + DISPATCH_METHOD, &dispparams, NULL, NULL, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); +todo_wine + ok(in[1] == test_bstr1[1], "[in] parameter should not be changed.\n"); + ok(in_ptr[1] == 'X', "[in] pointer should be changed.\n"); + ok(in_out[1] == 'X', "[in, out] parameter should be changed.\n"); + len = SysStringLen(out); + ok(len == lstrlenW(test_bstr4), "Got wrong length %d.\n", len); + ok(!memcmp(out, test_bstr4, len), "Got string %s.\n", wine_dbgstr_wn(out, len)); + + in[1] = test_bstr1[1]; + in_ptr[1] = test_bstr2[1]; + in_out[1] = test_bstr3[1]; + SysFreeString(out); + out = (BSTR)0xdeadbeef; + hr = IWidget_bstr(widget, in, &out, &in_ptr, &in_out); + ok(hr == S_OK, "Got hr %#x.\n", hr); +todo_wine { + ok(in[1] == test_bstr1[1], "[in] parameter should not be changed.\n"); + ok(in_ptr[1] == test_bstr2[1], "[in] pointer should not be changed.\n"); +} + ok(in_out[1] == 'X', "[in, out] parameter should be changed.\n"); + len = SysStringLen(out); + ok(len == lstrlenW(test_bstr4), "Got wrong length %d.\n", len); + ok(!memcmp(out, test_bstr4, len), "Got string %s.\n", wine_dbgstr_wn(out, len)); + SysFreeString(in); + SysFreeString(out); + SysFreeString(in_ptr); + SysFreeString(in_out); + + testmode = 1; + out = in_ptr = in_out = NULL; + hr = IWidget_bstr(widget, NULL, &out, &in_ptr, &in_out); + ok(hr == S_OK, "Got hr %#x.\n", hr); +} + static void test_typelibmarshal(void) { static const WCHAR szCat[] = { 'C','a','t',0 }; @@ -2619,6 +2711,7 @@ static void test_typelibmarshal(void) test_marshal_basetypes(pWidget, pDispatch); test_marshal_pointer(pWidget, pDispatch); test_marshal_iface(pWidget, pDispatch); + test_marshal_bstr(pWidget, pDispatch);
IDispatch_Release(pDispatch); IWidget_Release(pWidget); diff --git a/dlls/oleaut32/tests/tmarshal.idl b/dlls/oleaut32/tests/tmarshal.idl index 7e02453c41..3749c6a7aa 100644 --- a/dlls/oleaut32/tests/tmarshal.idl +++ b/dlls/oleaut32/tests/tmarshal.idl @@ -62,6 +62,7 @@ enum IWidget_dispids DISPID_TM_IFACE_IN, DISPID_TM_IFACE_OUT, DISPID_TM_IFACE_PTR, + DISPID_TM_BSTR, };
static const int DISPID_TM_NEG_RESTRICTED = -26; @@ -263,6 +264,9 @@ library TestTypelib
[id(DISPID_TM_IFACE_PTR)] HRESULT iface_ptr([in] ISomethingFromDispatch **in, [out] ISomethingFromDispatch **out, [in, out] ISomethingFromDispatch **in_out); + + [id(DISPID_TM_BSTR)] + HRESULT bstr([in] BSTR in, [out] BSTR *out, [in] BSTR *in_ptr, [in, out] BSTR *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=43601
Your paranoid android.
=== debian9 (32 bit Wine report) ===
oleaut32: tmarshal.c:1077: Test succeeded inside todo block: Got [out] 0. tmarshal.c:1717: Test succeeded inside todo block: Got [in] 123. Unhandled exception: page fault on write access to 0x00000000 in 32-bit code (0x7eb8ed06). typelib.c:5688: Test failed: got 0x00000000
Report errors: oleaut32:tmarshal crashed (c0000005)
=== debian9 (build log) ===
=== debian9 (32 bit WoW Wine report) ===
oleaut32: tmarshal.c:1077: Test succeeded inside todo block: Got [out] 0. tmarshal.c:1717: Test succeeded inside todo block: Got [in] 123. Unhandled exception: page fault on write access to 0x00000000 in 32-bit code (0x7eb77d06). 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 | 116 +++++++++++++++++++++++-------- dlls/oleaut32/tests/tmarshal.idl | 8 +-- 2 files changed, 92 insertions(+), 32 deletions(-)
diff --git a/dlls/oleaut32/tests/tmarshal.c b/dlls/oleaut32/tests/tmarshal.c index b705f40a40..e09aaa21c2 100644 --- a/dlls/oleaut32/tests/tmarshal.c +++ b/dlls/oleaut32/tests/tmarshal.c @@ -782,17 +782,6 @@ static HRESULT WINAPI Widget_VariantCArray( return S_OK; }
-static HRESULT WINAPI Widget_Variant( - IWidget __RPC_FAR * iface, - VARIANT var) -{ - trace("Variant()\n"); - ok(V_VT(&var) == VT_CY, "V_VT(&var) was %d\n", V_VT(&var)); - ok(S(V_CY(&var)).Hi == 0xdababe, "V_CY(&var).Hi was 0x%x\n", S(V_CY(&var)).Hi); - ok(S(V_CY(&var)).Lo == 0xdeadbeef, "V_CY(&var).Lo was 0x%x\n", S(V_CY(&var)).Lo); - return S_OK; -} - static HRESULT WINAPI Widget_VarArg( IWidget * iface, int numexpect, @@ -1238,6 +1227,37 @@ todo_wine_if(*out) return S_OK; }
+static HRESULT WINAPI Widget_variant(IWidget *iface, VARIANT in, VARIANT *out, VARIANT *in_ptr, VARIANT *in_out) +{ + ok(V_VT(&in) == VT_CY, "Got wrong type %#x.\n", V_VT(&in)); + ok(V_CY(&in).Hi == 0xdababe && V_CY(&in).Lo == 0xdeadbeef, + "Got wrong value %s.\n", wine_dbgstr_longlong(V_CY(&in).int64)); + if (testmode == 0) + { + ok(V_VT(out) == VT_I4, "Got wrong type %u.\n", V_VT(out)); + ok(V_I4(out) == 1, "Got wrong value %d.\n", V_I4(out)); + } + else +todo_wine + ok(V_VT(out) == VT_EMPTY, "Got wrong type %u.\n", V_VT(out)); + ok(V_VT(in_ptr) == VT_I4, "Got wrong type %u.\n", V_VT(in_ptr)); + ok(V_I4(in_ptr) == -1, "Got wrong value %d.\n", V_I4(in_ptr)); + ok(V_VT(in_out) == VT_BSTR, "Got wrong type %u.\n", V_VT(in_out)); + ok(!lstrcmpW(V_BSTR(in_out), test_bstr2), "Got wrong value %s.\n", + wine_dbgstr_w(V_BSTR(in_out))); + + V_VT(&in) = VT_I4; + V_I4(&in) = 2; + V_VT(out) = VT_UI1; + V_UI1(out) = 3; + V_VT(in_ptr) = VT_I2; + V_I2(in_ptr) = 4; + VariantClear(in_out); + V_VT(in_out) = VT_I1; + V_I1(in_out) = 5; + return S_OK; +} + static const struct IWidgetVtbl Widget_VTable = { Widget_QueryInterface, @@ -1262,7 +1282,6 @@ static const struct IWidgetVtbl Widget_VTable = Widget_Array, Widget_VariantArrayPtr, Widget_VariantCArray, - Widget_Variant, Widget_VarArg, Widget_StructArgs, Widget_Error, @@ -1287,6 +1306,7 @@ static const struct IWidgetVtbl Widget_VTable = Widget_iface_out, Widget_iface_ptr, Widget_bstr, + Widget_variant, };
static HRESULT WINAPI StaticWidget_QueryInterface(IStaticWidget *iface, REFIID riid, void **ppvObject) @@ -2098,6 +2118,61 @@ todo_wine { ok(hr == S_OK, "Got hr %#x.\n", hr); }
+static void test_marshal_variant(IWidget *widget, IDispatch *disp) +{ + VARIANTARG arg[4]; + DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0}; + VARIANT out, in_ptr, in_out; + HRESULT hr; + BSTR bstr; + + testmode = 0; + V_VT(&out) = VT_I4; + V_I4(&out) = 1; + V_VT(&in_ptr) = VT_I4; + V_I4(&in_ptr) = -1; + V_VT(&in_out) = VT_BSTR; + V_BSTR(&in_out) = bstr = SysAllocString(test_bstr2); + + V_VT(&arg[3]) = VT_CY; + V_CY(&arg[3]).Hi = 0xdababe; + V_CY(&arg[3]).Lo = 0xdeadbeef; + V_VT(&arg[2]) = VT_VARIANT|VT_BYREF; V_VARIANTREF(&arg[2]) = &out; + V_VT(&arg[1]) = VT_VARIANT|VT_BYREF; V_VARIANTREF(&arg[1]) = &in_ptr; + V_VT(&arg[0]) = VT_VARIANT|VT_BYREF; V_VARIANTREF(&arg[0]) = &in_out; + hr = IDispatch_Invoke(disp, DISPID_TM_VARIANT, &IID_NULL, LOCALE_NEUTRAL, + DISPATCH_METHOD, &dispparams, NULL, NULL, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(V_VT(&arg[3]) == VT_CY, "Got wrong type %u.\n", V_VT(&arg[3])); + ok(V_VT(&out) == VT_UI1, "Got wrong type %u.\n", V_VT(&out)); + ok(V_UI1(&out) == 3, "Got wrong value %d.\n", V_UI1(&out)); + VariantClear(&out); + ok(V_VT(&in_ptr) == VT_I2, "Got wrong type %u.\n", V_VT(&in_ptr)); + ok(V_I2(&in_ptr) == 4, "Got wrong value %d.\n", V_I1(&in_ptr)); + ok(V_VT(&in_out) == VT_I1, "Got wrong type %u.\n", V_VT(&in_out)); + ok(V_I1(&in_out) == 5, "Got wrong value %d.\n", V_I1(&in_out)); + SysFreeString(bstr); + + testmode = 1; + V_VT(&out) = VT_I4; + V_I4(&out) = 1; + V_VT(&in_ptr) = VT_I4; + V_I4(&in_ptr) = -1; + V_VT(&in_out) = VT_BSTR; + V_BSTR(&in_out) = bstr; + hr = IWidget_variant(widget, arg[3], &out, &in_ptr, &in_out); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(V_VT(&arg[3]) == VT_CY, "Got wrong type %u.\n", V_VT(&arg[3])); + ok(V_VT(&out) == VT_UI1, "Got wrong type %u.\n", V_VT(&out)); + ok(V_UI1(&out) == 3, "Got wrong value %d.\n", V_UI1(&out)); +todo_wine { + ok(V_VT(&in_ptr) == VT_I4, "Got wrong type %u.\n", V_VT(&in_ptr)); + ok(V_I2(&in_ptr) == -1, "Got wrong value %d.\n", V_I1(&in_ptr)); +} + ok(V_VT(&in_out) == VT_I1, "Got wrong type %u.\n", V_VT(&in_out)); + ok(V_I1(&in_out) == 5, "Got wrong value %d.\n", V_I1(&in_out)); +} + static void test_typelibmarshal(void) { static const WCHAR szCat[] = { 'C','a','t',0 }; @@ -2375,22 +2450,6 @@ static void test_typelibmarshal(void) ok(V_I2(&varresult) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult)); VariantClear(&varresult);
- /* call Variant - exercises variant copying in ITypeInfo::Invoke and - * handling of void return types */ - /* use a big type to ensure that the variant was properly copied into the - * destination function's args */ - V_VT(&vararg[0]) = VT_CY; - S(V_CY(&vararg[0])).Hi = 0xdababe; - S(V_CY(&vararg[0])).Lo = 0xdeadbeef; - dispparams.cNamedArgs = 0; - dispparams.cArgs = 1; - dispparams.rgdispidNamedArgs = NULL; - dispparams.rgvarg = vararg; - VariantInit(&varresult); - hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARIANT, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL); - ok_ole_success(hr, IDispatch_Invoke); - VariantClear(&varresult); - /* call Array with BSTR argument - type mismatch */ VariantInit(&vararg[0]); V_VT(&vararg[0]) = VT_BSTR; @@ -2712,6 +2771,7 @@ static void test_typelibmarshal(void) test_marshal_pointer(pWidget, pDispatch); test_marshal_iface(pWidget, pDispatch); test_marshal_bstr(pWidget, pDispatch); + test_marshal_variant(pWidget, pDispatch);
IDispatch_Release(pDispatch); IWidget_Release(pWidget); diff --git a/dlls/oleaut32/tests/tmarshal.idl b/dlls/oleaut32/tests/tmarshal.idl index 3749c6a7aa..16d2f9d2d9 100644 --- a/dlls/oleaut32/tests/tmarshal.idl +++ b/dlls/oleaut32/tests/tmarshal.idl @@ -37,7 +37,6 @@ enum IWidget_dispids DISPID_TM_ARRAY, DISPID_TM_VARARRAYPTR, DISPID_TM_VARCARRAY, - DISPID_TM_VARIANT, DISPID_TM_VARARG, DISPID_TM_STRUCTARGS, DISPID_TM_ERROR, @@ -63,6 +62,7 @@ enum IWidget_dispids DISPID_TM_IFACE_OUT, DISPID_TM_IFACE_PTR, DISPID_TM_BSTR, + DISPID_TM_VARIANT, };
static const int DISPID_TM_NEG_RESTRICTED = -26; @@ -189,9 +189,6 @@ library TestTypelib [id(DISPID_TM_VARCARRAY)] HRESULT VariantCArray([in] ULONG count, [in, out] VARIANT values[2]);
- [id(DISPID_TM_VARIANT)] - HRESULT Variant([in] VARIANT var); - [vararg, id(DISPID_TM_VARARG)] HRESULT VarArg([in] int numexpect, [in] SAFEARRAY(VARIANT) values);
@@ -267,6 +264,9 @@ library TestTypelib
[id(DISPID_TM_BSTR)] HRESULT bstr([in] BSTR in, [out] BSTR *out, [in] BSTR *in_ptr, [in, out] BSTR *in_out); + + [id(DISPID_TM_VARIANT)] + HRESULT variant([in] VARIANT in, [out] VARIANT *out, [in] VARIANT *in_ptr, [in, out] VARIANT *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=43602
Your paranoid android.
=== debian9 (32 bit Wine report) ===
oleaut32: tmarshal.c:1066: Test succeeded inside todo block: Got [out] 0. tmarshal.c:1737: Test succeeded inside todo block: Got [in] 123. Unhandled exception: page fault on write access to 0x00000000 in 32-bit code (0x7eb77d06). typelib.c:5688: Test failed: got 0x00000000
Report errors: oleaut32:tmarshal crashed (c0000005)
=== debian9 (build log) ===
=== debian9 (32 bit WoW Wine report) ===
oleaut32: tmarshal.c:1066: Test succeeded inside todo block: Got [out] 0. tmarshal.c:1737: Test succeeded inside todo block: Got [in] 123. Unhandled exception: page fault on write access to 0x00000000 in 32-bit code (0x7eb77d06). typelib.c:5688: Test failed: got 0x00000000
Report errors: oleaut32:tmarshal crashed (c0000005)
=== debian9 (build log) ===
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=43598
Your paranoid android.
=== debian9 (32 bit Wine report) ===
oleaut32: tmarshal.c:974: Test succeeded inside todo block: Got [out] 0. tmarshal.c:1493: 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) ===
=== debian9 (32 bit WoW Wine report) ===
oleaut32: tmarshal.c:974: Test succeeded inside todo block: Got [out] 0. tmarshal.c:1493: 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) ===