-- v5: vbscript: Implement SID_GetCaller for QueryService. vbscript: Add a ServiceProvider stub. jscript: Implement SID_GetCaller for QueryService. mshtml: Set SCRIPTPROP_ABBREVIATE_GLOBALNAME_RESOLUTION properly. mshtml: Defer populating the IActiveScript field until it's fully initialized. mshtml: Implement location props when there's no URI.
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmldoc.c | 3 ++ dlls/mshtml/htmllocation.c | 38 +++++++--------- dlls/mshtml/tests/htmllocation.c | 75 +++++++++++++++++++------------- 3 files changed, 63 insertions(+), 53 deletions(-)
diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index 90c4706abee..66b593920e2 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -1175,6 +1175,9 @@ static HRESULT WINAPI HTMLDocument_get_domain(IHTMLDocument2 *iface, BSTR *p) return E_NOTIMPL; }
+ if(This->outer_window && !This->outer_window->uri) + return E_FAIL; + nsAString_Init(&nsstr, NULL); nsres = nsIDOMHTMLDocument_GetDomain(This->html_document, &nsstr); if(NS_SUCCEEDED(nsres) && This->outer_window && This->outer_window->uri) { diff --git a/dlls/mshtml/htmllocation.c b/dlls/mshtml/htmllocation.c index 5376b3b8329..066ebb4f5e6 100644 --- a/dlls/mshtml/htmllocation.c +++ b/dlls/mshtml/htmllocation.c @@ -38,12 +38,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
static HRESULT get_url(HTMLLocation *This, const WCHAR **ret) { - if(!This->window || !This->window->base.outer_window || !This->window->base.outer_window->url) { - FIXME("No current URL\n"); - return E_NOTIMPL; - } - - *ret = This->window->base.outer_window->url; + if(!This->window || !This->window->base.outer_window || !This->window->base.outer_window->url) + *ret = L"about:blank"; + else + *ret = This->window->base.outer_window->url; return S_OK; }
@@ -295,10 +293,8 @@ static HRESULT WINAPI HTMLLocation_get_protocol(IHTMLLocation *iface, BSTR *p) if(!p) return E_POINTER;
- if(!(uri = get_uri(This))) { - FIXME("No current URI\n"); - return E_NOTIMPL; - } + if(!(uri = get_uri(This))) + return (*p = SysAllocString(L"about:")) ? S_OK : E_OUTOFMEMORY;
hres = IUri_GetSchemeName(uri, &protocol); if(FAILED(hres)) @@ -388,8 +384,8 @@ static HRESULT WINAPI HTMLLocation_get_hostname(IHTMLLocation *iface, BSTR *p) return E_POINTER;
if(!(uri = get_uri(This))) { - FIXME("No current URI\n"); - return E_NOTIMPL; + *p = NULL; + return S_OK; }
hres = IUri_GetHost(uri, &hostname); @@ -425,8 +421,8 @@ static HRESULT WINAPI HTMLLocation_get_port(IHTMLLocation *iface, BSTR *p) return E_POINTER;
if(!(uri = get_uri(This))) { - FIXME("No current URI\n"); - return E_NOTIMPL; + *p = NULL; + return S_OK; }
hres = IUri_GetPort(uri, &port); @@ -466,10 +462,8 @@ static HRESULT WINAPI HTMLLocation_get_pathname(IHTMLLocation *iface, BSTR *p) if(!p) return E_POINTER;
- if(!(uri = get_uri(This))) { - FIXME("No current URI\n"); - return E_NOTIMPL; - } + if(!(uri = get_uri(This))) + return (*p = SysAllocString(L"blank")) ? S_OK : E_OUTOFMEMORY;
hres = IUri_GetPath(uri, &path); if(FAILED(hres)) @@ -504,8 +498,8 @@ static HRESULT WINAPI HTMLLocation_get_search(IHTMLLocation *iface, BSTR *p) return E_POINTER;
if(!(uri = get_uri(This))) { - FIXME("No current URI\n"); - return E_NOTIMPL; + *p = NULL; + return S_OK; }
hres = IUri_GetQuery(uri, &query); @@ -562,8 +556,8 @@ static HRESULT WINAPI HTMLLocation_get_hash(IHTMLLocation *iface, BSTR *p) return E_POINTER;
if(!(uri = get_uri(This))) { - FIXME("No current URI\n"); - return E_NOTIMPL; + *p = NULL; + return S_OK; }
hres = IUri_GetFragment(uri, &hash); diff --git a/dlls/mshtml/tests/htmllocation.c b/dlls/mshtml/tests/htmllocation.c index 0b241085af2..222b9553816 100644 --- a/dlls/mshtml/tests/htmllocation.c +++ b/dlls/mshtml/tests/htmllocation.c @@ -39,6 +39,18 @@ struct location_test { };
static const struct location_test location_tests[] = { + { + "Empty", + NULL, + "about:blank", + "about:", + NULL, + NULL, + NULL, + "blank", + NULL, + NULL + }, { "HTTP", "http://www.winehq.org?search#hash", @@ -187,7 +199,7 @@ static void test_hostname(IHTMLLocation *loc, IHTMLDocument2 *doc, const struct SysFreeString(str);
hres = IHTMLDocument2_get_domain(doc, &str); - ok(hres == S_OK, "%s: get_domain failed: 0x%08lx\n", test->name, hres); + ok(hres == (test->url ? S_OK : E_FAIL), "%s: get_domain failed: 0x%08lx\n", test->name, hres); if(hres == S_OK) ok(str_eq_wa(str, test->hostname ? test->hostname : ""), "%s: expected retrieved domain to be L"%s", was: %s\n", @@ -280,7 +292,7 @@ static void perform_test(const struct location_test* test) WCHAR url[INTERNET_MAX_URL_LENGTH]; HRESULT hres; IBindCtx *bc; - IMoniker *url_mon; + IMoniker *url_mon = NULL; IPersistMoniker *persist_mon; IHTMLDocument2 *doc; IHTMLDocument6 *doc6; @@ -291,12 +303,14 @@ static void perform_test(const struct location_test* test) if(FAILED(hres)) return;
- MultiByteToWideChar(CP_ACP, 0, test->url, -1, url, ARRAY_SIZE(url)); - hres = CreateURLMoniker(NULL, url, &url_mon); - ok(hres == S_OK, "%s: CreateURLMoniker failed: 0x%08lx\n", test->name, hres); - if(FAILED(hres)){ - IBindCtx_Release(bc); - return; + if(test->url) { + MultiByteToWideChar(CP_ACP, 0, test->url, -1, url, ARRAY_SIZE(url)); + hres = CreateURLMoniker(NULL, url, &url_mon); + ok(hres == S_OK, "%s: CreateURLMoniker failed: 0x%08lx\n", test->name, hres); + if(FAILED(hres)){ + IBindCtx_Release(bc); + return; + } }
hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, @@ -307,7 +321,7 @@ static void perform_test(const struct location_test* test) #endif ok(hres == S_OK, "%s: CoCreateInstance failed: 0x%08lx\n", test->name, hres); if(FAILED(hres)){ - IMoniker_Release(url_mon); + if(url_mon) IMoniker_Release(url_mon); IBindCtx_Release(bc); return; } @@ -317,38 +331,39 @@ static void perform_test(const struct location_test* test) IHTMLDocument6_Release(doc6); }else{ win_skip("%s: Could not get IHTMLDocument6, probably too old IE. Requires IE 8+\n", test->name); - IMoniker_Release(url_mon); + if(url_mon) IMoniker_Release(url_mon); IBindCtx_Release(bc); return; }
- hres = IHTMLDocument2_QueryInterface(doc, &IID_IPersistMoniker, - (void**)&persist_mon); - ok(hres == S_OK, "%s: IHTMlDocument2_QueryInterface failed: 0x%08lx\n", test->name, hres); - if(FAILED(hres)){ - IHTMLDocument2_Release(doc); - IMoniker_Release(url_mon); - IBindCtx_Release(bc); - return; - } - - hres = IPersistMoniker_Load(persist_mon, FALSE, url_mon, bc, - STGM_SHARE_EXCLUSIVE | STGM_READWRITE); - ok(hres == S_OK, "%s: IPersistMoniker_Load failed: 0x%08lx\n", test->name, hres); - if(FAILED(hres)){ + if(url_mon) { + hres = IHTMLDocument2_QueryInterface(doc, &IID_IPersistMoniker, + (void**)&persist_mon); + ok(hres == S_OK, "%s: IHTMlDocument2_QueryInterface failed: 0x%08lx\n", test->name, hres); + if(FAILED(hres)){ + IHTMLDocument2_Release(doc); + IMoniker_Release(url_mon); + IBindCtx_Release(bc); + return; + } + + hres = IPersistMoniker_Load(persist_mon, FALSE, url_mon, bc, + STGM_SHARE_EXCLUSIVE | STGM_READWRITE); + ok(hres == S_OK, "%s: IPersistMoniker_Load failed: 0x%08lx\n", test->name, hres); IPersistMoniker_Release(persist_mon); - IHTMLDocument2_Release(doc); IMoniker_Release(url_mon); - IBindCtx_Release(bc); - return; + + if(FAILED(hres)){ + IHTMLDocument2_Release(doc); + IBindCtx_Release(bc); + return; + } }
hres = IHTMLDocument2_get_location(doc, &location); ok(hres == S_OK, "%s: IHTMLDocument2_get_location failed: 0x%08lx\n", test->name, hres); if(FAILED(hres)){ - IPersistMoniker_Release(persist_mon); IHTMLDocument2_Release(doc); - IMoniker_Release(url_mon); IBindCtx_Release(bc); return; } @@ -363,9 +378,7 @@ static void perform_test(const struct location_test* test) test_hash(location, test);
IHTMLLocation_Release(location); - IPersistMoniker_Release(persist_mon); IHTMLDocument2_Release(doc); - IMoniker_Release(url_mon); IBindCtx_Release(bc); }
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/script.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-)
diff --git a/dlls/mshtml/script.c b/dlls/mshtml/script.c index 5321080a8f9..32005728bd6 100644 --- a/dlls/mshtml/script.c +++ b/dlls/mshtml/script.c @@ -91,12 +91,12 @@ struct ScriptHost {
static ScriptHost *get_elem_script_host(HTMLInnerWindow*,HTMLScriptElement*);
-static BOOL set_script_prop(ScriptHost *script_host, DWORD property, VARIANT *val) +static BOOL set_script_prop(IActiveScript *script, DWORD property, VARIANT *val) { IActiveScriptProperty *script_prop; HRESULT hres;
- hres = IActiveScript_QueryInterface(script_host->script, &IID_IActiveScriptProperty, + hres = IActiveScript_QueryInterface(script, &IID_IActiveScriptProperty, (void**)&script_prop); if(FAILED(hres)) { WARN("Could not get IActiveScriptProperty iface: %08lx\n", hres); @@ -113,7 +113,7 @@ static BOOL set_script_prop(ScriptHost *script_host, DWORD property, VARIANT *va return TRUE; }
-static BOOL init_script_engine(ScriptHost *script_host) +static BOOL init_script_engine(ScriptHost *script_host, IActiveScript *script) { compat_mode_t compat_mode; IObjectSafety *safety; @@ -122,13 +122,13 @@ static BOOL init_script_engine(ScriptHost *script_host) VARIANT var; HRESULT hres;
- hres = IActiveScript_QueryInterface(script_host->script, &IID_IActiveScriptParse, (void**)&script_host->parse); + hres = IActiveScript_QueryInterface(script, &IID_IActiveScriptParse, (void**)&script_host->parse); if(FAILED(hres)) { WARN("Could not get IActiveScriptParse: %08lx\n", hres); return FALSE; }
- hres = IActiveScript_QueryInterface(script_host->script, &IID_IObjectSafety, (void**)&safety); + hres = IActiveScript_QueryInterface(script, &IID_IObjectSafety, (void**)&safety); if(FAILED(hres)) { FIXME("Could not get IObjectSafety: %08lx\n", hres); return FALSE; @@ -162,16 +162,16 @@ static BOOL init_script_engine(ScriptHost *script_host) } V_VT(&var) = VT_I4; V_I4(&var) = script_mode; - if(!set_script_prop(script_host, SCRIPTPROP_INVOKEVERSIONING, &var) && (script_mode & SCRIPTLANGUAGEVERSION_HTML)) { + if(!set_script_prop(script, SCRIPTPROP_INVOKEVERSIONING, &var) && (script_mode & SCRIPTLANGUAGEVERSION_HTML)) { /* If this failed, we're most likely using native jscript. */ WARN("Failed to set script mode to HTML version.\n"); V_I4(&var) = compat_mode < COMPAT_MODE_IE8 ? SCRIPTLANGUAGEVERSION_5_7 : SCRIPTLANGUAGEVERSION_5_8; - set_script_prop(script_host, SCRIPTPROP_INVOKEVERSIONING, &var); + set_script_prop(script, SCRIPTPROP_INVOKEVERSIONING, &var); }
V_VT(&var) = VT_BOOL; V_BOOL(&var) = VARIANT_TRUE; - set_script_prop(script_host, SCRIPTPROP_HACK_TRIDENTEVENTSINK, &var); + set_script_prop(script, SCRIPTPROP_HACK_TRIDENTEVENTSINK, &var);
hres = IActiveScriptParse_InitNew(script_host->parse); if(FAILED(hres)) { @@ -179,36 +179,36 @@ static BOOL init_script_engine(ScriptHost *script_host) return FALSE; }
- hres = IActiveScript_SetScriptSite(script_host->script, &script_host->IActiveScriptSite_iface); + hres = IActiveScript_SetScriptSite(script, &script_host->IActiveScriptSite_iface); if(FAILED(hres)) { WARN("SetScriptSite failed: %08lx\n", hres); - IActiveScript_Close(script_host->script); + IActiveScript_Close(script); return FALSE; }
- hres = IActiveScript_GetScriptState(script_host->script, &state); + hres = IActiveScript_GetScriptState(script, &state); if(FAILED(hres)) WARN("GetScriptState failed: %08lx\n", hres); else if(state != SCRIPTSTATE_INITIALIZED) FIXME("state = %x\n", state);
- hres = IActiveScript_SetScriptState(script_host->script, SCRIPTSTATE_STARTED); + hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_STARTED); if(FAILED(hres)) { WARN("Starting script failed: %08lx\n", hres); return FALSE; }
- hres = IActiveScript_AddNamedItem(script_host->script, L"window", + hres = IActiveScript_AddNamedItem(script, L"window", SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|SCRIPTITEM_GLOBALMEMBERS); if(SUCCEEDED(hres)) { V_VT(&var) = VT_BOOL; V_BOOL(&var) = VARIANT_TRUE; - set_script_prop(script_host, SCRIPTPROP_ABBREVIATE_GLOBALNAME_RESOLUTION, &var); + set_script_prop(script, SCRIPTPROP_ABBREVIATE_GLOBALNAME_RESOLUTION, &var); }else { WARN("AddNamedItem failed: %08lx\n", hres); }
- hres = IActiveScript_QueryInterface(script_host->script, &IID_IActiveScriptParseProcedure2, + hres = IActiveScript_QueryInterface(script, &IID_IActiveScriptParseProcedure2, (void**)&script_host->parse_proc); if(FAILED(hres)) { /* FIXME: QI for IActiveScriptParseProcedure */ @@ -690,6 +690,7 @@ static const IServiceProviderVtbl ASServiceProviderVtbl = {
static ScriptHost *create_script_host(HTMLInnerWindow *window, const GUID *guid) { + IActiveScript *script; ScriptHost *ret; HRESULT hres;
@@ -711,11 +712,15 @@ static ScriptHost *create_script_host(HTMLInnerWindow *window, const GUID *guid) list_add_tail(&window->script_hosts, &ret->entry);
hres = CoCreateInstance(&ret->guid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, - &IID_IActiveScript, (void**)&ret->script); + &IID_IActiveScript, (void**)&script); if(FAILED(hres)) WARN("Could not load script engine: %08lx\n", hres); - else if(!init_script_engine(ret)) - release_script_engine(ret); + else { + BOOL succeeded = init_script_engine(ret, script); + ret->script = script; + if(!succeeded) + release_script_engine(ret); + }
return ret; }
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/script.c | 24 +++ dlls/mshtml/tests/script.c | 412 ++++++++++++++++++++++++++++++++++--- 2 files changed, 413 insertions(+), 23 deletions(-)
diff --git a/dlls/mshtml/script.c b/dlls/mshtml/script.c index 32005728bd6..8b1c1f11938 100644 --- a/dlls/mshtml/script.c +++ b/dlls/mshtml/script.c @@ -201,9 +201,33 @@ static BOOL init_script_engine(ScriptHost *script_host, IActiveScript *script) hres = IActiveScript_AddNamedItem(script, L"window", SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|SCRIPTITEM_GLOBALMEMBERS); if(SUCCEEDED(hres)) { + ScriptHost *first_host; + V_VT(&var) = VT_BOOL; V_BOOL(&var) = VARIANT_TRUE; + + LIST_FOR_EACH_ENTRY(first_host, &script_host->window->script_hosts, ScriptHost, entry) { + if(first_host->script) { + V_BOOL(&var) = VARIANT_FALSE; + break; + } + } set_script_prop(script, SCRIPTPROP_ABBREVIATE_GLOBALNAME_RESOLUTION, &var); + + /* if this was second engine initialized, also set it to first engine, since it used to be TRUE */ + if(!V_BOOL(&var)) { + struct list *iter = &first_host->entry; + BOOL is_second_init = TRUE; + + while((iter = list_next(&script_host->window->script_hosts, iter))) { + if(LIST_ENTRY(iter, ScriptHost, entry)->script) { + is_second_init = FALSE; + break; + } + } + if(is_second_init) + set_script_prop(first_host->script, SCRIPTPROP_ABBREVIATE_GLOBALNAME_RESOLUTION, &var); + } }else { WARN("AddNamedItem failed: %08lx\n", hres); } diff --git a/dlls/mshtml/tests/script.c b/dlls/mshtml/tests/script.c index 8d9ff3cd3f7..2bcd588f51f 100644 --- a/dlls/mshtml/tests/script.c +++ b/dlls/mshtml/tests/script.c @@ -103,21 +103,32 @@ const GUID GUID_CUSTOM_CONFIRMOBJECTSAFETY =
DEFINE_EXPECT(CreateInstance); +DEFINE_EXPECT(CreateInstance2); DEFINE_EXPECT(GetInterfaceSafetyOptions); DEFINE_EXPECT(SetInterfaceSafetyOptions); +DEFINE_EXPECT(GetInterfaceSafetyOptions2); +DEFINE_EXPECT(SetInterfaceSafetyOptions2); DEFINE_EXPECT(InitNew); +DEFINE_EXPECT(InitNew2); DEFINE_EXPECT(Close); +DEFINE_EXPECT(Close2); DEFINE_EXPECT(SetProperty_HACK_TRIDENTEVENTSINK); DEFINE_EXPECT(SetProperty_INVOKEVERSIONING); DEFINE_EXPECT(SetProperty_ABBREVIATE_GLOBALNAME_RESOLUTION_FALSE); DEFINE_EXPECT(SetProperty_ABBREVIATE_GLOBALNAME_RESOLUTION_TRUE); +DEFINE_EXPECT(SetProperty2_HACK_TRIDENTEVENTSINK); +DEFINE_EXPECT(SetProperty2_INVOKEVERSIONING); +DEFINE_EXPECT(SetProperty2_ABBREVIATE_GLOBALNAME_RESOLUTION_FALSE); DEFINE_EXPECT(SetScriptSite); +DEFINE_EXPECT(SetScriptSite2); DEFINE_EXPECT(GetScriptState); DEFINE_EXPECT(SetScriptState_STARTED); DEFINE_EXPECT(SetScriptState_CONNECTED); DEFINE_EXPECT(SetScriptState_DISCONNECTED); DEFINE_EXPECT(AddNamedItem); +DEFINE_EXPECT(AddNamedItem2); DEFINE_EXPECT(ParseScriptText_script); +DEFINE_EXPECT(ParseScriptText_script2); DEFINE_EXPECT(ParseScriptText_execScript); DEFINE_EXPECT(GetScriptDispatch); DEFINE_EXPECT(funcDisp); @@ -140,7 +151,6 @@ DEFINE_EXPECT(ChangeType_bstr); DEFINE_EXPECT(ChangeType_dispatch); DEFINE_EXPECT(GetTypeInfo);
-#define TESTSCRIPT_CLSID "{178fc163-f585-4e24-9c13-4bb7faf80746}" #define TESTACTIVEX_CLSID "{178fc163-f585-4e24-9c13-4bb7faf80646}"
#define DISPID_SCRIPT_TESTPROP 0x100000 @@ -161,8 +171,10 @@ DEFINE_EXPECT(GetTypeInfo); #define DISPID_EXTERNAL_TESTHOSTCTX 0x30000C #define DISPID_EXTERNAL_GETMIMETYPE 0x30000D
-static const GUID CLSID_TestScript = - {0x178fc163,0xf585,0x4e24,{0x9c,0x13,0x4b,0xb7,0xfa,0xf8,0x07,0x46}}; +static const GUID CLSID_TestScript[] = { + {0x178fc163,0xf585,0x4e24,{0x9c,0x13,0x4b,0xb7,0xfa,0xf8,0x07,0x46}}, + {0x178fc163,0xf585,0x4e24,{0x9c,0x13,0x4b,0xb7,0xfa,0xf8,0x08,0x46}}, +}; static const GUID CLSID_TestActiveX = {0x178fc163,0xf585,0x4e24,{0x9c,0x13,0x4b,0xb7,0xfa,0xf8,0x06,0x46}};
@@ -178,25 +190,25 @@ static HRESULT ax_getopt_hres = S_OK, ax_setopt_dispex_hres = S_OK; static HRESULT ax_setopt_disp_caller_hres = S_OK, ax_setopt_disp_data_hres = S_OK; static BOOL skip_loadobject_tests;
-static IActiveScriptSite *site; -static SCRIPTSTATE state; +static IActiveScriptSite *site, *site2; +static SCRIPTSTATE state, state2;
-static BOOL init_key(const char *key_name, const char *def_value, BOOL init) +static BOOL init_key(const WCHAR *key_name, const WCHAR *def_value, BOOL init) { HKEY hkey; DWORD res;
if(!init) { - RegDeleteKeyA(HKEY_CLASSES_ROOT, key_name); + RegDeleteKeyW(HKEY_CLASSES_ROOT, key_name); return TRUE; }
- res = RegCreateKeyA(HKEY_CLASSES_ROOT, key_name, &hkey); + res = RegCreateKeyW(HKEY_CLASSES_ROOT, key_name, &hkey); if(res != ERROR_SUCCESS) return FALSE;
if(def_value) - res = RegSetValueA(hkey, NULL, REG_SZ, def_value, strlen(def_value)); + res = RegSetValueW(hkey, NULL, REG_SZ, def_value, wcslen(def_value));
RegCloseKey(hkey);
@@ -1927,9 +1939,9 @@ static IObjectSafety AXObjectSafety = { &AXObjectSafetyVtbl };
static BOOL set_safe_reg(BOOL safe_call, BOOL safe_data) { - return init_key("CLSID\"TESTACTIVEX_CLSID"\Implemented Categories\{7dd95801-9882-11cf-9fa9-00aa006c42c4}", + return init_key(L"CLSID\"TESTACTIVEX_CLSID"\Implemented Categories\{7dd95801-9882-11cf-9fa9-00aa006c42c4}", NULL, safe_call) - && init_key("CLSID\"TESTACTIVEX_CLSID"\Implemented Categories\{7dd95802-9882-11cf-9fa9-00aa006c42c4}", + && init_key(L"CLSID\"TESTACTIVEX_CLSID"\Implemented Categories\{7dd95802-9882-11cf-9fa9-00aa006c42c4}", NULL, safe_data); }
@@ -3336,6 +3348,252 @@ static const IActiveScriptVtbl ActiveScriptVtbl = {
static IActiveScript ActiveScript = { &ActiveScriptVtbl };
+static HRESULT WINAPI ObjectSafety2_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid, + DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions) +{ + CHECK_EXPECT(GetInterfaceSafetyOptions2); + + ok(IsEqualGUID(&IID_IActiveScriptParse, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + ok(pdwSupportedOptions != NULL, "pdwSupportedOptions == NULL\n"); + ok(pdwEnabledOptions != NULL, "pdwEnabledOptions == NULL\n"); + + *pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_DISPEX | INTERFACE_USES_SECURITY_MANAGER; + *pdwEnabledOptions = INTERFACE_USES_DISPEX; + + return S_OK; +} + +static HRESULT WINAPI ObjectSafety2_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid, + DWORD dwOptionSetMask, DWORD dwEnabledOptions) +{ + CHECK_EXPECT(SetInterfaceSafetyOptions2); + + ok(IsEqualGUID(&IID_IActiveScriptParse, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + + ok(dwOptionSetMask == (INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_DISPEX | INTERFACE_USES_SECURITY_MANAGER), + "dwOptionSetMask = %08lx\n", dwOptionSetMask); + ok(dwEnabledOptions == (INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_DISPEX | INTERFACE_USES_SECURITY_MANAGER), + "dwEnabledOptions = %08lx\n", dwOptionSetMask); + + return S_OK; +} + +static const IObjectSafetyVtbl ObjectSafety2Vtbl = { + ObjectSafety_QueryInterface, + ObjectSafety_AddRef, + ObjectSafety_Release, + ObjectSafety2_GetInterfaceSafetyOptions, + ObjectSafety2_SetInterfaceSafetyOptions +}; + +static IObjectSafety ObjectSafety2 = { &ObjectSafety2Vtbl }; + +static HRESULT WINAPI ActiveScriptProperty2_SetProperty(IActiveScriptProperty *iface, DWORD dwProperty, + VARIANT *pvarIndex, VARIANT *pvarValue) +{ + switch(dwProperty) { + case SCRIPTPROP_HACK_TRIDENTEVENTSINK: + CHECK_EXPECT(SetProperty2_HACK_TRIDENTEVENTSINK); + ok(V_VT(pvarValue) == VT_BOOL, "V_VT(pvarValue) = %d\n", V_VT(pvarValue)); + ok(V_BOOL(pvarValue) == VARIANT_TRUE, "V_BOOL(pvarValue) = %x\n", V_BOOL(pvarValue)); + break; + case SCRIPTPROP_INVOKEVERSIONING: + CHECK_EXPECT(SetProperty2_INVOKEVERSIONING); + ok(V_VT(pvarValue) == VT_I4, "V_VT(pvarValue) = %d\n", V_VT(pvarValue)); + ok(V_I4(pvarValue) == 1, "V_I4(pvarValue) = %ld\n", V_I4(pvarValue)); + break; + case SCRIPTPROP_ABBREVIATE_GLOBALNAME_RESOLUTION: + CHECK_EXPECT(SetProperty2_ABBREVIATE_GLOBALNAME_RESOLUTION_FALSE); + ok(V_VT(pvarValue) == VT_BOOL, "V_VT(pvarValue) = %d\n", V_VT(pvarValue)); + ok(!V_BOOL(pvarValue), "ABBREVIATE_GLOBALNAME_RESOLUTION is TRUE\n"); + break; + case 0x70000003: /* Undocumented property set by IE10 */ + return E_NOTIMPL; + default: + ok(0, "unexpected property %08lx\n", dwProperty); + return E_NOTIMPL; + } + + ok(!pvarIndex, "pvarIndex != NULL\n"); + ok(pvarValue != NULL, "pvarValue == NULL\n"); + + return S_OK; +} + +static const IActiveScriptPropertyVtbl ActiveScriptProperty2Vtbl = { + ActiveScriptProperty_QueryInterface, + ActiveScriptProperty_AddRef, + ActiveScriptProperty_Release, + ActiveScriptProperty_GetProperty, + ActiveScriptProperty2_SetProperty +}; + +static IActiveScriptProperty ActiveScriptProperty2 = { &ActiveScriptProperty2Vtbl }; + +static HRESULT WINAPI ActiveScriptParse2_InitNew(IActiveScriptParse *iface) +{ + CHECK_EXPECT(InitNew2); + return S_OK; +} + +static HRESULT WINAPI ActiveScriptParse2_ParseScriptText(IActiveScriptParse *iface, LPCOLESTR pstrCode, + LPCOLESTR pstrItemName, IUnknown *punkContext, LPCOLESTR pstrDelimiter, CTXARG_T dwSourceContextCookie, + ULONG ulStartingLine, DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo) +{ + ok(pvarResult != NULL, "pvarResult == NULL\n"); + ok(pexcepinfo != NULL, "pexcepinfo == NULL\n"); + + if(!lstrcmpW(pstrCode, L"second script")) { + CHECK_EXPECT(ParseScriptText_script2); + ok(!lstrcmpW(pstrItemName, L"window"), "pstrItemName = %s\n", wine_dbgstr_w(pstrItemName)); + ok(!lstrcmpW(pstrDelimiter, L"</SCRIPT>"), "pstrDelimiter = %s\n", wine_dbgstr_w(pstrDelimiter)); + ok(dwFlags == (SCRIPTTEXT_ISVISIBLE | SCRIPTTEXT_HOSTMANAGESSOURCE), "dwFlags = %08lx\n", dwFlags); + return S_OK; + } + + ok(0, "unexpected script %s\n", wine_dbgstr_w(pstrCode)); + return E_FAIL; +} + +static const IActiveScriptParseVtbl ActiveScriptParse2Vtbl = { + ActiveScriptParse_QueryInterface, + ActiveScriptParse_AddRef, + ActiveScriptParse_Release, + ActiveScriptParse2_InitNew, + ActiveScriptParse_AddScriptlet, + ActiveScriptParse2_ParseScriptText +}; + +static IActiveScriptParse ActiveScriptParse2 = { &ActiveScriptParse2Vtbl }; + +static HRESULT WINAPI ActiveScript2_QueryInterface(IActiveScript *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IActiveScript, riid)) { + *ppv = iface; + return S_OK; + } + + if(IsEqualGUID(&IID_IActiveScriptParse, riid)) { + *ppv = &ActiveScriptParse2; + return S_OK; + } + + if(IsEqualGUID(&IID_IActiveScriptParseProcedure2, riid)) { + *ppv = &ActiveScriptParseProcedure; + return S_OK; + } + + if(IsEqualGUID(&IID_IActiveScriptProperty, riid)) { + *ppv = &ActiveScriptProperty2; + return S_OK; + } + + if(IsEqualGUID(&IID_IObjectSafety, riid)) { + *ppv = &ObjectSafety2; + return S_OK; + } + + if(IsEqualGUID(&IID_IActiveScriptDebug, riid)) + return E_NOINTERFACE; + + trace("QI(%s)\n", wine_dbgstr_guid(riid)); + return E_NOINTERFACE; +} + +static HRESULT WINAPI ActiveScript2_SetScriptSite(IActiveScript *iface, IActiveScriptSite *pass) +{ + HRESULT hres; + + CHECK_EXPECT(SetScriptSite2); + ok(pass != NULL, "pass == NULL\n"); + ok(pass != site, "pass == site\n"); + + hres = IActiveScriptSite_OnStateChange(pass, (state2 = SCRIPTSTATE_INITIALIZED)); + ok(hres == S_OK, "OnStateChange failed: %08lx\n", hres); + + site2 = pass; + IActiveScriptSite_AddRef(site2); + return S_OK; +} + +static HRESULT WINAPI ActiveScript2_SetScriptState(IActiveScript *iface, SCRIPTSTATE ss) +{ + HRESULT hres = IActiveScriptSite_OnStateChange(site2, (state2 = ss)); + ok(hres == S_OK, "OnStateChange failed: %08lx\n", hres); + return S_OK; +} + +static HRESULT WINAPI ActiveScript2_GetScriptState(IActiveScript *iface, SCRIPTSTATE *pssState) +{ + *pssState = state2; + return S_OK; +} + +static HRESULT WINAPI ActiveScript2_Close(IActiveScript *iface) +{ + CHECK_EXPECT(Close2); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScript2_AddNamedItem(IActiveScript *iface, LPCOLESTR pstrName, DWORD dwFlags) +{ + IHTMLWindow2 *window, *window2; + IUnknown *unk = NULL; + HRESULT hres; + + CHECK_EXPECT(AddNamedItem2); + ok(!wcscmp(pstrName, L"window"), "pstrName = %s\n", wine_dbgstr_w(pstrName)); + ok(dwFlags == (SCRIPTITEM_ISVISIBLE | SCRIPTITEM_ISSOURCE | SCRIPTITEM_GLOBALMEMBERS), "dwFlags = %lx\n", dwFlags); + + hres = IActiveScriptSite_GetItemInfo(site2, L"window", SCRIPTINFO_IUNKNOWN, &unk, NULL); + ok(hres == S_OK, "GetItemInfo failed: %08lx\n", hres); + ok(unk != NULL, "unk == NULL\n"); + + /* Native is pretty broken here, it gives a different IUnknown than first site's SCRIPTINFO_IUNKNOWN, + * and querying for IDispatchEx gives different interfaces on both these *and* our window_dispex! + * That said, querying for IHTMLWindow2 *does* give the same interface for both?!? + */ + hres = IDispatchEx_QueryInterface(window_dispex, &IID_IHTMLWindow2, (void**)&window); + ok(hres == S_OK, "Could not get IHTMLWindow2 interface: %08lx\n", hres); + hres = IUnknown_QueryInterface(unk, &IID_IHTMLWindow2, (void**)&window2); + ok(hres == S_OK, "Could not get IHTMLWindow2 interface: %08lx\n", hres); + ok(window == window2, "first site window != second site window\n"); + IHTMLWindow2_Release(window2); + IHTMLWindow2_Release(window); + + IUnknown_Release(unk); + return S_OK; +} + +static HRESULT WINAPI ActiveScript2_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName, IDispatch **ppdisp) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const IActiveScriptVtbl ActiveScript2Vtbl = { + ActiveScript2_QueryInterface, + ActiveScript_AddRef, + ActiveScript_Release, + ActiveScript2_SetScriptSite, + ActiveScript_GetScriptSite, + ActiveScript2_SetScriptState, + ActiveScript2_GetScriptState, + ActiveScript2_Close, + ActiveScript2_AddNamedItem, + ActiveScript_AddTypeLib, + ActiveScript2_GetScriptDispatch, + ActiveScript_GetCurrentScriptThreadID, + ActiveScript_GetScriptThreadID, + ActiveScript_GetScriptThreadState, + ActiveScript_InterruptScriptThread, + ActiveScript_Clone +}; + +static IActiveScript ActiveScript2 = { &ActiveScript2Vtbl }; + static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv) { *ppv = NULL; @@ -3388,7 +3646,25 @@ static const IClassFactoryVtbl ClassFactoryVtbl = { ClassFactory_LockServer };
-static IClassFactory script_cf = { &ClassFactoryVtbl }; +static HRESULT WINAPI ClassFactory2_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv) +{ + CHECK_EXPECT(CreateInstance2); + + ok(!outer, "outer = %p\n", outer); + ok(IsEqualGUID(&IID_IActiveScript, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = &ActiveScript2; + return S_OK; +} + +static const IClassFactoryVtbl ClassFactory2Vtbl = { + ClassFactory_QueryInterface, + ClassFactory_AddRef, + ClassFactory_Release, + ClassFactory2_CreateInstance, + ClassFactory_LockServer +}; + +static IClassFactory script_cf[] = { { &ClassFactoryVtbl }, { &ClassFactory2Vtbl } };
typedef struct { IInternetProtocolEx IInternetProtocolEx_iface; @@ -3901,9 +4177,50 @@ static IClassFactory protocol_cf = { &ProtocolCFVtbl }; static const char simple_script_str[] = "<html><head></head><body>" "<div id="divid"></div>" - "<script language="TestScript">simple script</script>" + "<script language="TestScript1">simple script</script>" "</body></html>";
+static void test_insert_script_elem(IHTMLDocument2 *doc, const WCHAR *code, const WCHAR *lang) +{ + IHTMLDOMNode *node, *body_node, *inserted_node; + IHTMLScriptElement *script; + IHTMLElement *elem, *body; + HRESULT hres; + BSTR bstr; + + bstr = SysAllocString(L"script"); + hres = IHTMLDocument2_createElement(doc, bstr, &elem); + ok(hres == S_OK, "createElement failed: %08lx\n", hres); + SysFreeString(bstr); + + bstr = SysAllocString(lang); + hres = IHTMLElement_put_language(elem, bstr); + ok(hres == S_OK, "put_language failed: %08lx\n", hres); + SysFreeString(bstr); + + bstr = SysAllocString(code); + hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLScriptElement, (void**)&script); + ok(hres == S_OK, "Could not get IHTMLScriptElement iface: %08lx\n", hres); + hres = IHTMLScriptElement_put_text(script, bstr); + ok(hres == S_OK, "put_text failed: %08lx\n", hres); + IHTMLScriptElement_Release(script); + SysFreeString(bstr); + + hres = IHTMLDocument2_get_body(doc, &body); + ok(hres == S_OK, "get_body failed: %08lx\n", hres); + hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLDOMNode, (void**)&node); + ok(hres == S_OK, "Could not get IHTMLDOMNode iface: %08lx\n", hres); + hres = IHTMLElement_QueryInterface(body, &IID_IHTMLDOMNode, (void**)&body_node); + ok(hres == S_OK, "Could not get IHTMLDOMNode iface: %08lx\n", hres); + hres = IHTMLDOMNode_appendChild(body_node, node, &inserted_node); + ok(hres == S_OK, "appendChild failed: %08lx\n", hres); + IHTMLDOMNode_Release(inserted_node); + IHTMLDOMNode_Release(body_node); + IHTMLDOMNode_Release(node); + IHTMLElement_Release(body); + IHTMLElement_Release(elem); +} + static void test_exec_script(IHTMLDocument2 *doc, const WCHAR *codew, const WCHAR *langw) { IHTMLWindow2 *window; @@ -3974,20 +4291,50 @@ static void test_simple_script(void) CHECK_CALLED(ParseScriptText_script); CHECK_CALLED(SetScriptState_CONNECTED);
- test_exec_script(doc, L"execScript call", L"TestScript"); + SET_EXPECT(CreateInstance2); + SET_EXPECT(GetInterfaceSafetyOptions2); + SET_EXPECT(SetInterfaceSafetyOptions2); + SET_EXPECT(SetProperty2_INVOKEVERSIONING); + SET_EXPECT(SetProperty2_HACK_TRIDENTEVENTSINK); + SET_EXPECT(InitNew2); + SET_EXPECT(SetScriptSite2); + SET_EXPECT(AddNamedItem2); + SET_EXPECT(SetProperty_ABBREVIATE_GLOBALNAME_RESOLUTION_FALSE); + SET_EXPECT(SetProperty2_ABBREVIATE_GLOBALNAME_RESOLUTION_FALSE); + SET_EXPECT(ParseScriptText_script2); + + test_insert_script_elem(doc, L"second script", L"TestScript2"); + + CHECK_CALLED(CreateInstance2); + CHECK_CALLED(GetInterfaceSafetyOptions2); + CHECK_CALLED(SetInterfaceSafetyOptions2); + CHECK_CALLED(SetProperty2_INVOKEVERSIONING); + CHECK_CALLED(SetProperty2_HACK_TRIDENTEVENTSINK); + CHECK_CALLED(InitNew2); + CHECK_CALLED(SetScriptSite2); + CHECK_CALLED(AddNamedItem2); + CHECK_CALLED(SetProperty_ABBREVIATE_GLOBALNAME_RESOLUTION_FALSE); + CHECK_CALLED(SetProperty2_ABBREVIATE_GLOBALNAME_RESOLUTION_FALSE); + CHECK_CALLED(ParseScriptText_script2); + + test_exec_script(doc, L"execScript call", L"TestScript1");
if(site) IActiveScriptSite_Release(site); + if(site2) + IActiveScriptSite_Release(site2); if(window_dispex) IDispatchEx_Release(window_dispex);
SET_EXPECT(SetScriptState_DISCONNECTED); SET_EXPECT(Close); + SET_EXPECT(Close2);
IHTMLDocument2_Release(doc);
CHECK_CALLED(SetScriptState_DISCONNECTED); CHECK_CALLED(Close); + CHECK_CALLED(Close2); }
static void run_from_moniker(IMoniker *mon) @@ -4193,16 +4540,33 @@ static void run_js_tests(void)
static BOOL init_registry(BOOL init) { - return init_key("TestScript\CLSID", TESTSCRIPT_CLSID, init) - && init_key("CLSID\"TESTSCRIPT_CLSID"\Implemented Categories\{F0B7A1A1-9847-11CF-8F20-00805F2CD064}", - NULL, init) - && init_key("CLSID\"TESTSCRIPT_CLSID"\Implemented Categories\{F0B7A1A2-9847-11CF-8F20-00805F2CD064}", - NULL, init); + static const WCHAR fmt[] = L"CLSID\%s\Implemented Categories\{%08lX-9847-11CF-8F20-00805F2CD064}"; + WCHAR *clsid, buf[ARRAY_SIZE(fmt) + 40]; + BOOL ret = TRUE; + HRESULT hres; + unsigned i; + + for(i = 0; i < ARRAY_SIZE(CLSID_TestScript) && ret; i++) { + hres = StringFromCLSID(&CLSID_TestScript[i], &clsid); + ok(hres == S_OK, "StringFromCLSID failed: %08lx\n", hres); + + swprintf(buf, ARRAY_SIZE(buf), L"TestScript%u\CLSID", i + 1); + if((ret = init_key(buf, clsid, init))) { + swprintf(buf, ARRAY_SIZE(buf), fmt, clsid, 0xf0b7a1a1); + if((ret = init_key(buf, NULL, init))) { + swprintf(buf, ARRAY_SIZE(buf), fmt, clsid, 0xf0b7a1a2); + ret = init_key(buf, NULL, init); + } + } + CoTaskMemFree(clsid); + } + return ret; }
static BOOL register_script_engine(void) { DWORD regid; + unsigned i; HRESULT hres;
if(!init_registry(TRUE)) { @@ -4210,9 +4574,11 @@ static BOOL register_script_engine(void) return FALSE; }
- hres = CoRegisterClassObject(&CLSID_TestScript, (IUnknown *)&script_cf, - CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, ®id); - ok(hres == S_OK, "Could not register script engine: %08lx\n", hres); + for(i = 0; i < ARRAY_SIZE(CLSID_TestScript); i++) { + hres = CoRegisterClassObject(&CLSID_TestScript[i], (IUnknown *)&script_cf[i], + CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, ®id); + ok(hres == S_OK, "Could not register TestScript%u engine: %08lx\n", i + 1, hres); + }
return TRUE; } @@ -4299,7 +4665,7 @@ START_TEST(script) test_simple_script(); init_registry(FALSE); }else { - skip("Could not register TestScript engine\n"); + skip("Could not register TestScript engines\n"); } run_js_tests(); }else {
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 9 ++ dlls/jscript/jscript.c | 17 ++- dlls/jscript/jscript.h | 3 + dlls/jscript/jsutils.c | 9 ++ dlls/jscript/tests/caller.c | 212 +++++++++++++++++++++++++++++++++++- 5 files changed, 241 insertions(+), 9 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 2c35f2ae9cc..4b56ec9fc70 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -1900,6 +1900,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { jsdisp_t *This = impl_from_IDispatchEx(iface); + IServiceProvider *prev_caller; dispex_prop_t *prop; jsexcept_t ei; HRESULT hres; @@ -1917,6 +1918,11 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
enter_script(This->ctx, &ei);
+ prev_caller = This->ctx->jscaller->caller; + This->ctx->jscaller->caller = pspCaller; + if(pspCaller) + IServiceProvider_AddRef(pspCaller); + switch(wFlags) { case DISPATCH_METHOD|DISPATCH_PROPERTYGET: wFlags = DISPATCH_METHOD; @@ -2000,6 +2006,9 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc break; }
+ This->ctx->jscaller->caller = prev_caller; + if(pspCaller) + IServiceProvider_Release(pspCaller); return leave_script(This->ctx, hres); }
diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index f5331a13b96..401f6ca85b0 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -428,6 +428,17 @@ static void release_named_item_list(JScript *This) } }
+static HRESULT exec_global_code(script_ctx_t *ctx, bytecode_t *code, jsval_t *r) +{ + IServiceProvider *prev_caller = ctx->jscaller->caller; + HRESULT hres; + + ctx->jscaller->caller = SP_CALLER_UNINITIALIZED; + hres = exec_source(ctx, EXEC_GLOBAL, code, &code->global_code, NULL, NULL, NULL, 0, NULL, r); + ctx->jscaller->caller = prev_caller; + return hres; +} + static void exec_queued_code(JScript *This) { bytecode_t *iter; @@ -436,7 +447,7 @@ static void exec_queued_code(JScript *This)
LIST_FOR_EACH_ENTRY(iter, &This->queued_code, bytecode_t, entry) { enter_script(This->ctx, &ei); - hres = exec_source(This->ctx, EXEC_GLOBAL, iter, &iter->global_code, NULL, NULL, NULL, 0, NULL, NULL); + hres = exec_global_code(This->ctx, iter, NULL); leave_script(This->ctx, hres); if(FAILED(hres)) break; @@ -1103,7 +1114,7 @@ static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface, if(dwFlags & SCRIPTTEXT_ISEXPRESSION) { jsval_t r;
- hres = exec_source(This->ctx, EXEC_GLOBAL, code, &code->global_code, NULL, NULL, NULL, 0, NULL, &r); + hres = exec_global_code(This->ctx, code, &r); if(SUCCEEDED(hres)) { if(pvarResult) hres = jsval_to_variant(r, pvarResult); @@ -1122,7 +1133,7 @@ static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface, if(!pvarResult && !is_started(This->ctx)) { list_add_tail(&This->queued_code, &code->entry); }else { - hres = exec_source(This->ctx, EXEC_GLOBAL, code, &code->global_code, NULL, NULL, NULL, 0, NULL, NULL); + hres = exec_global_code(This->ctx, code, NULL); if(code->is_persistent) list_add_tail(&This->persistent_code, &code->entry); else diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index b633f390508..36a6d23c917 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -331,12 +331,15 @@ typedef struct {
void release_cc(cc_ctx_t*) DECLSPEC_HIDDEN;
+#define SP_CALLER_UNINITIALIZED ((IServiceProvider*)IntToPtr(-1)) + typedef struct { IServiceProvider IServiceProvider_iface;
LONG ref;
script_ctx_t *ctx; + IServiceProvider *caller; } JSCaller;
#include "jsval.h" diff --git a/dlls/jscript/jsutils.c b/dlls/jscript/jsutils.c index 3dfcd08f14c..a26b63833ee 100644 --- a/dlls/jscript/jsutils.c +++ b/dlls/jscript/jsutils.c @@ -1034,6 +1034,14 @@ static HRESULT WINAPI JSCaller_QueryService(IServiceProvider *iface, REFGUID gui { JSCaller *This = impl_from_IServiceProvider(iface);
+ if(IsEqualGUID(guidService, &SID_GetCaller)) { + TRACE("(%p)->(SID_GetCaller)\n", This); + *ppv = NULL; + if(!This->caller) + return S_OK; + return (This->caller == SP_CALLER_UNINITIALIZED) ? E_NOINTERFACE : IServiceProvider_QueryInterface(This->caller, riid, ppv); + } + if(IsEqualGUID(guidService, &SID_VariantConversion) && This->ctx && This->ctx->active_script) { TRACE("(%p)->(SID_VariantConversion)\n", This); return IActiveScript_QueryInterface(This->ctx->active_script, riid, ppv); @@ -1063,6 +1071,7 @@ HRESULT create_jscaller(script_ctx_t *ctx) ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl; ret->ref = 1; ret->ctx = ctx; + ret->caller = SP_CALLER_UNINITIALIZED;
ctx->jscaller = ret; return S_OK; diff --git a/dlls/jscript/tests/caller.c b/dlls/jscript/tests/caller.c index 836f5a820a1..8a1ebb83a33 100644 --- a/dlls/jscript/tests/caller.c +++ b/dlls/jscript/tests/caller.c @@ -74,14 +74,23 @@ static const CLSID CLSID_JScript = #define CLEAR_CALLED(func) \ expect_ ## func = called_ ## func = FALSE
+DEFINE_EXPECT(sp_caller_QI_NULL); DEFINE_EXPECT(testArgConv); +DEFINE_EXPECT(testGetCaller); +DEFINE_EXPECT(testGetCallerJS); +DEFINE_EXPECT(testGetCallerNested); DEFINE_EXPECT(OnEnterScript); DEFINE_EXPECT(OnLeaveScript);
+static IActiveScriptParse *active_script_parser; static IVariantChangeType *script_change_type; static IDispatch *stored_obj; +static IServiceProvider *test_get_caller_sp;
#define DISPID_TEST_TESTARGCONV 0x1000 +#define DISPID_TEST_TESTGETCALLER 0x1001 +#define DISPID_TEST_TESTGETCALLERJS 0x1002 +#define DISPID_TEST_TESTGETCALLERNESTED 0x1003
typedef struct { int int_result; @@ -254,6 +263,55 @@ static void test_caller(IServiceProvider *caller, IDispatch *arg_obj) IVariantChangeType_Release(change_type); }
+static IServiceProvider sp_caller_obj; + +static HRESULT WINAPI sp_caller_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IServiceProvider, riid)) + *ppv = &sp_caller_obj; + else { + ok(IsEqualGUID(&IID_NULL, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + CHECK_EXPECT(sp_caller_QI_NULL); + *ppv = NULL; + return E_NOINTERFACE; + } + + return S_OK; +} + +static ULONG WINAPI sp_caller_AddRef(IServiceProvider *iface) +{ + return 2; +} + +static ULONG WINAPI sp_caller_Release(IServiceProvider *iface) +{ + return 1; +} + +static HRESULT WINAPI sp_caller_QueryService(IServiceProvider *iface, REFGUID guidService, + REFIID riid, void **ppv) +{ + if(IsEqualGUID(guidService, &SID_GetCaller)) { + ok(IsEqualGUID(riid, &IID_IServiceProvider), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = NULL; + return S_OK; + } + + ok(0, "unexpected guidService %s with riid %s\n", wine_dbgstr_guid(guidService), wine_dbgstr_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; +} + +static const IServiceProviderVtbl sp_caller_vtbl = { + sp_caller_QueryInterface, + sp_caller_AddRef, + sp_caller_Release, + sp_caller_QueryService +}; + +static IServiceProvider sp_caller_obj = { &sp_caller_vtbl }; + static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) { if(IsEqualGUID(riid, &IID_IUnknown)) { @@ -350,6 +408,21 @@ static HRESULT WINAPI Test_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD gr *pid = DISPID_TEST_TESTARGCONV; return S_OK; } + if(!lstrcmpW(bstrName, L"testGetCaller")) { + ok(grfdex == fdexNameCaseSensitive, "grfdex = %lx\n", grfdex); + *pid = DISPID_TEST_TESTGETCALLER; + return S_OK; + } + if(!lstrcmpW(bstrName, L"testGetCallerJS")) { + ok(grfdex == fdexNameCaseSensitive, "grfdex = %lx\n", grfdex); + *pid = DISPID_TEST_TESTGETCALLERJS; + return S_OK; + } + if(!lstrcmpW(bstrName, L"testGetCallerNested")) { + ok(grfdex == fdexNameCaseSensitive, "grfdex = %lx\n", grfdex); + *pid = DISPID_TEST_TESTGETCALLERNESTED; + return S_OK; + }
return E_NOTIMPL; } @@ -357,6 +430,9 @@ static HRESULT WINAPI Test_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD gr static HRESULT WINAPI Test_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { + IServiceProvider *caller = (void*)0xdeadbeef; + HRESULT hres; + ok(pspCaller != NULL, "pspCaller == NULL\n");
switch(id) { @@ -380,6 +456,80 @@ static HRESULT WINAPI Test_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WO IDispatch_AddRef(stored_obj); break;
+ case DISPID_TEST_TESTGETCALLER: { + void *iface = (void*)0xdeadbeef; + + CHECK_EXPECT(testGetCaller); + CHECK_CALLED(OnEnterScript); + + ok(wFlags == DISPATCH_METHOD, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pvarRes, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + SET_EXPECT(testGetCallerNested); + hres = IActiveScriptParse_ParseScriptText(active_script_parser, L"testGetCallerNested(1,2)", + NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + ok(hres == S_OK, "ParseScriptText failed: %08lx\n", hres); + CHECK_CALLED(testGetCallerNested); + CHECK_CALLED(OnLeaveScript); + CHECK_CALLED(OnEnterScript); + SET_EXPECT(OnLeaveScript); + + hres = IServiceProvider_QueryService(pspCaller, &SID_GetCaller, &IID_IServiceProvider, (void**)&caller); + ok(hres == S_OK, "Could not get SID_GetCaller service: %08lx\n", hres); + ok(caller == test_get_caller_sp, "caller != test_get_caller_sp\n"); + if(caller) IServiceProvider_Release(caller); + + if(test_get_caller_sp) + SET_EXPECT(sp_caller_QI_NULL); + hres = IServiceProvider_QueryService(pspCaller, &SID_GetCaller, &IID_NULL, &iface); + ok(hres == (test_get_caller_sp ? E_NOINTERFACE : S_OK), "Could not query SID_GetCaller with IID_NULL: %08lx\n", hres); + ok(iface == NULL, "iface != NULL\n"); + if(test_get_caller_sp) + CHECK_CALLED(sp_caller_QI_NULL); + break; + } + + case DISPID_TEST_TESTGETCALLERJS: + CHECK_EXPECT(testGetCallerJS); + + ok(wFlags == DISPATCH_METHOD, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pvarRes, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + ok(V_VT(pdp->rgvarg) == VT_I4, "V_VT(rgvarg) = %d\n", V_VT(pdp->rgvarg)); + ok(V_I4(pdp->rgvarg) == 42, "V_I4(rgvarg) = %ld\n", V_I4(pdp->rgvarg)); + + hres = IServiceProvider_QueryService(pspCaller, &SID_GetCaller, &IID_IServiceProvider, (void**)&caller); + ok(hres == E_NOINTERFACE, "QueryService(SID_GetCaller) returned: %08lx\n", hres); + ok(caller == NULL, "caller != NULL\n"); + break; + + case DISPID_TEST_TESTGETCALLERNESTED: + CHECK_EXPECT(testGetCallerNested); + + ok(wFlags == DISPATCH_METHOD, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->cArgs == 2, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pvarRes, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + ok(V_VT(&pdp->rgvarg[0]) == VT_I4, "V_VT(rgvarg[0]) = %d\n", V_VT(&pdp->rgvarg[0])); + ok(V_VT(&pdp->rgvarg[1]) == VT_I4, "V_VT(rgvarg[1]) = %d\n", V_VT(&pdp->rgvarg[1])); + ok(V_I4(&pdp->rgvarg[0]) == 2, "V_I4(rgvarg[0]) = %ld\n", V_I4(&pdp->rgvarg[0])); + ok(V_I4(&pdp->rgvarg[1]) == 1, "V_I4(rgvarg[1]) = %ld\n", V_I4(&pdp->rgvarg[1])); + + hres = IServiceProvider_QueryService(pspCaller, &SID_GetCaller, &IID_IServiceProvider, (void**)&caller); + ok(hres == E_NOINTERFACE, "QueryService(SID_GetCaller) returned: %08lx\n", hres); + ok(caller == NULL, "caller != NULL\n"); + break; + default: ok(0, "unexpected call\n"); return E_NOTIMPL; @@ -542,22 +692,32 @@ static IActiveScriptParse *create_script(void)
static void run_scripts(void) { - IActiveScriptParse *parser; + IActiveScript *active_script; + DISPPARAMS dp = { 0 }; + IDispatchEx *dispex; + IDispatch *disp; + DISPID dispid; HRESULT hres; + VARIANT var; + BSTR bstr;
- parser = create_script(); + active_script_parser = create_script();
- hres = IActiveScriptParse_QueryInterface(parser, &IID_IVariantChangeType, (void**)&script_change_type); + hres = IActiveScriptParse_QueryInterface(active_script_parser, &IID_IVariantChangeType, (void**)&script_change_type); ok(hres == S_OK, "Could not get IVariantChangeType iface: %08lx\n", hres);
SET_EXPECT(OnEnterScript); /* checked in callback */ SET_EXPECT(testArgConv); - parse_script(parser, + SET_EXPECT(testGetCallerJS); + parse_script(active_script_parser, L"var obj = {" L" toString: function() { return 'strval'; }," L" valueOf: function() { return 10; }" L"};" - L"testArgConv(obj);"); + L"testArgConv(obj);" + L"function testGetCallerFunc() { testGetCaller(); };" + L"testGetCallerJS(42);"); + CHECK_CALLED(testGetCallerJS); CHECK_CALLED(testArgConv); CHECK_CALLED(OnLeaveScript); /* set in callback */
@@ -565,7 +725,47 @@ static void run_scripts(void) IDispatch_Release(stored_obj); IVariantChangeType_Release(script_change_type);
- IActiveScriptParse_Release(parser); + hres = IActiveScriptParse_QueryInterface(active_script_parser, &IID_IActiveScript, (void**)&active_script); + ok(hres == S_OK, "Could not get IActiveScript: %08lx\n", hres); + hres = IActiveScript_GetScriptDispatch(active_script, NULL, &disp); + ok(hres == S_OK, "GetScriptDispatch failed: %08lx\n", hres); + IActiveScript_Release(active_script); + hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "Could not get IDispatchEx: %08lx\n", hres); + IDispatch_Release(disp); + bstr = SysAllocString(L"testGetCallerFunc"); + hres = IDispatchEx_GetDispID(dispex, bstr, 0, &dispid); + ok(hres == S_OK, "GetDispID failed: %08lx\n", hres); + SysFreeString(bstr); + + hres = IDispatchEx_InvokeEx(dispex, dispid, 0, DISPATCH_PROPERTYGET, &dp, &var, NULL, NULL); + ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres); + ok(V_VT(&var) == VT_DISPATCH, "V_VT(testGetCallerFunc) = %d\n", V_VT(&var)); + ok(V_DISPATCH(&var) != NULL, "V_DISPATCH(testGetCallerFunc) = NULL\n"); + IDispatchEx_Release(dispex); + hres = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "Could not get IDispatchEx: %08lx\n", hres); + IDispatch_Release(V_DISPATCH(&var)); + + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + SET_EXPECT(testGetCaller); + hres = IDispatchEx_InvokeEx(dispex, DISPID_VALUE, 0, DISPATCH_METHOD, &dp, NULL, NULL, NULL); + ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres); + CHECK_CALLED(testGetCaller); + CHECK_CALLED(OnLeaveScript); + test_get_caller_sp = &sp_caller_obj; + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + SET_EXPECT(testGetCaller); + hres = IDispatchEx_InvokeEx(dispex, DISPID_VALUE, 0, DISPATCH_METHOD, &dp, NULL, NULL, test_get_caller_sp); + ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres); + CHECK_CALLED(testGetCaller); + CHECK_CALLED(OnLeaveScript); + IDispatchEx_Release(dispex); + + IActiveScriptParse_Release(active_script_parser); + active_script_parser = NULL; }
static BOOL check_jscript(void)
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/vbscript/vbdisp.c | 4 +- dlls/vbscript/vbscript.c | 83 ++++++++++++++++++++++++++++++++++++++++ dlls/vbscript/vbscript.h | 7 ++++ 3 files changed, 92 insertions(+), 2 deletions(-)
diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index e19ed2b53d4..13236ad4b29 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -1661,7 +1661,7 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, DISPPARAMS *dp,
hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); if(SUCCEEDED(hres)) { - hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, dp, retv, &ei, NULL /* CALLER_FIXME */); + hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, dp, retv, &ei, &ctx->vbcaller->IServiceProvider_iface); IDispatchEx_Release(dispex); }else { UINT err = 0; @@ -1699,7 +1699,7 @@ HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags,
hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); if(SUCCEEDED(hres)) { - hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, dp, NULL, &ei, NULL /* FIXME! */); + hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, dp, NULL, &ei, &ctx->vbcaller->IServiceProvider_iface); IDispatchEx_Release(dispex); }else { UINT err = 0; diff --git a/dlls/vbscript/vbscript.c b/dlls/vbscript/vbscript.c index b6364410931..d010ba4b51d 100644 --- a/dlls/vbscript/vbscript.c +++ b/dlls/vbscript/vbscript.c @@ -366,6 +366,80 @@ static void decrease_state(VBScript *This, SCRIPTSTATE state) } }
+static inline struct vbcaller *vbcaller_from_IServiceProvider(IServiceProvider *iface) +{ + return CONTAINING_RECORD(iface, struct vbcaller, IServiceProvider_iface); +} + +static HRESULT WINAPI vbcaller_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) +{ + struct vbcaller *This = vbcaller_from_IServiceProvider(iface); + + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IServiceProvider, riid)) { + *ppv = &This->IServiceProvider_iface; + }else { + WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI vbcaller_AddRef(IServiceProvider *iface) +{ + struct vbcaller *This = vbcaller_from_IServiceProvider(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%ld\n", This, ref); + + return ref; +} + +static ULONG WINAPI vbcaller_Release(IServiceProvider *iface) +{ + struct vbcaller *This = vbcaller_from_IServiceProvider(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%ld\n", This, ref); + + if(!ref) + free(This); + + return ref; +} + +static HRESULT WINAPI vbcaller_QueryService(IServiceProvider *iface, REFGUID guidService, + REFIID riid, void **ppv) +{ + struct vbcaller *This = vbcaller_from_IServiceProvider(iface); + + FIXME("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv); + + *ppv = NULL; + return E_NOINTERFACE; +} + +static const IServiceProviderVtbl ServiceProviderVtbl = { + vbcaller_QueryInterface, + vbcaller_AddRef, + vbcaller_Release, + vbcaller_QueryService +}; + +static struct vbcaller *create_vbcaller(void) +{ + struct vbcaller *ret; + + ret = malloc(sizeof(*ret)); + if(ret) { + ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl; + ret->ref = 1; + } + return ret; +} + static inline VBScriptError *impl_from_IActiveScriptError(IActiveScriptError *iface) { return CONTAINING_RECORD(iface, VBScriptError, IActiveScriptError_iface); @@ -545,6 +619,7 @@ static ULONG WINAPI VBScript_Release(IActiveScript *iface) if(!ref) { decrease_state(This, SCRIPTSTATE_CLOSED); detach_global_objects(This->ctx); + IServiceProvider_Release(&This->ctx->vbcaller->IServiceProvider_iface); free(This->ctx); free(This); } @@ -1102,6 +1177,7 @@ static const IObjectSafetyVtbl VBScriptSafetyVtbl = {
HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter, REFIID riid, void **ppv) { + struct vbcaller *vbcaller; script_ctx_t *ctx; VBScript *ret; HRESULT hres; @@ -1112,6 +1188,11 @@ HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pU if(!ret) return E_OUTOFMEMORY;
+ if(!(vbcaller = create_vbcaller())) { + free(ret); + return E_OUTOFMEMORY; + } + ret->IActiveScript_iface.lpVtbl = &VBScriptVtbl; ret->IActiveScriptDebug_iface.lpVtbl = &VBScriptDebugVtbl; ret->IActiveScriptParse_iface.lpVtbl = &VBScriptParseVtbl; @@ -1123,10 +1204,12 @@ HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pU
ctx = ret->ctx = calloc(1, sizeof(*ctx)); if(!ctx) { + IServiceProvider_Release(&vbcaller->IServiceProvider_iface); free(ret); return E_OUTOFMEMORY; }
+ ctx->vbcaller = vbcaller; ctx->safeopt = INTERFACE_USES_DISPEX; list_init(&ctx->objects); list_init(&ctx->code_list); diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index 8286b37bbab..c42b0d31391 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -180,12 +180,19 @@ static inline VARIANT *get_arg(DISPPARAMS *dp, DWORD i) return dp->rgvarg + dp->cArgs-i-1; }
+struct vbcaller { + IServiceProvider IServiceProvider_iface; + + LONG ref; +}; + struct _script_ctx_t { IActiveScriptSite *site; LCID lcid; UINT codepage;
IInternetHostSecurityManager *secmgr; + struct vbcaller *vbcaller; DWORD safeopt;
ScriptDisp *script_obj;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/vbscript/tests/Makefile.in | 1 + dlls/vbscript/tests/caller.c | 551 ++++++++++++++++++++++++++++++++ dlls/vbscript/vbdisp.c | 45 ++- dlls/vbscript/vbscript.c | 17 +- dlls/vbscript/vbscript.h | 4 + 5 files changed, 609 insertions(+), 9 deletions(-) create mode 100644 dlls/vbscript/tests/caller.c
diff --git a/dlls/vbscript/tests/Makefile.in b/dlls/vbscript/tests/Makefile.in index 35379baf198..927280bef22 100644 --- a/dlls/vbscript/tests/Makefile.in +++ b/dlls/vbscript/tests/Makefile.in @@ -2,6 +2,7 @@ TESTDLL = vbscript.dll IMPORTS = oleaut32 ole32 advapi32
C_SRCS = \ + caller.c \ createobj.c \ run.c \ vbscript.c diff --git a/dlls/vbscript/tests/caller.c b/dlls/vbscript/tests/caller.c new file mode 100644 index 00000000000..19eccfe715d --- /dev/null +++ b/dlls/vbscript/tests/caller.c @@ -0,0 +1,551 @@ +/* + * Copyright 2023 Gabriel Ivăncescu for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdio.h> + +#define COBJMACROS +#define CONST_VTABLE + +#include <ole2.h> +#include <dispex.h> +#include <activscp.h> +#include <objsafe.h> + +#include "wine/test.h" + +#ifdef _WIN64 + +#define IActiveScriptParse_QueryInterface IActiveScriptParse64_QueryInterface +#define IActiveScriptParse_Release IActiveScriptParse64_Release +#define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew +#define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText + +#else + +#define IActiveScriptParse_QueryInterface IActiveScriptParse32_QueryInterface +#define IActiveScriptParse_Release IActiveScriptParse32_Release +#define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew +#define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText + +#endif + +extern const CLSID CLSID_VBScript; + +#define DEFINE_EXPECT(func) \ + static BOOL expect_ ## func = FALSE, called_ ## func = FALSE + +#define SET_EXPECT(func) \ + expect_ ## func = TRUE + +#define CHECK_EXPECT2(func) \ + do { \ + ok(expect_ ##func, "unexpected call " #func "\n"); \ + called_ ## func = TRUE; \ + }while(0) + +#define CHECK_EXPECT(func) \ + do { \ + CHECK_EXPECT2(func); \ + expect_ ## func = FALSE; \ + }while(0) + +#define CHECK_CALLED(func) \ + do { \ + ok(called_ ## func, "expected " #func "\n"); \ + expect_ ## func = called_ ## func = FALSE; \ + }while(0) + +#define CLEAR_CALLED(func) \ + expect_ ## func = called_ ## func = FALSE + +DEFINE_EXPECT(sp_caller_QI_NULL); +DEFINE_EXPECT(testGetCaller); +DEFINE_EXPECT(testGetCallerVBS); +DEFINE_EXPECT(testGetCallerNested); +DEFINE_EXPECT(OnEnterScript); +DEFINE_EXPECT(OnLeaveScript); + +static IActiveScript *active_script; +static IServiceProvider *test_get_caller_sp; + +#define DISPID_TEST_TESTGETCALLER 0x1000 +#define DISPID_TEST_TESTGETCALLERVBS 0x1001 +#define DISPID_TEST_TESTGETCALLERNESTED 0x1002 + +#define parse_script(a,s) _parse_script(__LINE__,a,s) +static void _parse_script(unsigned line, IActiveScript *active_script, const WCHAR *script) +{ + IActiveScriptParse *parser; + HRESULT hres; + + hres = IActiveScript_QueryInterface(active_script, &IID_IActiveScriptParse, (void**)&parser); + ok_(__FILE__,line)(hres == S_OK, "Could not get IActiveScriptParse: %08lx\n", hres); + + hres = IActiveScriptParse_ParseScriptText(parser, script, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + ok_(__FILE__,line)(hres == S_OK, "ParseScriptText failed: %08lx\n", hres); + IActiveScriptParse_Release(parser); +} + +static IServiceProvider sp_caller_obj; + +static HRESULT WINAPI sp_caller_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IServiceProvider, riid)) + *ppv = &sp_caller_obj; + else { + ok(IsEqualGUID(&IID_NULL, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + CHECK_EXPECT(sp_caller_QI_NULL); + *ppv = NULL; + return E_NOINTERFACE; + } + + return S_OK; +} + +static ULONG WINAPI sp_caller_AddRef(IServiceProvider *iface) +{ + return 2; +} + +static ULONG WINAPI sp_caller_Release(IServiceProvider *iface) +{ + return 1; +} + +static HRESULT WINAPI sp_caller_QueryService(IServiceProvider *iface, REFGUID guidService, + REFIID riid, void **ppv) +{ + if(IsEqualGUID(guidService, &SID_GetCaller)) { + ok(IsEqualGUID(riid, &IID_IServiceProvider), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = NULL; + return S_OK; + } + + ok(0, "unexpected guidService %s with riid %s\n", wine_dbgstr_guid(guidService), wine_dbgstr_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; +} + +static const IServiceProviderVtbl sp_caller_vtbl = { + sp_caller_QueryInterface, + sp_caller_AddRef, + sp_caller_Release, + sp_caller_QueryService +}; + +static IServiceProvider sp_caller_obj = { &sp_caller_vtbl }; + +static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(riid, &IID_IUnknown)) { + *ppv = iface; + }else if(IsEqualGUID(riid, &IID_IDispatch) || IsEqualGUID(riid, &IID_IDispatchEx)) { + *ppv = iface; + }else if(IsEqualGUID(&IID_IObjectSafety, riid)) { + ok(0, "Unexpected IID_IObjectSafety query\n"); + }else { + *ppv = NULL; + return E_NOINTERFACE; + } + + return S_OK; +} + +static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface) +{ + return 2; +} + +static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface) +{ + return 1; +} + +static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid, LPOLESTR *rgszNames, + UINT cNames, LCID lcid, DISPID *rgDispId) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember, REFIID riid, LCID lcid, + WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Test_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) +{ + if(!lstrcmpW(bstrName, L"testGetCaller")) { + ok(grfdex == fdexNameCaseInsensitive, "grfdex = %lx\n", grfdex); + *pid = DISPID_TEST_TESTGETCALLER; + return S_OK; + } + if(!lstrcmpW(bstrName, L"testGetCallerVBS")) { + ok(grfdex == fdexNameCaseInsensitive, "grfdex = %lx\n", grfdex); + *pid = DISPID_TEST_TESTGETCALLERVBS; + return S_OK; + } + if(!lstrcmpW(bstrName, L"testGetCallerNested")) { + ok(grfdex == fdexNameCaseInsensitive, "grfdex = %lx\n", grfdex); + *pid = DISPID_TEST_TESTGETCALLERNESTED; + return S_OK; + } + + return E_NOTIMPL; +} + +static HRESULT WINAPI Test_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + IServiceProvider *caller = (void*)0xdeadbeef; + HRESULT hres; + + ok(pspCaller != NULL, "pspCaller == NULL\n"); + + switch(id) { + case DISPID_TEST_TESTGETCALLER: { + void *iface = (void*)0xdeadbeef; + + CHECK_EXPECT(testGetCaller); + CHECK_CALLED(OnEnterScript); + + ok(wFlags == DISPATCH_METHOD, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pvarRes, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + SET_EXPECT(testGetCallerNested); + parse_script(active_script, L"Call testGetCallerNested(1,2)"); + CHECK_CALLED(testGetCallerNested); + CHECK_CALLED(OnLeaveScript); + CHECK_CALLED(OnEnterScript); + SET_EXPECT(OnLeaveScript); + + hres = IServiceProvider_QueryService(pspCaller, &SID_GetCaller, &IID_IServiceProvider, (void**)&caller); + ok(hres == S_OK, "Could not get SID_GetCaller service: %08lx\n", hres); + ok(caller == test_get_caller_sp, "caller != test_get_caller_sp\n"); + if(caller) IServiceProvider_Release(caller); + + if(test_get_caller_sp) + SET_EXPECT(sp_caller_QI_NULL); + hres = IServiceProvider_QueryService(pspCaller, &SID_GetCaller, &IID_NULL, &iface); + ok(hres == (test_get_caller_sp ? E_NOINTERFACE : S_OK), "Could not query SID_GetCaller with IID_NULL: %08lx\n", hres); + ok(iface == NULL, "iface != NULL\n"); + if(test_get_caller_sp) + CHECK_CALLED(sp_caller_QI_NULL); + break; + } + + case DISPID_TEST_TESTGETCALLERVBS: + CHECK_EXPECT(testGetCallerVBS); + + ok(wFlags == DISPATCH_METHOD, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pvarRes, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + ok(V_VT(pdp->rgvarg) == VT_I2, "V_VT(rgvarg) = %d\n", V_VT(pdp->rgvarg)); + ok(V_I2(pdp->rgvarg) == 42, "V_I2(rgvarg) = %d\n", V_I2(pdp->rgvarg)); + + hres = IServiceProvider_QueryService(pspCaller, &SID_GetCaller, &IID_IServiceProvider, (void**)&caller); + ok(hres == E_NOINTERFACE, "QueryService(SID_GetCaller) returned: %08lx\n", hres); + ok(caller == NULL, "caller != NULL\n"); + break; + + case DISPID_TEST_TESTGETCALLERNESTED: + CHECK_EXPECT(testGetCallerNested); + + ok(wFlags == DISPATCH_METHOD, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->cArgs == 2, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pvarRes, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + ok(V_VT(&pdp->rgvarg[0]) == VT_I2, "V_VT(rgvarg[0]) = %d\n", V_VT(&pdp->rgvarg[0])); + ok(V_VT(&pdp->rgvarg[1]) == VT_I2, "V_VT(rgvarg[1]) = %d\n", V_VT(&pdp->rgvarg[1])); + ok(V_I2(&pdp->rgvarg[0]) == 2, "V_I2(rgvarg[0]) = %d\n", V_I2(&pdp->rgvarg[0])); + ok(V_I2(&pdp->rgvarg[1]) == 1, "V_I2(rgvarg[1]) = %d\n", V_I2(&pdp->rgvarg[1])); + + hres = IServiceProvider_QueryService(pspCaller, &SID_GetCaller, &IID_IServiceProvider, (void**)&caller); + ok(hres == E_NOINTERFACE, "QueryService(SID_GetCaller) returned: %08lx\n", hres); + ok(caller == NULL, "caller != NULL\n"); + break; + + default: + ok(0, "unexpected call\n"); + return E_NOTIMPL; + } + + return S_OK; +} + +static IDispatchExVtbl testObjVtbl = { + DispatchEx_QueryInterface, + DispatchEx_AddRef, + DispatchEx_Release, + DispatchEx_GetTypeInfoCount, + DispatchEx_GetTypeInfo, + DispatchEx_GetIDsOfNames, + DispatchEx_Invoke, + Test_GetDispID, + Test_InvokeEx, + DispatchEx_DeleteMemberByName, + DispatchEx_DeleteMemberByDispID, + DispatchEx_GetMemberProperties, + DispatchEx_GetMemberName, + DispatchEx_GetNextDispID, + DispatchEx_GetNameSpaceParent +}; + +static IDispatchEx testObj = { &testObjVtbl }; + +static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(&IID_IUnknown, riid)) { + *ppv = iface; + }else if(IsEqualGUID(&IID_IActiveScriptSite, riid)) { + *ppv = iface; + }else { + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI ActiveScriptSite_AddRef(IActiveScriptSite *iface) +{ + return 2; +} + +static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface) +{ + return 1; +} + +static HRESULT WINAPI ActiveScriptSite_GetLCID(IActiveScriptSite *iface, LCID *plcid) +{ + *plcid = GetUserDefaultLCID(); + return S_OK; +} + +static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface, LPCOLESTR pstrName, + DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti) +{ + ok(dwReturnMask == SCRIPTINFO_IUNKNOWN, "unexpected dwReturnMask %lx\n", dwReturnMask); + ok(!ppti, "ppti != NULL\n"); + ok(!lstrcmpW(pstrName, L"test"), "pstrName = %s\n", wine_dbgstr_w(pstrName)); + + *ppiunkItem = (IUnknown*)&testObj; + return S_OK; +} + +static HRESULT WINAPI ActiveScriptSite_GetDocVersionString(IActiveScriptSite *iface, BSTR *pbstrVersion) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnScriptTerminate(IActiveScriptSite *iface, + const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, SCRIPTSTATE ssScriptState) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, IActiveScriptError *pscripterror) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnEnterScript(IActiveScriptSite *iface) +{ + CHECK_EXPECT(OnEnterScript); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnLeaveScript(IActiveScriptSite *iface) +{ + CHECK_EXPECT(OnLeaveScript); + return E_NOTIMPL; +} + +static const IActiveScriptSiteVtbl ActiveScriptSiteVtbl = { + ActiveScriptSite_QueryInterface, + ActiveScriptSite_AddRef, + ActiveScriptSite_Release, + ActiveScriptSite_GetLCID, + ActiveScriptSite_GetItemInfo, + ActiveScriptSite_GetDocVersionString, + ActiveScriptSite_OnScriptTerminate, + ActiveScriptSite_OnStateChange, + ActiveScriptSite_OnScriptError, + ActiveScriptSite_OnEnterScript, + ActiveScriptSite_OnLeaveScript +}; + +static IActiveScriptSite ActiveScriptSite = { &ActiveScriptSiteVtbl }; + +static IActiveScript *create_script(void) +{ + IActiveScriptParse *parser; + IActiveScript *script; + HRESULT hres; + + hres = CoCreateInstance(&CLSID_VBScript, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, + &IID_IActiveScript, (void**)&script); + if(FAILED(hres)) + return NULL; + + hres = IActiveScript_QueryInterface(script, &IID_IActiveScriptParse, (void**)&parser); + ok(hres == S_OK, "Could not get IActiveScriptParse: %08lx\n", hres); + + hres = IActiveScriptParse_InitNew(parser); + ok(hres == S_OK, "InitNew failed: %08lx\n", hres); + IActiveScriptParse_Release(parser); + + hres = IActiveScript_SetScriptSite(script, &ActiveScriptSite); + ok(hres == S_OK, "SetScriptSite failed: %08lx\n", hres); + + hres = IActiveScript_AddNamedItem(script, L"test", + SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|SCRIPTITEM_GLOBALMEMBERS); + ok(hres == S_OK, "AddNamedItem failed: %08lx\n", hres); + + hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_STARTED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08lx\n", hres); + + return script; +} + +static void run_scripts(void) +{ + DISPPARAMS dp = { 0 }; + IDispatchEx *dispex; + IDispatch *disp; + DISPID dispid; + HRESULT hres; + BSTR bstr; + + active_script = create_script(); + + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + SET_EXPECT(testGetCallerVBS); + parse_script(active_script, + L"Sub testGetCallerFunc\nCall testGetCaller\nEnd Sub\n" + L"Call testGetCallerVBS(42)"); + CHECK_CALLED(testGetCallerVBS); + CHECK_CALLED(OnLeaveScript); + CHECK_CALLED(OnEnterScript); + + hres = IActiveScript_GetScriptDispatch(active_script, NULL, &disp); + ok(hres == S_OK, "GetScriptDispatch failed: %08lx\n", hres); + hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "Could not get IDispatchEx: %08lx\n", hres); + IDispatch_Release(disp); + bstr = SysAllocString(L"testGetCallerFunc"); + hres = IDispatchEx_GetDispID(dispex, bstr, 0, &dispid); + ok(hres == S_OK, "GetDispID failed: %08lx\n", hres); + SysFreeString(bstr); + + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + SET_EXPECT(testGetCaller); + hres = IDispatchEx_InvokeEx(dispex, dispid, 0, DISPATCH_METHOD, &dp, NULL, NULL, NULL); + ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres); + CHECK_CALLED(testGetCaller); + CHECK_CALLED(OnLeaveScript); + test_get_caller_sp = &sp_caller_obj; + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + SET_EXPECT(testGetCaller); + hres = IDispatchEx_InvokeEx(dispex, dispid, 0, DISPATCH_METHOD, &dp, NULL, NULL, test_get_caller_sp); + ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres); + CHECK_CALLED(testGetCaller); + CHECK_CALLED(OnLeaveScript); + IDispatchEx_Release(dispex); + + IActiveScript_Release(active_script); + active_script = NULL; +} + +START_TEST(caller) +{ + CoInitialize(NULL); + + run_scripts(); + + CoUninitialize(); +} diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index 13236ad4b29..0ede0cfd6ba 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -413,6 +413,8 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { vbdisp_t *This = impl_from_IDispatchEx(iface); + IServiceProvider *prev_caller; + HRESULT hres;
TRACE("(%p)->(%lx %lx %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
@@ -422,7 +424,17 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc if(pvarRes) V_VT(pvarRes) = VT_EMPTY;
- return invoke_vbdisp(This, id, wFlags, TRUE, pdp, pvarRes); + prev_caller = This->desc->ctx->vbcaller->caller; + This->desc->ctx->vbcaller->caller = pspCaller; + if(pspCaller) + IServiceProvider_AddRef(pspCaller); + + hres = invoke_vbdisp(This, id, wFlags, TRUE, pdp, pvarRes); + + This->desc->ctx->vbcaller->caller = prev_caller; + if(pspCaller) + IServiceProvider_Release(pspCaller); + return hres; }
static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) @@ -1414,6 +1426,7 @@ static HRESULT WINAPI ScriptDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { ScriptDisp *This = ScriptDisp_from_IDispatchEx(iface); + IServiceProvider *prev_caller; HRESULT hres;
TRACE("(%p)->(%lx %lx %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); @@ -1421,11 +1434,18 @@ static HRESULT WINAPI ScriptDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc if (!This->ctx) return E_UNEXPECTED;
+ prev_caller = This->ctx->vbcaller->caller; + This->ctx->vbcaller->caller = pspCaller; + if(pspCaller) + IServiceProvider_AddRef(pspCaller); + if (id & DISPID_FUNCTION_MASK) { id &= ~DISPID_FUNCTION_MASK; - if (id > This->global_funcs_cnt) - return DISP_E_MEMBERNOTFOUND; + if (id > This->global_funcs_cnt) { + hres = DISP_E_MEMBERNOTFOUND; + goto done; + }
switch (wFlags) { @@ -1438,19 +1458,28 @@ static HRESULT WINAPI ScriptDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc hres = E_NOTIMPL; }
- return hres; + goto done; }
- if (id > This->global_vars_cnt) - return DISP_E_MEMBERNOTFOUND; + if (id > This->global_vars_cnt) { + hres = DISP_E_MEMBERNOTFOUND; + goto done; + }
if (This->global_vars[id - 1]->is_const) { FIXME("const not supported\n"); - return E_NOTIMPL; + hres = E_NOTIMPL; + goto done; }
- return invoke_variant_prop(This->ctx, &This->global_vars[id - 1]->v, wFlags, pdp, pvarRes); + hres = invoke_variant_prop(This->ctx, &This->global_vars[id - 1]->v, wFlags, pdp, pvarRes); + +done: + This->ctx->vbcaller->caller = prev_caller; + if(pspCaller) + IServiceProvider_Release(pspCaller); + return hres; }
static HRESULT WINAPI ScriptDisp_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) diff --git a/dlls/vbscript/vbscript.c b/dlls/vbscript/vbscript.c index d010ba4b51d..39a5e3b1648 100644 --- a/dlls/vbscript/vbscript.c +++ b/dlls/vbscript/vbscript.c @@ -96,6 +96,7 @@ static HRESULT exec_global_code(script_ctx_t *ctx, vbscode_t *code, VARIANT *res ScriptDisp *obj = ctx->script_obj; function_t *func_iter, **new_funcs; dynamic_var_t *var, **new_vars; + IServiceProvider *prev_caller; size_t cnt, i; HRESULT hres;
@@ -185,7 +186,12 @@ static HRESULT exec_global_code(script_ctx_t *ctx, vbscode_t *code, VARIANT *res }
code->pending_exec = FALSE; - return exec_script(ctx, TRUE, &code->main_code, NULL, NULL, res); + + prev_caller = ctx->vbcaller->caller; + ctx->vbcaller->caller = SP_CALLER_UNINITIALIZED; + hres = exec_script(ctx, TRUE, &code->main_code, NULL, NULL, res); + ctx->vbcaller->caller = prev_caller; + return hres; }
static void exec_queued_code(script_ctx_t *ctx) @@ -415,6 +421,14 @@ static HRESULT WINAPI vbcaller_QueryService(IServiceProvider *iface, REFGUID gui { struct vbcaller *This = vbcaller_from_IServiceProvider(iface);
+ if(IsEqualGUID(guidService, &SID_GetCaller)) { + TRACE("(%p)->(SID_GetCaller)\n", This); + *ppv = NULL; + if(!This->caller) + return S_OK; + return (This->caller == SP_CALLER_UNINITIALIZED) ? E_NOINTERFACE : IServiceProvider_QueryInterface(This->caller, riid, ppv); + } + FIXME("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
*ppv = NULL; @@ -436,6 +450,7 @@ static struct vbcaller *create_vbcaller(void) if(ret) { ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl; ret->ref = 1; + ret->caller = SP_CALLER_UNINITIALIZED; } return ret; } diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index c42b0d31391..5b0a2222767 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -180,10 +180,14 @@ static inline VARIANT *get_arg(DISPPARAMS *dp, DWORD i) return dp->rgvarg + dp->cArgs-i-1; }
+#define SP_CALLER_UNINITIALIZED ((IServiceProvider*)IntToPtr(-1)) + struct vbcaller { IServiceProvider IServiceProvider_iface;
LONG ref; + + IServiceProvider *caller; };
struct _script_ctx_t {
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=128809
Your paranoid android.
=== debian11 (32 bit report) ===
dinput: hid.c:730: Test succeeded inside todo block: WaitForSingleObject returned 0
This merge request was approved by Jacek Caban.