[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