Hi Nikolay, On 06/11/2016 12:02 PM, Nikolay Sivov wrote:
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com> ---
This deprecates patch 123111.
dlls/msscript.ocx/msscript.c | 237 ++++++++++++++++- dlls/msscript.ocx/tests/Makefile.in | 2 +- dlls/msscript.ocx/tests/msscript.c | 488 ++++++++++++++++++++++++++++++++++++ include/activscp.idl | 16 ++ 4 files changed, 737 insertions(+), 6 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 5a03f0c..b6764f4 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -22,6 +22,7 @@ #include "initguid.h" #include "ole2.h" #include "olectl.h" +#include "activscp.h" #include "rpcproxy.h" #include "msscript.h"
@@ -29,14 +30,21 @@
WINE_DEFAULT_DEBUG_CHANNEL(msscript);
+static const WCHAR vbscriptW[] = {'V','B','S','c','r','i','p','t',0}; +static const WCHAR jscriptW[] = {'J','S','c','r','i','p','t',0}; + struct ScriptControl { IScriptControl IScriptControl_iface; IPersistStreamInit IPersistStreamInit_iface; IOleObject IOleObject_iface; IOleControl IOleControl_iface; + IActiveScriptSite IActiveScriptSite_iface; LONG ref; IOleClientSite *site; SIZEL extent; + BSTR lang; + IActiveScript *script; + SCRIPTSTATE script_state; };
It's a good moment to think a bit about the design here. I don't think you want to reuse IActiveScriptSite for all script engines you load. A separated object would allow better ref counting, would be cleaner and safer in my opinion. A quick test on Windows suggests that native does that.
static HINSTANCE msscript_instance; @@ -120,6 +128,29 @@ static void release_typelib(void) ITypeLib_Release(typelib); }
+static void release_script_engine(ScriptControl *sc) +{ + if (!sc->script) + return; + + switch (sc->script_state) { + case SCRIPTSTATE_CONNECTED: + IActiveScript_SetScriptState(sc->script, SCRIPTSTATE_DISCONNECTED); + + case SCRIPTSTATE_STARTED: + case SCRIPTSTATE_DISCONNECTED: + case SCRIPTSTATE_INITIALIZED: + IActiveScript_Close(sc->script); + + default: + ; + }
Some "fall through" comments to avoid static analyser fixes follow ups would be nice.
-static HRESULT WINAPI ScriptControl_put_Language(IScriptControl *iface, BSTR language) +static HRESULT WINAPI ScriptControl_put_Language(IScriptControl *iface, BSTR lang) { ScriptControl *This = impl_from_IScriptControl(iface); - FIXME("(%p)->(%s)\n", This, debugstr_w(language)); - return E_NOTIMPL; + HRESULT hr; + GUID guid; + + TRACE("(%p)->(%s)\n", This, debugstr_w(lang)); + + if (!lang) { + release_script_engine(This); + set_script_name(This, NULL); + return S_OK; + } + + hr = CLSIDFromProgID(lang, &guid); + if (FAILED(hr)) + return CTL_E_INVALIDPROPERTYVALUE; + + hr = CoCreateInstance(&guid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, + &IID_IActiveScript, (void**)&This->script); + if (FAILED(hr)) + return CTL_E_INVALIDPROPERTYVALUE; + else if (!init_script_engine(This)) { + release_script_engine(This); + return CTL_E_INVALIDPROPERTYVALUE; + } + + /* store engine name */ + if (!lstrcmpiW(lang, vbscriptW)) + This->lang = SysAllocString(vbscriptW); + else if (!lstrcmpiW(lang, jscriptW)) + This->lang = SysAllocString(jscriptW); + else
Why do you need those? My guess is that returned script may have different upper/lower cases, but if that the case, then we should probably use ProgIDFromCLSID in getter and just store CLSID.
+ This->lang = SysAllocString(lang); + + return S_OK; }
static HRESULT WINAPI ScriptControl_get_State(IScriptControl *iface, ScriptControlStates *p) @@ -873,8 +1096,12 @@ static HRESULT WINAPI ScriptControl_CreateInstance(IClassFactory *iface, IUnknow script_control->IPersistStreamInit_iface.lpVtbl = &PersistStreamInitVtbl; script_control->IOleObject_iface.lpVtbl = &OleObjectVtbl; script_control->IOleControl_iface.lpVtbl = &OleControlVtbl; + script_control->IActiveScriptSite_iface.lpVtbl = &ActiveScriptSiteVtbl; script_control->ref = 1; script_control->site = NULL; + script_control->lang = NULL; + script_control->script_state = SCRIPTSTATE_UNINITIALIZED; + script_control->script = NULL;
hdc = GetDC(0); dpi_x = GetDeviceCaps(hdc, LOGPIXELSX); diff --git a/dlls/msscript.ocx/tests/Makefile.in b/dlls/msscript.ocx/tests/Makefile.in index 8d769d3..cc62590 100644 --- a/dlls/msscript.ocx/tests/Makefile.in +++ b/dlls/msscript.ocx/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = msscript.ocx -IMPORTS = user32 gdi32 ole32 +IMPORTS = user32 gdi32 ole32 oleaut32 advapi32
C_SRCS = \ msscript.c diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index 12f7003..d1d553b 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -22,10 +22,411 @@ #include <initguid.h> #include <ole2.h> #include <olectl.h> +#include "dispex.h" +#include "activscp.h" +#include "activdbg.h" +#include "objsafe.h"
#include "msscript.h" #include "wine/test.h"
+#define TESTSCRIPT_CLSID "{178fc164-f585-4e24-9c13-4bb7faf80746}" +static const GUID CLSID_TestScript = + {0x178fc164,0xf585,0x4e24,{0x9c,0x13,0x4b,0xb7,0xfa,0xf8,0x07,0x46}}; + +#ifdef _WIN64 + +#define CTXARG_T DWORDLONG +#define IActiveScriptParseVtbl IActiveScriptParse64Vtbl +#define IActiveScriptSiteDebug_Release IActiveScriptSiteDebug64_Release + +#else + +#define CTXARG_T DWORD +#define IActiveScriptParseVtbl IActiveScriptParse32Vtbl +#define IActiveScriptSiteDebug_Release IActiveScriptSiteDebug32_Release + +#endif + +static IActiveScriptSite *site; +static SCRIPTSTATE state; + +static HRESULT WINAPI ActiveScriptParse_QueryInterface(IActiveScriptParse *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + ok(0, "unexpected call\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI ActiveScriptParse_AddRef(IActiveScriptParse *iface) +{ + return 2; +} + +static ULONG WINAPI ActiveScriptParse_Release(IActiveScriptParse *iface) +{ + return 1; +} + +static HRESULT WINAPI ActiveScriptParse_InitNew(IActiveScriptParse *iface) +{ + return S_OK; +} + +static HRESULT WINAPI ActiveScriptParse_AddScriptlet(IActiveScriptParse *iface, + LPCOLESTR pstrDefaultName, LPCOLESTR pstrCode, LPCOLESTR pstrItemName, + LPCOLESTR pstrSubItemName, LPCOLESTR pstrEventName, LPCOLESTR pstrDelimiter, + CTXARG_T dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, + BSTR *pbstrName, EXCEPINFO *pexcepinfo) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *iface, + LPCOLESTR pstrCode, LPCOLESTR pstrItemName, IUnknown *punkContext, + LPCOLESTR pstrDelimiter, CTXARG_T dwSourceContextCookie, ULONG ulStartingLine, + DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const IActiveScriptParseVtbl ActiveScriptParseVtbl = { + ActiveScriptParse_QueryInterface, + ActiveScriptParse_AddRef, + ActiveScriptParse_Release, + ActiveScriptParse_InitNew, + ActiveScriptParse_AddScriptlet, + ActiveScriptParse_ParseScriptText +}; + +static IActiveScriptParse ActiveScriptParse = { &ActiveScriptParseVtbl }; + +static HRESULT WINAPI ObjectSafety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI ObjectSafety_AddRef(IObjectSafety *iface) +{ + return 2; +} + +static ULONG WINAPI ObjectSafety_Release(IObjectSafety *iface) +{ + return 1; +} + +static HRESULT WINAPI ObjectSafety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid, + DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions) +{ + ok(IsEqualGUID(&IID_IActiveScriptParse, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + ok(pdwSupportedOptions != NULL, "pdwSupportedOptions == NULL\n"); + ok(pdwEnabledOptions != NULL, "pdwEnabledOptions == NULL\n"); + + *pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER; + *pdwEnabledOptions = INTERFACE_USES_DISPEX; + + return S_OK; +} + +static HRESULT WINAPI ObjectSafety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid, + DWORD mask, DWORD options) +{ + ok(IsEqualGUID(&IID_IActiveScriptParse, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + + ok(mask == INTERFACESAFE_FOR_UNTRUSTED_DATA, "option mask = %x\n", mask); + ok(options == 0, "options = %x\n", options); + + return S_OK; +} + +static const IObjectSafetyVtbl ObjectSafetyVtbl = { + ObjectSafety_QueryInterface, + ObjectSafety_AddRef, + ObjectSafety_Release, + ObjectSafety_GetInterfaceSafetyOptions, + ObjectSafety_SetInterfaceSafetyOptions +}; + +static IObjectSafety ObjectSafety = { &ObjectSafetyVtbl }; + +static HRESULT WINAPI ActiveScript_QueryInterface(IActiveScript *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IActiveScript, riid)) { + *ppv = iface; + return S_OK; + } + + if(IsEqualGUID(&IID_IObjectSafety, riid)) { + *ppv = &ObjectSafety; + return S_OK; + } + + if(IsEqualGUID(&IID_IActiveScriptParse, riid)) { + *ppv = &ActiveScriptParse; + return S_OK; + } + + if(IsEqualGUID(&IID_IActiveScriptGarbageCollector, riid)) { + return E_NOINTERFACE; + } + + ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI ActiveScript_AddRef(IActiveScript *iface) +{ + return 2; +} + +static ULONG WINAPI ActiveScript_Release(IActiveScript *iface) +{ + return 1; +} + +static HRESULT WINAPI ActiveScript_SetScriptSite(IActiveScript *iface, IActiveScriptSite *pass) +{ + IActiveScriptSiteInterruptPoll *poll; + IActiveScriptSiteDebug *debug; + IServiceProvider *service; + ICanHandleException *canexpection; + LCID lcid; + HRESULT hres; + + ok(pass != NULL, "pass == NULL\n"); + + hres = IActiveScriptSite_QueryInterface(pass, &IID_IActiveScriptSiteInterruptPoll, (void**)&poll); + ok(hres == E_NOINTERFACE, "Could not get IActiveScriptSiteInterruptPoll interface: %08x\n", hres); + + hres = IActiveScriptSite_GetLCID(pass, &lcid); + 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); + ok(hres == E_NOINTERFACE, "Could not get IActiveScriptSiteDebug interface: %08x\n", hres); + + hres = IActiveScriptSite_QueryInterface(pass, &IID_ICanHandleException, (void**)&canexpection); + ok(hres == E_NOINTERFACE, "Could not get IID_ICanHandleException interface: %08x\n", hres); + + hres = IActiveScriptSite_QueryInterface(pass, &IID_IServiceProvider, (void**)&service); +todo_wine + ok(hres == S_OK, "Could not get IServiceProvider interface: %08x\n", hres); + if(SUCCEEDED(hres)) + IServiceProvider_Release(service); + + site = pass; + IActiveScriptSite_AddRef(site); + return S_OK; +} + +static HRESULT WINAPI ActiveScript_GetScriptSite(IActiveScript *iface, REFIID riid, + void **ppvObject) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScript_SetScriptState(IActiveScript *iface, SCRIPTSTATE ss) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScript_GetScriptState(IActiveScript *iface, SCRIPTSTATE *pssState) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScript_Close(IActiveScript *iface) +{ + return S_OK; +} + +static HRESULT WINAPI ActiveScript_AddNamedItem(IActiveScript *iface, + LPCOLESTR pstrName, DWORD dwFlags) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScript_AddTypeLib(IActiveScript *iface, REFGUID rguidTypeLib, + DWORD dwMajor, DWORD dwMinor, DWORD dwFlags) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName, + IDispatch **ppdisp) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScript_GetCurrentScriptThreadID(IActiveScript *iface, + SCRIPTTHREADID *pstridThread) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScript_GetScriptThreadID(IActiveScript *iface, + DWORD dwWin32ThreadId, SCRIPTTHREADID *pstidThread) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScript_GetScriptThreadState(IActiveScript *iface, + SCRIPTTHREADID stidThread, SCRIPTTHREADSTATE *pstsState) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScript_InterruptScriptThread(IActiveScript *iface, + SCRIPTTHREADID stidThread, const EXCEPINFO *pexcepinfo, DWORD dwFlags) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScript_Clone(IActiveScript *iface, IActiveScript **ppscript) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const IActiveScriptVtbl ActiveScriptVtbl = { + ActiveScript_QueryInterface, + ActiveScript_AddRef, + ActiveScript_Release, + ActiveScript_SetScriptSite, + ActiveScript_GetScriptSite, + ActiveScript_SetScriptState, + ActiveScript_GetScriptState, + ActiveScript_Close, + ActiveScript_AddNamedItem, + ActiveScript_AddTypeLib, + ActiveScript_GetScriptDispatch, + ActiveScript_GetCurrentScriptThreadID, + ActiveScript_GetScriptThreadID, + ActiveScript_GetScriptThreadState, + ActiveScript_InterruptScriptThread, + ActiveScript_Clone +}; + +static IActiveScript ActiveScript = { &ActiveScriptVtbl }; + +static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IClassFactory, riid)) { + *ppv = iface; + return S_OK; + } + + if(IsEqualGUID(&IID_IMarshal, riid)) + return E_NOINTERFACE; + + ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface) +{ + return 2; +} + +static ULONG WINAPI ClassFactory_Release(IClassFactory *iface) +{ + return 1; +} + +static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv) +{ + ok(!outer, "outer = %p\n", outer); + ok(IsEqualGUID(&IID_IActiveScript, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = &ActiveScript; + return S_OK; +} + +static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock) +{ + ok(0, "unexpected call\n"); + return S_OK; +} + +static const IClassFactoryVtbl ClassFactoryVtbl = { + ClassFactory_QueryInterface, + ClassFactory_AddRef, + ClassFactory_Release, + ClassFactory_CreateInstance, + ClassFactory_LockServer +}; + +static IClassFactory script_cf = { &ClassFactoryVtbl }; + +static BOOL init_key(const char *key_name, const char *def_value, BOOL init) +{ + HKEY hkey; + DWORD res; + + if(!init) { + RegDeleteKeyA(HKEY_CLASSES_ROOT, key_name); + return TRUE; + } + + res = RegCreateKeyA(HKEY_CLASSES_ROOT, key_name, &hkey); + if(res != ERROR_SUCCESS) + return FALSE; + + if(def_value) + res = RegSetValueA(hkey, NULL, REG_SZ, def_value, strlen(def_value)); + + RegCloseKey(hkey); + + return res == ERROR_SUCCESS; +} + +static BOOL init_registry(BOOL init) +{ + return init_key("TestScript\\CLSID", TESTSCRIPT_CLSID, init) + && init_key("CLSID\\"TESTSCRIPT_CLSID"\\Implemented Categories\\{F0B7A1A1-9847-11CF-8F20-00805F2CD064}", + NULL, init) + && init_key("CLSID\\"TESTSCRIPT_CLSID"\\Implemented Categories\\{F0B7A1A2-9847-11CF-8F20-00805F2CD064}", + NULL, init); +} + +static BOOL register_script_engine(void) +{ + DWORD regid; + HRESULT hres; + + if(!init_registry(TRUE)) { + init_registry(FALSE); + return FALSE; + } + + hres = CoRegisterClassObject(&CLSID_TestScript, (IUnknown *)&script_cf, + CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, ®id); + ok(hres == S_OK, "Could not register script engine: %08x\n", hres); + + return TRUE; +} + static HRESULT WINAPI OleClientSite_QueryInterface(IOleClientSite *iface, REFIID riid, void **obj) { if (IsEqualIID(riid, &IID_IOleClientSite) || IsEqualIID(riid, &IID_IUnknown)) @@ -213,6 +614,92 @@ static void test_olecontrol(void) IOleControl_Release(olecontrol); }
+static void test_Language(void) +{ + static const WCHAR vbW[] = {'V','B','S','c','r','i','p','t',0}; + static const WCHAR jsW[] = {'J','S','c','r','i','p','t',0}; + static const WCHAR vb2W[] = {'v','B','s','c','r','i','p','t',0}; + static const WCHAR dummyW[] = {'d','u','m','m','y',0}; + IScriptControl *sc; + HRESULT hr; + BSTR str; + + hr = CoCreateInstance(&CLSID_ScriptControl, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, + &IID_IScriptControl, (void**)&sc); + ok(hr == S_OK, "got 0x%08x\n", hr); + + 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); + ok(str == NULL, "got %s\n", wine_dbgstr_w(str)); + + str = SysAllocString(vbW); + hr = IScriptControl_put_Language(sc, str); + ok(hr == S_OK, "got 0x%08x\n", hr); + SysFreeString(str); + + str = SysAllocString(vb2W); + hr = IScriptControl_put_Language(sc, str); + ok(hr == S_OK, "got 0x%08x\n", hr); + SysFreeString(str); + + hr = IScriptControl_get_Language(sc, &str); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(!lstrcmpW(str, vbW), "got %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + str = SysAllocString(dummyW); + hr = IScriptControl_put_Language(sc, str); + ok(hr == CTL_E_INVALIDPROPERTYVALUE, "got 0x%08x\n", hr); + SysFreeString(str); + + hr = IScriptControl_get_Language(sc, &str); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(!lstrcmpW(str, vbW), "got %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + str = SysAllocString(jsW); + hr = IScriptControl_put_Language(sc, str); + ok(hr == S_OK, "got 0x%08x\n", hr); + SysFreeString(str); + + hr = IScriptControl_get_Language(sc, &str); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(!lstrcmpW(str, jsW), "got %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hr = IScriptControl_put_Language(sc, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + + 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)); + + /* custom script engine */ + if (register_script_engine()) { + static const WCHAR testscriptW[] = {'t','e','s','t','s','c','r','i','p','t',0}; + + str = SysAllocString(testscriptW); + hr = IScriptControl_put_Language(sc, str); + ok(hr == S_OK, "got 0x%08x\n", hr); + SysFreeString(str);
It's nice to have tests with emulated script engine, but please also add test of called callbacks. Please add something like CHECK_EXPECT()/CHECK_CALLED() macros or alike. Otherwise important informations that your tests already gather are hidden and not tested.
+ + hr = IScriptControl_get_Language(sc, &str); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(!lstrcmpW(testscriptW, str), "%s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + init_registry(FALSE); + } + else + skip("Could not register TestScript engine\n"); + + IScriptControl_Release(sc); +} + START_TEST(msscript) { IUnknown *unk; @@ -231,6 +718,7 @@ START_TEST(msscript) test_oleobject(); test_persiststreaminit(); test_olecontrol(); + test_Language();
CoUninitialize(); } diff --git a/include/activscp.idl b/include/activscp.idl index 8a3d75d..e539b04 100644 --- a/include/activscp.idl +++ b/include/activscp.idl @@ -71,6 +71,11 @@ typedef enum tagSCRIPTUICHANDLING { SCRIPTUICHANDLING_NOUIDEFAULT = 2 } SCRIPTUICHANDLING;
+typedef enum tagSCRIPTGCTYPE { + SCRIPTGCTYPE_NORMAL = 0, + SCRIPTGCTYPE_EXHAUSTIVE = 1 +} SCRIPTGCTYPE; + typedef DWORD SCRIPTTHREADID; cpp_quote("#define SCRIPTTHREADID_CURRENT ((SCRIPTTHREADID)-1)") cpp_quote("#define SCRIPTTHREADID_BASE ((SCRIPTTHREADID)-2)") @@ -551,3 +556,14 @@ interface IActiveScriptProperty : IUnknown [in] VARIANT *pvarIndex, [in] VARIANT *pvarValue); } + +[ + object, + uuid(6aa2c4a0-2b53-11d4-a2a0-00104bd35090), + pointer_default(unique) +] +interface IActiveScriptGarbageCollector : IUnknown +{ + HRESULT CollectGarbage( + [in] SCRIPTGCTYPE gctype); +}
It's not too important, but technically it deserves a separated patch. Thanks, Jacek