[PATCH 2/2] oleaut32/tests: Add some tests for marshalling of coclasses.

Zebediah Figura z.figura12 at gmail.com
Tue Nov 13 22:21:58 CST 2018


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/oleaut32/tests/tmarshal.c   | 451 +++++++++++++++++++++++++++++--
 dlls/oleaut32/tests/tmarshal.idl |  57 +++-
 2 files changed, 480 insertions(+), 28 deletions(-)

diff --git a/dlls/oleaut32/tests/tmarshal.c b/dlls/oleaut32/tests/tmarshal.c
index 4049d195e0..c26feb121f 100644
--- a/dlls/oleaut32/tests/tmarshal.c
+++ b/dlls/oleaut32/tests/tmarshal.c
@@ -487,6 +487,176 @@ static ISomethingFromDispatch *create_disp_obj(void)
     return &obj->ISomethingFromDispatch_iface;
 }
 
+struct coclass_obj
+{
+    ICoclass1 ICoclass1_iface;
+    ICoclass2 ICoclass2_iface;
+    LONG ref;
+};
+
+static inline struct coclass_obj *impl_from_ICoclass1(ICoclass1 *iface)
+{
+    return CONTAINING_RECORD(iface, struct coclass_obj, ICoclass1_iface);
+}
+
+static inline struct coclass_obj *impl_from_ICoclass2(ICoclass2 *iface)
+{
+    return CONTAINING_RECORD(iface, struct coclass_obj, ICoclass2_iface);
+}
+
+static HRESULT WINAPI coclass1_QueryInterface(ICoclass1 *iface, REFIID iid, void **out)
+{
+    struct coclass_obj *obj = impl_from_ICoclass1(iface);
+
+    if (IsEqualGUID(iid, &IID_IUnknown)
+            || IsEqualGUID(iid, &IID_IDispatch)
+            || IsEqualGUID(iid, &IID_ICoclass1))
+    {
+        *out = iface;
+        ICoclass1_AddRef(iface);
+        return S_OK;
+    }
+    else if (IsEqualGUID(iid, &IID_ICoclass2))
+    {
+        *out = &obj->ICoclass2_iface;
+        ICoclass2_AddRef(*out);
+        return S_OK;
+    }
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI coclass1_AddRef(ICoclass1 *iface)
+{
+    struct coclass_obj *obj = impl_from_ICoclass1(iface);
+    return ++obj->ref;
+}
+
+static ULONG WINAPI coclass1_Release(ICoclass1 *iface)
+{
+    struct coclass_obj *obj = impl_from_ICoclass1(iface);
+    LONG ref = --obj->ref;
+    if (!ref)
+        CoTaskMemFree(obj);
+    return ref;
+}
+
+static HRESULT WINAPI coclass1_GetTypeInfoCount(ICoclass1 *iface, UINT *count)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI coclass1_GetTypeInfo(ICoclass1 *iface, UINT index,
+        LCID lcid, ITypeInfo **typeinfo)
+{
+    ok(index == 0xdeadbeef, "Got unexpected index %#x.\n", index);
+    return 0xbeefdead;
+}
+
+static HRESULT WINAPI coclass1_GetIDsOfNames(ICoclass1 *iface, REFIID iid,
+        LPOLESTR *names, UINT count, LCID lcid, DISPID *ids)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI coclass1_Invoke(ICoclass1 *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 coclass1_test(ICoclass1 *iface)
+{
+    return 1;
+}
+
+static HRESULT WINAPI coclass2_QueryInterface(ICoclass2 *iface, REFIID iid, void **out)
+{
+    struct coclass_obj *obj = impl_from_ICoclass2(iface);
+    return ICoclass1_QueryInterface(&obj->ICoclass1_iface, iid, out);
+}
+
+static ULONG WINAPI coclass2_AddRef(ICoclass2 *iface)
+{
+    struct coclass_obj *obj = impl_from_ICoclass2(iface);
+    return ICoclass1_AddRef(&obj->ICoclass1_iface);
+}
+
+static ULONG WINAPI coclass2_Release(ICoclass2 *iface)
+{
+    struct coclass_obj *obj = impl_from_ICoclass2(iface);
+    return ICoclass1_Release(&obj->ICoclass1_iface);
+}
+
+static HRESULT WINAPI coclass2_GetTypeInfoCount(ICoclass2 *iface, UINT *count)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI coclass2_GetTypeInfo(ICoclass2 *iface, UINT index,
+        LCID lcid, ITypeInfo **typeinfo)
+{
+    ok(index == 0xdeadbeef, "Got unexpected index %#x.\n", index);
+    return 0xbeefdead;
+}
+
+static HRESULT WINAPI coclass2_GetIDsOfNames(ICoclass2 *iface, REFIID iid,
+        LPOLESTR *names, UINT count, LCID lcid, DISPID *ids)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI coclass2_Invoke(ICoclass2 *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 coclass2_test(ICoclass2 *iface)
+{
+    return 2;
+}
+
+static const ICoclass1Vtbl coclass1_vtbl =
+{
+    coclass1_QueryInterface,
+    coclass1_AddRef,
+    coclass1_Release,
+    coclass1_GetTypeInfoCount,
+    coclass1_GetTypeInfo,
+    coclass1_GetIDsOfNames,
+    coclass1_Invoke,
+    coclass1_test,
+};
+
+static const ICoclass2Vtbl coclass2_vtbl =
+{
+    coclass2_QueryInterface,
+    coclass2_AddRef,
+    coclass2_Release,
+    coclass2_GetTypeInfoCount,
+    coclass2_GetTypeInfo,
+    coclass2_GetIDsOfNames,
+    coclass2_Invoke,
+    coclass2_test,
+};
+
+static struct coclass_obj *create_coclass_obj(void)
+{
+    struct coclass_obj *obj = CoTaskMemAlloc(sizeof(*obj));
+    obj->ICoclass1_iface.lpVtbl = &coclass1_vtbl;
+    obj->ICoclass2_iface.lpVtbl = &coclass2_vtbl;
+    obj->ref = 1;
+    return obj;
+};
+
 static int testmode;
 
 typedef struct Widget
@@ -935,14 +1105,6 @@ static HRESULT WINAPI Widget_VarArg_Ref_Run(
     return S_OK;
 }
 
-static HRESULT WINAPI Widget_Coclass(
-    IWidget *iface, ApplicationObject2 *param)
-{
-    trace("Coclass(%p)\n", param);
-    ok(param == (ApplicationObject2 *)iface, "expected param == %p, got %p\n", iface, param);
-    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)
@@ -1329,6 +1491,62 @@ static HRESULT WINAPI Widget_myint(IWidget *iface, myint_t val, myint_t *ptr, my
     return S_OK;
 }
 
+static HRESULT WINAPI Widget_Coclass(IWidget *iface, Coclass1 *class1, Coclass2 *class2, Coclass3 *class3)
+{
+    HRESULT hr;
+
+    hr = ICoclass1_test((ICoclass1 *)class1);
+    ok(hr == 1, "Got hr %#x.\n", hr);
+
+    hr = ICoclass2_test((ICoclass2 *)class2);
+    ok(hr == 2, "Got hr %#x.\n", hr);
+
+    hr = ICoclass1_test((ICoclass1 *)class3);
+    ok(hr == 1, "Got hr %#x.\n", hr);
+
+    return S_OK;
+}
+
+static HRESULT WINAPI Widget_Coclass_ptr(IWidget *iface, Coclass1 **in, Coclass1 **out, Coclass1 **in_out)
+{
+    struct coclass_obj *obj;
+    HRESULT hr;
+
+    ok(!*out, "Got [out] %p.\n", *out);
+    if (testmode == 0 || testmode == 1)
+    {
+        hr = ICoclass1_test((ICoclass1 *)*in);
+        ok(hr == 1, "Got hr %#x.\n", hr);
+        hr = ICoclass1_test((ICoclass1 *)*in_out);
+        ok(hr == 1, "Got hr %#x.\n", hr);
+    }
+
+    if (testmode == 1)
+    {
+        obj = create_coclass_obj();
+        *out = (Coclass1 *)&obj->ICoclass1_iface;
+
+        ICoclass1_Release((ICoclass1 *)*in_out);
+        obj = create_coclass_obj();
+        *in_out = (Coclass1 *)&obj->ICoclass1_iface;
+    }
+    else if (testmode == 2)
+    {
+        ok(!*in_out, "Got [in, out] %p.\n", *in_out);
+        obj = create_coclass_obj();
+        *in_out = (Coclass1 *)&obj->ICoclass1_iface;
+    }
+    else if (testmode == 3)
+    {
+        hr = ICoclass1_test((ICoclass1 *)*in_out);
+        ok(hr == 1, "Got hr %#x.\n", hr);
+        ICoclass1_Release((ICoclass1 *)*in_out);
+        *in_out = NULL;
+    }
+
+    return S_OK;
+}
+
 static const struct IWidgetVtbl Widget_VTable =
 {
     Widget_QueryInterface,
@@ -1365,7 +1583,6 @@ static const struct IWidgetVtbl Widget_VTable =
     Widget_neg_restrict,
     Widget_VarArg_Run,
     Widget_VarArg_Ref_Run,
-    Widget_Coclass,
     Widget_basetypes_in,
     Widget_basetypes_out,
     Widget_float_abi,
@@ -1385,6 +1602,8 @@ static const struct IWidgetVtbl Widget_VTable =
     Widget_variant_array,
     Widget_mystruct_array,
     Widget_myint,
+    Widget_Coclass,
+    Widget_Coclass_ptr,
 };
 
 static HRESULT WINAPI StaticWidget_QueryInterface(IStaticWidget *iface, REFIID riid, void **ppvObject)
@@ -2352,6 +2571,204 @@ static void test_marshal_array(IWidget *widget, IDispatch *disp)
     ok(hr == S_OK, "Got hr %#x.\n", hr);
 }
 
+static void test_marshal_coclass(IWidget *widget, IDispatch *disp)
+{
+    VARIANTARG arg[3];
+    DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
+    struct coclass_obj *class1, *class2, *class3;
+    IUnknown *unk_in, *unk_out, *unk_in_out;
+    ICoclass1 *in, *out, *in_out;
+    HRESULT hr;
+
+    class1 = create_coclass_obj();
+    class2 = create_coclass_obj();
+    class3 = create_coclass_obj();
+
+    hr = IWidget_Coclass(widget, (Coclass1 *)&class1->ICoclass1_iface,
+            (Coclass2 *)&class2->ICoclass1_iface, (Coclass3 *)&class3->ICoclass1_iface);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    hr = IWidget_Coclass(widget, (Coclass1 *)&class1->ICoclass2_iface,
+            (Coclass2 *)&class2->ICoclass2_iface, (Coclass3 *)&class3->ICoclass2_iface);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    release_iface(&class1->ICoclass1_iface);
+    release_iface(&class2->ICoclass1_iface);
+    release_iface(&class3->ICoclass1_iface);
+
+    testmode = 0;
+    class1 = create_coclass_obj();
+    class2 = create_coclass_obj();
+    class3 = create_coclass_obj();
+    in = &class1->ICoclass1_iface;
+    out = &class2->ICoclass1_iface;
+    in_out = &class3->ICoclass1_iface;
+    hr = IWidget_Coclass_ptr(widget, (Coclass1 **)&in, (Coclass1 **)&out, (Coclass1 **)&in_out);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    ok(in == &class1->ICoclass1_iface, "[in] parameter should not have changed.\n");
+    ok(!out, "[out] parameter should have been cleared.\n");
+    ok(in_out == &class3->ICoclass1_iface, "[in, out] parameter should not have changed.\n");
+    release_iface(&class1->ICoclass1_iface);
+    release_iface(&class2->ICoclass1_iface);
+    release_iface(&class3->ICoclass1_iface);
+
+    testmode = 1;
+    class1 = create_coclass_obj();
+    class3 = create_coclass_obj();
+    in = &class1->ICoclass1_iface;
+    in_out = &class3->ICoclass1_iface;
+    ICoclass1_AddRef(in_out);
+    hr = IWidget_Coclass_ptr(widget, (Coclass1 **)&in,
+            (Coclass1 **)&out, (Coclass1 **)&in_out);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    hr = ICoclass1_test(out);
+    ok(hr == 1, "Got hr %#x.\n", hr);
+    ok(in_out != &class3->ICoclass1_iface, "[in, out] parameter should have changed.\n");
+    hr = ICoclass1_test(in_out);
+    ok(hr == 1, "Got hr %#x.\n", hr);
+    release_iface(out);
+    release_iface(in_out);
+    release_iface(&class1->ICoclass1_iface);
+
+    testmode = 2;
+    in = out = in_out = NULL;
+    hr = IWidget_Coclass_ptr(widget, (Coclass1 **)&in,
+            (Coclass1 **)&out, (Coclass1 **)&in_out);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    hr = ICoclass1_test(in_out);
+    ok(hr == 1, "Got hr %#x.\n", hr);
+    release_iface(in_out);
+
+    testmode = 3;
+    in = out = NULL;
+    class3 = create_coclass_obj();
+    in_out = &class3->ICoclass1_iface;
+    hr = IWidget_Coclass_ptr(widget, (Coclass1 **)&in,
+            (Coclass1 **)&out, (Coclass1 **)&in_out);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    ok(!in_out, "Got [in, out] %p.\n", in_out);
+
+    /* Test with Invoke(). Note that since we pass VT_UNKNOWN, we don't get our
+     * interface back, but rather an IUnknown. */
+
+    class1 = create_coclass_obj();
+    class2 = create_coclass_obj();
+    class3 = create_coclass_obj();
+
+    V_VT(&arg[2]) = VT_UNKNOWN;  V_UNKNOWN(&arg[2]) = (IUnknown *)&class1->ICoclass1_iface;
+    V_VT(&arg[1]) = VT_UNKNOWN;  V_UNKNOWN(&arg[1]) = (IUnknown *)&class2->ICoclass1_iface;
+    V_VT(&arg[0]) = VT_UNKNOWN;  V_UNKNOWN(&arg[0]) = (IUnknown *)&class3->ICoclass1_iface;
+    hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS, &IID_NULL, LOCALE_NEUTRAL,
+            DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
+todo_wine
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    V_VT(&arg[2]) = VT_UNKNOWN;  V_UNKNOWN(&arg[2]) = (IUnknown *)&class1->ICoclass2_iface;
+    V_VT(&arg[1]) = VT_UNKNOWN;  V_UNKNOWN(&arg[1]) = (IUnknown *)&class2->ICoclass2_iface;
+    V_VT(&arg[0]) = VT_UNKNOWN;  V_UNKNOWN(&arg[0]) = (IUnknown *)&class3->ICoclass2_iface;
+    hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS, &IID_NULL, LOCALE_NEUTRAL,
+            DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
+todo_wine
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    V_VT(&arg[2]) = VT_DISPATCH; V_DISPATCH(&arg[2]) = (IDispatch *)&class1->ICoclass1_iface;
+    V_VT(&arg[1]) = VT_DISPATCH; V_DISPATCH(&arg[1]) = (IDispatch *)&class2->ICoclass1_iface;
+    V_VT(&arg[0]) = VT_DISPATCH; V_DISPATCH(&arg[0]) = (IDispatch *)&class3->ICoclass1_iface;
+    hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS, &IID_NULL, LOCALE_NEUTRAL,
+            DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
+todo_wine
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    release_iface(&class1->ICoclass1_iface);
+    release_iface(&class2->ICoclass1_iface);
+    release_iface(&class3->ICoclass1_iface);
+
+    testmode = 0;
+    class1 = create_coclass_obj();
+    class3 = create_coclass_obj();
+    unk_in = (IUnknown *)&class1->ICoclass1_iface;
+    unk_out = NULL;
+    unk_in_out = (IUnknown *)&class3->ICoclass1_iface;
+    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_COCLASS_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 *)&class1->ICoclass1_iface, "[in] parameter should not have changed.\n");
+    ok(!unk_out, "[out] parameter should have been cleared.\n");
+    ok(unk_in_out == (IUnknown *)&class3->ICoclass1_iface, "[in, out] parameter should not have changed.\n");
+    release_iface(&class1->ICoclass1_iface);
+    release_iface(&class3->ICoclass1_iface);
+
+    testmode = 1;
+    class1 = create_coclass_obj();
+    class3 = create_coclass_obj();
+    unk_in = (IUnknown *)&class1->ICoclass1_iface;
+    unk_out = NULL;
+    unk_in_out = (IUnknown *)&class3->ICoclass1_iface;
+    IUnknown_AddRef(unk_in_out);
+    hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS_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_ICoclass1, (void **)&out);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    hr = ICoclass1_test(out);
+    ok(hr == 1, "Got hr %#x.\n", hr);
+    ICoclass1_Release(out);
+
+    ok(unk_in_out != (IUnknown *)&class3->ICoclass1_iface, "[in, out] parameter should have changed.\n");
+    hr = IUnknown_QueryInterface(unk_in_out, &IID_ICoclass1, (void **)&in_out);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    hr = ICoclass1_test(in_out);
+    ok(hr == 1, "Got hr %#x.\n", hr);
+    ICoclass1_Release(in_out);
+
+    release_iface(unk_out);
+    release_iface(unk_in_out);
+}
+    release_iface(&class1->ICoclass1_iface);
+todo_wine
+    release_iface(&class3->ICoclass1_iface);
+
+    testmode = 2;
+    unk_in = unk_out = unk_in_out = NULL;
+    hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS_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_ICoclass1, (void **)&in_out);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    hr = ICoclass1_test(in_out);
+    ok(hr == 1, "Got hr %#x.\n", hr);
+    ICoclass1_Release(in_out);
+
+    release_iface(unk_in_out);
+}
+
+    testmode = 3;
+    unk_in = unk_out = NULL;
+    class3 = create_coclass_obj();
+    unk_in_out = (IUnknown *)&class3->ICoclass1_iface;
+    IUnknown_AddRef(unk_in_out);
+    hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS_PTR, &IID_NULL, LOCALE_NEUTRAL,
+            DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
+todo_wine
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+todo_wine
+    ok(!unk_in_out, "[in, out] parameter should have been cleared.\n");
+
+todo_wine
+    release_iface(&class3->ICoclass1_iface);
+}
+
 static void test_typelibmarshal(void)
 {
     static const WCHAR szCat[] = { 'C','a','t',0 };
@@ -2583,21 +3000,6 @@ static void test_typelibmarshal(void)
     ok(V_VT(&varresult) == VT_DISPATCH, "V_VT(&varresult) was %d instead of VT_DISPATCH\n", V_VT(&varresult));
     ok(V_DISPATCH(&varresult) != NULL, "expected V_DISPATCH(&varresult) != NULL\n");
 
-    /* call Coclass with VT_DISPATCH type */
-    vararg[0] = varresult;
-    dispparams.cNamedArgs = 0;
-    dispparams.rgdispidNamedArgs = NULL;
-    dispparams.cArgs = 1;
-    dispparams.rgvarg = vararg;
-    VariantInit(&varresult);
-    hr = IDispatch_Invoke(pDispatch, DISPID_TM_COCLASS, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
-    todo_wine ok_ole_success(hr, IDispatch_Invoke);
-    ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
-        "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
-        excepinfo.wCode, excepinfo.scode);
-    VariantClear(&varresult);
-    VariantClear(&vararg[0]);
-
     /* call Value with a VT_VARIANT|VT_BYREF type */
     V_VT(&vararg[0]) = VT_VARIANT|VT_BYREF;
     V_VARIANTREF(&vararg[0]) = &vararg[1];
@@ -2930,6 +3332,7 @@ static void test_typelibmarshal(void)
     test_marshal_safearray(pWidget, pDispatch);
     test_marshal_struct(pWidget, pDispatch);
     test_marshal_array(pWidget, pDispatch);
+    test_marshal_coclass(pWidget, pDispatch);
 
     IDispatch_Release(pDispatch);
     IWidget_Release(pWidget);
diff --git a/dlls/oleaut32/tests/tmarshal.idl b/dlls/oleaut32/tests/tmarshal.idl
index 543d229ce2..cdc7dc14d3 100644
--- a/dlls/oleaut32/tests/tmarshal.idl
+++ b/dlls/oleaut32/tests/tmarshal.idl
@@ -49,7 +49,6 @@ enum IWidget_dispids
     DISPID_TM_TESTSECONDIFACE,
     DISPID_TM_VARARG_RUN,
     DISPID_TM_VARARG_REF_RUN,
-    DISPID_TM_COCLASS,
 
     DISPID_TM_BASETYPES_IN,
     DISPID_TM_BASETYPES_OUT,
@@ -70,6 +69,8 @@ enum IWidget_dispids
     DISPID_TM_VARIANT_ARRAY,
     DISPID_TM_STRUCT_ARRAY,
     DISPID_TM_TYPEDEF,
+    DISPID_TM_COCLASS,
+    DISPID_TM_COCLASS_PTR,
 };
 
 static const int DISPID_TM_NEG_RESTRICTED = -26;
