Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
I don't know what Windows supplies this object for (I tried all the SIDs in Wine's headers and none pass except SID_GetCaller), but this does "match" Windows behavior. More importantly, should an app request some service, we can now see it in the FIXME and implement it accordingly.
dlls/msscript.ocx/msscript.c | 86 +++++++++++++++++++++++++++++- dlls/msscript.ocx/tests/msscript.c | 30 +++++++++++ 2 files changed, 114 insertions(+), 2 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index ed17be9..7031cd1 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -434,6 +434,76 @@ static HRESULT parse_script_text(ScriptModule *module, BSTR script_text, DWORD f return hr; }
+struct sp_caller +{ + IServiceProvider IServiceProvider_iface; + LONG ref; +}; + +static inline struct sp_caller *sp_caller_from_IServiceProvider(IServiceProvider *iface) +{ + return CONTAINING_RECORD(iface, struct sp_caller, IServiceProvider_iface); +} + +static HRESULT WINAPI sp_caller_QueryInterface(IServiceProvider *iface, REFIID riid, void **obj) +{ + struct sp_caller *This = sp_caller_from_IServiceProvider(iface); + + if (IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IServiceProvider, riid)) + *obj = &This->IServiceProvider_iface; + else + { + *obj = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*obj); + return S_OK; +} + +static ULONG WINAPI sp_caller_AddRef(IServiceProvider *iface) +{ + struct sp_caller *This = sp_caller_from_IServiceProvider(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + return ref; +} + +static ULONG WINAPI sp_caller_Release(IServiceProvider *iface) +{ + struct sp_caller *This = sp_caller_from_IServiceProvider(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + if (!ref) + heap_free(This); + + return ref; +} + +static HRESULT WINAPI sp_caller_QueryService(IServiceProvider *iface, REFGUID service, REFIID riid, void **obj) +{ + struct sp_caller *This = sp_caller_from_IServiceProvider(iface); + + FIXME("(%p)->(%s %s %p)\n", This, debugstr_guid(service), debugstr_guid(riid), obj); + + *obj = NULL; + if (IsEqualGUID(&SID_GetCaller, service)) + return S_OK; + + return E_NOINTERFACE; +} + +static const IServiceProviderVtbl sp_caller_vtbl = { + sp_caller_QueryInterface, + sp_caller_AddRef, + sp_caller_Release, + sp_caller_QueryService +}; + static HRESULT run_procedure(ScriptModule *module, BSTR procedure_name, SAFEARRAY *args, VARIANT *res) { IDispatchEx *dispex; @@ -474,8 +544,20 @@ static HRESULT run_procedure(ScriptModule *module, BSTR procedure_name, SAFEARRA } else { - hr = IDispatchEx_InvokeEx(dispex, dispid, LOCALE_USER_DEFAULT, - DISPATCH_METHOD, &dp, res, NULL, NULL); + struct sp_caller *sp_caller = heap_alloc(sizeof(*sp_caller)); + + if (sp_caller) + { + sp_caller->IServiceProvider_iface.lpVtbl = &sp_caller_vtbl; + sp_caller->ref = 1; + hr = IDispatchEx_InvokeEx(dispex, dispid, LOCALE_USER_DEFAULT, + DISPATCH_METHOD, &dp, res, NULL, + &sp_caller->IServiceProvider_iface); + IServiceProvider_Release(&sp_caller->IServiceProvider_iface); + } + else + hr = E_OUTOFMEMORY; + IDispatchEx_Release(dispex); } } diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index a6ec099..4f43764 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -673,6 +673,10 @@ static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DW static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { + IServiceProvider *sp; + IUnknown *unk; + HRESULT hr; + CHECK_EXPECT(InvokeEx); ok(lcid == LOCALE_USER_DEFAULT, "unexpected lcid %u.\n", lcid); ok(wFlags == DISPATCH_METHOD, "unexpected wFlags %u.\n", wFlags); @@ -690,6 +694,32 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc "unexpected second parameter V_VT = %d, V_I4 = %d.\n", V_VT(pdp->rgvarg), V_I4(pdp->rgvarg)); } + ok(!!pspCaller, "unexpected NULL pspCaller.\n"); + + hr = IActiveScriptSite_QueryInterface(site, &IID_IServiceProvider, (void**)&sp); + ok(hr == S_OK, "Failed to retrieve IID_IServiceProvider from script site: 0x%08x.\n", hr); + ok(sp != pspCaller, "Same IServiceProvider objects.\n"); + IServiceProvider_Release(sp); + + hr = IServiceProvider_QueryInterface(pspCaller, &IID_IActiveScriptSite, (void**)&unk); + ok(hr == E_NOINTERFACE, "QueryInterface IActiveScriptSite returned: 0x%08x.\n", hr); + + unk = (IUnknown*)0xdeadbeef; + hr = IServiceProvider_QueryService(pspCaller, &SID_GetCaller, NULL, (void**)&unk); + ok(hr == S_OK, "QueryService failed: 0x%08x.\n", hr); + ok(!unk, "unexpected object returned %p.\n", unk); + unk = (IUnknown*)0xdeadbeef; + hr = IServiceProvider_QueryService(pspCaller, &SID_GetCaller, &IID_IUnknown, (void**)&unk); + ok(hr == S_OK, "QueryService failed: 0x%08x.\n", hr); + ok(!unk, "unexpected object returned %p.\n", unk); + sp = (IServiceProvider*)0xdeadbeef; + hr = IServiceProvider_QueryService(pspCaller, &SID_GetCaller, &IID_IServiceProvider, (void**)&sp); + ok(hr == S_OK, "QueryService failed: 0x%08x.\n", hr); + ok(!sp, "unexpected object returned %p.\n", sp); + unk = (IUnknown*)0xdeadbeef; + hr = IServiceProvider_QueryService(pspCaller, &SID_VariantConversion, &IID_IVariantChangeType, (void**)&unk); + ok(hr == E_NOINTERFACE, "QueryService returned: 0x%08x.\n", hr); + ok(!unk, "unexpected object returned %p.\n", unk);
V_VT(pvarRes) = VT_I2; V_I2(pvarRes) = 42;