[PATCH 0/2] MR10855: oleaut32: Don't fake IDispatch inheritance for TKIND_DISPATCH without an impl type.
GetTypeAttr unconditionally inflated cFuncs by the IDispatch vtbl size and GetRefTypeOfImplType(0) returned dispatch_href, even for typeinfos created via ICreateTypeLib2 without AddImplType. In that case dispatch_href is -1, so callers that walked GetRefTypeOfImplType chains followed an invalid href. Only inflate cFuncs when an impl type is registered, and only return dispatch_href when the typelib actually has an IDispatch reference. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10855
From: Francis De Brabandere <francisdb@gmail.com> A typeinfo built with ICreateTypeLib2 + ICreateTypeInfo as TKIND_DISPATCH but without an explicit AddImplType has no parent registered. Native reports cFuncs reflecting only the funcs added directly (no phantom IDispatch slots) and GetRefTypeOfImplType(0) returns TYPE_E_ELEMENTNOTFOUND. Wine inflates cFuncs by the IDispatch vtbl size and returns a stale dispatch_href; mark these as todo_wine until the typelib.c logic is fixed. --- dlls/oleaut32/tests/typelib.c | 79 +++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/dlls/oleaut32/tests/typelib.c b/dlls/oleaut32/tests/typelib.c index 153964e17d5..f390d2eccee 100644 --- a/dlls/oleaut32/tests/typelib.c +++ b/dlls/oleaut32/tests/typelib.c @@ -8763,6 +8763,84 @@ static void test_DeleteFuncDesc(void) DeleteFileW(filenameW); } +static void test_dispatch_no_implparent(void) +{ + OLECHAR typelibW[] = L"typelib"; + OLECHAR ifaceW[] = L"iface"; + OLECHAR funcW[] = L"func"; + OLECHAR *funcnames[] = { funcW }; + OLECHAR varW[] = L"var"; + WCHAR filenameW[MAX_PATH], temp_path[MAX_PATH]; + ICreateTypeInfo *createti; + ICreateTypeLib2 *createtl; + FUNCDESC funcdesc; + VARDESC vardesc; + TYPEATTR *typeattr; + HREFTYPE href; + ITypeInfo *ti; + HRESULT hr; + + GetTempPathW(ARRAY_SIZE(temp_path), temp_path); + GetTempFileNameW(temp_path, L"tlb", 0, filenameW); + + hr = CreateTypeLib2(SYS_WIN64, filenameW, &createtl); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = ICreateTypeLib2_SetName(createtl, typelibW); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = ICreateTypeLib2_CreateTypeInfo(createtl, ifaceW, TKIND_DISPATCH, &createti); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = ICreateTypeInfo_SetTypeFlags(createti, TYPEFLAG_FDISPATCHABLE); + ok(hr == S_OK, "got %#lx\n", hr); + + memset(&funcdesc, 0, sizeof(funcdesc)); + funcdesc.memid = 0x100; + funcdesc.funckind = FUNC_DISPATCH; + funcdesc.invkind = INVOKE_FUNC; + funcdesc.callconv = CC_STDCALL; + funcdesc.elemdescFunc.tdesc.vt = VT_VOID; + hr = ICreateTypeInfo_AddFuncDesc(createti, 0, &funcdesc); + ok(hr == S_OK, "got %#lx\n", hr); + hr = ICreateTypeInfo_SetFuncAndParamNames(createti, 0, funcnames, 1); + ok(hr == S_OK, "got %#lx\n", hr); + + memset(&vardesc, 0, sizeof(vardesc)); + vardesc.memid = 0x101; + vardesc.varkind = VAR_DISPATCH; + vardesc.elemdescVar.tdesc.vt = VT_I4; + hr = ICreateTypeInfo_AddVarDesc(createti, 0, &vardesc); + ok(hr == S_OK, "got %#lx\n", hr); + hr = ICreateTypeInfo_SetVarName(createti, 0, varW); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = ICreateTypeInfo_LayOut(createti); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = ICreateTypeInfo_QueryInterface(createti, &IID_ITypeInfo, (void **)&ti); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = ITypeInfo_GetTypeAttr(ti, &typeattr); + ok(hr == S_OK, "got %#lx\n", hr); + ok(typeattr->typekind == TKIND_DISPATCH, "typekind %d\n", typeattr->typekind); + todo_wine + ok(typeattr->cFuncs == 1, "cFuncs %u\n", typeattr->cFuncs); + ok(typeattr->cVars == 1, "cVars %u\n", typeattr->cVars); + ok(typeattr->cImplTypes == 0, "cImplTypes %u\n", typeattr->cImplTypes); + ITypeInfo_ReleaseTypeAttr(ti, typeattr); + + href = 0xdeadbeef; + hr = ITypeInfo_GetRefTypeOfImplType(ti, 0, &href); + todo_wine + ok(hr == TYPE_E_ELEMENTNOTFOUND, "got %#lx\n", hr); + + ITypeInfo_Release(ti); + ICreateTypeInfo_Release(createti); + ICreateTypeLib2_Release(createtl); + DeleteFileW(filenameW); +} + START_TEST(typelib) { const WCHAR *filename; @@ -8806,4 +8884,5 @@ START_TEST(typelib) test_stub(); test_DeleteImplType(); test_DeleteFuncDesc(); + test_dispatch_no_implparent(); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10855
From: Francis De Brabandere <francisdb@gmail.com> GetTypeAttr unconditionally inflated cFuncs by the IDispatch vtbl size and GetRefTypeOfImplType(0) returned dispatch_href, even for typeinfos created via ICreateTypeLib2 without AddImplType. In that case dispatch_href is -1, so callers that walked GetRefTypeOfImplType chains followed an invalid href. Only inflate cFuncs when an impl type is registered, and only return dispatch_href when the typelib actually has an IDispatch reference. --- dlls/oleaut32/tests/typelib.c | 2 -- dlls/oleaut32/typelib.c | 10 +++++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/dlls/oleaut32/tests/typelib.c b/dlls/oleaut32/tests/typelib.c index f390d2eccee..8e7e20ca4ef 100644 --- a/dlls/oleaut32/tests/typelib.c +++ b/dlls/oleaut32/tests/typelib.c @@ -8824,7 +8824,6 @@ static void test_dispatch_no_implparent(void) hr = ITypeInfo_GetTypeAttr(ti, &typeattr); ok(hr == S_OK, "got %#lx\n", hr); ok(typeattr->typekind == TKIND_DISPATCH, "typekind %d\n", typeattr->typekind); - todo_wine ok(typeattr->cFuncs == 1, "cFuncs %u\n", typeattr->cFuncs); ok(typeattr->cVars == 1, "cVars %u\n", typeattr->cVars); ok(typeattr->cImplTypes == 0, "cImplTypes %u\n", typeattr->cImplTypes); @@ -8832,7 +8831,6 @@ static void test_dispatch_no_implparent(void) href = 0xdeadbeef; hr = ITypeInfo_GetRefTypeOfImplType(ti, 0, &href); - todo_wine ok(hr == TYPE_E_ELEMENTNOTFOUND, "got %#lx\n", hr); ITypeInfo_Release(ti); diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c index e9997a86d24..aa997531e7d 100644 --- a/dlls/oleaut32/typelib.c +++ b/dlls/oleaut32/typelib.c @@ -5757,7 +5757,7 @@ static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface, if (This->tdescAlias) TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, This->tdescAlias, *ppTypeAttr + 1); - if((*ppTypeAttr)->typekind == TKIND_DISPATCH) { + if((*ppTypeAttr)->typekind == TKIND_DISPATCH && This->typeattr.cImplTypes) { /* This should include all the inherited funcs */ (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size; /* This is always the size of IDispatch's vtbl */ @@ -6279,9 +6279,13 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType( hr = TYPE_E_ELEMENTNOTFOUND; } } - else if(index == 0 && This->typeattr.typekind == TKIND_DISPATCH) + else if(index == 0 && This->typeattr.typekind == TKIND_DISPATCH + && This->pTypeLib->dispatch_href != -1) { - /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */ + /* TKIND_DISPATCH inherits from IDispatch when the typelib has a + * registered IDispatch reference. Without one (e.g. typelibs built + * via ICreateTypeLib2 with no explicit AddImplType), index 0 is + * out of range. */ *pRefType = This->pTypeLib->dispatch_href; } else -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10855
Closed as requested by reviewer, no native-parity fixes without app evidence. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10855#note_139676
This merge request was closed by Francis De Brabandere. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10855
participants (2)
-
Francis De Brabandere -
Francis De Brabandere (@francisdb)