From 8fac69ba50d957599869d6a62355efaf0f68f182 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Thu, 26 Mar 2020 20:54:17 +0100 Subject: [PATCH] oleaut32: Fix handling dual interfaces in ITypeInfo::GetRefTypeInfo. Based on patch by Puetz Kevin. Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- dlls/oleaut32/tests/tmarshal.idl | 23 +++++++++++++ dlls/oleaut32/tests/typelib.c | 58 +++++++++++++++++++++++++++++-- dlls/oleaut32/typelib.c | 59 +++++++++++++++++++------------- 3 files changed, 114 insertions(+), 26 deletions(-) diff --git a/dlls/oleaut32/tests/tmarshal.idl b/dlls/oleaut32/tests/tmarshal.idl index 9182def313a..a594f9137d8 100644 --- a/dlls/oleaut32/tests/tmarshal.idl +++ b/dlls/oleaut32/tests/tmarshal.idl @@ -582,4 +582,27 @@ cpp_quote("struct Coclass3 { ICoclass1 *iface; };") interface ItestIF7; } + [ + object, + uuid(ec236d8e-2cc7-44f2-b394-46c86ff3da74), + dual, + oleautomation + ] + interface ItestIF12 : IDispatch + { + [id(0x1234)] HRESULT fn4([in] int a); + [id(0x1235)] HRESULT fn5([in] int a); + } + + [ + object, + uuid(f711b105-554d-4751-818c-56fcc5d7c0d5), + dual, + oleautomation + ] + interface ItestIF13 : ItestIF12 + { + [id(0x1236)] HRESULT fn6([in] GUID a); + } + }; diff --git a/dlls/oleaut32/tests/typelib.c b/dlls/oleaut32/tests/typelib.c index 75f8d78f07c..5e5b44a0345 100644 --- a/dlls/oleaut32/tests/typelib.c +++ b/dlls/oleaut32/tests/typelib.c @@ -1577,7 +1577,7 @@ static void test_inheritance(void) { HRESULT hr; ITypeLib *pTL; - ITypeInfo *pTI, *pTI_p; + ITypeInfo *pTI, *pTI_p, *dual_ti; TYPEATTR *pTA; HREFTYPE href; FUNCDESC *pFD; @@ -1720,7 +1720,7 @@ static void test_inheritance(void) hr = ITypeInfo_GetTypeAttr(pTI, &pTA); ok(hr == S_OK, "hr %08x\n", hr); ok(pTA->typekind == TKIND_DISPATCH, "kind %04x\n", pTA->typekind); - ok(pTA->cbSizeVft == 7 * sizeof(void *), "sizevft %d\n", pTA->cbSizeVft); + ok(pTA->cbSizeVft == sizeof(IDispatchVtbl), "sizevft %d\n", pTA->cbSizeVft); ok(pTA->wTypeFlags == TYPEFLAG_FDISPATCHABLE, "typeflags %x\n", pTA->wTypeFlags); ok(pTA->cFuncs == 3, "cfuncs %d\n", pTA->cFuncs); ok(pTA->cImplTypes == 1, "cimpltypes %d\n", pTA->cImplTypes); @@ -1815,6 +1815,60 @@ static void test_inheritance(void) ITypeInfo_ReleaseFuncDesc(pTI, pFD); ITypeInfo_Release(pTI); + /* ItestIF13 is dual with inherited dual ifaces */ + hr = ITypeLib_GetTypeInfoOfGuid(pTL, &IID_ItestIF13, &pTI); + ok(hr == S_OK, "hr %08x\n", hr); + + hr = ITypeInfo_GetTypeAttr(pTI, &pTA); + ok(hr == S_OK, "hr %08x\n", hr); + ok(pTA->typekind == TKIND_DISPATCH, "kind %04x\n", pTA->typekind); + ok(pTA->cbSizeVft == 7 * sizeof(void *), "sizevft %d\n", pTA->cbSizeVft); + ok(pTA->wTypeFlags == (TYPEFLAG_FDISPATCHABLE|TYPEFLAG_FDUAL), "typeflags %x\n", pTA->wTypeFlags); + ok(pTA->cFuncs == 10, "cfuncs %d\n", pTA->cFuncs); + ok(pTA->cImplTypes == 1, "cimpltypes %d\n", pTA->cImplTypes); + ITypeInfo_ReleaseTypeAttr(pTI, pTA); + + hr = ITypeInfo_GetRefTypeOfImplType(pTI, 0, &href); + ok(hr == S_OK, "hr %08x\n", hr); + hr = ITypeInfo_GetRefTypeInfo(pTI, href, &pTI_p); + ok(hr == S_OK, "hr %08x\n", hr); + hr = ITypeInfo_GetTypeAttr(pTI_p, &pTA); + ok(hr == S_OK, "got %08x\n", hr); + ok(IsEqualGUID(&pTA->guid, &IID_IDispatch), "guid %s\n", wine_dbgstr_guid(&pTA->guid)); + ITypeInfo_ReleaseTypeAttr(pTI_p, pTA); + + hr = ITypeInfo_GetFuncDesc(pTI, 9, &pFD); + ok(hr == S_OK, "hr %08x\n", hr); + ok(pFD->memid == 0x1236, "memid %08x\n", pFD->memid); + ITypeInfo_ReleaseFuncDesc(pTI, pFD); + + hr = ITypeInfo_GetRefTypeInfo(pTI, -2, &dual_ti); + ok(hr == S_OK, "hr %08x\n", hr); + + hr = ITypeInfo_GetTypeAttr(dual_ti, &pTA); + ok(hr == S_OK, "hr %08x\n", hr); + ok(pTA->typekind == TKIND_INTERFACE, "kind %04x\n", pTA->typekind); + ok(pTA->cbSizeVft == sizeof(ItestIF13Vtbl), "sizevft %d\n", pTA->cbSizeVft); + ok(pTA->wTypeFlags == (TYPEFLAG_FDISPATCHABLE|TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL), "typeflags %x\n", pTA->wTypeFlags); + ok(pTA->cFuncs == 1, "cfuncs %d\n", pTA->cFuncs); + ok(pTA->cImplTypes == 1, "cimpltypes %d\n", pTA->cImplTypes); + ITypeInfo_ReleaseTypeAttr(dual_ti, pTA); + + hr = ITypeInfo_GetRefTypeOfImplType(dual_ti, 0, &href); + ok(hr == S_OK, "hr %08x\n", hr); + hr = ITypeInfo_GetRefTypeInfo(dual_ti, href, &pTI_p); + ok(hr == S_OK, "hr %08x\n", hr); + hr = ITypeInfo_GetTypeAttr(pTI_p, &pTA); + ok(hr == S_OK, "got %08x\n", hr); + ok(pTA->typekind == TKIND_INTERFACE, "kind %04x\n", pTA->typekind); + ok(pTA->cbSizeVft == sizeof(ItestIF12Vtbl), "sizevft %d\n", pTA->cbSizeVft); + ok(IsEqualGUID(&pTA->guid, &IID_ItestIF12), "guid %s\n", wine_dbgstr_guid(&pTA->guid)); + ITypeInfo_ReleaseTypeAttr(pTI_p, pTA); + ITypeInfo_Release(pTI_p); + + ITypeInfo_Release(dual_ti); + ITypeInfo_Release(pTI); + ITypeLib_Release(pTL); return; diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c index 68c31e1d88d..f8d71368345 100644 --- a/dlls/oleaut32/typelib.c +++ b/dlls/oleaut32/typelib.c @@ -7911,7 +7911,10 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo( ITypeInfo **ppTInfo) { ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); + ITypeInfo *type_info = NULL; HRESULT result = E_FAIL; + TLBRefType *ref_type; + UINT i; if(!ppTInfo) return E_INVALIDARG; @@ -7944,32 +7947,32 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo( * refcount goes to zero, but we need to signal to the new instance to * not free its data structures when it is destroyed */ pTypeInfoImpl->not_attached_to_typelib = TRUE; - ITypeInfo_AddRef(*ppTInfo); - result = S_OK; - } else if ((hRefType & DISPATCH_HREF_MASK) && - (This->typeattr.typekind == TKIND_DISPATCH)) - { - HREFTYPE href_dispatch = hRefType; - result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo); - } else { - TLBRefType *ref_type; - ITypeLib *pTLib = NULL; - UINT i; + TRACE("got dual interface %p\n", *ppTInfo); + return S_OK; + } - if(!(hRefType & 0x1)){ - for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i) + if ((hRefType & DISPATCH_HREF_MASK) && (This->typeattr.typekind == TKIND_DISPATCH)) + return ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &hRefType, ppTInfo); + + if(!(hRefType & 0x1)) + { + for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i) + { + if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3))) { - if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3))) - { - result = S_OK; - *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface; - ITypeInfo_AddRef(*ppTInfo); - goto end; - } + result = S_OK; + type_info = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface; + ITypeInfo_AddRef(type_info); + break; } } + } + + if (!type_info) + { + ITypeLib *pTLib = NULL; LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry) { @@ -7979,7 +7982,7 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo( if(&ref_type->entry == &This->pTypeLib->ref_list) { FIXME("Can't find pRefType for ref %x\n", hRefType); - goto end; + return E_FAIL; } if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) { @@ -8057,15 +8060,23 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo( } if(SUCCEEDED(result)) { if(ref_type->index == TLB_REF_USE_GUID) - result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo); + result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), &type_info); else - result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo); + result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, &type_info); } if (pTLib != NULL) ITypeLib_Release(pTLib); + if (FAILED(result)) + { + WARN("(%p) failed hreftype 0x%04x\n", This, hRefType); + return result; + } } -end: + if ((hRefType & 0x2) && SUCCEEDED(ITypeInfo_GetRefTypeInfo(type_info, -2, ppTInfo))) + ITypeInfo_Release(type_info); + else *ppTInfo = type_info; + TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType, SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo); return result;