[PATCH 3/5] oleaut32/tests: Add some tests for marshalling interfaces.
Zebediah Figura
z.figura12 at gmail.com
Sun Oct 28 18:04:14 CDT 2018
Signed-off-by: Zebediah Figura <z.figura12 at 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);
}
[
--
2.18.0
More information about the wine-devel
mailing list