diff --git a/dlls/oleaut32/tests/tmarshal.c b/dlls/oleaut32/tests/tmarshal.c index e1564d5a0b7..756cca844d7 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,201 @@ 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); + 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); + 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); + 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 +2997,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); - 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 +3329,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 543d229ce29..cdc7dc14d39 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); } [