@@ -147,6 +148,51 @@ library TestTypelib
         HRESULT test();
     }
 
+    [
+        oleautomation,
+        uuid(3f7e06fe-0bce-46f0-8b7d-3a68393c796a)
+    ]
+    interface ICoclass1 : IDispatch
+    {
+        HRESULT test();
+    }
+
+    [
+        oleautomation,
+        uuid(3f7e06fe-0bce-46f0-8b7d-3a68393c796b)
+    ]
+    interface ICoclass2 : IDispatch
+    {
+        HRESULT test();
+    }
+
+    [
+        uuid(3f7e06fe-0bce-46f0-8b7d-3a68393c796c)
+    ]
+    coclass Coclass1
+    {
+        [default] interface ICoclass1;
+        interface ICoclass2;
+    }
+
+    [
+        uuid(3f7e06fe-0bce-46f0-8b7d-3a68393c796d)
+    ]
+    coclass Coclass2
+    {
+        interface ICoclass1;
+        [default] interface ICoclass2;
+    }
+
+    [
+        uuid(3f7e06fe-0bce-46f0-8b7d-3a68393c796e)
+    ]
+    coclass Coclass3
+    {
+        interface ICoclass1;
+        interface ICoclass2;
+    }
+
     [
         odl,
         uuid(a1f8cae3-c947-4c5f-b57d-c87b9b5f3586),
@@ -234,9 +280,6 @@ library TestTypelib
         [id(DISPID_TM_VARARG_REF_RUN), vararg]
         HRESULT VarArg_Ref_Run([in] BSTR name, [in] SAFEARRAY(VARIANT) *params, [out, retval] VARIANT *result);
 
-        [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,
@@ -305,6 +348,12 @@ library TestTypelib
 
         [id(DISPID_TM_TYPEDEF)]
         HRESULT myint([in] myint_t val, [in] myint_t *ptr, [in] myint_t **ptr_ptr);
+
+        [id(DISPID_TM_COCLASS)]
+        HRESULT Coclass([in] Coclass1 *class1, [in] Coclass2 *class2, [in] Coclass3 *class3);
+
+        [id(DISPID_TM_COCLASS_PTR)]
+        HRESULT Coclass_ptr([in] Coclass1 **in, [out] Coclass1 **out, [in, out] Coclass1 **in_out);
     }
 
     [
-- 
2.19.1




More information about the wine-devel mailing list