diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 0b73073a267..4ffb378d528 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -1057,7 +1057,7 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, DIS return IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, flags, dp, retv, &ei->ei, &err); } - hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, dp, retv, &ei->ei, caller); + hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, dp, retv, &ei->ei, &ctx->jscaller->IServiceProvider_iface); IDispatchEx_Release(dispex); return hres; @@ -1120,7 +1120,8 @@ HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, VARIANT *val hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); if(SUCCEEDED(hres)) { - hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, DISPATCH_PROPERTYPUT, &dp, NULL, &ei->ei, caller); + hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, DISPATCH_PROPERTYPUT, &dp, NULL, &ei->ei, + &ctx->jscaller->IServiceProvider_iface); IDispatchEx_Release(dispex); }else { ULONG err = 0; @@ -1207,7 +1208,8 @@ HRESULT disp_propget(script_ctx_t *ctx, IDispatch *disp, DISPID id, VARIANT *val return IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, INVOKE_PROPERTYGET, &dp, val, &ei->ei, &err); } - hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, INVOKE_PROPERTYGET, &dp, val, &ei->ei, caller); + hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, INVOKE_PROPERTYGET, &dp, val, &ei->ei, + &ctx->jscaller->IServiceProvider_iface); IDispatchEx_Release(dispex); return hres; diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index 750104ca46f..4453bcc9caf 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -72,6 +72,8 @@ void script_release(script_ctx_t *ctx) jsheap_free(&ctx->tmp_heap); SysFreeString(ctx->last_match); + IServiceProvider_Release(&ctx->jscaller->IServiceProvider_iface); + heap_free(ctx); } @@ -694,6 +696,7 @@ static HRESULT WINAPI JScriptParse_InitNew(IActiveScriptParse *iface) { JScript *This = impl_from_IActiveScriptParse(iface); script_ctx_t *ctx; + HRESULT hres; TRACE("(%p)\n", This); @@ -710,6 +713,12 @@ static HRESULT WINAPI JScriptParse_InitNew(IActiveScriptParse *iface) ctx->version = This->version; jsheap_init(&ctx->tmp_heap); + hres = create_jscaller(ctx); + if(FAILED(hres)) { + heap_free(ctx); + return hres; + } + ctx = InterlockedCompareExchangePointer((void**)&This->ctx, ctx, NULL); if(ctx) { script_release(ctx); diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index cbe3cf9fca4..9248f23fde8 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -279,10 +279,19 @@ typedef struct { void release_cc(cc_ctx_t*) DECLSPEC_HIDDEN; +typedef struct { + IServiceProvider IServiceProvider_iface; + + LONG ref; + + script_ctx_t *ctx; +} JSCaller; + struct _script_ctx_t { LONG ref; SCRIPTSTATE state; + exec_ctx_t *exec_ctx; named_item_t *named_items; IActiveScriptSite *site; @@ -291,6 +300,7 @@ struct _script_ctx_t { DWORD version; LCID lcid; cc_ctx_t *cc; + JSCaller *jscaller; jsheap_t tmp_heap; @@ -344,6 +354,7 @@ HRESULT create_string_constr(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN HRESULT create_vbarray_constr(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN; IUnknown *create_ax_site(script_ctx_t*) DECLSPEC_HIDDEN; +HRESULT create_jscaller(script_ctx_t*) DECLSPEC_HIDDEN; typedef struct { const WCHAR *str; diff --git a/dlls/jscript/jsutils.c b/dlls/jscript/jsutils.c index b145d8a2fdc..ba9f7801455 100644 --- a/dlls/jscript/jsutils.c +++ b/dlls/jscript/jsutils.c @@ -656,3 +656,84 @@ HRESULT to_object(script_ctx_t *ctx, VARIANT *v, IDispatch **disp) return S_OK; } + +static inline JSCaller *impl_from_IServiceProvider(IServiceProvider *iface) +{ + return CONTAINING_RECORD(iface, JSCaller, IServiceProvider_iface); +} + +static HRESULT WINAPI JSCaller_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) +{ + JSCaller *This = impl_from_IServiceProvider(iface); + + if(IsEqualGUID(&IID_IUnknown, riid)) { + TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); + *ppv = &This->IServiceProvider_iface; + }else if(IsEqualGUID(&IID_IServiceProvider, riid)) { + TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv); + *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 JSCaller_AddRef(IServiceProvider *iface) +{ + JSCaller *This = impl_from_IServiceProvider(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + return ref; +} + +static ULONG WINAPI JSCaller_Release(IServiceProvider *iface) +{ + JSCaller *This = impl_from_IServiceProvider(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + if(!ref) + heap_free(This); + + return ref; +} + +static HRESULT WINAPI JSCaller_QueryService(IServiceProvider *iface, REFGUID guidService, + REFIID riid, void **ppv) +{ + JSCaller *This = impl_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 = { + JSCaller_QueryInterface, + JSCaller_AddRef, + JSCaller_Release, + JSCaller_QueryService +}; + +HRESULT create_jscaller(script_ctx_t *ctx) +{ + JSCaller *ret; + + ret = heap_alloc(sizeof(*ret)); + if(!ret) + return E_OUTOFMEMORY; + + ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl; + ret->ref = 1; + + ctx->jscaller = ret; + return S_OK; +} diff --git a/dlls/jscript/tests/run.c b/dlls/jscript/tests/run.c index f83cedd30f9..64a8c7e5308 100644 --- a/dlls/jscript/tests/run.c +++ b/dlls/jscript/tests/run.c @@ -286,6 +286,8 @@ static HRESULT WINAPI testObj_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD static HRESULT WINAPI testObj_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { + ok(pspCaller != NULL, "pspCaller = NULL\n"); + switch(id) { case DISPID_VALUE: ok(pdp != NULL, "pdp == NULL\n"); @@ -498,6 +500,8 @@ static HRESULT WINAPI Global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { + ok(pspCaller != NULL, "pspCaller = NULL\n"); + switch(id) { case DISPID_GLOBAL_OK: ok(wFlags == INVOKE_FUNC || wFlags == (INVOKE_FUNC|INVOKE_PROPERTYGET), "wFlags = %x\n", wFlags);