[PATCH 04/14] vbscript: Implement ScriptTypeInfo_GetNames.
Gabriel Ivăncescu
gabrielopcode at gmail.com
Mon Dec 9 09:29:27 CST 2019
Signed-off-by: Gabriel Ivăncescu <gabrielopcode at 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++;
}
--
2.21.0
More information about the wine-devel
mailing list