-- v2: 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: 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 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.c | 17 +++- dlls/jscript/jscript.h | 3 + dlls/jscript/jsutils.c | 9 ++ dlls/jscript/tests/caller.c | 158 ++++++++++++++++++++++++++++++++++-- 5 files changed, 187 insertions(+), 9 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 04632f4c755..c35d8c78f02 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; @@ -1998,6 +2004,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 8c1eedf4283..c8d6b09102e 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..a70ab5bae1e 100644 --- a/dlls/jscript/tests/caller.c +++ b/dlls/jscript/tests/caller.c @@ -74,14 +74,22 @@ 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(testGetCaller_two_args); DEFINE_EXPECT(OnEnterScript); DEFINE_EXPECT(OnLeaveScript);
+static IActiveScriptParse *active_script_parser; 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 +262,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 +407,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 +419,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 +445,66 @@ 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); + CHECK_CALLED(OnEnterScript); + + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + SET_EXPECT(testGetCaller_two_args); + hres = IActiveScriptParse_ParseScriptText(active_script_parser, L"testGetCaller(1,2)", + NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + ok(hres == S_OK, "ParseScriptText failed: %08lx\n", hres); + CHECK_CALLED(testGetCaller_two_args); + 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); + }else if(pdp->cArgs == 1) { + CHECK_EXPECT(testGetCaller); + 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); + }else { + CHECK_EXPECT(testGetCaller_two_args); + ok(pdp->cArgs == 2, "cArgs = %d\n", pdp->cArgs); + 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 +667,25 @@ static IActiveScriptParse *create_script(void)
static void run_scripts(void) { - IActiveScriptParse *parser; + DISPPARAMS dp = { 0 }; HRESULT hres;
- 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(testGetCaller); + 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"testGetCaller(function() { testGetCaller(); });"); + CHECK_CALLED(testGetCaller); CHECK_CALLED(testArgConv); CHECK_CALLED(OnLeaveScript); /* set in callback */
@@ -565,7 +693,25 @@ static void run_scripts(void) IDispatch_Release(stored_obj); IVariantChangeType_Release(script_change_type);
- IActiveScriptParse_Release(parser); + 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); + 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); + IDispatchEx_Release(test_get_caller_func); + + 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..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 | 524 ++++++++++++++++++++++++++++++++ dlls/vbscript/vbdisp.c | 45 ++- dlls/vbscript/vbscript.c | 17 +- dlls/vbscript/vbscript.h | 4 + 5 files changed, 582 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..5dab73436e5 --- /dev/null +++ b/dlls/vbscript/tests/caller.c @@ -0,0 +1,524 @@ +/* + * 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(testGetCaller_two_args); +DEFINE_EXPECT(OnEnterScript); +DEFINE_EXPECT(OnLeaveScript); + +static IActiveScript *active_script; +static IServiceProvider *test_get_caller_sp; + +#define DISPID_TEST_TESTGETCALLER 0x1000 + +#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; + } + + 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); + CHECK_CALLED(OnEnterScript); + + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + SET_EXPECT(testGetCaller_two_args); + parse_script(active_script, L"Call testGetCaller(1,2)"); + CHECK_CALLED(testGetCaller_two_args); + 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); + }else if(pdp->cArgs == 1) { + 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"); + }else { + CHECK_EXPECT(testGetCaller_two_args); + ok(pdp->cArgs == 2, "cArgs = %d\n", pdp->cArgs); + 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(testGetCaller); + parse_script(active_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(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_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); + 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); + 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 a0d693df2a1..5c1c28ab696 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 {