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 49640cff9da..e01d820ea06 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 | 12 +- dlls/mshtml/tests/script.c | 376 ++++++++++++++++++++++++++++++++++--- 2 files changed, 362 insertions(+), 26 deletions(-)
diff --git a/dlls/mshtml/script.c b/dlls/mshtml/script.c index 5321080a8f9..7c9fd1887d1 100644 --- a/dlls/mshtml/script.c +++ b/dlls/mshtml/script.c @@ -201,9 +201,17 @@ static BOOL init_script_engine(ScriptHost *script_host) hres = IActiveScript_AddNamedItem(script_host->script, L"window", SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|SCRIPTITEM_GLOBALMEMBERS); if(SUCCEEDED(hres)) { + const struct list *list = &script_host->window->script_hosts, *head = list_head(list); V_VT(&var) = VT_BOOL; - V_BOOL(&var) = VARIANT_TRUE; + V_BOOL(&var) = head ? VARIANT_FALSE : VARIANT_TRUE; set_script_prop(script_host, SCRIPTPROP_ABBREVIATE_GLOBALNAME_RESOLUTION, &var); + + /* if this was second engine added, also set it to first engine, since it used to be TRUE */ + if(head && !list_next(list, head)) { + ScriptHost *first_host = LIST_ENTRY(head, ScriptHost, entry); + if(first_host->script) + set_script_prop(first_host, SCRIPTPROP_ABBREVIATE_GLOBALNAME_RESOLUTION, &var); + } }else { WARN("AddNamedItem failed: %08lx\n", hres); } @@ -708,7 +716,6 @@ static ScriptHost *create_script_host(HTMLInnerWindow *window, const GUID *guid) ret->script_state = SCRIPTSTATE_UNINITIALIZED;
ret->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); @@ -717,6 +724,7 @@ static ScriptHost *create_script_host(HTMLInnerWindow *window, const GUID *guid) else if(!init_script_engine(ret)) release_script_engine(ret);
+ list_add_tail(&window->script_hosts, &ret->entry); return ret; }
diff --git a/dlls/mshtml/tests/script.c b/dlls/mshtml/tests/script.c index 8d9ff3cd3f7..c06009d1996 100644 --- a/dlls/mshtml/tests/script.c +++ b/dlls/mshtml/tests/script.c @@ -103,21 +103,33 @@ 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(SetProperty2_ABBREVIATE_GLOBALNAME_RESOLUTION_TRUE); 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 +152,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 +172,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 +191,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 +1940,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 +3349,260 @@ 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: + if(V_BOOL(pvarValue)) + CHECK_EXPECT(SetProperty2_ABBREVIATE_GLOBALNAME_RESOLUTION_TRUE); + else { + CHECK_EXPECT(SetProperty2_ABBREVIATE_GLOBALNAME_RESOLUTION_FALSE); + SET_EXPECT(SetProperty_ABBREVIATE_GLOBALNAME_RESOLUTION_FALSE); + } + ok(V_VT(pvarValue) == VT_BOOL, "V_VT(pvarValue) = %d\n", V_VT(pvarValue)); + 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); + + /* IE8 */ + CHECK_CALLED_BROKEN(SetProperty_ABBREVIATE_GLOBALNAME_RESOLUTION_TRUE); + SET_EXPECT(SetProperty2_ABBREVIATE_GLOBALNAME_RESOLUTION_FALSE); + 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 +3655,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,7 +4186,8 @@ 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>" + "<script language="TestScript2">second script</script>" "</body></html>";
static void test_exec_script(IHTMLDocument2 *doc, const WCHAR *codew, const WCHAR *langw) @@ -3945,49 +4231,72 @@ static void test_simple_script(void) return;
SET_EXPECT(CreateInstance); + SET_EXPECT(CreateInstance2); SET_EXPECT(GetInterfaceSafetyOptions); SET_EXPECT(SetInterfaceSafetyOptions); + SET_EXPECT(GetInterfaceSafetyOptions2); + SET_EXPECT(SetInterfaceSafetyOptions2); SET_EXPECT(SetProperty_INVOKEVERSIONING); /* IE8 */ + SET_EXPECT(SetProperty2_INVOKEVERSIONING); /* IE8 */ SET_EXPECT(SetProperty_HACK_TRIDENTEVENTSINK); + SET_EXPECT(SetProperty2_HACK_TRIDENTEVENTSINK); SET_EXPECT(InitNew); + SET_EXPECT(InitNew2); SET_EXPECT(SetScriptSite); + SET_EXPECT(SetScriptSite2); SET_EXPECT(GetScriptState); SET_EXPECT(SetScriptState_STARTED); SET_EXPECT(AddNamedItem); + SET_EXPECT(AddNamedItem2); SET_EXPECT(SetProperty_ABBREVIATE_GLOBALNAME_RESOLUTION_TRUE); /* IE8 */ SET_EXPECT(ParseScriptText_script); + SET_EXPECT(ParseScriptText_script2); SET_EXPECT(SetScriptState_CONNECTED);
load_doc(doc, simple_script_str);
CHECK_CALLED(CreateInstance); + CHECK_CALLED(CreateInstance2); CHECK_CALLED(GetInterfaceSafetyOptions); CHECK_CALLED(SetInterfaceSafetyOptions); + CHECK_CALLED(GetInterfaceSafetyOptions2); + CHECK_CALLED(SetInterfaceSafetyOptions2); CHECK_CALLED_BROKEN(SetProperty_INVOKEVERSIONING); /* IE8 */ + CHECK_CALLED_BROKEN(SetProperty2_INVOKEVERSIONING); /* IE8 */ CHECK_CALLED(SetProperty_HACK_TRIDENTEVENTSINK); + CHECK_CALLED(SetProperty2_HACK_TRIDENTEVENTSINK); CHECK_CALLED(InitNew); + CHECK_CALLED(InitNew2); CHECK_CALLED(SetScriptSite); + CHECK_CALLED(SetScriptSite2); CHECK_CALLED(GetScriptState); CHECK_CALLED(SetScriptState_STARTED); CHECK_CALLED(AddNamedItem); - CHECK_CALLED_BROKEN(SetProperty_ABBREVIATE_GLOBALNAME_RESOLUTION_TRUE); /* IE8 */ + CHECK_CALLED(AddNamedItem2); + CHECK_CALLED_BROKEN(SetProperty_ABBREVIATE_GLOBALNAME_RESOLUTION_FALSE); /* IE8 */ + CHECK_CALLED_BROKEN(SetProperty2_ABBREVIATE_GLOBALNAME_RESOLUTION_FALSE); /* IE8 */ CHECK_CALLED(ParseScriptText_script); + CHECK_CALLED(ParseScriptText_script2); CHECK_CALLED(SetScriptState_CONNECTED);
- test_exec_script(doc, L"execScript call", L"TestScript"); + 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 +4502,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 +4536,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 +4627,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.h | 1 + dlls/jscript/jsutils.c | 11 ++++ dlls/jscript/tests/caller.c | 125 +++++++++++++++++++++++++++++++++++- 4 files changed, 145 insertions(+), 1 deletion(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 1a7a75875df..c66d74af2a2 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -1578,6 +1578,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; @@ -1595,6 +1596,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; @@ -1676,6 +1682,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.h b/dlls/jscript/jscript.h index e1a3da04097..71f9cc18244 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -322,6 +322,7 @@ typedef struct { 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 8c1eedf4283..a7f35f8b5ac 100644 --- a/dlls/jscript/jsutils.c +++ b/dlls/jscript/jsutils.c @@ -979,6 +979,8 @@ HRESULT variant_change_type(script_ctx_t *ctx, VARIANT *dst, VARIANT *src, VARTY return S_OK; }
+#define CALLER_UNINITIALIZED ((IServiceProvider*)IntToPtr(-1)) + static inline JSCaller *impl_from_IServiceProvider(IServiceProvider *iface) { return CONTAINING_RECORD(iface, JSCaller, IServiceProvider_iface); @@ -1034,6 +1036,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 == 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 +1073,7 @@ HRESULT create_jscaller(script_ctx_t *ctx) ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl; ret->ref = 1; ret->ctx = ctx; + ret->caller = CALLER_UNINITIALIZED;
ctx->jscaller = ret; return S_OK; diff --git a/dlls/jscript/tests/caller.c b/dlls/jscript/tests/caller.c index 836f5a820a1..579a3cbf0a2 100644 --- a/dlls/jscript/tests/caller.c +++ b/dlls/jscript/tests/caller.c @@ -74,14 +74,20 @@ 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(testGetCaller_no_args); DEFINE_EXPECT(OnEnterScript); DEFINE_EXPECT(OnLeaveScript);
static IVariantChangeType *script_change_type; static IDispatch *stored_obj; +static IDispatchEx *test_get_caller_func; +static IServiceProvider *test_get_caller_sp;
#define DISPID_TEST_TESTARGCONV 0x1000 +#define DISPID_TEST_TESTGETCALLER 0x1001
typedef struct { int int_result; @@ -254,6 +260,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 +405,11 @@ 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; + }
return E_NOTIMPL; } @@ -357,6 +417,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 +443,43 @@ static HRESULT WINAPI Test_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WO IDispatch_AddRef(stored_obj); break;
+ case DISPID_TEST_TESTGETCALLER: + 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"); + + if(pdp->cArgs == 0) { + void *iface = (void*)0xdeadbeef; + + CHECK_EXPECT(testGetCaller_no_args); + 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); + }else { + CHECK_EXPECT(testGetCaller); + ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs); + ok(V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(rgvarg) = %d\n", V_VT(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"); + + hres = IDispatch_QueryInterface(V_DISPATCH(pdp->rgvarg), &IID_IDispatchEx, (void**)&test_get_caller_func); + ok(hres == S_OK, "Could not get IDispatchEx interface: %08lx\n", hres); + } + break; + default: ok(0, "unexpected call\n"); return E_NOTIMPL; @@ -543,6 +643,7 @@ static IActiveScriptParse *create_script(void) static void run_scripts(void) { IActiveScriptParse *parser; + DISPPARAMS dp = { 0 }; HRESULT hres;
parser = create_script(); @@ -552,12 +653,15 @@ static void run_scripts(void)
SET_EXPECT(OnEnterScript); /* checked in callback */ SET_EXPECT(testArgConv); + SET_EXPECT(testGetCaller); parse_script(parser, L"var obj = {" L" toString: function() { return 'strval'; }," L" valueOf: function() { return 10; }" L"};" - L"testArgConv(obj);"); + L"testArgConv(obj);" + L"testGetCaller(function() { testGetCaller(); });"); + CHECK_CALLED(testGetCaller); CHECK_CALLED(testArgConv); CHECK_CALLED(OnLeaveScript); /* set in callback */
@@ -565,6 +669,25 @@ static void run_scripts(void) IDispatch_Release(stored_obj); IVariantChangeType_Release(script_change_type);
+ SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + SET_EXPECT(testGetCaller_no_args); + hres = IDispatchEx_InvokeEx(test_get_caller_func, DISPID_VALUE, 0, DISPATCH_METHOD, &dp, NULL, NULL, NULL); + ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres); + CHECK_CALLED(testGetCaller_no_args); + CHECK_CALLED(OnLeaveScript); + CHECK_CALLED(OnEnterScript); + test_get_caller_sp = &sp_caller_obj; + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + SET_EXPECT(testGetCaller_no_args); + hres = IDispatchEx_InvokeEx(test_get_caller_func, DISPID_VALUE, 0, DISPATCH_METHOD, &dp, NULL, NULL, test_get_caller_sp); + ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres); + CHECK_CALLED(testGetCaller_no_args); + CHECK_CALLED(OnLeaveScript); + CHECK_CALLED(OnEnterScript); + IDispatchEx_Release(test_get_caller_func); + IActiveScriptParse_Release(parser); }
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..a0d693df2a1 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 = InterlockedIncrement(&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 | 502 ++++++++++++++++++++++++++++++++ dlls/vbscript/vbdisp.c | 45 ++- dlls/vbscript/vbscript.c | 11 + dlls/vbscript/vbscript.h | 2 + 5 files changed, 553 insertions(+), 8 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..28921992ca5 --- /dev/null +++ b/dlls/vbscript/tests/caller.c @@ -0,0 +1,502 @@ +/* + * Copyright 2022 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(testGetCaller_no_args); +DEFINE_EXPECT(OnEnterScript); +DEFINE_EXPECT(OnLeaveScript); + +static IServiceProvider *test_get_caller_sp; + +#define DISPID_TEST_TESTGETCALLER 0x1000 + +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; + } + + 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: + 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"); + + if(pdp->cArgs == 0) { + void *iface = (void*)0xdeadbeef; + + CHECK_EXPECT(testGetCaller_no_args); + 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); + }else { + CHECK_EXPECT(testGetCaller); + ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs); + 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; + + 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 }; + +#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 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) +{ + IActiveScript *script; + DISPPARAMS dp = { 0 }; + IDispatchEx *dispex; + IDispatch *disp; + DISPID dispid; + HRESULT hres; + BSTR bstr; + + script = create_script(); + + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + SET_EXPECT(testGetCaller); + parse_script(script, + L"Sub testGetCallerFunc\nCall testGetCaller\nEnd Sub\n" + L"Call testGetCaller(42)"); + CHECK_CALLED(testGetCaller); + CHECK_CALLED(OnLeaveScript); + CHECK_CALLED(OnEnterScript); + + hres = IActiveScript_GetScriptDispatch(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_no_args); + hres = IDispatchEx_InvokeEx(dispex, dispid, 0, DISPATCH_METHOD, &dp, NULL, NULL, NULL); + ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres); + CHECK_CALLED(testGetCaller_no_args); + CHECK_CALLED(OnLeaveScript); + CHECK_CALLED(OnEnterScript); + test_get_caller_sp = &sp_caller_obj; + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + SET_EXPECT(testGetCaller_no_args); + 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_no_args); + CHECK_CALLED(OnLeaveScript); + CHECK_CALLED(OnEnterScript); + IDispatchEx_Release(dispex); + + IActiveScript_Release(script); +} + +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 a0d693df2a1..47c4b624d31 100644 --- a/dlls/vbscript/vbscript.c +++ b/dlls/vbscript/vbscript.c @@ -366,6 +366,8 @@ static void decrease_state(VBScript *This, SCRIPTSTATE state) } }
+#define CALLER_UNINITIALIZED ((IServiceProvider*)IntToPtr(-1)) + static inline struct vbcaller *vbcaller_from_IServiceProvider(IServiceProvider *iface) { return CONTAINING_RECORD(iface, struct vbcaller, IServiceProvider_iface); @@ -415,6 +417,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 == 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 +446,7 @@ static struct vbcaller *create_vbcaller(void) if(ret) { ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl; ret->ref = 1; + ret->caller = CALLER_UNINITIALIZED; } return ret; } diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index c42b0d31391..8e4e089962c 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -184,6 +184,8 @@ struct vbcaller { IServiceProvider IServiceProvider_iface;
LONG ref; + + IServiceProvider *caller; };
struct _script_ctx_t {
Nikolay Sivov (@nsivov) commented about dlls/vbscript/vbdisp.c:
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;
Why do you need to do addref/release?
On Wed Dec 7 18:39:06 2022 +0000, Nikolay Sivov wrote:
Why do you need to do addref/release?
Well we store a ref to it so it can be returned by QueryService, so I assumed it protects against corner cases, such as it being released during this whole thing, theoretically (by app code)? And it feels more correct to me.
What should we use for scripts executed directly by `ParseScriptText`? Your patch will reuse whatever caller is on the stack, is that right?
On Fri Dec 9 15:08:34 2022 +0000, Jacek Caban wrote:
What should we use for scripts executed directly by `ParseScriptText`? Your patch will reuse whatever caller is on the stack, is that right?
Good point, from quick test it looks like it doesn't, uses the "uninitialized" part (E_NOINTERFACE). It does contribute to the stack though. I'll write proper test and fix it (haven't tested vbscript, though I suspect it's the same)