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); }
[