Signed-off-by: Zebediah Figura <z.figura12(a)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);
}
[
--
2.18.0