From: Francis De Brabandere <francisdb@gmail.com> ICreateTypeInfo2_fnLayOut starts cbSizeVft at 7*ptr_size for TKIND_DISPATCH to position own funcs after the IDispatch vtbl, then increments per added func. The own funcs receive correct oVft offsets that way, but the resulting stored cbSizeVft is too large by exactly the IDispatch vtbl size: GetTypeAttr later derives cFuncs as cbSizeVft/ptr_size and so reports own_count + 7 instead of own_count. Subtract the prefix at the end of LayOut so cFuncs matches native, both in-memory and after SaveAllChanges + LoadTypeLibEx. Public cbSizeVft is unchanged: GetTypeAttr already overrides it to sizeof(IDispatchVtbl). --- dlls/oleaut32/tests/typelib.c | 2 -- dlls/oleaut32/typelib.c | 9 +++++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/dlls/oleaut32/tests/typelib.c b/dlls/oleaut32/tests/typelib.c index 091defda68d..7010b879582 100644 --- a/dlls/oleaut32/tests/typelib.c +++ b/dlls/oleaut32/tests/typelib.c @@ -8822,7 +8822,6 @@ static void test_dispatch_with_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, "in-memory cFuncs %u\n", typeattr->cFuncs); ok(typeattr->cImplTypes == 1, "in-memory cImplTypes %u\n", typeattr->cImplTypes); ok(typeattr->cbSizeVft == sizeof(IDispatchVtbl), "in-memory cbSizeVft %u\n", typeattr->cbSizeVft); @@ -8842,7 +8841,6 @@ static void test_dispatch_with_implparent(void) ok(hr == S_OK, "got %#lx\n", hr); hr = ITypeInfo_GetTypeAttr(ti, &typeattr); ok(hr == S_OK, "got %#lx\n", hr); - todo_wine ok(typeattr->cFuncs == 1, "reloaded cFuncs %u\n", typeattr->cFuncs); ok(typeattr->cImplTypes == 1, "reloaded cImplTypes %u\n", typeattr->cImplTypes); ITypeInfo_ReleaseTypeAttr(ti, typeattr); diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c index e9997a86d24..d604ccc0fd8 100644 --- a/dlls/oleaut32/typelib.c +++ b/dlls/oleaut32/typelib.c @@ -11193,6 +11193,15 @@ static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface) if (user_vft > This->typeattr.cbSizeVft) This->typeattr.cbSizeVft = user_vft + This->pTypeLib->ptr_size; + /* For TKIND_DISPATCH, the IDispatch vtbl slots are not part of the + * stored cbSizeVft on native ICreateTypeLib2 typelibs - GetTypeAttr + * later overrides cbSizeVft to sizeof(IDispatchVtbl) for the public + * API regardless. Subtract the prefix here so that GetTypeAttr's + * `cFuncs = cbSizeVft / ptr_size` derivation yields the own-func + * count (matching native), without changing oVft assignments. */ + if (This->typeattr.typekind == TKIND_DISPATCH) + This->typeattr.cbSizeVft -= 7 * This->pTypeLib->ptr_size; + for(i = 0; i < This->typeattr.cVars; ++i){ TLBVarDesc *var_desc = &This->vardescs[i]; if(var_desc->vardesc.memid == MEMBERID_NIL){ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10857