[PATCH] msscript: Initial support for hosting script engines
Nikolay Sivov
nsivov at codeweavers.com
Thu Jul 14 09:35:27 CDT 2016
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/msscript.ocx/msscript.c | 286 ++++++++++++++++++++++++++++++++++++-
dlls/msscript.ocx/tests/msscript.c | 15 +-
2 files changed, 289 insertions(+), 12 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c
index bc3f5c1..3abd929 100644
--- a/dlls/msscript.ocx/msscript.c
+++ b/dlls/msscript.ocx/msscript.c
@@ -22,6 +22,8 @@
#include "initguid.h"
#include "ole2.h"
#include "olectl.h"
+#include "objsafe.h"
+#include "activscp.h"
#include "rpcproxy.h"
#include "msscript.h"
@@ -29,6 +31,20 @@
WINE_DEFAULT_DEBUG_CHANNEL(msscript);
+#ifdef _WIN64
+
+#define IActiveScriptParse_Release IActiveScriptParse64_Release
+#define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew
+#define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText
+
+#else
+
+#define IActiveScriptParse_Release IActiveScriptParse32_Release
+#define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew
+#define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText
+
+#endif
+
struct ScriptControl;
typedef struct ConnectionPoint ConnectionPoint;
@@ -39,6 +55,15 @@ struct ConnectionPoint {
ConnectionPoint *next;
};
+typedef struct ScriptHost {
+ IActiveScriptSite IActiveScriptSite_iface;
+ LONG ref;
+
+ IActiveScript *script;
+ IActiveScriptParse *parse;
+ CLSID clsid;
+} ScriptHost;
+
struct ScriptControl {
IScriptControl IScriptControl_iface;
IPersistStreamInit IPersistStreamInit_iface;
@@ -56,6 +81,8 @@ struct ScriptControl {
ConnectionPoint *cp_list;
ConnectionPoint cp_scsource;
ConnectionPoint cp_propnotif;
+
+ ScriptHost *host;
};
static HINSTANCE msscript_instance;
@@ -184,6 +211,220 @@ static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *ifac
return CONTAINING_RECORD(iface, ConnectionPoint, IConnectionPoint_iface);
}
+static inline ScriptHost *impl_from_IActiveScriptSite(IActiveScriptSite *iface)
+{
+ return CONTAINING_RECORD(iface, ScriptHost, IActiveScriptSite_iface);
+}
+
+/* IActiveScriptSite */
+static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, REFIID riid, void **ppv)
+{
+ ScriptHost *This = impl_from_IActiveScriptSite(iface);
+
+ if(IsEqualGUID(&IID_IUnknown, riid)) {
+ TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
+ *ppv = &This->IActiveScriptSite_iface;
+ }else if(IsEqualGUID(&IID_IActiveScriptSite, riid)) {
+ TRACE("(%p)->(IID_IActiveScriptSite %p)\n", This, ppv);
+ *ppv = &This->IActiveScriptSite_iface;
+ }else {
+ FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI ActiveScriptSite_AddRef(IActiveScriptSite *iface)
+{
+ ScriptHost *This = impl_from_IActiveScriptSite(iface);
+ LONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) ref=%d\n", This, ref);
+
+ return ref;
+}
+
+static void release_script_engine(ScriptHost *host)
+{
+ if (host->script) {
+ IActiveScript_Close(host->script);
+ IActiveScript_Release(host->script);
+ }
+
+ if (host->parse)
+ IActiveScriptParse_Release(host->parse);
+
+ host->parse = NULL;
+ host->script = NULL;
+}
+
+static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface)
+{
+ ScriptHost *This = impl_from_IActiveScriptSite(iface);
+ LONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) ref=%d\n", This, ref);
+
+ if(!ref)
+ heap_free(This);
+
+ return ref;
+}
+
+static HRESULT WINAPI ActiveScriptSite_GetLCID(IActiveScriptSite *iface, LCID *lcid)
+{
+ ScriptHost *This = impl_from_IActiveScriptSite(iface);
+
+ TRACE("(%p, %p)\n", This, lcid);
+
+ *lcid = GetUserDefaultLCID();
+ return S_OK;
+}
+
+static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface, LPCOLESTR name, DWORD returnmask,
+ IUnknown **item, ITypeInfo **ti)
+{
+ ScriptHost *This = impl_from_IActiveScriptSite(iface);
+
+ FIXME("(%p, %s, %#x, %p, %p)\n", This, debugstr_w(name), returnmask, item, ti);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ActiveScriptSite_GetDocVersionString(IActiveScriptSite *iface, BSTR *version)
+{
+ ScriptHost *This = impl_from_IActiveScriptSite(iface);
+
+ FIXME("(%p, %p)\n", This, version);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ActiveScriptSite_OnScriptTerminate(IActiveScriptSite *iface, const VARIANT *result,
+ const EXCEPINFO *ei)
+{
+ ScriptHost *This = impl_from_IActiveScriptSite(iface);
+
+ FIXME("(%p, %s, %p)\n", This, debugstr_variant(result), ei);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, SCRIPTSTATE state)
+{
+ ScriptHost *This = impl_from_IActiveScriptSite(iface);
+
+ FIXME("(%p, %d)\n", This, state);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, IActiveScriptError *script_error)
+{
+ ScriptHost *This = impl_from_IActiveScriptSite(iface);
+
+ FIXME("(%p, %p)\n", This, script_error);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ActiveScriptSite_OnEnterScript(IActiveScriptSite *iface)
+{
+ ScriptHost *This = impl_from_IActiveScriptSite(iface);
+
+ FIXME("(%p)\n", This);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ActiveScriptSite_OnLeaveScript(IActiveScriptSite *iface)
+{
+ ScriptHost *This = impl_from_IActiveScriptSite(iface);
+
+ FIXME("(%p)\n", This);
+
+ 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 HRESULT init_script_host(const CLSID *clsid, ScriptHost **ret)
+{
+ IObjectSafety *objsafety;
+ ScriptHost *host;
+ HRESULT hr;
+
+ *ret = NULL;
+
+ host = heap_alloc(sizeof(*host));
+ if (!host)
+ return E_OUTOFMEMORY;
+
+ host->IActiveScriptSite_iface.lpVtbl = &ActiveScriptSiteVtbl;
+ host->ref = 1;
+ host->script = NULL;
+ host->parse = NULL;
+ host->clsid = *clsid;
+
+ hr = CoCreateInstance(&host->clsid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
+ &IID_IActiveScript, (void**)&host->script);
+ if (FAILED(hr)) {
+ WARN("Failed to create an instance for %s, %#x\n", debugstr_guid(clsid), hr);
+ goto failed;
+ }
+
+ hr = IActiveScript_QueryInterface(host->script, &IID_IObjectSafety, (void**)&objsafety);
+ if (FAILED(hr)) {
+ FIXME("Could not get IObjectSafety, %#x\n", hr);
+ goto failed;
+ }
+
+ hr = IObjectSafety_SetInterfaceSafetyOptions(objsafety, &IID_IActiveScriptParse, INTERFACESAFE_FOR_UNTRUSTED_DATA, 0);
+ if (FAILED(hr))
+ FIXME("SetInterfaceSafetyOptions failed, %#x\n", hr);
+ IObjectSafety_Release(objsafety);
+
+ hr = IActiveScript_SetScriptSite(host->script, &host->IActiveScriptSite_iface);
+ if (FAILED(hr)) {
+ WARN("SetScriptSite failed, %#x\n", hr);
+ goto failed;
+ }
+
+ hr = IActiveScript_QueryInterface(host->script, &IID_IActiveScriptParse, (void**)&host->parse);
+ if (FAILED(hr)) {
+ WARN("Failed to get IActiveScriptParse, %#x\n", hr);
+ goto failed;
+ }
+
+ hr = IActiveScriptParse_InitNew(host->parse);
+ if (FAILED(hr)) {
+ WARN("InitNew failed, %#x\n", hr);
+ goto failed;
+ }
+
+ *ret = host;
+ return S_OK;
+
+failed:
+ IActiveScriptSite_Release(&host->IActiveScriptSite_iface);
+ return hr;
+}
+
static HRESULT WINAPI ScriptControl_QueryInterface(IScriptControl *iface, REFIID riid, void **ppv)
{
ScriptControl *This = impl_from_IScriptControl(iface);
@@ -257,6 +498,10 @@ static ULONG WINAPI ScriptControl_Release(IScriptControl *iface)
if(!ref) {
if (This->site)
IOleClientSite_Release(This->site);
+ if (This->host) {
+ release_script_engine(This->host);
+ IActiveScriptSite_Release(&This->host->IActiveScriptSite_iface);
+ }
heap_free(This);
}
@@ -321,15 +566,47 @@ static HRESULT WINAPI ScriptControl_Invoke(IScriptControl *iface, DISPID dispIdM
static HRESULT WINAPI ScriptControl_get_Language(IScriptControl *iface, BSTR *p)
{
ScriptControl *This = impl_from_IScriptControl(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ LPOLESTR progidW;
+ HRESULT hr;
+
+ TRACE("(%p)->(%p)\n", This, p);
+
+ if (!p)
+ return E_POINTER;
+
+ *p = NULL;
+
+ if (!This->host)
+ return S_OK;
+
+ hr = ProgIDFromCLSID(&This->host->clsid, &progidW);
+ if (FAILED(hr))
+ return hr;
+
+ *p = SysAllocStringLen(progidW, lstrlenW(progidW));
+ CoTaskMemFree(progidW);
+ return *p ? S_OK : E_OUTOFMEMORY;
}
static HRESULT WINAPI ScriptControl_put_Language(IScriptControl *iface, BSTR language)
{
ScriptControl *This = impl_from_IScriptControl(iface);
- FIXME("(%p)->(%s)\n", This, debugstr_w(language));
- return E_NOTIMPL;
+ CLSID clsid;
+
+ TRACE("(%p)->(%s)\n", This, debugstr_w(language));
+
+ if (language && FAILED(CLSIDFromProgID(language, &clsid)))
+ return CTL_E_INVALIDPROPERTYVALUE;
+
+ if (This->host) {
+ IActiveScriptSite_Release(&This->host->IActiveScriptSite_iface);
+ This->host = NULL;
+ }
+
+ if (!language)
+ return S_OK;
+
+ return init_script_host(&clsid, &This->host);
}
static HRESULT WINAPI ScriptControl_get_State(IScriptControl *iface, ScriptControlStates *p)
@@ -1379,6 +1656,7 @@ static HRESULT WINAPI ScriptControl_CreateInstance(IClassFactory *iface, IUnknow
script_control->ref = 1;
script_control->site = NULL;
script_control->cp_list = NULL;
+ script_control->host = NULL;
ConnectionPoint_Init(&script_control->cp_scsource, script_control, &DIID_DScriptControlSource);
ConnectionPoint_Init(&script_control->cp_propnotif, script_control, &IID_IPropertyNotifySink);
diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c
index f4e6306..0768174 100644
--- a/dlls/msscript.ocx/tests/msscript.c
+++ b/dlls/msscript.ocx/tests/msscript.c
@@ -92,6 +92,7 @@ DEFINE_EXPECT(SetInterfaceSafetyOptions);
DEFINE_EXPECT(InitNew);
DEFINE_EXPECT(Close);
DEFINE_EXPECT(SetScriptSite);
+DEFINE_EXPECT(QI_IActiveScriptParse);
#define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
static void _expect_ref(IUnknown* obj, ULONG ref, int line)
@@ -220,6 +221,7 @@ static HRESULT WINAPI ActiveScript_QueryInterface(IActiveScript *iface, REFIID r
}
if(IsEqualGUID(&IID_IActiveScriptParse, riid)) {
+ CHECK_EXPECT(QI_IActiveScriptParse);
*ppv = &ActiveScriptParse;
return S_OK;
}
@@ -261,7 +263,6 @@ static HRESULT WINAPI ActiveScript_SetScriptSite(IActiveScript *iface, IActiveSc
ok(hres == S_OK, "GetLCID failed: %08x\n", hres);
hres = IActiveScriptSite_OnStateChange(pass, (state = SCRIPTSTATE_INITIALIZED));
-todo_wine
ok(hres == E_NOTIMPL, "OnStateChange failed: %08x\n", hres);
hres = IActiveScriptSite_QueryInterface(pass, &IID_IActiveScriptSiteDebug, (void**)&debug);
@@ -683,14 +684,12 @@ static void test_Language(void)
&IID_IScriptControl, (void**)&sc);
ok(hr == S_OK, "got 0x%08x\n", hr);
-todo_wine {
hr = IScriptControl_get_Language(sc, NULL);
ok(hr == E_POINTER, "got 0x%08x\n", hr);
str = (BSTR)0xdeadbeef;
hr = IScriptControl_get_Language(sc, &str);
ok(hr == S_OK, "got 0x%08x\n", hr);
-if (hr == S_OK)
ok(str == NULL, "got %s\n", wine_dbgstr_w(str));
str = SysAllocString(vbW);
@@ -715,7 +714,6 @@ if (hr == S_OK)
hr = IScriptControl_get_Language(sc, &str);
ok(hr == S_OK, "got 0x%08x\n", hr);
-if (hr == S_OK)
ok(!lstrcmpW(str, vbW), "got %s\n", wine_dbgstr_w(str));
SysFreeString(str);
@@ -725,7 +723,7 @@ if (hr == S_OK)
SysFreeString(str);
hr = IScriptControl_get_Language(sc, &str);
-if (hr == S_OK)
+ ok(hr == S_OK, "got 0x%08x\n", hr);
ok(!lstrcmpW(str, jsW), "got %s\n", wine_dbgstr_w(str));
SysFreeString(str);
@@ -735,8 +733,8 @@ if (hr == S_OK)
hr = IScriptControl_get_Language(sc, &str);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(str == NULL, "got %s\n", wine_dbgstr_w(str));
+
IScriptControl_Release(sc);
-}
/* custom script engine */
if (register_script_engine()) {
@@ -746,10 +744,10 @@ if (hr == S_OK)
&IID_IScriptControl, (void**)&sc);
ok(hr == S_OK, "got 0x%08x\n", hr);
- todo_wine {
SET_EXPECT(CreateInstance);
SET_EXPECT(SetInterfaceSafetyOptions);
SET_EXPECT(SetScriptSite);
+ SET_EXPECT(QI_IActiveScriptParse);
SET_EXPECT(InitNew);
str = SysAllocString(testscriptW);
@@ -760,8 +758,10 @@ if (hr == S_OK)
CHECK_CALLED(CreateInstance);
CHECK_CALLED(SetInterfaceSafetyOptions);
CHECK_CALLED(SetScriptSite);
+ CHECK_CALLED(QI_IActiveScriptParse);
CHECK_CALLED(InitNew);
hr = IScriptControl_get_Language(sc, &str);
+ todo_wine
ok(hr == S_OK, "got 0x%08x\n", hr);
if (hr == S_OK)
ok(!lstrcmpW(testscriptW, str), "%s\n", wine_dbgstr_w(str));
@@ -775,7 +775,6 @@ if (hr == S_OK)
CHECK_CALLED(Close);
}
- }
else
skip("Could not register TestScript engine\n");
}
--
2.8.1
More information about the wine-patches
mailing list