Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
We need to map the member IDs to the variables and functions. Functions can be replaced or skipped (if private) so we have to keep a map for them.
dlls/vbscript/vbdisp.c | 92 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 3 deletions(-)
diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index e27ce22..5d43c43 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -539,6 +539,9 @@ typedef struct { ITypeComp ITypeComp_iface; LONG ref;
+ UINT func_memid_map_cnt; + UINT *func_memid_map; + UINT num_vars; UINT num_funcs; struct typeinfo_func *funcs; @@ -546,6 +549,30 @@ typedef struct { ScriptDisp *disp; } ScriptTypeInfo;
+enum memid_type { + memid_invalid, + memid_inherited, + memid_func, + memid_var +}; + +static inline enum memid_type get_memid_type(const ScriptTypeInfo *typeinfo, MEMBERID memid) +{ + if (memid <= 0) return memid_invalid; + if (memid & DISPID_FUNCTION_MASK) + { + memid &= ~DISPID_FUNCTION_MASK; + if (memid >= typeinfo->func_memid_map_cnt) + return memid_inherited; + if (typeinfo->func_memid_map[memid] == ~0) + return memid_invalid; + return memid_func; + } + if (memid > typeinfo->num_vars) + return memid_inherited; + return memid_var; +} + static inline ScriptTypeInfo *ScriptTypeInfo_from_ITypeInfo(ITypeInfo *iface) { return CONTAINING_RECORD(iface, ScriptTypeInfo, ITypeInfo_iface); @@ -600,6 +627,7 @@ static ULONG WINAPI ScriptTypeInfo_Release(ITypeInfo *iface) release_vbscode(This->funcs[i].func->code_ctx);
IDispatchEx_Release(&This->disp->IDispatchEx_iface); + heap_free(This->func_memid_map); heap_free(This->funcs); heap_free(This); } @@ -707,10 +735,53 @@ static HRESULT WINAPI ScriptTypeInfo_GetNames(ITypeInfo *iface, MEMBERID memid, UINT cMaxNames, UINT *pcNames) { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface); + enum memid_type memid_type = get_memid_type(This, memid); + ITypeInfo *disp_typeinfo; + HRESULT hr; + UINT i = 0;
- FIXME("(%p)->(%d %p %u %p)\n", This, memid, rgBstrNames, cMaxNames, pcNames); + TRACE("(%p)->(%d %p %u %p)\n", This, memid, rgBstrNames, cMaxNames, pcNames);
- return E_NOTIMPL; + if (!rgBstrNames || !pcNames) return E_INVALIDARG; + if (memid_type == memid_invalid) return TYPE_E_ELEMENTNOTFOUND; + if (memid_type == memid_inherited) + { + hr = get_dispatch_typeinfo(&disp_typeinfo); + if (FAILED(hr)) return hr; + + return ITypeInfo_GetNames(disp_typeinfo, memid, rgBstrNames, cMaxNames, pcNames); + } + + *pcNames = 0; + if (!cMaxNames) return S_OK; + + if (memid_type == memid_func) + { + UINT index = This->func_memid_map[memid & ~DISPID_FUNCTION_MASK]; + UINT num = min(cMaxNames, This->funcs[index].func->arg_cnt + 1); + arg_desc_t *args = This->funcs[index].func->args; + + rgBstrNames[0] = SysAllocString(This->funcs[index].func->name); + if (!rgBstrNames[0]) return E_OUTOFMEMORY; + + for (i = 1; i < num; i++) + { + if (!(rgBstrNames[i] = SysAllocString(args[i - 1].name))) + { + do SysFreeString(rgBstrNames[--i]); while (i); + return E_OUTOFMEMORY; + } + } + } + else + { + rgBstrNames[0] = SysAllocString(This->disp->global_vars[memid - 1]->name); + if (!rgBstrNames[0]) return E_OUTOFMEMORY; + i++; + } + + *pcNames = i; + return S_OK; }
static HRESULT WINAPI ScriptTypeInfo_GetRefTypeOfImplType(ITypeInfo *iface, UINT index, HREFTYPE *pRefType) @@ -1119,21 +1190,36 @@ static HRESULT WINAPI ScriptDisp_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, LC type_info->ref = 1; type_info->num_funcs = num_funcs; type_info->num_vars = This->global_vars_cnt; + type_info->func_memid_map_cnt = This->global_funcs_cnt + 1; type_info->disp = This;
+ type_info->func_memid_map = heap_alloc(sizeof(*type_info->func_memid_map) * type_info->func_memid_map_cnt); + if(!type_info->func_memid_map) + { + heap_free(type_info); + return E_OUTOFMEMORY; + } + type_info->funcs = heap_alloc(sizeof(*type_info->funcs) * num_funcs); if(!type_info->funcs) { + heap_free(type_info->func_memid_map); heap_free(type_info); return E_OUTOFMEMORY; }
+ type_info->func_memid_map[0] = ~0; for(j = 0, i = 0; i < This->global_funcs_cnt; i++) { - if(!This->global_funcs[i]->is_public) continue; + if(!This->global_funcs[i]->is_public) + { + type_info->func_memid_map[i + 1] = ~0; + continue; + }
type_info->funcs[j].memid = i + 1 + DISPID_FUNCTION_MASK; type_info->funcs[j].func = This->global_funcs[i]; + type_info->func_memid_map[i + 1] = j; grab_vbscode(This->global_funcs[i]->code_ctx); j++; }