Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
This is be needed for the next patches in the series.
dlls/vbscript/interp.c | 7 +++---- dlls/vbscript/vbscript.c | 16 ++++++++-------- dlls/vbscript/vbscript.h | 2 +- 3 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index 906545c..b328674 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -114,7 +114,6 @@ static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_ { ScriptDisp *script_obj = ctx->script->script_obj; named_item_t *item; - IDispatch *disp; unsigned i; DISPID id; HRESULT hres; @@ -196,10 +195,10 @@ static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_ return S_OK; }
- disp = lookup_named_item(ctx->script, name, SCRIPTITEM_ISVISIBLE); - if(disp) { + item = lookup_named_item(ctx->script, name, SCRIPTITEM_ISVISIBLE); + if(item && item->disp) { ref->type = REF_OBJ; - ref->u.obj = disp; + ref->u.obj = item->disp; return S_OK; }
diff --git a/dlls/vbscript/vbscript.c b/dlls/vbscript/vbscript.c index 2b691af..0bbff30 100644 --- a/dlls/vbscript/vbscript.c +++ b/dlls/vbscript/vbscript.c @@ -189,7 +189,7 @@ static void exec_queued_code(script_ctx_t *ctx) } }
-IDispatch *lookup_named_item(script_ctx_t *ctx, const WCHAR *name, unsigned flags) +named_item_t *lookup_named_item(script_ctx_t *ctx, const WCHAR *name, unsigned flags) { named_item_t *item; HRESULT hres; @@ -214,7 +214,7 @@ IDispatch *lookup_named_item(script_ctx_t *ctx, const WCHAR *name, unsigned flag } }
- return item->disp; + return item; } }
@@ -870,7 +870,7 @@ static HRESULT WINAPI VBScriptParse_ParseScriptText(IActiveScriptParse *iface, DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo) { VBScript *This = impl_from_IActiveScriptParse(iface); - IDispatch *context = NULL; + named_item_t *item = NULL; vbscode_t *code; HRESULT hres;
@@ -882,9 +882,9 @@ static HRESULT WINAPI VBScriptParse_ParseScriptText(IActiveScriptParse *iface, return E_UNEXPECTED;
if(pstrItemName) { - context = lookup_named_item(This->ctx, pstrItemName, 0); - if(!context) { - WARN("Inknown context %s\n", debugstr_w(pstrItemName)); + item = lookup_named_item(This->ctx, pstrItemName, 0); + if(!item) { + WARN("Unknown context %s\n", debugstr_w(pstrItemName)); return E_INVALIDARG; } } @@ -893,8 +893,8 @@ static HRESULT WINAPI VBScriptParse_ParseScriptText(IActiveScriptParse *iface, if(FAILED(hres)) return hres;
- if(context) - IDispatch_AddRef(code->context = context); + if(item && item->disp) + IDispatch_AddRef(code->context = item->disp);
if(!(dwFlags & SCRIPTTEXT_ISEXPRESSION) && !is_started(This)) { code->pending_exec = TRUE; diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index 33ecb45..a3f32fd 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -372,7 +372,7 @@ HRESULT compile_script(script_ctx_t*,const WCHAR*,const WCHAR*,DWORD_PTR,unsigne HRESULT compile_procedure(script_ctx_t*,const WCHAR*,const WCHAR*,DWORD_PTR,unsigned,DWORD,class_desc_t**) DECLSPEC_HIDDEN; HRESULT exec_script(script_ctx_t*,BOOL,function_t*,vbdisp_t*,DISPPARAMS*,VARIANT*) DECLSPEC_HIDDEN; void release_dynamic_var(dynamic_var_t*) DECLSPEC_HIDDEN; -IDispatch *lookup_named_item(script_ctx_t*,const WCHAR*,unsigned) DECLSPEC_HIDDEN; +named_item_t *lookup_named_item(script_ctx_t*,const WCHAR*,unsigned) DECLSPEC_HIDDEN; void clear_ei(EXCEPINFO*) DECLSPEC_HIDDEN; HRESULT report_script_error(script_ctx_t*,const vbscode_t*,unsigned) DECLSPEC_HIDDEN; void detach_global_objects(script_ctx_t*) DECLSPEC_HIDDEN;
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/vbscript/compile.c | 23 ++++++++++++++++++----- dlls/vbscript/vbscript.c | 19 ++++--------------- dlls/vbscript/vbscript.h | 4 ++-- 3 files changed, 24 insertions(+), 22 deletions(-)
diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index eac048d..9888109 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -1921,16 +1921,25 @@ static void release_compiler(compile_ctx_t *ctx) release_vbscode(ctx->code); }
-HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *delimiter, DWORD_PTR cookie, - unsigned start_line, DWORD flags, vbscode_t **ret) +HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *item_name, const WCHAR *delimiter, + DWORD_PTR cookie, unsigned start_line, DWORD flags, vbscode_t **ret) { function_decl_t *func_decl; + named_item_t *item = NULL; class_decl_t *class_decl; function_t *new_func; compile_ctx_t ctx; vbscode_t *code; HRESULT hres;
+ if(item_name) { + item = lookup_named_item(script, item_name, 0); + if(!item) { + WARN("Unknown context %s\n", debugstr_w(item_name)); + return E_INVALIDARG; + } + } + memset(&ctx, 0, sizeof(ctx)); code = ctx.code = alloc_vbscode(&ctx, src, cookie, start_line); if(!ctx.code) @@ -1993,19 +2002,23 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *deli ctx.code = NULL; release_compiler(&ctx);
+ if(item && item->disp) + IDispatch_AddRef(code->context = item->disp); + list_add_tail(&script->code_list, &code->entry); *ret = code; return S_OK; }
-HRESULT compile_procedure(script_ctx_t *script, const WCHAR *src, const WCHAR *delimiter, DWORD_PTR cookie, - unsigned start_line, DWORD flags, class_desc_t **ret) +HRESULT compile_procedure(script_ctx_t *script, const WCHAR *src, const WCHAR *item_name, const WCHAR *delimiter, + DWORD_PTR cookie, unsigned start_line, DWORD flags, class_desc_t **ret) { class_desc_t *desc; vbscode_t *code; HRESULT hres;
- hres = compile_script(script, src, delimiter, cookie, start_line, flags & ~SCRIPTTEXT_ISPERSISTENT, &code); + hres = compile_script(script, src, item_name, delimiter, cookie, start_line, + flags & ~SCRIPTTEXT_ISPERSISTENT, &code); if(FAILED(hres)) return hres;
diff --git a/dlls/vbscript/vbscript.c b/dlls/vbscript/vbscript.c index 0bbff30..b597389 100644 --- a/dlls/vbscript/vbscript.c +++ b/dlls/vbscript/vbscript.c @@ -870,7 +870,6 @@ static HRESULT WINAPI VBScriptParse_ParseScriptText(IActiveScriptParse *iface, DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo) { VBScript *This = impl_from_IActiveScriptParse(iface); - named_item_t *item = NULL; vbscode_t *code; HRESULT hres;
@@ -881,21 +880,11 @@ static HRESULT WINAPI VBScriptParse_ParseScriptText(IActiveScriptParse *iface, if(This->thread_id != GetCurrentThreadId() || This->state == SCRIPTSTATE_CLOSED) return E_UNEXPECTED;
- if(pstrItemName) { - item = lookup_named_item(This->ctx, pstrItemName, 0); - if(!item) { - WARN("Unknown context %s\n", debugstr_w(pstrItemName)); - return E_INVALIDARG; - } - } - - hres = compile_script(This->ctx, pstrCode, pstrDelimiter, dwSourceContextCookie, ulStartingLine, dwFlags, &code); + hres = compile_script(This->ctx, pstrCode, pstrItemName, pstrDelimiter, dwSourceContextCookie, + ulStartingLine, dwFlags, &code); if(FAILED(hres)) return hres;
- if(item && item->disp) - IDispatch_AddRef(code->context = item->disp); - if(!(dwFlags & SCRIPTTEXT_ISEXPRESSION) && !is_started(This)) { code->pending_exec = TRUE; return S_OK; @@ -953,8 +942,8 @@ static HRESULT WINAPI VBScriptParseProcedure_ParseProcedureText(IActiveScriptPar if(This->thread_id != GetCurrentThreadId() || This->state == SCRIPTSTATE_CLOSED) return E_UNEXPECTED;
- hres = compile_procedure(This->ctx, pstrCode, pstrDelimiter, dwSourceContextCookie, ulStartingLineNumber, - dwFlags, &desc); + hres = compile_procedure(This->ctx, pstrCode, pstrItemName, pstrDelimiter, dwSourceContextCookie, + ulStartingLineNumber, dwFlags, &desc); if(FAILED(hres)) return hres;
diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index a3f32fd..f37b0ce 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -368,8 +368,8 @@ static inline void grab_vbscode(vbscode_t *code) }
void release_vbscode(vbscode_t*) DECLSPEC_HIDDEN; -HRESULT compile_script(script_ctx_t*,const WCHAR*,const WCHAR*,DWORD_PTR,unsigned,DWORD,vbscode_t**) DECLSPEC_HIDDEN; -HRESULT compile_procedure(script_ctx_t*,const WCHAR*,const WCHAR*,DWORD_PTR,unsigned,DWORD,class_desc_t**) DECLSPEC_HIDDEN; +HRESULT compile_script(script_ctx_t*,const WCHAR*,const WCHAR*,const WCHAR*,DWORD_PTR,unsigned,DWORD,vbscode_t**) DECLSPEC_HIDDEN; +HRESULT compile_procedure(script_ctx_t*,const WCHAR*,const WCHAR*,const WCHAR*,DWORD_PTR,unsigned,DWORD,class_desc_t**) DECLSPEC_HIDDEN; HRESULT exec_script(script_ctx_t*,BOOL,function_t*,vbdisp_t*,DISPPARAMS*,VARIANT*) DECLSPEC_HIDDEN; void release_dynamic_var(dynamic_var_t*) DECLSPEC_HIDDEN; named_item_t *lookup_named_item(script_ctx_t*,const WCHAR*,unsigned) DECLSPEC_HIDDEN;
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
This is needed for next patch to avoid forward declaring ScriptDisp.
dlls/vbscript/vbscript.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index f37b0ce..589abc3 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -55,14 +55,6 @@ typedef struct _vbscode_t vbscode_t; typedef struct _script_ctx_t script_ctx_t; typedef struct _vbdisp_t vbdisp_t;
-typedef struct named_item_t { - IDispatch *disp; - DWORD flags; - LPWSTR name; - - struct list entry; -} named_item_t; - typedef enum { VBDISP_CALLGET, VBDISP_LET, @@ -156,6 +148,14 @@ typedef struct { script_ctx_t *ctx; } BuiltinDisp;
+typedef struct named_item_t { + IDispatch *disp; + DWORD flags; + LPWSTR name; + + struct list entry; +} named_item_t; + HRESULT create_vbdisp(const class_desc_t*,vbdisp_t**) DECLSPEC_HIDDEN; HRESULT disp_get_id(IDispatch*,BSTR,vbdisp_invoke_type_t,BOOL,DISPID*) DECLSPEC_HIDDEN; HRESULT vbdisp_get_id(vbdisp_t*,BSTR,vbdisp_invoke_type_t,BOOL,DISPID*) DECLSPEC_HIDDEN;
Each named item should have its own associated script dispatch object. The default object is special, though, because it's the only one that is reset when the code is persistent (the others become dummies).
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
Tests in next patch will demonstrate this behavior.
dlls/vbscript/compile.c | 12 +++++++----- dlls/vbscript/interp.c | 10 +++++----- dlls/vbscript/vbscript.c | 38 +++++++++++++++++++++++++++++++++++--- dlls/vbscript/vbscript.h | 2 ++ 4 files changed, 49 insertions(+), 13 deletions(-)
diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index 9888109..a7e82ad 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -1778,9 +1778,8 @@ static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl) return S_OK; }
-static BOOL lookup_script_identifier(script_ctx_t *script, const WCHAR *identifier) +static BOOL lookup_script_identifier(script_ctx_t *script, ScriptDisp *obj, const WCHAR *identifier) { - ScriptDisp *obj = script->script_obj; class_desc_t *class; vbscode_t *code; unsigned i; @@ -1805,7 +1804,7 @@ static BOOL lookup_script_identifier(script_ctx_t *script, const WCHAR *identifi var_desc_t *vars = code->main_code.vars; function_t *func;
- if(!code->pending_exec) + if(!code->pending_exec || code->script_obj != obj) continue;
for(i = 0; i < var_cnt; i++) { @@ -1831,17 +1830,18 @@ static HRESULT check_script_collisions(compile_ctx_t *ctx, script_ctx_t *script) { unsigned i, var_cnt = ctx->code->main_code.var_cnt; var_desc_t *vars = ctx->code->main_code.vars; + ScriptDisp *obj = ctx->code->script_obj; class_desc_t *class;
for(i = 0; i < var_cnt; i++) { - if(lookup_script_identifier(script, vars[i].name)) { + if(lookup_script_identifier(script, obj, vars[i].name)) { FIXME("%s: redefined\n", debugstr_w(vars[i].name)); return E_FAIL; } }
for(class = ctx->code->classes; class; class = class->next) { - if(lookup_script_identifier(script, class->name)) { + if(lookup_script_identifier(script, obj, class->name)) { FIXME("%s: redefined\n", debugstr_w(class->name)); return E_FAIL; } @@ -1945,6 +1945,8 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *item if(!ctx.code) return E_OUTOFMEMORY;
+ code->script_obj = item ? item->script_obj : script->script_obj; + hres = parse_script(&ctx.parser, code->source, delimiter, flags); if(FAILED(hres)) { if(ctx.parser.error_loc != -1) diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index b328674..8ded5cd 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -112,7 +112,7 @@ static BOOL lookup_global_vars(ScriptDisp *script, const WCHAR *name, ref_t *ref
static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_t invoke_type, ref_t *ref) { - ScriptDisp *script_obj = ctx->script->script_obj; + ScriptDisp *script_obj = ctx->code->script_obj; named_item_t *item; unsigned i; DISPID id; @@ -221,7 +221,7 @@ static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_ static HRESULT add_dynamic_var(exec_ctx_t *ctx, const WCHAR *name, BOOL is_const, VARIANT **out_var) { - ScriptDisp *script_obj = ctx->script->script_obj; + ScriptDisp *script_obj = ctx->code->script_obj; dynamic_var_t *new_var; heap_pool_t *heap; WCHAR *str; @@ -1122,7 +1122,7 @@ static HRESULT interp_new(exec_ctx_t *ctx) return stack_push(ctx, &v); }
- for(class_desc = ctx->script->script_obj->classes; class_desc; class_desc = class_desc->next) { + for(class_desc = ctx->code->script_obj->classes; class_desc; class_desc = class_desc->next) { if(!wcsicmp(class_desc->name, arg)) break; } @@ -1142,7 +1142,7 @@ static HRESULT interp_new(exec_ctx_t *ctx)
static HRESULT interp_dim(exec_ctx_t *ctx) { - ScriptDisp *script_obj = ctx->script->script_obj; + ScriptDisp *script_obj = ctx->code->script_obj; const BSTR ident = ctx->instr->arg1.bstr; const unsigned array_id = ctx->instr->arg2.uint; const array_desc_t *array_desc; @@ -1511,7 +1511,7 @@ static HRESULT interp_me(exec_ctx_t *ctx) else if(ctx->script->host_global) disp = ctx->script->host_global; else - disp = (IDispatch*)&ctx->script->script_obj->IDispatchEx_iface; + disp = (IDispatch*)&ctx->code->script_obj->IDispatchEx_iface;
IDispatch_AddRef(disp); V_VT(&v) = VT_DISPATCH; diff --git a/dlls/vbscript/vbscript.c b/dlls/vbscript/vbscript.c index b597389..bea2415 100644 --- a/dlls/vbscript/vbscript.c +++ b/dlls/vbscript/vbscript.c @@ -93,11 +93,20 @@ static inline BOOL is_started(VBScript *This)
static HRESULT exec_global_code(script_ctx_t *ctx, vbscode_t *code, VARIANT *res) { - ScriptDisp *obj = ctx->script_obj; + ScriptDisp *obj = code->script_obj; function_t *func_iter, **new_funcs; dynamic_var_t *var, **new_vars; size_t cnt, i;
+ if (!obj) + { + /* A persistent script with a dangling context calls these, + for some reason, even though it won't be executed. */ + IActiveScriptSite_OnEnterScript(ctx->site); + IActiveScriptSite_OnLeaveScript(ctx->site); + return S_OK; + } + cnt = obj->global_vars_cnt + code->main_code.var_cnt; if (cnt > obj->global_vars_size) { @@ -196,7 +205,7 @@ named_item_t *lookup_named_item(script_ctx_t *ctx, const WCHAR *name, unsigned f
LIST_FOR_EACH_ENTRY(item, &ctx->named_items, named_item_t, entry) { if((item->flags & flags) == flags && !wcsicmp(item->name, name)) { - if(!item->disp) { + if(!item->disp && !(item->flags & SCRIPTITEM_CODEONLY)) { IUnknown *unk;
hres = IActiveScriptSite_GetItemInfo(ctx->site, item->name, @@ -234,6 +243,7 @@ static void release_script(script_ctx_t *ctx) { code->pending_exec = TRUE; if(code->last_class) code->last_class->next = NULL; + if(code->script_obj != ctx->script_obj) code->script_obj = NULL; } else { @@ -248,6 +258,8 @@ static void release_script(script_ctx_t *ctx) list_remove(&iter->entry); if(iter->disp) IDispatch_Release(iter->disp); + iter->script_obj->ctx = NULL; + IDispatchEx_Release(&iter->script_obj->IDispatchEx_iface); heap_free(iter->name); heap_free(iter); } @@ -504,6 +516,7 @@ static ULONG WINAPI VBScript_Release(IActiveScript *iface) static HRESULT WINAPI VBScript_SetScriptSite(IActiveScript *iface, IActiveScriptSite *pass) { VBScript *This = impl_from_IActiveScript(iface); + vbscode_t *code; LCID lcid; HRESULT hres;
@@ -522,6 +535,11 @@ static HRESULT WINAPI VBScript_SetScriptSite(IActiveScript *iface, IActiveScript if(FAILED(hres)) return hres;
+ /* Fix the dangling pointers to the old script dispatch */ + LIST_FOR_EACH_ENTRY(code, &This->ctx->code_list, vbscode_t, entry) + if(code->script_obj) + code->script_obj = This->ctx->script_obj; + This->ctx->site = pass; IActiveScriptSite_AddRef(This->ctx->site);
@@ -658,6 +676,11 @@ static HRESULT WINAPI VBScript_AddNamedItem(IActiveScript *iface, LPCOLESTR pstr item->disp = disp; item->flags = dwFlags; item->name = heap_strdupW(pstrName); + hres = create_script_disp(This->ctx, &item->script_obj); + if(FAILED(hres)) { + heap_free(item->name); + item->name = NULL; + } if(!item->name) { if(disp) IDispatch_Release(disp); @@ -680,6 +703,7 @@ static HRESULT WINAPI VBScript_AddTypeLib(IActiveScript *iface, REFGUID rguidTyp static HRESULT WINAPI VBScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName, IDispatch **ppdisp) { VBScript *This = impl_from_IActiveScript(iface); + ScriptDisp *script_obj;
TRACE("(%p)->(%s %p)\n", This, debugstr_w(pstrItemName), ppdisp);
@@ -691,7 +715,15 @@ static HRESULT WINAPI VBScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR return E_UNEXPECTED; }
- *ppdisp = (IDispatch*)&This->ctx->script_obj->IDispatchEx_iface; + if(pstrItemName) { + named_item_t *item = lookup_named_item(This->ctx, pstrItemName, 0); + if(!item) return E_INVALIDARG; + script_obj = item->script_obj; + } + else + script_obj = This->ctx->script_obj; + + *ppdisp = (IDispatch*)&script_obj->IDispatchEx_iface; IDispatch_AddRef(*ppdisp); return S_OK; } diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index 589abc3..dd6d5bf 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -152,6 +152,7 @@ typedef struct named_item_t { IDispatch *disp; DWORD flags; LPWSTR name; + ScriptDisp *script_obj;
struct list entry; } named_item_t; @@ -349,6 +350,7 @@ struct _vbscode_t { BOOL is_persistent; function_t main_code; IDispatch *context; + ScriptDisp *script_obj;
BSTR *bstr_pool; unsigned bstr_pool_size;
Hi Gabriel,
On 31.01.2020 14:29, Gabriel Ivăncescu wrote:
diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index b328674..8ded5cd 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -112,7 +112,7 @@ static BOOL lookup_global_vars(ScriptDisp *script, const WCHAR *name, ref_t *ref
static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_t invoke_type, ref_t *ref) {
- ScriptDisp *script_obj = ctx->script->script_obj;
- ScriptDisp *script_obj = ctx->code->script_obj;
Does it really use this script instead of global script global context? My guess would be that both should be looked up in this case. A test to clarify that would be nice.
- if (!obj)
- {
/* A persistent script with a dangling context calls these,
for some reason, even though it won't be executed. */
IActiveScriptSite_OnEnterScript(ctx->site);
IActiveScriptSite_OnLeaveScript(ctx->site);
return S_OK;
- }
Is it just to satisfy a test? I'd suggest to leave it in todo_wine for OnEnterScript/OnLeaveScript. Otherwise, it would deserve a closer look to see if we can solve it more generally and avoid such special case.
return hres;
- /* Fix the dangling pointers to the old script dispatch */
- LIST_FOR_EACH_ENTRY(code, &This->ctx->code_list, vbscode_t, entry)
if(code->script_obj)
code->script_obj = This->ctx->script_obj;
That's not pretty. Depending on result of test I mentioned earlier, we may want to simply not store global script context in vbscode_t (and only store named item-based script object).
Thanks,
Jacek
Hi Jacek,
On 03/02/2020 19:17, Jacek Caban wrote:
Hi Gabriel,
On 31.01.2020 14:29, Gabriel Ivăncescu wrote:
diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index b328674..8ded5cd 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -112,7 +112,7 @@ static BOOL lookup_global_vars(ScriptDisp *script, const WCHAR *name, ref_t *ref
static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_t invoke_type, ref_t *ref) {
- ScriptDisp *script_obj = ctx->script->script_obj;
- ScriptDisp *script_obj = ctx->code->script_obj;
Does it really use this script instead of global script global context? My guess would be that both should be looked up in this case. A test to clarify that would be nice.
Yes, sorry about that, I forgot to add this test to the actual patch (I did fiddle manually with it though).
I double checked and added such a test, it does appear that it was correct: it cannot access the global context or dispatch at all.
See: https://testbot.winehq.org/JobDetails.pl?Key=64413
In fact, for jscript (which I'll send after these), it cannot even access the built-in identifiers! (since they are attached to the global object). For example, it cannot access the 'Math' object.
- if (!obj)
- {
/* A persistent script with a dangling context calls these,
for some reason, even though it won't be executed. */
IActiveScriptSite_OnEnterScript(ctx->site);
IActiveScriptSite_OnLeaveScript(ctx->site);
return S_OK;
- }
Is it just to satisfy a test? I'd suggest to leave it in todo_wine for OnEnterScript/OnLeaveScript. Otherwise, it would deserve a closer look to see if we can solve it more generally and avoid such special case.
It's mostly to satisfy the tests, yes. I didn't realize it would be an issue though. Note that we'd still have to check for if (!obj) and return S_OK, otherwise the code will crash.
return hres;
- /* Fix the dangling pointers to the old script dispatch */
- LIST_FOR_EACH_ENTRY(code, &This->ctx->code_list, vbscode_t, entry)
if(code->script_obj)
code->script_obj = This->ctx->script_obj;
That's not pretty. Depending on result of test I mentioned earlier, we may want to simply not store global script context in vbscode_t (and only store named item-based script object).
Yeah it's not pretty, but unfortunately I couldn't find a simpler way without adding extra fields just for this, which to me would be even worse.
Note that the "fix" has to be done for the global context, otherwise persistent code would be useless. For other contexts it seems they are completely "lost" when script is restarted (even adding a named item of same name will not work to gain access to them -- it's in the tests), and they will also do nothing *except* that they'll trigger the OnEnterScript/OnLeaveScript for some reason.
Obviously, this is only for persistent code.
Thanks,
Jacek
Hi Gabriel,
On 03.02.2020 17:59, Gabriel Ivăncescu wrote:
Hi Jacek,
On 03/02/2020 19:17, Jacek Caban wrote:
Hi Gabriel,
On 31.01.2020 14:29, Gabriel Ivăncescu wrote:
diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index b328674..8ded5cd 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -112,7 +112,7 @@ static BOOL lookup_global_vars(ScriptDisp *script, const WCHAR *name, ref_t *ref static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_t invoke_type, ref_t *ref) { - ScriptDisp *script_obj = ctx->script->script_obj; + ScriptDisp *script_obj = ctx->code->script_obj;
Does it really use this script instead of global script global context? My guess would be that both should be looked up in this case. A test to clarify that would be nice.
Yes, sorry about that, I forgot to add this test to the actual patch (I did fiddle manually with it though).
I double checked and added such a test, it does appear that it was correct: it cannot access the global context or dispatch at all.
I don't see the test I was interested in there. I wrote a simple test on top of that (see attachment) and it confirms that my guess was right. Scripts ran in context of named item can access global properties. The test succeeded on win10, but failed on patched Wine.
+ if (!obj) + { + /* A persistent script with a dangling context calls these, + for some reason, even though it won't be executed. */ + IActiveScriptSite_OnEnterScript(ctx->site); + IActiveScriptSite_OnLeaveScript(ctx->site); + return S_OK; + }
Is it just to satisfy a test? I'd suggest to leave it in todo_wine for OnEnterScript/OnLeaveScript. Otherwise, it would deserve a closer look to see if we can solve it more generally and avoid such special case.
It's mostly to satisfy the tests, yes. I didn't realize it would be an issue though. Note that we'd still have to check for if (!obj) and return S_OK, otherwise the code will crash.
It's not really a big deal, I would probably not bother you with that the patch would be ready for Wine otherwise. I recently fixed and unified those script site notifications. Your tests indicates that there is more work needed. I would rather fix it properly and introducing more ad-hoc calls like this. But it's probably not worth bothering at the moment. if(!obj) return S_OK; combined with todo_wine is probably fine (assuming that it still makes sense one we figure out host to handle named objects given the problem above).
return hres; + /* Fix the dangling pointers to the old script dispatch */ + LIST_FOR_EACH_ENTRY(code, &This->ctx->code_list, vbscode_t, entry) + if(code->script_obj) + code->script_obj = This->ctx->script_obj;
That's not pretty. Depending on result of test I mentioned earlier, we may want to simply not store global script context in vbscode_t (and only store named item-based script object).
Yeah it's not pretty, but unfortunately I couldn't find a simpler way without adding extra fields just for this, which to me would be even worse.
Note that the "fix" has to be done for the global context, otherwise persistent code would be useless. For other contexts it seems they are completely "lost" when script is restarted (even adding a named item of same name will not work to gain access to them -- it's in the tests), and they will also do nothing *except* that they'll trigger the OnEnterScript/OnLeaveScript for some reason.
Obviously, this is only for persistent code.
Taking into account the problem shown by the test, I think we want to handle global script object differently. There will be no problems like this if we don't use vbscode_t to store global script object.
Thanks,
Jacek
On 03/02/2020 21:26, Jacek Caban wrote:
Hi Gabriel,
On 03.02.2020 17:59, Gabriel Ivăncescu wrote:
Hi Jacek,
On 03/02/2020 19:17, Jacek Caban wrote:
Hi Gabriel,
On 31.01.2020 14:29, Gabriel Ivăncescu wrote:
diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index b328674..8ded5cd 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -112,7 +112,7 @@ static BOOL lookup_global_vars(ScriptDisp *script, const WCHAR *name, ref_t *ref static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_t invoke_type, ref_t *ref) { - ScriptDisp *script_obj = ctx->script->script_obj; + ScriptDisp *script_obj = ctx->code->script_obj;
Does it really use this script instead of global script global context? My guess would be that both should be looked up in this case. A test to clarify that would be nice.
Yes, sorry about that, I forgot to add this test to the actual patch (I did fiddle manually with it though).
I double checked and added such a test, it does appear that it was correct: it cannot access the global context or dispatch at all.
I don't see the test I was interested in there. I wrote a simple test on top of that (see attachment) and it confirms that my guess was right. Scripts ran in context of named item can access global properties. The test succeeded on win10, but failed on patched Wine.
Ok, I've analyzed this deeper, part of the problems is because the current test adds a visibleItem which always returns S_OK, so in fact that snippet you added could use any identifier and still have it parse correctly. It fails on Wine but that is a separate issue currently.
However, now that I've changed it to a different identifier in my tests (testSub_global) and had it return DISP_E_UNKNOWNNAME with anything other than testCall, it still passes on Windows, so you are indeed correct.
It can access the global namespace but only through code, not with GetIDsOfNames.
So I'll have to revise it now. :-)
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/vbscript/tests/vbscript.c | 115 +++++++++++++++++++++++++++++---- 1 file changed, 104 insertions(+), 11 deletions(-)
diff --git a/dlls/vbscript/tests/vbscript.c b/dlls/vbscript/tests/vbscript.c index f0b75ad..6a35015 100644 --- a/dlls/vbscript/tests/vbscript.c +++ b/dlls/vbscript/tests/vbscript.c @@ -431,14 +431,14 @@ static void test_safety(IActiveScript *script) IObjectSafety_Release(safety); }
-static IDispatchEx *get_script_dispatch(IActiveScript *script) +static IDispatchEx *get_script_dispatch(IActiveScript *script, const WCHAR *item_name) { IDispatchEx *dispex; IDispatch *disp; HRESULT hres;
disp = (void*)0xdeadbeef; - hres = IActiveScript_GetScriptDispatch(script, NULL, &disp); + hres = IActiveScript_GetScriptDispatch(script, item_name, &disp); ok(hres == S_OK, "GetScriptDispatch failed: %08x\n", hres); if(FAILED(hres)) return NULL; @@ -531,7 +531,7 @@ static void test_scriptdisp(void) ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres); CHECK_CALLED(GetLCID);
- script_disp2 = get_script_dispatch(vbscript); + script_disp2 = get_script_dispatch(vbscript, NULL);
test_state(vbscript, SCRIPTSTATE_UNINITIALIZED);
@@ -549,7 +549,7 @@ static void test_scriptdisp(void)
test_state(vbscript, SCRIPTSTATE_CONNECTED);
- script_disp = get_script_dispatch(vbscript); + script_disp = get_script_dispatch(vbscript, NULL); ok(script_disp == script_disp2, "script_disp != script_disp2\n"); IDispatchEx_Release(script_disp2);
@@ -676,7 +676,7 @@ static void test_code_persistence(void) ok(hr == S_OK, "ParseScriptText failed: %08x\n", hr);
/* Pending code does not add identifiers to the global scope */ - script_disp = get_script_dispatch(vbscript); + script_disp = get_script_dispatch(vbscript, NULL); id = 0; get_disp_id(script_disp, "x", DISP_E_UNKNOWNNAME, &id); ok(id == -1, "id = %d, expected -1\n", id); @@ -715,7 +715,7 @@ static void test_code_persistence(void) CHECK_CALLED_MULTI(OnLeaveScript, 2); test_state(vbscript, SCRIPTSTATE_CONNECTED);
- script_disp = get_script_dispatch(vbscript); + script_disp = get_script_dispatch(vbscript, NULL); id = 0; get_disp_id(script_disp, "x", DISP_E_UNKNOWNNAME, &id); ok(id == -1, "id = %d, expected -1\n", id); @@ -761,7 +761,7 @@ static void test_code_persistence(void) CHECK_CALLED(GetLCID); CHECK_CALLED(OnStateChange_INITIALIZED);
- script_disp = get_script_dispatch(vbscript); + script_disp = get_script_dispatch(vbscript, NULL); id = 0; get_disp_id(script_disp, "z", DISP_E_UNKNOWNNAME, &id); ok(id == -1, "id = %d, expected -1\n", id); @@ -777,7 +777,7 @@ static void test_code_persistence(void) CHECK_CALLED(OnLeaveScript); test_state(vbscript, SCRIPTSTATE_CONNECTED);
- script_disp = get_script_dispatch(vbscript); + script_disp = get_script_dispatch(vbscript, NULL); id = 0; get_disp_id(script_disp, "z", S_OK, &id); ok(id != -1, "id = -1\n"); @@ -840,7 +840,7 @@ static void test_code_persistence(void) CHECK_CALLED(OnStateChange_CONNECTED); test_state(vbscript, SCRIPTSTATE_CONNECTED);
- script_disp = get_script_dispatch(vbscript); + script_disp = get_script_dispatch(vbscript, NULL); id = 0; get_disp_id(script_disp, "y", DISP_E_UNKNOWNNAME, &id); ok(id == -1, "id = %d, expected -1\n", id); @@ -953,7 +953,7 @@ static void test_script_typeinfo(void) "implicit = 10\n" "dim obj\nset obj = new C\n");
- script_disp = get_script_dispatch(vbscript); + script_disp = get_script_dispatch(vbscript, NULL); hr = IDispatchEx_QueryInterface(script_disp, &IID_ITypeInfo, (void**)&typeinfo); ok(hr == E_NOINTERFACE, "QueryInterface(IID_ITypeInfo) returned: %08x\n", hr); hr = IDispatchEx_GetTypeInfo(script_disp, 1, LOCALE_USER_DEFAULT, &typeinfo); @@ -1446,7 +1446,7 @@ static void test_vbscript_uninitializing(void)
test_state(script, SCRIPTSTATE_CONNECTED);
- dispex = get_script_dispatch(script); + dispex = get_script_dispatch(script, NULL); ok(dispex != NULL, "dispex == NULL\n"); if(dispex) IDispatchEx_Release(dispex); @@ -1631,8 +1631,11 @@ static void test_vbscript_initializing(void)
static void test_named_items(void) { + IDispatchEx *script_disp, *script_disp2; IActiveScriptParse *parse; IActiveScript *script; + IDispatch *disp; + DISPID id; ULONG ref; HRESULT hres;
@@ -1647,6 +1650,8 @@ static void test_named_items(void) ok(hres == E_UNEXPECTED, "AddNamedItem returned: %08x\n", hres); hres = IActiveScript_AddNamedItem(script, L"globalItem", SCRIPTITEM_GLOBALMEMBERS); ok(hres == E_UNEXPECTED, "AddNamedItem returned: %08x\n", hres); + hres = IActiveScript_AddNamedItem(script, L"code context", SCRIPTITEM_CODEONLY); + ok(hres == E_UNEXPECTED, "AddNamedItem returned: %08x\n", hres);
SET_EXPECT(GetLCID); hres = IActiveScript_SetScriptSite(script, &ActiveScriptSite); @@ -1660,10 +1665,19 @@ static void test_named_items(void)
hres = IActiveScript_AddNamedItem(script, L"visibleItem", SCRIPTITEM_ISVISIBLE); ok(hres == S_OK, "AddNamedItem failed: %08x\n", hres); + hres = IActiveScript_AddNamedItem(script, L"code context", SCRIPTITEM_CODEONLY); + ok(hres == S_OK, "AddNamedItem failed: %08x\n", hres);
ok(global_named_item_ref > 0, "global_named_item_ref = %u\n", global_named_item_ref); ok(visible_named_item_ref == 0, "visible_named_item_ref = %u\n", visible_named_item_ref);
+ hres = IActiveScript_GetScriptDispatch(script, L"no context", &disp); + ok(hres == E_INVALIDARG, "GetScriptDispatch returned: %08x\n", hres); + + script_disp = get_script_dispatch(script, NULL); + script_disp2 = get_script_dispatch(script, L"code CONTEXT"); + ok(script_disp != script_disp2, "get_script_dispatch returned same dispatch objects.\n"); + SET_EXPECT(OnStateChange_INITIALIZED); hres = IActiveScriptParse_InitNew(parse); ok(hres == S_OK, "InitNew failed: %08x\n", hres); @@ -1691,6 +1705,85 @@ static void test_named_items(void) parse_script(parse, "visibleItem.testCall\n"); CHECK_CALLED(testCall);
+ hres = IActiveScriptParse_ParseScriptText(parse, L"sub testSub\nend sub\n", L"no context", NULL, NULL, 0, 0, 0, NULL, NULL); + ok(hres == E_INVALIDARG, "ParseScriptText returned: %08x\n", hres); + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hres = IActiveScriptParse_ParseScriptText(parse, L"sub testSub\nend sub\n", L"code context", NULL, NULL, 0, 0, 0, NULL, NULL); + ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hres = IActiveScriptParse_ParseScriptText(parse, L"sub testSub2\nend sub\n", L"Code Context", NULL, NULL, 0, 0, SCRIPTTEXT_ISPERSISTENT, NULL, NULL); + ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + + id = 0; + get_disp_id(script_disp, "testSub", DISP_E_UNKNOWNNAME, &id); + ok(id == -1, "id = %d, expected -1\n", id); + id = 0; + get_disp_id(script_disp2, "testSub", S_OK, &id); + ok(id != -1, "id = -1\n"); + id = 0; + get_disp_id(script_disp2, "testSub2", S_OK, &id); + ok(id != -1, "id = -1\n"); + + IDispatchEx_Release(script_disp2); + IDispatchEx_Release(script_disp); + + SET_EXPECT(OnStateChange_DISCONNECTED); + SET_EXPECT(OnStateChange_INITIALIZED); + SET_EXPECT(OnStateChange_UNINITIALIZED); + hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_UNINITIALIZED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_UNINITIALIZED) failed: %08x\n", hres); + CHECK_CALLED(OnStateChange_DISCONNECTED); + CHECK_CALLED(OnStateChange_INITIALIZED); + CHECK_CALLED(OnStateChange_UNINITIALIZED); + test_no_script_dispatch(script); + + hres = IActiveScript_GetScriptDispatch(script, L"code context", &disp); + ok(hres == E_UNEXPECTED, "hres = %08x, expected E_UNEXPECTED\n", hres); + + SET_EXPECT(GetLCID); + SET_EXPECT(OnStateChange_INITIALIZED); + hres = IActiveScript_SetScriptSite(script, &ActiveScriptSite); + ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres); + CHECK_CALLED(GetLCID); + CHECK_CALLED(OnStateChange_INITIALIZED); + + hres = IActiveScript_AddNamedItem(script, L"code context", SCRIPTITEM_CODEONLY); + ok(hres == S_OK, "AddNamedItem failed: %08x\n", hres); + + SET_EXPECT(OnStateChange_CONNECTED); + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_CONNECTED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_CONNECTED) failed: %08x\n", hres); + CHECK_CALLED(OnStateChange_CONNECTED); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + test_state(script, SCRIPTSTATE_CONNECTED); + + script_disp = get_script_dispatch(script, NULL); + id = 0; + get_disp_id(script_disp, "testSub", DISP_E_UNKNOWNNAME, &id); + ok(id == -1, "id = %d, expected -1\n", id); + id = 0; + get_disp_id(script_disp, "testSub2", DISP_E_UNKNOWNNAME, &id); + ok(id == -1, "id = %d, expected -1\n", id); + IDispatchEx_Release(script_disp); + + script_disp = get_script_dispatch(script, L"code context"); + id = 0; + get_disp_id(script_disp, "testSub", DISP_E_UNKNOWNNAME, &id); + ok(id == -1, "id = %d, expected -1\n", id); + id = 0; + get_disp_id(script_disp, "testSub2", DISP_E_UNKNOWNNAME, &id); + ok(id == -1, "id = %d, expected -1\n", id); + IDispatchEx_Release(script_disp); + SET_EXPECT(OnStateChange_DISCONNECTED); SET_EXPECT(OnStateChange_INITIALIZED); SET_EXPECT(OnStateChange_CLOSED);