From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/vbscript/tests/Makefile.in | 1 + dlls/vbscript/tests/caller.c | 551 ++++++++++++++++++++++++++++++++ dlls/vbscript/vbdisp.c | 45 ++- dlls/vbscript/vbscript.c | 17 +- dlls/vbscript/vbscript.h | 4 + 5 files changed, 609 insertions(+), 9 deletions(-) create mode 100644 dlls/vbscript/tests/caller.c
diff --git a/dlls/vbscript/tests/Makefile.in b/dlls/vbscript/tests/Makefile.in index 35379baf198..927280bef22 100644 --- a/dlls/vbscript/tests/Makefile.in +++ b/dlls/vbscript/tests/Makefile.in @@ -2,6 +2,7 @@ TESTDLL = vbscript.dll IMPORTS = oleaut32 ole32 advapi32
C_SRCS = \ + caller.c \ createobj.c \ run.c \ vbscript.c diff --git a/dlls/vbscript/tests/caller.c b/dlls/vbscript/tests/caller.c new file mode 100644 index 00000000000..19eccfe715d --- /dev/null +++ b/dlls/vbscript/tests/caller.c @@ -0,0 +1,551 @@ +/* + * Copyright 2023 Gabriel Ivăncescu for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdio.h> + +#define COBJMACROS +#define CONST_VTABLE + +#include <ole2.h> +#include <dispex.h> +#include <activscp.h> +#include <objsafe.h> + +#include "wine/test.h" + +#ifdef _WIN64 + +#define IActiveScriptParse_QueryInterface IActiveScriptParse64_QueryInterface +#define IActiveScriptParse_Release IActiveScriptParse64_Release +#define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew +#define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText + +#else + +#define IActiveScriptParse_QueryInterface IActiveScriptParse32_QueryInterface +#define IActiveScriptParse_Release IActiveScriptParse32_Release +#define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew +#define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText + +#endif + +extern const CLSID CLSID_VBScript; + +#define DEFINE_EXPECT(func) \ + static BOOL expect_ ## func = FALSE, called_ ## func = FALSE + +#define SET_EXPECT(func) \ + expect_ ## func = TRUE + +#define CHECK_EXPECT2(func) \ + do { \ + ok(expect_ ##func, "unexpected call " #func "\n"); \ + called_ ## func = TRUE; \ + }while(0) + +#define CHECK_EXPECT(func) \ + do { \ + CHECK_EXPECT2(func); \ + expect_ ## func = FALSE; \ + }while(0) + +#define CHECK_CALLED(func) \ + do { \ + ok(called_ ## func, "expected " #func "\n"); \ + expect_ ## func = called_ ## func = FALSE; \ + }while(0) + +#define CLEAR_CALLED(func) \ + expect_ ## func = called_ ## func = FALSE + +DEFINE_EXPECT(sp_caller_QI_NULL); +DEFINE_EXPECT(testGetCaller); +DEFINE_EXPECT(testGetCallerVBS); +DEFINE_EXPECT(testGetCallerNested); +DEFINE_EXPECT(OnEnterScript); +DEFINE_EXPECT(OnLeaveScript); + +static IActiveScript *active_script; +static IServiceProvider *test_get_caller_sp; + +#define DISPID_TEST_TESTGETCALLER 0x1000 +#define DISPID_TEST_TESTGETCALLERVBS 0x1001 +#define DISPID_TEST_TESTGETCALLERNESTED 0x1002 + +#define parse_script(a,s) _parse_script(__LINE__,a,s) +static void _parse_script(unsigned line, IActiveScript *active_script, const WCHAR *script) +{ + IActiveScriptParse *parser; + HRESULT hres; + + hres = IActiveScript_QueryInterface(active_script, &IID_IActiveScriptParse, (void**)&parser); + ok_(__FILE__,line)(hres == S_OK, "Could not get IActiveScriptParse: %08lx\n", hres); + + hres = IActiveScriptParse_ParseScriptText(parser, script, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + ok_(__FILE__,line)(hres == S_OK, "ParseScriptText failed: %08lx\n", hres); + IActiveScriptParse_Release(parser); +} + +static IServiceProvider sp_caller_obj; + +static HRESULT WINAPI sp_caller_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IServiceProvider, riid)) + *ppv = &sp_caller_obj; + else { + ok(IsEqualGUID(&IID_NULL, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + CHECK_EXPECT(sp_caller_QI_NULL); + *ppv = NULL; + return E_NOINTERFACE; + } + + return S_OK; +} + +static ULONG WINAPI sp_caller_AddRef(IServiceProvider *iface) +{ + return 2; +} + +static ULONG WINAPI sp_caller_Release(IServiceProvider *iface) +{ + return 1; +} + +static HRESULT WINAPI sp_caller_QueryService(IServiceProvider *iface, REFGUID guidService, + REFIID riid, void **ppv) +{ + if(IsEqualGUID(guidService, &SID_GetCaller)) { + ok(IsEqualGUID(riid, &IID_IServiceProvider), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = NULL; + return S_OK; + } + + ok(0, "unexpected guidService %s with riid %s\n", wine_dbgstr_guid(guidService), wine_dbgstr_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; +} + +static const IServiceProviderVtbl sp_caller_vtbl = { + sp_caller_QueryInterface, + sp_caller_AddRef, + sp_caller_Release, + sp_caller_QueryService +}; + +static IServiceProvider sp_caller_obj = { &sp_caller_vtbl }; + +static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(riid, &IID_IUnknown)) { + *ppv = iface; + }else if(IsEqualGUID(riid, &IID_IDispatch) || IsEqualGUID(riid, &IID_IDispatchEx)) { + *ppv = iface; + }else if(IsEqualGUID(&IID_IObjectSafety, riid)) { + ok(0, "Unexpected IID_IObjectSafety query\n"); + }else { + *ppv = NULL; + return E_NOINTERFACE; + } + + return S_OK; +} + +static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface) +{ + return 2; +} + +static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface) +{ + return 1; +} + +static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid, LPOLESTR *rgszNames, + UINT cNames, LCID lcid, DISPID *rgDispId) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember, REFIID riid, LCID lcid, + WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Test_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) +{ + if(!lstrcmpW(bstrName, L"testGetCaller")) { + ok(grfdex == fdexNameCaseInsensitive, "grfdex = %lx\n", grfdex); + *pid = DISPID_TEST_TESTGETCALLER; + return S_OK; + } + if(!lstrcmpW(bstrName, L"testGetCallerVBS")) { + ok(grfdex == fdexNameCaseInsensitive, "grfdex = %lx\n", grfdex); + *pid = DISPID_TEST_TESTGETCALLERVBS; + return S_OK; + } + if(!lstrcmpW(bstrName, L"testGetCallerNested")) { + ok(grfdex == fdexNameCaseInsensitive, "grfdex = %lx\n", grfdex); + *pid = DISPID_TEST_TESTGETCALLERNESTED; + return S_OK; + } + + return E_NOTIMPL; +} + +static HRESULT WINAPI Test_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + IServiceProvider *caller = (void*)0xdeadbeef; + HRESULT hres; + + ok(pspCaller != NULL, "pspCaller == NULL\n"); + + switch(id) { + case DISPID_TEST_TESTGETCALLER: { + void *iface = (void*)0xdeadbeef; + + CHECK_EXPECT(testGetCaller); + CHECK_CALLED(OnEnterScript); + + ok(wFlags == DISPATCH_METHOD, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pvarRes, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + SET_EXPECT(testGetCallerNested); + parse_script(active_script, L"Call testGetCallerNested(1,2)"); + CHECK_CALLED(testGetCallerNested); + CHECK_CALLED(OnLeaveScript); + CHECK_CALLED(OnEnterScript); + SET_EXPECT(OnLeaveScript); + + hres = IServiceProvider_QueryService(pspCaller, &SID_GetCaller, &IID_IServiceProvider, (void**)&caller); + ok(hres == S_OK, "Could not get SID_GetCaller service: %08lx\n", hres); + ok(caller == test_get_caller_sp, "caller != test_get_caller_sp\n"); + if(caller) IServiceProvider_Release(caller); + + if(test_get_caller_sp) + SET_EXPECT(sp_caller_QI_NULL); + hres = IServiceProvider_QueryService(pspCaller, &SID_GetCaller, &IID_NULL, &iface); + ok(hres == (test_get_caller_sp ? E_NOINTERFACE : S_OK), "Could not query SID_GetCaller with IID_NULL: %08lx\n", hres); + ok(iface == NULL, "iface != NULL\n"); + if(test_get_caller_sp) + CHECK_CALLED(sp_caller_QI_NULL); + break; + } + + case DISPID_TEST_TESTGETCALLERVBS: + CHECK_EXPECT(testGetCallerVBS); + + ok(wFlags == DISPATCH_METHOD, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pvarRes, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + ok(V_VT(pdp->rgvarg) == VT_I2, "V_VT(rgvarg) = %d\n", V_VT(pdp->rgvarg)); + ok(V_I2(pdp->rgvarg) == 42, "V_I2(rgvarg) = %d\n", V_I2(pdp->rgvarg)); + + hres = IServiceProvider_QueryService(pspCaller, &SID_GetCaller, &IID_IServiceProvider, (void**)&caller); + ok(hres == E_NOINTERFACE, "QueryService(SID_GetCaller) returned: %08lx\n", hres); + ok(caller == NULL, "caller != NULL\n"); + break; + + case DISPID_TEST_TESTGETCALLERNESTED: + CHECK_EXPECT(testGetCallerNested); + + ok(wFlags == DISPATCH_METHOD, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->cArgs == 2, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pvarRes, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + ok(V_VT(&pdp->rgvarg[0]) == VT_I2, "V_VT(rgvarg[0]) = %d\n", V_VT(&pdp->rgvarg[0])); + ok(V_VT(&pdp->rgvarg[1]) == VT_I2, "V_VT(rgvarg[1]) = %d\n", V_VT(&pdp->rgvarg[1])); + ok(V_I2(&pdp->rgvarg[0]) == 2, "V_I2(rgvarg[0]) = %d\n", V_I2(&pdp->rgvarg[0])); + ok(V_I2(&pdp->rgvarg[1]) == 1, "V_I2(rgvarg[1]) = %d\n", V_I2(&pdp->rgvarg[1])); + + hres = IServiceProvider_QueryService(pspCaller, &SID_GetCaller, &IID_IServiceProvider, (void**)&caller); + ok(hres == E_NOINTERFACE, "QueryService(SID_GetCaller) returned: %08lx\n", hres); + ok(caller == NULL, "caller != NULL\n"); + break; + + default: + ok(0, "unexpected call\n"); + return E_NOTIMPL; + } + + return S_OK; +} + +static IDispatchExVtbl testObjVtbl = { + DispatchEx_QueryInterface, + DispatchEx_AddRef, + DispatchEx_Release, + DispatchEx_GetTypeInfoCount, + DispatchEx_GetTypeInfo, + DispatchEx_GetIDsOfNames, + DispatchEx_Invoke, + Test_GetDispID, + Test_InvokeEx, + DispatchEx_DeleteMemberByName, + DispatchEx_DeleteMemberByDispID, + DispatchEx_GetMemberProperties, + DispatchEx_GetMemberName, + DispatchEx_GetNextDispID, + DispatchEx_GetNameSpaceParent +}; + +static IDispatchEx testObj = { &testObjVtbl }; + +static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(&IID_IUnknown, riid)) { + *ppv = iface; + }else if(IsEqualGUID(&IID_IActiveScriptSite, riid)) { + *ppv = iface; + }else { + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI ActiveScriptSite_AddRef(IActiveScriptSite *iface) +{ + return 2; +} + +static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface) +{ + return 1; +} + +static HRESULT WINAPI ActiveScriptSite_GetLCID(IActiveScriptSite *iface, LCID *plcid) +{ + *plcid = GetUserDefaultLCID(); + return S_OK; +} + +static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface, LPCOLESTR pstrName, + DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti) +{ + ok(dwReturnMask == SCRIPTINFO_IUNKNOWN, "unexpected dwReturnMask %lx\n", dwReturnMask); + ok(!ppti, "ppti != NULL\n"); + ok(!lstrcmpW(pstrName, L"test"), "pstrName = %s\n", wine_dbgstr_w(pstrName)); + + *ppiunkItem = (IUnknown*)&testObj; + return S_OK; +} + +static HRESULT WINAPI ActiveScriptSite_GetDocVersionString(IActiveScriptSite *iface, BSTR *pbstrVersion) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnScriptTerminate(IActiveScriptSite *iface, + const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, SCRIPTSTATE ssScriptState) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, IActiveScriptError *pscripterror) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnEnterScript(IActiveScriptSite *iface) +{ + CHECK_EXPECT(OnEnterScript); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnLeaveScript(IActiveScriptSite *iface) +{ + CHECK_EXPECT(OnLeaveScript); + return E_NOTIMPL; +} + +static const IActiveScriptSiteVtbl ActiveScriptSiteVtbl = { + ActiveScriptSite_QueryInterface, + ActiveScriptSite_AddRef, + ActiveScriptSite_Release, + ActiveScriptSite_GetLCID, + ActiveScriptSite_GetItemInfo, + ActiveScriptSite_GetDocVersionString, + ActiveScriptSite_OnScriptTerminate, + ActiveScriptSite_OnStateChange, + ActiveScriptSite_OnScriptError, + ActiveScriptSite_OnEnterScript, + ActiveScriptSite_OnLeaveScript +}; + +static IActiveScriptSite ActiveScriptSite = { &ActiveScriptSiteVtbl }; + +static IActiveScript *create_script(void) +{ + IActiveScriptParse *parser; + IActiveScript *script; + HRESULT hres; + + hres = CoCreateInstance(&CLSID_VBScript, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, + &IID_IActiveScript, (void**)&script); + if(FAILED(hres)) + return NULL; + + hres = IActiveScript_QueryInterface(script, &IID_IActiveScriptParse, (void**)&parser); + ok(hres == S_OK, "Could not get IActiveScriptParse: %08lx\n", hres); + + hres = IActiveScriptParse_InitNew(parser); + ok(hres == S_OK, "InitNew failed: %08lx\n", hres); + IActiveScriptParse_Release(parser); + + hres = IActiveScript_SetScriptSite(script, &ActiveScriptSite); + ok(hres == S_OK, "SetScriptSite failed: %08lx\n", hres); + + hres = IActiveScript_AddNamedItem(script, L"test", + SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|SCRIPTITEM_GLOBALMEMBERS); + ok(hres == S_OK, "AddNamedItem failed: %08lx\n", hres); + + hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_STARTED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08lx\n", hres); + + return script; +} + +static void run_scripts(void) +{ + DISPPARAMS dp = { 0 }; + IDispatchEx *dispex; + IDispatch *disp; + DISPID dispid; + HRESULT hres; + BSTR bstr; + + active_script = create_script(); + + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + SET_EXPECT(testGetCallerVBS); + parse_script(active_script, + L"Sub testGetCallerFunc\nCall testGetCaller\nEnd Sub\n" + L"Call testGetCallerVBS(42)"); + CHECK_CALLED(testGetCallerVBS); + CHECK_CALLED(OnLeaveScript); + CHECK_CALLED(OnEnterScript); + + hres = IActiveScript_GetScriptDispatch(active_script, NULL, &disp); + ok(hres == S_OK, "GetScriptDispatch failed: %08lx\n", hres); + hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "Could not get IDispatchEx: %08lx\n", hres); + IDispatch_Release(disp); + bstr = SysAllocString(L"testGetCallerFunc"); + hres = IDispatchEx_GetDispID(dispex, bstr, 0, &dispid); + ok(hres == S_OK, "GetDispID failed: %08lx\n", hres); + SysFreeString(bstr); + + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + SET_EXPECT(testGetCaller); + hres = IDispatchEx_InvokeEx(dispex, dispid, 0, DISPATCH_METHOD, &dp, NULL, NULL, NULL); + ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres); + CHECK_CALLED(testGetCaller); + CHECK_CALLED(OnLeaveScript); + test_get_caller_sp = &sp_caller_obj; + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + SET_EXPECT(testGetCaller); + hres = IDispatchEx_InvokeEx(dispex, dispid, 0, DISPATCH_METHOD, &dp, NULL, NULL, test_get_caller_sp); + ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres); + CHECK_CALLED(testGetCaller); + CHECK_CALLED(OnLeaveScript); + IDispatchEx_Release(dispex); + + IActiveScript_Release(active_script); + active_script = NULL; +} + +START_TEST(caller) +{ + CoInitialize(NULL); + + run_scripts(); + + CoUninitialize(); +} diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index 13236ad4b29..0ede0cfd6ba 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -413,6 +413,8 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { vbdisp_t *This = impl_from_IDispatchEx(iface); + IServiceProvider *prev_caller; + HRESULT hres;
TRACE("(%p)->(%lx %lx %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
@@ -422,7 +424,17 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc if(pvarRes) V_VT(pvarRes) = VT_EMPTY;
- return invoke_vbdisp(This, id, wFlags, TRUE, pdp, pvarRes); + prev_caller = This->desc->ctx->vbcaller->caller; + This->desc->ctx->vbcaller->caller = pspCaller; + if(pspCaller) + IServiceProvider_AddRef(pspCaller); + + hres = invoke_vbdisp(This, id, wFlags, TRUE, pdp, pvarRes); + + This->desc->ctx->vbcaller->caller = prev_caller; + if(pspCaller) + IServiceProvider_Release(pspCaller); + return hres; }
static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) @@ -1414,6 +1426,7 @@ static HRESULT WINAPI ScriptDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { ScriptDisp *This = ScriptDisp_from_IDispatchEx(iface); + IServiceProvider *prev_caller; HRESULT hres;
TRACE("(%p)->(%lx %lx %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); @@ -1421,11 +1434,18 @@ static HRESULT WINAPI ScriptDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc if (!This->ctx) return E_UNEXPECTED;
+ prev_caller = This->ctx->vbcaller->caller; + This->ctx->vbcaller->caller = pspCaller; + if(pspCaller) + IServiceProvider_AddRef(pspCaller); + if (id & DISPID_FUNCTION_MASK) { id &= ~DISPID_FUNCTION_MASK; - if (id > This->global_funcs_cnt) - return DISP_E_MEMBERNOTFOUND; + if (id > This->global_funcs_cnt) { + hres = DISP_E_MEMBERNOTFOUND; + goto done; + }
switch (wFlags) { @@ -1438,19 +1458,28 @@ static HRESULT WINAPI ScriptDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc hres = E_NOTIMPL; }
- return hres; + goto done; }
- if (id > This->global_vars_cnt) - return DISP_E_MEMBERNOTFOUND; + if (id > This->global_vars_cnt) { + hres = DISP_E_MEMBERNOTFOUND; + goto done; + }
if (This->global_vars[id - 1]->is_const) { FIXME("const not supported\n"); - return E_NOTIMPL; + hres = E_NOTIMPL; + goto done; }
- return invoke_variant_prop(This->ctx, &This->global_vars[id - 1]->v, wFlags, pdp, pvarRes); + hres = invoke_variant_prop(This->ctx, &This->global_vars[id - 1]->v, wFlags, pdp, pvarRes); + +done: + This->ctx->vbcaller->caller = prev_caller; + if(pspCaller) + IServiceProvider_Release(pspCaller); + return hres; }
static HRESULT WINAPI ScriptDisp_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) diff --git a/dlls/vbscript/vbscript.c b/dlls/vbscript/vbscript.c index d010ba4b51d..39a5e3b1648 100644 --- a/dlls/vbscript/vbscript.c +++ b/dlls/vbscript/vbscript.c @@ -96,6 +96,7 @@ static HRESULT exec_global_code(script_ctx_t *ctx, vbscode_t *code, VARIANT *res ScriptDisp *obj = ctx->script_obj; function_t *func_iter, **new_funcs; dynamic_var_t *var, **new_vars; + IServiceProvider *prev_caller; size_t cnt, i; HRESULT hres;
@@ -185,7 +186,12 @@ static HRESULT exec_global_code(script_ctx_t *ctx, vbscode_t *code, VARIANT *res }
code->pending_exec = FALSE; - return exec_script(ctx, TRUE, &code->main_code, NULL, NULL, res); + + prev_caller = ctx->vbcaller->caller; + ctx->vbcaller->caller = SP_CALLER_UNINITIALIZED; + hres = exec_script(ctx, TRUE, &code->main_code, NULL, NULL, res); + ctx->vbcaller->caller = prev_caller; + return hres; }
static void exec_queued_code(script_ctx_t *ctx) @@ -415,6 +421,14 @@ static HRESULT WINAPI vbcaller_QueryService(IServiceProvider *iface, REFGUID gui { struct vbcaller *This = vbcaller_from_IServiceProvider(iface);
+ if(IsEqualGUID(guidService, &SID_GetCaller)) { + TRACE("(%p)->(SID_GetCaller)\n", This); + *ppv = NULL; + if(!This->caller) + return S_OK; + return (This->caller == SP_CALLER_UNINITIALIZED) ? E_NOINTERFACE : IServiceProvider_QueryInterface(This->caller, riid, ppv); + } + FIXME("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
*ppv = NULL; @@ -436,6 +450,7 @@ static struct vbcaller *create_vbcaller(void) if(ret) { ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl; ret->ref = 1; + ret->caller = SP_CALLER_UNINITIALIZED; } return ret; } diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index c42b0d31391..5b0a2222767 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -180,10 +180,14 @@ static inline VARIANT *get_arg(DISPPARAMS *dp, DWORD i) return dp->rgvarg + dp->cArgs-i-1; }
+#define SP_CALLER_UNINITIALIZED ((IServiceProvider*)IntToPtr(-1)) + struct vbcaller { IServiceProvider IServiceProvider_iface;
LONG ref; + + IServiceProvider *caller; };
struct _script_ctx_t {