From: "Gabriel Ivăncescu" Subject: [PATCH 3/9] vbscript: Store the necessary function and variable info in the script TypeInfo. Message-Id: <097f8035ef39de040d128b5750343431d5ca561a.1571150960.git.gabrielopcode@gmail.com> Date: Tue, 15 Oct 2019 17:54:54 +0300 In-Reply-To: References: Signed-off-by: Gabriel Ivăncescu --- The TypeInfo is built when it is retrieved, even if the script changes after that and more stuff is added to it (tests at the end of the patch series will show this). This builds most of the necessary information for subsequent patches. dlls/vbscript/vbdisp.c | 106 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index c0535f1..fea82c1 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -26,6 +26,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(vbscript); #define FDEX_VERSION_MASK 0xf0000000 +static WCHAR *copy_string_to_heap_pool(const WCHAR *str, heap_pool_t *heap) +{ + size_t size = (lstrlenW(str) + 1) * sizeof(WCHAR); + WCHAR *ret; + + if ((ret = heap_pool_alloc(heap, size))) + memcpy(ret, str, size); + return ret; +} + static inline BOOL is_func_id(vbdisp_t *This, DISPID id) { return id < This->desc->func_cnt; @@ -724,9 +734,29 @@ static ident_map_t *add_func_ident(ScriptDisp *This, function_t *func) return ident; } +struct script_typeinfo_var { + const WCHAR *name; + MEMBERID memid; +}; + +struct script_typeinfo_func { + const WCHAR *name; + const WCHAR **arg_names; + MEMBERID memid; + VARTYPE ret_type; + WORD num_args; +}; + typedef struct { ITypeInfo ITypeInfo_iface; LONG ref; + + UINT num_funcs; + UINT num_vars; + struct script_typeinfo_func *funcs; + struct script_typeinfo_var *vars; + + heap_pool_t heap; } ScriptTypeInfo; static inline ScriptTypeInfo *ScriptTypeInfo_from_ITypeInfo(ITypeInfo *iface) @@ -771,6 +801,7 @@ static ULONG WINAPI ScriptTypeInfo_Release(ITypeInfo *iface) if (!ref) { + heap_pool_free(&This->heap); heap_free(This); } return ref; @@ -974,15 +1005,90 @@ static const ITypeInfoVtbl ScriptTypeInfoVtbl = { static ITypeInfo *create_script_typeinfo(ScriptDisp *disp) { + struct script_typeinfo_func *typefunc; + struct script_typeinfo_var *typevar; + UINT num_funcs = 0, num_vars = 0; + dynamic_var_t *var; + function_t *func; ScriptTypeInfo *p; + BOOL add_const; + /* Populate the identifiers to get the DISPIDs which have to match the MEMBERIDs */ + for (var = disp->ctx->global_vars; var; var = var->next) + { + if (!var->dispid && !add_var_ident(disp, var)) + return NULL; + num_vars++; + } + + for (func = disp->ctx->global_funcs; func; func = func->next) + { + if (!func->is_public) continue; + if (!func->dispid && !add_func_ident(disp, func)) + return NULL; + num_funcs++; + } + + /* Now we can allocate the typeinfo */ if (!(p = heap_alloc(sizeof(*p)))) return NULL; p->ITypeInfo_iface.lpVtbl = &ScriptTypeInfoVtbl; p->ref = 1; + p->num_vars = num_vars; + p->num_funcs = num_funcs; + heap_pool_init(&p->heap); + + p->funcs = heap_pool_alloc(&p->heap, sizeof(*p->funcs) * num_funcs); + if (!p->funcs) goto fail; + p->vars = heap_pool_alloc(&p->heap, sizeof(*p->vars) * num_vars); + if (!p->vars) goto fail; + + /* Const variables must be placed after the other variables, + and the order for all reversed compared to the original. */ + typevar = p->vars + num_vars - 1; + add_const = TRUE; + for (;;) + { + for (var = disp->ctx->global_vars; var; var = var->next) + { + if (var->is_const != add_const) continue; + if (!(typevar->name = copy_string_to_heap_pool(var->name, &p->heap))) + goto fail; + typevar->memid = var->dispid; + typevar--; + } + if (!add_const) break; + add_const = FALSE; + } + + for (typefunc = p->funcs, func = disp->ctx->global_funcs; func; func = func->next) + { + UINT i; + + if (!func->is_public) continue; + if (!(typefunc->name = copy_string_to_heap_pool(func->name, &p->heap))) + goto fail; + + typefunc->arg_names = heap_pool_alloc(&p->heap, func->arg_cnt * sizeof(WCHAR*)); + if (!typefunc->arg_names) + goto fail; + for (i = 0; i < func->arg_cnt; i++) + if (!(typefunc->arg_names[i] = copy_string_to_heap_pool(func->args[i].name, &p->heap))) + goto fail; + + typefunc->memid = func->dispid; + typefunc->num_args = func->arg_cnt; + typefunc->ret_type = (func->type == FUNC_SUB) ? VT_VOID : VT_VARIANT; + typefunc++; + } return &p->ITypeInfo_iface; + +fail: + heap_pool_free(&p->heap); + heap_free(p); + return NULL; } static inline ScriptDisp *ScriptDisp_from_IDispatchEx(IDispatchEx *iface) -- 2.21.0