From: Francis De Brabandere <francisdb@gmail.com> Implement GetTypeInfo on vbdisp_t (VBScript class instances) by returning a lightweight ITypeInfo that reports the class name via GetDocumentation(MEMBERID_NIL). This makes TypeName() return the actual class name (e.g. "MyClass") instead of falling back to "Object". --- dlls/vbscript/tests/api.vbs | 11 ++ dlls/vbscript/vbdisp.c | 228 +++++++++++++++++++++++++++++++++++- 2 files changed, 237 insertions(+), 2 deletions(-) diff --git a/dlls/vbscript/tests/api.vbs b/dlls/vbscript/tests/api.vbs index e18d887306b..d989ba8a332 100644 --- a/dlls/vbscript/tests/api.vbs +++ b/dlls/vbscript/tests/api.vbs @@ -1711,6 +1711,17 @@ Dim regex set regex = new RegExp Call ok(TypeName(regex) = "IRegExp2", "TypeName(regex) = " & TypeName(regex)) +' TypeName for VBScript class instances +Dim emptyClsObj +Set emptyClsObj = New EmptyClass +Call ok(TypeName(emptyClsObj) = "EmptyClass", "TypeName(EmptyClass) = " & TypeName(emptyClsObj)) +Call ok(getVT(TypeName(emptyClsObj)) = "VT_BSTR", "getVT(TypeName(EmptyClass)) = " & getVT(TypeName(emptyClsObj))) +Dim valClsObj +Set valClsObj = New ValClass +Call ok(TypeName(valClsObj) = "ValClass", "TypeName(ValClass) = " & TypeName(valClsObj)) +Set emptyClsObj = Nothing +Call ok(TypeName(emptyClsObj) = "Nothing", "TypeName after Set Nothing = " & TypeName(emptyClsObj)) + Call ok(VarType(Empty) = vbEmpty, "VarType(Empty) = " & VarType(Empty)) Call ok(getVT(VarType(Empty)) = "VT_I2", "getVT(VarType(Empty)) = " & getVT(VarType(Empty))) Call ok(VarType(Null) = vbNull, "VarType(Null) = " & VarType(Null)) diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index db3059c7fca..c5168d38d7d 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -358,12 +358,236 @@ static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pcti return S_OK; } +typedef struct { + ITypeInfo ITypeInfo_iface; + LONG ref; + const WCHAR *name; +} VBDispTypeInfo; + +static inline VBDispTypeInfo *VBDispTypeInfo_from_ITypeInfo(ITypeInfo *iface) +{ + return CONTAINING_RECORD(iface, VBDispTypeInfo, ITypeInfo_iface); +} + +static HRESULT WINAPI VBDispTypeInfo_QueryInterface(ITypeInfo *iface, REFIID riid, void **ppv) +{ + VBDispTypeInfo *This = VBDispTypeInfo_from_ITypeInfo(iface); + + if (IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_ITypeInfo, riid)) + *ppv = &This->ITypeInfo_iface; + else + { + WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*ppv); + return S_OK; +} + +static ULONG WINAPI VBDispTypeInfo_AddRef(ITypeInfo *iface) +{ + VBDispTypeInfo *This = VBDispTypeInfo_from_ITypeInfo(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%ld\n", This, ref); + + return ref; +} + +static ULONG WINAPI VBDispTypeInfo_Release(ITypeInfo *iface) +{ + VBDispTypeInfo *This = VBDispTypeInfo_from_ITypeInfo(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%ld\n", This, ref); + + if (!ref) + free(This); + + return ref; +} + +static HRESULT WINAPI VBDispTypeInfo_GetTypeAttr(ITypeInfo *iface, TYPEATTR **ppTypeAttr) +{ + FIXME("(%p)->(%p)\n", iface, ppTypeAttr); + return E_NOTIMPL; +} + +static HRESULT WINAPI VBDispTypeInfo_GetTypeComp(ITypeInfo *iface, ITypeComp **ppTComp) +{ + FIXME("(%p)->(%p)\n", iface, ppTComp); + return E_NOTIMPL; +} + +static HRESULT WINAPI VBDispTypeInfo_GetFuncDesc(ITypeInfo *iface, UINT index, FUNCDESC **ppFuncDesc) +{ + FIXME("(%p)->(%u %p)\n", iface, index, ppFuncDesc); + return E_NOTIMPL; +} + +static HRESULT WINAPI VBDispTypeInfo_GetVarDesc(ITypeInfo *iface, UINT index, VARDESC **ppVarDesc) +{ + FIXME("(%p)->(%u %p)\n", iface, index, ppVarDesc); + return E_NOTIMPL; +} + +static HRESULT WINAPI VBDispTypeInfo_GetNames(ITypeInfo *iface, MEMBERID memid, BSTR *rgBstrNames, + UINT cMaxNames, UINT *pcNames) +{ + FIXME("(%p)->(%ld %p %u %p)\n", iface, memid, rgBstrNames, cMaxNames, pcNames); + return E_NOTIMPL; +} + +static HRESULT WINAPI VBDispTypeInfo_GetRefTypeOfImplType(ITypeInfo *iface, UINT index, HREFTYPE *pRefType) +{ + FIXME("(%p)->(%u %p)\n", iface, index, pRefType); + return E_NOTIMPL; +} + +static HRESULT WINAPI VBDispTypeInfo_GetImplTypeFlags(ITypeInfo *iface, UINT index, INT *pImplTypeFlags) +{ + FIXME("(%p)->(%u %p)\n", iface, index, pImplTypeFlags); + return E_NOTIMPL; +} + +static HRESULT WINAPI VBDispTypeInfo_GetIDsOfNames(ITypeInfo *iface, LPOLESTR *rgszNames, + UINT cNames, MEMBERID *pMemId) +{ + FIXME("(%p)->(%p %u %p)\n", iface, rgszNames, cNames, pMemId); + return E_NOTIMPL; +} + +static HRESULT WINAPI VBDispTypeInfo_Invoke(ITypeInfo *iface, PVOID pvInstance, MEMBERID memid, + WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) +{ + FIXME("(%p)->(%p %ld %d %p %p %p %p)\n", iface, pvInstance, memid, wFlags, + pDispParams, pVarResult, pExcepInfo, puArgErr); + return E_NOTIMPL; +} + +static HRESULT WINAPI VBDispTypeInfo_GetDocumentation(ITypeInfo *iface, MEMBERID memid, BSTR *pBstrName, + BSTR *pBstrDocString, DWORD *pdwHelpContext, BSTR *pBstrHelpFile) +{ + VBDispTypeInfo *This = VBDispTypeInfo_from_ITypeInfo(iface); + + TRACE("(%p)->(%ld %p %p %p %p)\n", This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile); + + if (pBstrDocString) *pBstrDocString = NULL; + if (pdwHelpContext) *pdwHelpContext = 0; + if (pBstrHelpFile) *pBstrHelpFile = NULL; + + if (memid == MEMBERID_NIL) + { + if (pBstrName && !(*pBstrName = SysAllocString(This->name))) + return E_OUTOFMEMORY; + return S_OK; + } + + return TYPE_E_ELEMENTNOTFOUND; +} + +static HRESULT WINAPI VBDispTypeInfo_GetDllEntry(ITypeInfo *iface, MEMBERID memid, INVOKEKIND invKind, + BSTR *pBstrDllName, BSTR *pBstrName, WORD *pwOrdinal) +{ + FIXME("(%p)->(%ld %d %p %p %p)\n", iface, memid, invKind, pBstrDllName, pBstrName, pwOrdinal); + return E_NOTIMPL; +} + +static HRESULT WINAPI VBDispTypeInfo_GetRefTypeInfo(ITypeInfo *iface, HREFTYPE hRefType, ITypeInfo **ppTInfo) +{ + FIXME("(%p)->(%lu %p)\n", iface, hRefType, ppTInfo); + return E_NOTIMPL; +} + +static HRESULT WINAPI VBDispTypeInfo_AddressOfMember(ITypeInfo *iface, MEMBERID memid, INVOKEKIND invKind, PVOID *ppv) +{ + FIXME("(%p)->(%ld %d %p)\n", iface, memid, invKind, ppv); + return E_NOTIMPL; +} + +static HRESULT WINAPI VBDispTypeInfo_CreateInstance(ITypeInfo *iface, IUnknown *pUnkOuter, REFIID riid, PVOID *ppvObj) +{ + FIXME("(%p)->(%p %s %p)\n", iface, pUnkOuter, debugstr_guid(riid), ppvObj); + return E_NOTIMPL; +} + +static HRESULT WINAPI VBDispTypeInfo_GetMops(ITypeInfo *iface, MEMBERID memid, BSTR *pBstrMops) +{ + FIXME("(%p)->(%ld %p)\n", iface, memid, pBstrMops); + return E_NOTIMPL; +} + +static HRESULT WINAPI VBDispTypeInfo_GetContainingTypeLib(ITypeInfo *iface, ITypeLib **ppTLib, UINT *pIndex) +{ + FIXME("(%p)->(%p %p)\n", iface, ppTLib, pIndex); + return E_NOTIMPL; +} + +static void WINAPI VBDispTypeInfo_ReleaseTypeAttr(ITypeInfo *iface, TYPEATTR *pTypeAttr) +{ + FIXME("(%p)->(%p)\n", iface, pTypeAttr); +} + +static void WINAPI VBDispTypeInfo_ReleaseFuncDesc(ITypeInfo *iface, FUNCDESC *pFuncDesc) +{ + FIXME("(%p)->(%p)\n", iface, pFuncDesc); +} + +static void WINAPI VBDispTypeInfo_ReleaseVarDesc(ITypeInfo *iface, VARDESC *pVarDesc) +{ + FIXME("(%p)->(%p)\n", iface, pVarDesc); +} + +static const ITypeInfoVtbl VBDispTypeInfoVtbl = { + VBDispTypeInfo_QueryInterface, + VBDispTypeInfo_AddRef, + VBDispTypeInfo_Release, + VBDispTypeInfo_GetTypeAttr, + VBDispTypeInfo_GetTypeComp, + VBDispTypeInfo_GetFuncDesc, + VBDispTypeInfo_GetVarDesc, + VBDispTypeInfo_GetNames, + VBDispTypeInfo_GetRefTypeOfImplType, + VBDispTypeInfo_GetImplTypeFlags, + VBDispTypeInfo_GetIDsOfNames, + VBDispTypeInfo_Invoke, + VBDispTypeInfo_GetDocumentation, + VBDispTypeInfo_GetDllEntry, + VBDispTypeInfo_GetRefTypeInfo, + VBDispTypeInfo_AddressOfMember, + VBDispTypeInfo_CreateInstance, + VBDispTypeInfo_GetMops, + VBDispTypeInfo_GetContainingTypeLib, + VBDispTypeInfo_ReleaseTypeAttr, + VBDispTypeInfo_ReleaseFuncDesc, + VBDispTypeInfo_ReleaseVarDesc +}; + static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) { vbdisp_t *This = impl_from_IDispatchEx(iface); - FIXME("(%p)->(%u %lu %p)\n", This, iTInfo, lcid, ppTInfo); - return E_NOTIMPL; + VBDispTypeInfo *type_info; + + TRACE("(%p)->(%u %lu %p)\n", This, iTInfo, lcid, ppTInfo); + + if (iTInfo) + return DISP_E_BADINDEX; + + if (!This->desc) + return E_UNEXPECTED; + + if (!(type_info = malloc(sizeof(*type_info)))) + return E_OUTOFMEMORY; + + type_info->ITypeInfo_iface.lpVtbl = &VBDispTypeInfoVtbl; + type_info->ref = 1; + type_info->name = This->desc->name; + + *ppTInfo = &type_info->ITypeInfo_iface; + return S_OK; } static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid, -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10461