[PATCH] msscript.ocx: Supply a stub ServiceProvider to InvokeEx in run_procedure.
Gabriel Ivăncescu
gabrielopcode at gmail.com
Tue Sep 8 10:00:18 CDT 2020
Signed-off-by: Gabriel Ivăncescu <gabrielopcode at 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;
--
2.21.0
More information about the wine-devel
mailing list