msscript: Initial support for hosting script engines.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
1fda7ca72e
commit
b22dfdc98c
|
@ -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,224 @@ 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;
|
||||
|
||||
IActiveScriptSite_Release(&host->IActiveScriptSite_iface);
|
||||
}
|
||||
|
||||
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);
|
||||
IObjectSafety_Release(objsafety);
|
||||
if (FAILED(hr)) {
|
||||
FIXME("SetInterfaceSafetyOptions failed, %#x\n", hr);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
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:
|
||||
release_script_engine(host);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI ScriptControl_QueryInterface(IScriptControl *iface, REFIID riid, void **ppv)
|
||||
{
|
||||
ScriptControl *This = impl_from_IScriptControl(iface);
|
||||
|
@ -257,6 +502,8 @@ static ULONG WINAPI ScriptControl_Release(IScriptControl *iface)
|
|||
if(!ref) {
|
||||
if (This->site)
|
||||
IOleClientSite_Release(This->site);
|
||||
if (This->host)
|
||||
release_script_engine(This->host);
|
||||
heap_free(This);
|
||||
}
|
||||
|
||||
|
@ -321,15 +568,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 = SysAllocString(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) {
|
||||
release_script_engine(This->host);
|
||||
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 +1658,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);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue