[PATCH v2 0/1] MR10858: Draft: vbscript: Register IDispatch as the class typeinfo's parent and lay non-default funcs first.
build_class_typeinfo now adds IDispatch as the implicit base via AddRefTypeInfo + AddImplType so the resulting typeinfo reports cImplTypes == 1 and returns the IDispatch typeinfo via GetRefTypeOfImplType -> GetRefTypeInfo, matching native. Compile-time slot 0 is reserved for the default getter/method, so build_class_typeinfo previously emitted the default at FUNCDESC index 0 ahead of declaration-order members. Native lays out non-default funcs first and places the default last. Iterate desc->funcs[1..N] before desc->funcs[0] so 'Public Sub method' lands at index 0 with INVOKE_FUNC and 'Public Default Property Get defprop' lands last. Drop the corresponding todo_wine markers from test_vbdisp_typeinfo; together with the matching oleaut32 changes (cbSizeVft accounting and the GetFuncDesc bound for TKIND_DISPATCH built via ICreateTypeLib2) the four todos and the GetFuncDesc(cFuncs) probe pass on Wine. This requires !10851, !10856, !10857 to be merged first -- v2: vbscript: Register IDispatch as the class typeinfo's parent and lay non-default funcs first. https://gitlab.winehq.org/wine/wine/-/merge_requests/10858
From: Francis De Brabandere <francisdb@gmail.com> build_class_typeinfo now adds IDispatch as the implicit base via AddRefTypeInfo + AddImplType so the resulting typeinfo reports cImplTypes == 1 and returns the IDispatch typeinfo via GetRefTypeOfImplType -> GetRefTypeInfo, matching native. Compile-time slot 0 is reserved for the default getter/method, so build_class_typeinfo previously emitted the default at FUNCDESC index 0 ahead of declaration-order members. Native lays out non-default funcs first and places the default last. Iterate desc->funcs[1..N] before desc->funcs[0] so 'Public Sub method' lands at index 0 with INVOKE_FUNC and 'Public Default Property Get defprop' lands last. Drop the corresponding todo_wine markers from test_vbdisp_typeinfo; together with the matching oleaut32 changes (cbSizeVft accounting and the GetFuncDesc bound for TKIND_DISPATCH built via ICreateTypeLib2) the four todos and the GetFuncDesc(cFuncs) probe pass on Wine. --- dlls/vbscript/tests/vbscript.c | 16 +++------ dlls/vbscript/vbdisp.c | 60 +++++++++++++++++++++++++--------- 2 files changed, 48 insertions(+), 28 deletions(-) diff --git a/dlls/vbscript/tests/vbscript.c b/dlls/vbscript/tests/vbscript.c index 6fe7893d3b0..c2389e8350a 100644 --- a/dlls/vbscript/tests/vbscript.c +++ b/dlls/vbscript/tests/vbscript.c @@ -1657,12 +1657,9 @@ static void test_vbdisp_typeinfo(void) hr = ITypeInfo_GetTypeAttr(typeinfo, &attr); ok(hr == S_OK, "GetTypeAttr failed: %08lx\n", hr); ok(attr->typekind == TKIND_DISPATCH, "Unexpected typekind %u\n", attr->typekind); - /* On Wine, oleaut32 CreateTypeLib2 currently adds 7 phantom inherited - * IDispatch methods to TKIND_DISPATCH typeinfos, inflating cFuncs - * from 4 to 11 and zeroing cImplTypes. */ - todo_wine ok(attr->cFuncs == 4, "Unexpected cFuncs %u\n", attr->cFuncs); + ok(attr->cFuncs == 4, "Unexpected cFuncs %u\n", attr->cFuncs); ok(attr->cVars == 1, "Unexpected cVars %u\n", attr->cVars); - todo_wine ok(attr->cImplTypes == 1, "Unexpected cImplTypes %u\n", attr->cImplTypes); + ok(attr->cImplTypes == 1, "Unexpected cImplTypes %u\n", attr->cImplTypes); ok(attr->wTypeFlags == TYPEFLAG_FDISPATCHABLE, "Unexpected wTypeFlags 0x%x\n", attr->wTypeFlags); ITypeInfo_ReleaseTypeAttr(typeinfo, attr); @@ -1672,10 +1669,7 @@ static void test_vbdisp_typeinfo(void) hr = ITypeInfo_GetFuncDesc(typeinfo, 0, &funcdesc); ok(hr == S_OK, "GetFuncDesc failed: %08lx\n", hr); ok(funcdesc->funckind == FUNC_DISPATCH, "Unexpected funckind %u\n", funcdesc->funckind); - /* Wine's phantom IDispatch methods occupy slots 0-6, so func[0] is - * QueryInterface (invkind reported as PROPERTYGET due to a separate - * Wine bug) instead of our 'method'. */ - todo_wine ok(funcdesc->invkind == INVOKE_FUNC, "Unexpected invkind %u\n", funcdesc->invkind); + ok(funcdesc->invkind == INVOKE_FUNC, "Unexpected invkind %u\n", funcdesc->invkind); ITypeInfo_ReleaseFuncDesc(typeinfo, funcdesc); wcscpy(str, L"add"); @@ -1754,13 +1748,11 @@ static void test_vbdisp_typeinfo(void) hr = ITypeInfo_GetImplTypeFlags(typeinfo, 1, &implTypeFlags); ok(hr == TYPE_E_ELEMENTNOTFOUND, "GetImplTypeFlags(1) returned: %08lx\n", hr); - /* IDispatch parent. Wine's CreateTypeLib2 returns success here - * but the resulting reftype isn't usable via GetRefTypeInfo. */ hr = ITypeInfo_GetRefTypeOfImplType(typeinfo, 0, &reftype); ok(hr == S_OK, "GetRefTypeOfImplType failed: %08lx\n", hr); if(SUCCEEDED(hr)) { hr = ITypeInfo_GetRefTypeInfo(typeinfo, reftype, &typeinfo2); - todo_wine ok(hr == S_OK, "GetRefTypeInfo failed: %08lx\n", hr); + ok(hr == S_OK, "GetRefTypeInfo failed: %08lx\n", hr); if(SUCCEEDED(hr)) { hr = ITypeInfo_GetDocumentation(typeinfo2, MEMBERID_NIL, &bstr, NULL, NULL, NULL); ok(hr == S_OK, "GetDocumentation failed: %08lx\n", hr); diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index 1ea228c8aca..abf6e431e53 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -478,11 +478,34 @@ static HRESULT add_class_member_func(ICreateTypeInfo *cti, unsigned slot, DISPID return hr; } +static HRESULT add_class_funcprop(ICreateTypeInfo *cti, unsigned *slot, unsigned i, + const class_desc_t *desc) +{ + const vbdisp_funcprop_desc_t *fp = &desc->funcs[i]; + vbdisp_invoke_type_t which; + HRESULT hr; + + if(!fp->is_public || !fp->name) return S_OK; + if(desc->class_initialize_id && i == desc->class_initialize_id) return S_OK; + if(desc->class_terminate_id && i == desc->class_terminate_id) return S_OK; + + if(fp->entries[VBDISP_CALLGET]) which = VBDISP_CALLGET; + else if(fp->entries[VBDISP_LET]) which = VBDISP_LET; + else if(fp->entries[VBDISP_SET]) which = VBDISP_SET; + else return S_OK; + + hr = add_class_member_func(cti, *slot, i, fp, which); + if(SUCCEEDED(hr)) (*slot)++; + return hr; +} + static HRESULT build_class_typeinfo(class_desc_t *desc, ITypeInfo **out) { ICreateTypeLib2 *ctl = NULL; ICreateTypeInfo *cti = NULL; - ITypeLib *tl = NULL; + ITypeLib *stdole = NULL, *tl = NULL; + ITypeInfo *idispatch_ti = NULL; + HREFTYPE href; HRESULT hr; unsigned i, slot; @@ -496,26 +519,29 @@ static HRESULT build_class_typeinfo(class_desc_t *desc, ITypeInfo **out) ICreateTypeInfo_SetTypeFlags(cti, TYPEFLAG_FDISPATCHABLE); + hr = LoadTypeLib(L"stdole2.tlb", &stdole); + if(SUCCEEDED(hr)) { + hr = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &idispatch_ti); + if(SUCCEEDED(hr)) { + hr = ICreateTypeInfo_AddRefTypeInfo(cti, idispatch_ti, &href); + if(SUCCEEDED(hr)) + hr = ICreateTypeInfo_AddImplType(cti, 0, href); + } + } + if(FAILED(hr)) goto done; + /* One FUNCDESC per public named func/property (matching native). * Property get/let/set collapse into a single entry; pick the get - * entry when present, else let, else set. */ + * entry when present, else let, else set. desc->funcs[0] holds the + * default getter/method; native lays out non-default funcs in + * declaration order with the default last. */ slot = 0; - for(i = 0; i < desc->func_cnt; i++) { - const vbdisp_funcprop_desc_t *fp = &desc->funcs[i]; - vbdisp_invoke_type_t which; - if(!fp->is_public || !fp->name) continue; - if(desc->class_initialize_id && i == desc->class_initialize_id) continue; - if(desc->class_terminate_id && i == desc->class_terminate_id) continue; - - if(fp->entries[VBDISP_CALLGET]) which = VBDISP_CALLGET; - else if(fp->entries[VBDISP_LET]) which = VBDISP_LET; - else if(fp->entries[VBDISP_SET]) which = VBDISP_SET; - else continue; - - hr = add_class_member_func(cti, slot, i, fp, which); + for(i = 1; i < desc->func_cnt; i++) { + hr = add_class_funcprop(cti, &slot, i, desc); if(FAILED(hr)) goto done; - slot++; } + hr = add_class_funcprop(cti, &slot, 0, desc); + if(FAILED(hr)) goto done; /* Public properties (Dim'd vars). */ slot = 0; @@ -547,6 +573,8 @@ static HRESULT build_class_typeinfo(class_desc_t *desc, ITypeInfo **out) hr = ITypeLib_GetTypeInfo(tl, 0, out); done: + if(idispatch_ti) ITypeInfo_Release(idispatch_ti); + if(stdole) ITypeLib_Release(stdole); if(tl) ITypeLib_Release(tl); if(cti) ICreateTypeInfo_Release(cti); if(ctl) ICreateTypeLib2_Release(ctl); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10858
participants (2)
-
Francis De Brabandere -
Francis De Brabandere (@francisdb)