Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
v2: Split tests and use separate objects for externally referenced modules. v3: Use the index in the module object instead of a pointer.
dlls/msscript.ocx/msscript.c | 166 ++++++++++++++++++++++++++++++++++- 1 file changed, 163 insertions(+), 3 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index c4c6485..57200da 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -106,6 +106,9 @@ struct ScriptControl { IAdviseSink *view_sink; DWORD view_sink_flags;
+ /* modules */ + IScriptModuleCollection IScriptModuleCollection_iface; + ScriptHost *host; };
@@ -113,6 +116,7 @@ static HINSTANCE msscript_instance;
typedef enum tid_t { IScriptControl_tid, + IScriptModuleCollection_tid, LAST_tid } tid_t;
@@ -120,7 +124,8 @@ static ITypeLib *typelib; static ITypeInfo *typeinfos[LAST_tid];
static REFIID tid_ids[] = { - &IID_IScriptControl + &IID_IScriptControl, + &IID_IScriptModuleCollection, };
static HRESULT load_typelib(void) @@ -277,6 +282,11 @@ static inline ScriptControl *impl_from_IConnectionPointContainer(IConnectionPoin return CONTAINING_RECORD(iface, ScriptControl, IConnectionPointContainer_iface); }
+static inline ScriptControl *impl_from_IScriptModuleCollection(IScriptModuleCollection *iface) +{ + return CONTAINING_RECORD(iface, ScriptControl, IScriptModuleCollection_iface); +} + static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface) { return CONTAINING_RECORD(iface, ConnectionPoint, IConnectionPoint_iface); @@ -551,6 +561,151 @@ static const IServiceProviderVtbl ServiceProviderVtbl = { ServiceProvider_QueryService };
+static HRESULT WINAPI ScriptModuleCollection_QueryInterface(IScriptModuleCollection *iface, REFIID riid, void **ppv) +{ + ScriptControl *This = impl_from_IScriptModuleCollection(iface); + + if (IsEqualGUID(&IID_IDispatch, riid) || IsEqualGUID(&IID_IUnknown, riid) || + IsEqualGUID(&IID_IScriptModuleCollection, riid)) + { + *ppv = &This->IScriptModuleCollection_iface; + } + else + { + WARN("unsupported interface: (%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI ScriptModuleCollection_AddRef(IScriptModuleCollection *iface) +{ + ScriptControl *This = impl_from_IScriptModuleCollection(iface); + return IScriptControl_AddRef(&This->IScriptControl_iface); +} + +static ULONG WINAPI ScriptModuleCollection_Release(IScriptModuleCollection *iface) +{ + ScriptControl *This = impl_from_IScriptModuleCollection(iface); + return IScriptControl_Release(&This->IScriptControl_iface); +} + +static HRESULT WINAPI ScriptModuleCollection_GetTypeInfoCount(IScriptModuleCollection *iface, UINT *pctinfo) +{ + ScriptControl *This = impl_from_IScriptModuleCollection(iface); + + TRACE("(%p)->(%p)\n", This, pctinfo); + + *pctinfo = 1; + return S_OK; +} + +static HRESULT WINAPI ScriptModuleCollection_GetTypeInfo(IScriptModuleCollection *iface, UINT iTInfo, + LCID lcid, ITypeInfo **ppTInfo) +{ + ScriptControl *This = impl_from_IScriptModuleCollection(iface); + + TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); + + return get_typeinfo(IScriptModuleCollection_tid, ppTInfo); +} + +static HRESULT WINAPI ScriptModuleCollection_GetIDsOfNames(IScriptModuleCollection *iface, REFIID riid, + LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) +{ + ScriptControl *This = impl_from_IScriptModuleCollection(iface); + ITypeInfo *typeinfo; + HRESULT hr; + + TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId); + + hr = get_typeinfo(IScriptModuleCollection_tid, &typeinfo); + if (SUCCEEDED(hr)) + { + hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId); + ITypeInfo_Release(typeinfo); + } + + return hr; +} + +static HRESULT WINAPI ScriptModuleCollection_Invoke(IScriptModuleCollection *iface, DISPID dispIdMember, + REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, + EXCEPINFO *pExcepInfo, UINT *puArgErr) +{ + ScriptControl *This = impl_from_IScriptModuleCollection(iface); + ITypeInfo *typeinfo; + HRESULT hr; + + TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), + lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); + + hr = get_typeinfo(IScriptModuleCollection_tid, &typeinfo); + if(SUCCEEDED(hr)) + { + hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags, + pDispParams, pVarResult, pExcepInfo, puArgErr); + ITypeInfo_Release(typeinfo); + } + + return hr; +} + +static HRESULT WINAPI ScriptModuleCollection_get__NewEnum(IScriptModuleCollection *iface, IUnknown **ppenumContexts) +{ + ScriptControl *This = impl_from_IScriptModuleCollection(iface); + + FIXME("(%p)->(%p)\n", This, ppenumContexts); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ScriptModuleCollection_get_Item(IScriptModuleCollection *iface, VARIANT index, + IScriptModule **ppmod) +{ + ScriptControl *This = impl_from_IScriptModuleCollection(iface); + + FIXME("(%p)->(%s %p)\n", This, wine_dbgstr_variant(&index), ppmod); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ScriptModuleCollection_get_Count(IScriptModuleCollection *iface, LONG *plCount) +{ + ScriptControl *This = impl_from_IScriptModuleCollection(iface); + + FIXME("(%p)->(%p)\n", This, plCount); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ScriptModuleCollection_Add(IScriptModuleCollection *iface, BSTR name, + VARIANT *object, IScriptModule **ppmod) +{ + ScriptControl *This = impl_from_IScriptModuleCollection(iface); + + FIXME("(%p)->(%s %s %p)\n", This, wine_dbgstr_w(name), wine_dbgstr_variant(object), ppmod); + + return E_NOTIMPL; +} + +static const IScriptModuleCollectionVtbl ScriptModuleCollectionVtbl = { + ScriptModuleCollection_QueryInterface, + ScriptModuleCollection_AddRef, + ScriptModuleCollection_Release, + ScriptModuleCollection_GetTypeInfoCount, + ScriptModuleCollection_GetTypeInfo, + ScriptModuleCollection_GetIDsOfNames, + ScriptModuleCollection_Invoke, + ScriptModuleCollection_get__NewEnum, + ScriptModuleCollection_get_Item, + ScriptModuleCollection_get_Count, + ScriptModuleCollection_Add +}; + static HRESULT init_script_host(const CLSID *clsid, ScriptHost **ret) { IObjectSafety *objsafety; @@ -922,8 +1077,12 @@ static HRESULT WINAPI ScriptControl_put_UseSafeSubset(IScriptControl *iface, VAR static HRESULT WINAPI ScriptControl_get_Modules(IScriptControl *iface, IScriptModuleCollection **p) { ScriptControl *This = impl_from_IScriptControl(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + + TRACE("(%p)->(%p)\n", This, p); + + *p = &This->IScriptModuleCollection_iface; + IScriptControl_AddRef(iface); + return S_OK; }
static HRESULT WINAPI ScriptControl_get_Error(IScriptControl *iface, IScriptError **p) @@ -2031,6 +2190,7 @@ static HRESULT WINAPI ScriptControl_CreateInstance(IClassFactory *iface, IUnknow script_control->IViewObjectEx_iface.lpVtbl = &ViewObjectExVtbl; script_control->IPointerInactive_iface.lpVtbl = &PointerInactiveVtbl; script_control->IConnectionPointContainer_iface.lpVtbl = &ConnectionPointContainerVtbl; + script_control->IScriptModuleCollection_iface.lpVtbl = &ScriptModuleCollectionVtbl; script_control->ref = 1; script_control->site = NULL; script_control->cp_list = NULL;
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 252 ++++++++++++++++++++++++++++++++++- 1 file changed, 250 insertions(+), 2 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 57200da..91e1e94 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -50,6 +50,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msscript); #endif
struct ScriptControl; +typedef struct ScriptModule ScriptModule; typedef struct ConnectionPoint ConnectionPoint;
struct ConnectionPoint { @@ -65,6 +66,18 @@ struct named_item { IDispatch *disp; };
+struct module { + BSTR name; + ScriptModule *object; +}; + +struct ScriptModule { + IScriptModule IScriptModule_iface; + LONG ref; + UINT idx; + ScriptControl *control; +}; + typedef struct ScriptHost { IActiveScriptSite IActiveScriptSite_iface; IActiveScriptSiteWindow IActiveScriptSiteWindow_iface; @@ -107,6 +120,8 @@ struct ScriptControl { DWORD view_sink_flags;
/* modules */ + UINT num_modules; + struct module *modules; IScriptModuleCollection IScriptModuleCollection_iface;
ScriptHost *host; @@ -117,6 +132,7 @@ static HINSTANCE msscript_instance; typedef enum tid_t { IScriptControl_tid, IScriptModuleCollection_tid, + IScriptModule_tid, LAST_tid } tid_t;
@@ -126,6 +142,7 @@ static ITypeInfo *typeinfos[LAST_tid]; static REFIID tid_ids[] = { &IID_IScriptControl, &IID_IScriptModuleCollection, + &IID_IScriptModule };
static HRESULT load_typelib(void) @@ -287,6 +304,11 @@ static inline ScriptControl *impl_from_IScriptModuleCollection(IScriptModuleColl return CONTAINING_RECORD(iface, ScriptControl, IScriptModuleCollection_iface); }
+static inline ScriptModule *impl_from_IScriptModule(IScriptModule *iface) +{ + return CONTAINING_RECORD(iface, ScriptModule, IScriptModule_iface); +} + static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface) { return CONTAINING_RECORD(iface, ConnectionPoint, IConnectionPoint_iface); @@ -561,6 +583,216 @@ static const IServiceProviderVtbl ServiceProviderVtbl = { ServiceProvider_QueryService };
+static void release_modules(ScriptControl *control) +{ + UINT i = control->num_modules - 1; + + if (!control->modules) return; + do + { + struct module *module = &control->modules[i]; + if (module->object) + { + module->object->control = NULL; + IScriptControl_Release(&control->IScriptControl_iface); + } + SysFreeString(module->name); + } while (i--); + + heap_free(control->modules); +} + +static HRESULT WINAPI ScriptModule_QueryInterface(IScriptModule *iface, REFIID riid, void **ppv) +{ + ScriptModule *This = impl_from_IScriptModule(iface); + + if (IsEqualGUID(&IID_IDispatch, riid) || IsEqualGUID(&IID_IUnknown, riid) || + IsEqualGUID(&IID_IScriptModule, riid)) + { + *ppv = &This->IScriptModule_iface; + } + else + { + WARN("unsupported interface: (%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI ScriptModule_AddRef(IScriptModule *iface) +{ + ScriptModule *This = impl_from_IScriptModule(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + return ref; +} + +static ULONG WINAPI ScriptModule_Release(IScriptModule *iface) +{ + ScriptModule *This = impl_from_IScriptModule(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + if (!ref) + { + if (This->control) + { + This->control->modules[This->idx].object = NULL; + IScriptControl_Release(&This->control->IScriptControl_iface); + } + heap_free(This); + } + + return ref; +} + +static HRESULT WINAPI ScriptModule_GetTypeInfoCount(IScriptModule *iface, UINT *pctinfo) +{ + ScriptModule *This = impl_from_IScriptModule(iface); + + TRACE("(%p)->(%p)\n", This, pctinfo); + + *pctinfo = 1; + return S_OK; +} + +static HRESULT WINAPI ScriptModule_GetTypeInfo(IScriptModule *iface, UINT iTInfo, + LCID lcid, ITypeInfo **ppTInfo) +{ + ScriptModule *This = impl_from_IScriptModule(iface); + + TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); + + return get_typeinfo(IScriptModule_tid, ppTInfo); +} + +static HRESULT WINAPI ScriptModule_GetIDsOfNames(IScriptModule *iface, REFIID riid, + LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) +{ + ScriptModule *This = impl_from_IScriptModule(iface); + ITypeInfo *typeinfo; + HRESULT hr; + + TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId); + + hr = get_typeinfo(IScriptModule_tid, &typeinfo); + if (SUCCEEDED(hr)) + { + hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId); + ITypeInfo_Release(typeinfo); + } + + return hr; +} + +static HRESULT WINAPI ScriptModule_Invoke(IScriptModule *iface, DISPID dispIdMember, + REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, + EXCEPINFO *pExcepInfo, UINT *puArgErr) +{ + ScriptModule *This = impl_from_IScriptModule(iface); + ITypeInfo *typeinfo; + HRESULT hr; + + TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), + lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); + + hr = get_typeinfo(IScriptModule_tid, &typeinfo); + if(SUCCEEDED(hr)) + { + hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags, + pDispParams, pVarResult, pExcepInfo, puArgErr); + ITypeInfo_Release(typeinfo); + } + + return hr; +} + +static HRESULT WINAPI ScriptModule_get_Name(IScriptModule *iface, BSTR *pbstrName) +{ + ScriptModule *This = impl_from_IScriptModule(iface); + + FIXME("(%p)->(%p)\n", This, pbstrName); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ScriptModule_get_CodeObject(IScriptModule *iface, IDispatch **ppdispObject) +{ + ScriptModule *This = impl_from_IScriptModule(iface); + + FIXME("(%p)->(%p)\n", This, ppdispObject); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ScriptModule_get_Procedures(IScriptModule *iface, IScriptProcedureCollection **ppdispProcedures) +{ + ScriptModule *This = impl_from_IScriptModule(iface); + + FIXME("(%p)->(%p)\n", This, ppdispProcedures); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ScriptModule_AddCode(IScriptModule *iface, BSTR code) +{ + ScriptModule *This = impl_from_IScriptModule(iface); + + FIXME("(%p)->(%s)\n", This, debugstr_w(code)); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ScriptModule_Eval(IScriptModule *iface, BSTR expression, VARIANT *res) +{ + ScriptModule *This = impl_from_IScriptModule(iface); + + FIXME("(%p)->(%s, %p)\n", This, debugstr_w(expression), res); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ScriptModule_ExecuteStatement(IScriptModule *iface, BSTR statement) +{ + ScriptModule *This = impl_from_IScriptModule(iface); + + FIXME("(%p)->(%s)\n", This, debugstr_w(statement)); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ScriptModule_Run(IScriptModule *iface, BSTR procedure_name, SAFEARRAY **parameters, VARIANT *res) +{ + ScriptModule *This = impl_from_IScriptModule(iface); + + FIXME("(%p)->(%s %p %p)\n", This, debugstr_w(procedure_name), parameters, res); + + return E_NOTIMPL; +} + +static const IScriptModuleVtbl ScriptModuleVtbl = { + ScriptModule_QueryInterface, + ScriptModule_AddRef, + ScriptModule_Release, + ScriptModule_GetTypeInfoCount, + ScriptModule_GetTypeInfo, + ScriptModule_GetIDsOfNames, + ScriptModule_Invoke, + ScriptModule_get_Name, + ScriptModule_get_CodeObject, + ScriptModule_get_Procedures, + ScriptModule_AddCode, + ScriptModule_Eval, + ScriptModule_ExecuteStatement, + ScriptModule_Run +}; + static HRESULT WINAPI ScriptModuleCollection_QueryInterface(IScriptModuleCollection *iface, REFIID riid, void **ppv) { ScriptControl *This = impl_from_IScriptModuleCollection(iface); @@ -677,9 +909,12 @@ static HRESULT WINAPI ScriptModuleCollection_get_Count(IScriptModuleCollection * { ScriptControl *This = impl_from_IScriptModuleCollection(iface);
- FIXME("(%p)->(%p)\n", This, plCount); + TRACE("(%p)->(%p)\n", This, plCount);
- return E_NOTIMPL; + if (!plCount) return E_POINTER; + + *plCount = This->num_modules; + return S_OK; }
static HRESULT WINAPI ScriptModuleCollection_Add(IScriptModuleCollection *iface, BSTR name, @@ -850,6 +1085,7 @@ static ULONG WINAPI ScriptControl_Release(IScriptControl *iface) IOleClientSite_Release(This->site); if (This->host) release_script_engine(This->host); + release_modules(This); heap_free(This); }
@@ -939,6 +1175,7 @@ static HRESULT WINAPI ScriptControl_get_Language(IScriptControl *iface, BSTR *p) static HRESULT WINAPI ScriptControl_put_Language(IScriptControl *iface, BSTR language) { ScriptControl *This = impl_from_IScriptControl(iface); + struct module *modules; CLSID clsid;
TRACE("(%p)->(%s)\n", This, debugstr_w(language)); @@ -946,11 +1183,19 @@ static HRESULT WINAPI ScriptControl_put_Language(IScriptControl *iface, BSTR lan if (language && FAILED(CLSIDFromProgID(language, &clsid))) return CTL_E_INVALIDPROPERTYVALUE;
+ /* Alloc new global module */ + modules = heap_alloc_zero(sizeof(*modules)); + if (!modules) return E_OUTOFMEMORY; + if (This->host) { release_script_engine(This->host); This->host = NULL; }
+ release_modules(This); + This->modules = modules; + This->num_modules = 1; + if (!language) return S_OK;
@@ -1080,6 +1325,8 @@ static HRESULT WINAPI ScriptControl_get_Modules(IScriptControl *iface, IScriptMo
TRACE("(%p)->(%p)\n", This, p);
+ if (!This->modules) return E_FAIL; + *p = &This->IScriptModuleCollection_iface; IScriptControl_AddRef(iface); return S_OK; @@ -2201,6 +2448,7 @@ static HRESULT WINAPI ScriptControl_CreateInstance(IClassFactory *iface, IUnknow script_control->allow_ui = VARIANT_TRUE; script_control->use_safe_subset = VARIANT_FALSE; script_control->state = Initialized; + script_control->modules = NULL;
ConnectionPoint_Init(&script_control->cp_scsource, script_control, &DIID_DScriptControlSource); ConnectionPoint_Init(&script_control->cp_propnotif, script_control, &IID_IPropertyNotifySink);
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/tests/msscript.c | 194 ++++++++++++++++++++++++++++- 1 file changed, 190 insertions(+), 4 deletions(-)
diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index 22db28e..9acf60e 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -150,6 +150,7 @@ static HRESULT WINAPI ActiveScriptParse_AddScriptlet(IActiveScriptParse *iface, return E_NOTIMPL; }
+static const WCHAR *parse_item_name; static DWORD parse_flags = 0;
static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *iface, @@ -158,7 +159,8 @@ static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *ifac DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo) { ok(!!pstrCode, "got wrong pointer: %p.\n", pstrCode); - ok(!pstrItemName, "got wrong pointer: %p.\n", pstrItemName); + ok(!lstrcmpW(pstrItemName, parse_item_name), "got wrong item name: %s (expected %s).\n", + wine_dbgstr_w(pstrItemName), wine_dbgstr_w(parse_item_name)); ok(!punkContext, "got wrong pointer: %p.\n", punkContext); ok(!pstrDelimiter, "got wrong pointer: %p.\n", pstrDelimiter); ok(!dwSourceContextCookie, "got wrong value: %s.\n", wine_dbgstr_longlong(dwSourceContextCookie)); @@ -522,12 +524,13 @@ static HRESULT WINAPI ActiveScript_Close(IActiveScript *iface) return E_NOTIMPL; }
+static const WCHAR *AddNamedItem_expected_name; +static DWORD AddNamedItem_expected_flags; static HRESULT WINAPI ActiveScript_AddNamedItem(IActiveScript *iface, LPCOLESTR name, DWORD flags) { - static const WCHAR oW[] = {'o',0}; CHECK_EXPECT(AddNamedItem); - ok(!lstrcmpW(name, oW), "got name %s\n", wine_dbgstr_w(name)); - ok(flags == (SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|SCRIPTITEM_GLOBALMEMBERS), "got flags %#x\n", flags); + ok(!lstrcmpW(name, AddNamedItem_expected_name), "got name %s\n", wine_dbgstr_w(name)); + ok(flags == AddNamedItem_expected_flags, "got flags %#x\n", flags); return S_OK; }
@@ -1413,6 +1416,8 @@ static void test_AddObject(void) ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
SET_EXPECT(AddNamedItem); + AddNamedItem_expected_name = objname; + AddNamedItem_expected_flags = SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|SCRIPTITEM_GLOBALMEMBERS; hr = IScriptControl_AddObject(sc, objname, &testdisp, VARIANT_TRUE); ok(hr == S_OK, "got 0x%08x\n", hr); CHECK_CALLED(AddNamedItem); @@ -1693,6 +1698,7 @@ static void test_IScriptControl_Eval(void)
SET_EXPECT(SetScriptState_STARTED); SET_EXPECT(ParseScriptText); + parse_item_name = NULL; parse_flags = SCRIPTTEXT_ISEXPRESSION; script_str = SysAllocString(L"var1 = 1 + 1"); V_VT(&var) = VT_NULL; @@ -1806,6 +1812,7 @@ static void test_IScriptControl_AddCode(void)
SET_EXPECT(SetScriptState_STARTED); SET_EXPECT(ParseScriptText); + parse_item_name = NULL; parse_flags = SCRIPTTEXT_ISVISIBLE; code_str = SysAllocString(L"1 + 1"); hr = IScriptControl_AddCode(sc, code_str); @@ -1823,6 +1830,7 @@ static void test_IScriptControl_AddCode(void)
/* Call Eval() after AddCode() for checking if it will call SetScriptState() again. */ SET_EXPECT(ParseScriptText); + parse_item_name = NULL; parse_flags = SCRIPTTEXT_ISEXPRESSION; code_str = SysAllocString(L"var2 = 10 + var1"); V_VT(&var) = VT_NULL; @@ -1905,6 +1913,7 @@ static void test_IScriptControl_ExecuteStatement(void)
SET_EXPECT(SetScriptState_STARTED); SET_EXPECT(ParseScriptText); + parse_item_name = NULL; parse_flags = 0; str = SysAllocString(L"1 + 1"); hr = IScriptControl_ExecuteStatement(sc, str); @@ -2125,6 +2134,182 @@ static void test_IScriptControl_Run(void) SafeArrayDestroy(params); }
+static void test_IScriptControl_get_Modules(void) +{ + IScriptModuleCollection *mods; + IScriptModule *mod; + IScriptControl *sc; + VARIANT var; + LONG count; + HRESULT hr; + BSTR str; + + hr = CoCreateInstance(&CLSID_ScriptControl, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, + &IID_IScriptControl, (void**)&sc); + ok(hr == S_OK, "Failed to create IScriptControl interface: 0x%08x.\n", hr); + + hr = IScriptControl_get_Modules(sc, &mods); + ok(hr == E_FAIL, "IScriptControl_get_Modules returned: 0x%08x.\n", hr); + + str = SysAllocString(L"jscript"); + hr = IScriptControl_put_Language(sc, str); + ok(hr == S_OK, "IScriptControl_put_Language failed: 0x%08x.\n", hr); + SysFreeString(str); + + hr = IScriptControl_get_Modules(sc, &mods); + ok(hr == S_OK, "IScriptControl_get_Modules failed: 0x%08x.\n", hr); + + hr = IScriptModuleCollection_get_Count(mods, NULL); + ok(hr == E_POINTER, "IScriptModuleCollection_get_Count returned: 0x%08x.\n", hr); + hr = IScriptModuleCollection_get_Count(mods, &count); + ok(hr == S_OK, "IScriptModuleCollection_get_Count failed: 0x%08x.\n", hr); + ok(count == 1, "count is not 1, got %d.\n", count); + + V_VT(&var) = VT_I4; + V_I4(&var) = -1; + hr = IScriptModuleCollection_get_Item(mods, var, NULL); + todo_wine ok(hr == E_POINTER, "IScriptModuleCollection_get_Item returned: 0x%08x.\n", hr); + hr = IScriptModuleCollection_get_Item(mods, var, &mod); + todo_wine ok(hr == 0x800a0009, "IScriptModuleCollection_get_Item returned: 0x%08x.\n", hr); + + V_VT(&var) = VT_EMPTY; + str = SysAllocString(L"foobar"); + hr = IScriptModuleCollection_Add(mods, str, &var, &mod); + todo_wine ok(hr == E_INVALIDARG, "IScriptModuleCollection_Add returned: 0x%08x.\n", hr); + hr = IScriptModuleCollection_Add(mods, str, &var, NULL); + todo_wine ok(hr == E_POINTER, "IScriptModuleCollection_Add returned: 0x%08x.\n", hr); + V_VT(&var) = VT_DISPATCH; + V_DISPATCH(&var) = NULL; + hr = IScriptModuleCollection_Add(mods, NULL, &var, &mod); + todo_wine ok(hr == E_INVALIDARG, "IScriptModuleCollection_Add returned: 0x%08x.\n", hr); + hr = IScriptModuleCollection_Add(mods, str, &var, &mod); + todo_wine ok(hr == S_OK, "IScriptModuleCollection_Add failed: 0x%08x.\n", hr); + if (hr == S_OK) IScriptModule_Release(mod); + SysFreeString(str); + + str = SysAllocString(L"some other Module"); + hr = IScriptModuleCollection_Add(mods, str, &var, &mod); + todo_wine ok(hr == S_OK, "IScriptModuleCollection_Add failed: 0x%08x.\n", hr); + if (hr == S_OK) IScriptModule_Release(mod); + SysFreeString(str); + + /* Adding a module with the same name is invalid (case insensitive) */ + str = SysAllocString(L"FooBar"); + hr = IScriptModuleCollection_Add(mods, str, &var, &mod); + todo_wine ok(hr == E_INVALIDARG, "IScriptModuleCollection_Add failed: 0x%08x.\n", hr); + SysFreeString(str); + + hr = IScriptModuleCollection_get_Count(mods, &count); + ok(hr == S_OK, "IScriptModuleCollection_get_Count failed: 0x%08x.\n", hr); + todo_wine ok(count == 3, "count is not 3, got %d.\n", count); + V_VT(&var) = VT_I4; + V_I4(&var) = count + 1; + hr = IScriptModuleCollection_get_Item(mods, var, &mod); + todo_wine ok(hr == 0x800a0009, "IScriptModuleCollection_get_Item returned: 0x%08x.\n", hr); + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = SysAllocString(L"non-existent module"); + hr = IScriptModuleCollection_get_Item(mods, var, &mod); + todo_wine ok(hr == CTL_E_ILLEGALFUNCTIONCALL, "IScriptModuleCollection_get_Item returned: 0x%08x.\n", hr); + ok(V_VT(&var) == VT_BSTR, "var type not BSTR, got %d.\n", V_VT(&var)); + VariantClear(&var); + + V_VT(&var) = VT_I4; + V_I4(&var) = 1; + hr = IScriptModuleCollection_get_Item(mods, var, &mod); + todo_wine ok(hr == S_OK, "IScriptModuleCollection_get_Item failed: 0x%08x.\n", hr); + if (hr == S_OK) IScriptModule_Release(mod); + + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = SysAllocString(L"some other module"); + hr = IScriptModuleCollection_get_Item(mods, var, &mod); + todo_wine ok(hr == S_OK, "IScriptModuleCollection_get_Item failed: 0x%08x.\n", hr); + ok(V_VT(&var) == VT_BSTR, "var type not BSTR, got %d.\n", V_VT(&var)); + VariantClear(&var); + if (hr == S_OK) IScriptModule_Release(mod); + + V_VT(&var) = VT_R8; + V_R8(&var) = 2.0; + hr = IScriptModuleCollection_get_Item(mods, var, &mod); + todo_wine ok(hr == S_OK, "IScriptModuleCollection_get_Item failed: 0x%08x.\n", hr); + if (hr == S_OK) IScriptModule_Release(mod); + + str = SysAllocString(L"vbscript"); + hr = IScriptControl_put_Language(sc, str); + ok(hr == S_OK, "IScriptControl_put_Language failed: 0x%08x.\n", hr); + SysFreeString(str); + + hr = IScriptModuleCollection_get_Count(mods, &count); + ok(hr == S_OK, "IScriptModuleCollection_get_Count failed: 0x%08x.\n", hr); + ok(count == 1, "count is not 1, got %d.\n", count); + + IScriptModuleCollection_Release(mods); + IScriptControl_Release(sc); + + /* custom script engine */ + if (have_custom_engine) + { + /* A module collection ref keeps the control alive */ + hr = CoCreateInstance(&CLSID_ScriptControl, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, + &IID_IScriptControl, (void**)&sc); + ok(hr == S_OK, "Failed to create IScriptControl interface: 0x%08x.\n", hr); + + SET_EXPECT(CreateInstance); + SET_EXPECT(SetInterfaceSafetyOptions); + SET_EXPECT(SetScriptSite); + SET_EXPECT(QI_IActiveScriptParse); + SET_EXPECT(InitNew); + str = SysAllocString(L"testscript"); + hr = IScriptControl_put_Language(sc, str); + ok(hr == S_OK, "IScriptControl_put_Language failed: 0x%08x.\n", hr); + SysFreeString(str); + CHECK_CALLED(CreateInstance); + CHECK_CALLED(SetInterfaceSafetyOptions); + CHECK_CALLED(SetScriptSite); + CHECK_CALLED(QI_IActiveScriptParse); + CHECK_CALLED(InitNew); + + hr = IScriptControl_get_Modules(sc, &mods); + ok(hr == S_OK, "IScriptControl_get_Modules failed: 0x%08x.\n", hr); + + IActiveScriptSite_Release(site); + IScriptControl_Release(sc); + + SET_EXPECT(Close); + IScriptModuleCollection_Release(mods); + CHECK_CALLED(Close); + + hr = CoCreateInstance(&CLSID_ScriptControl, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, + &IID_IScriptControl, (void**)&sc); + ok(hr == S_OK, "Failed to create IScriptControl interface: 0x%08x.\n", hr); + + SET_EXPECT(CreateInstance); + SET_EXPECT(SetInterfaceSafetyOptions); + SET_EXPECT(SetScriptSite); + SET_EXPECT(QI_IActiveScriptParse); + SET_EXPECT(InitNew); + str = SysAllocString(L"testscript"); + hr = IScriptControl_put_Language(sc, str); + ok(hr == S_OK, "IScriptControl_put_Language failed: 0x%08x.\n", hr); + SysFreeString(str); + CHECK_CALLED(CreateInstance); + CHECK_CALLED(SetInterfaceSafetyOptions); + CHECK_CALLED(SetScriptSite); + CHECK_CALLED(QI_IActiveScriptParse); + CHECK_CALLED(InitNew); + + hr = IScriptControl_get_Modules(sc, &mods); + ok(hr == S_OK, "IScriptControl_get_Modules failed: 0x%08x.\n", hr); + + SET_EXPECT(Close); + hr = IScriptControl_put_Language(sc, NULL); + ok(hr == S_OK, "IScriptControl_put_Language failed: 0x%08x.\n", hr); + CHECK_CALLED(Close); + IScriptModuleCollection_Release(mods); + IActiveScriptSite_Release(site); + IScriptControl_Release(sc); + } +} + START_TEST(msscript) { IUnknown *unk; @@ -2162,6 +2347,7 @@ START_TEST(msscript) test_IScriptControl_AddCode(); test_IScriptControl_ExecuteStatement(); test_IScriptControl_Run(); + test_IScriptControl_get_Modules();
init_registry(FALSE);
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 63 +++++++++++++++++++++++++++++- dlls/msscript.ocx/tests/msscript.c | 32 ++++++++++++--- 2 files changed, 87 insertions(+), 8 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 91e1e94..b1e455b 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -602,6 +602,23 @@ static void release_modules(ScriptControl *control) heap_free(control->modules); }
+static UINT find_module(ScriptControl *control, BSTR name) +{ + UINT i, len = SysStringLen(name); + + if (len == sizeof("Global") - 1 && !wcsicmp(name, L"Global")) + return 0; + + for (i = 1; i < control->num_modules; i++) + { + BSTR modname = control->modules[i].name; + if (SysStringLen(modname) == len && !wcsicmp(name, modname)) + return i; + } + + return ~0; +} + static HRESULT WINAPI ScriptModule_QueryInterface(IScriptModule *iface, REFIID riid, void **ppv) { ScriptModule *This = impl_from_IScriptModule(iface); @@ -793,6 +810,26 @@ static const IScriptModuleVtbl ScriptModuleVtbl = { ScriptModule_Run };
+static HRESULT grab_module_object(ScriptControl *control, UINT index) +{ + struct module *module = &control->modules[index]; + + if (module->object) + IScriptModule_AddRef(&module->object->IScriptModule_iface); + else + { + if (!(module->object = heap_alloc(sizeof(*module->object)))) + return E_OUTOFMEMORY; + + module->object->IScriptModule_iface.lpVtbl = &ScriptModuleVtbl; + module->object->ref = 1; + module->object->idx = index; + module->object->control = control; + IScriptControl_AddRef(&control->IScriptControl_iface); + } + return S_OK; +} + static HRESULT WINAPI ScriptModuleCollection_QueryInterface(IScriptModuleCollection *iface, REFIID riid, void **ppv) { ScriptControl *This = impl_from_IScriptModuleCollection(iface); @@ -899,10 +936,32 @@ static HRESULT WINAPI ScriptModuleCollection_get_Item(IScriptModuleCollection *i IScriptModule **ppmod) { ScriptControl *This = impl_from_IScriptModuleCollection(iface); + HRESULT hr; + UINT i;
- FIXME("(%p)->(%s %p)\n", This, wine_dbgstr_variant(&index), ppmod); + TRACE("(%p)->(%s %p)\n", This, wine_dbgstr_variant(&index), ppmod);
- return E_NOTIMPL; + if (!ppmod) return E_POINTER; + + if (V_VT(&index) == VT_BSTR) + { + i = find_module(This, V_BSTR(&index)); + if (i == ~0) return CTL_E_ILLEGALFUNCTIONCALL; + } + else + { + hr = VariantChangeType(&index, &index, 0, VT_INT); + if (FAILED(hr)) return hr; + + i = V_INT(&index) - 1; + if (i >= This->num_modules) return 0x800a0009; + } + + hr = grab_module_object(This, i); + if (FAILED(hr)) return hr; + + *ppmod = &This->modules[i].object->IScriptModule_iface; + return S_OK; }
static HRESULT WINAPI ScriptModuleCollection_get_Count(IScriptModuleCollection *iface, LONG *plCount) diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index 9acf60e..a7b301d 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -2168,9 +2168,9 @@ static void test_IScriptControl_get_Modules(void) V_VT(&var) = VT_I4; V_I4(&var) = -1; hr = IScriptModuleCollection_get_Item(mods, var, NULL); - todo_wine ok(hr == E_POINTER, "IScriptModuleCollection_get_Item returned: 0x%08x.\n", hr); + ok(hr == E_POINTER, "IScriptModuleCollection_get_Item returned: 0x%08x.\n", hr); hr = IScriptModuleCollection_get_Item(mods, var, &mod); - todo_wine ok(hr == 0x800a0009, "IScriptModuleCollection_get_Item returned: 0x%08x.\n", hr); + ok(hr == 0x800a0009, "IScriptModuleCollection_get_Item returned: 0x%08x.\n", hr);
V_VT(&var) = VT_EMPTY; str = SysAllocString(L"foobar"); @@ -2205,19 +2205,28 @@ static void test_IScriptControl_get_Modules(void) V_VT(&var) = VT_I4; V_I4(&var) = count + 1; hr = IScriptModuleCollection_get_Item(mods, var, &mod); - todo_wine ok(hr == 0x800a0009, "IScriptModuleCollection_get_Item returned: 0x%08x.\n", hr); + ok(hr == 0x800a0009, "IScriptModuleCollection_get_Item returned: 0x%08x.\n", hr); V_VT(&var) = VT_BSTR; V_BSTR(&var) = SysAllocString(L"non-existent module"); hr = IScriptModuleCollection_get_Item(mods, var, &mod); - todo_wine ok(hr == CTL_E_ILLEGALFUNCTIONCALL, "IScriptModuleCollection_get_Item returned: 0x%08x.\n", hr); + ok(hr == CTL_E_ILLEGALFUNCTIONCALL, "IScriptModuleCollection_get_Item returned: 0x%08x.\n", hr); ok(V_VT(&var) == VT_BSTR, "var type not BSTR, got %d.\n", V_VT(&var)); VariantClear(&var);
V_VT(&var) = VT_I4; V_I4(&var) = 1; hr = IScriptModuleCollection_get_Item(mods, var, &mod); - todo_wine ok(hr == S_OK, "IScriptModuleCollection_get_Item failed: 0x%08x.\n", hr); - if (hr == S_OK) IScriptModule_Release(mod); + ok(hr == S_OK, "IScriptModuleCollection_get_Item failed: 0x%08x.\n", hr); + hr = IScriptModule_get_Name(mod, NULL); + todo_wine ok(hr == E_POINTER, "IScriptModule_get_Name returned: 0x%08x.\n", hr); + hr = IScriptModule_get_Name(mod, &str); + todo_wine ok(hr == S_OK, "IScriptModule_get_Name failed: 0x%08x.\n", hr); + if (hr == S_OK) SysFreeString(str); + str = SysAllocString(L"function add(a, b) { return a + b; }\n"); + hr = IScriptModule_AddCode(mod, str); + todo_wine ok(hr == S_OK, "IScriptModule_AddCode failed: 0x%08x.\n", hr); + IScriptModule_Release(mod); + SysFreeString(str);
V_VT(&var) = VT_BSTR; V_BSTR(&var) = SysAllocString(L"some other module"); @@ -2233,6 +2242,17 @@ static void test_IScriptControl_get_Modules(void) todo_wine ok(hr == S_OK, "IScriptModuleCollection_get_Item failed: 0x%08x.\n", hr); if (hr == S_OK) IScriptModule_Release(mod);
+ /* The 'Global' module is the same as the script control */ + str = SysAllocString(L"add(10, 5)"); + hr = IScriptControl_Eval(sc, str, &var); + todo_wine ok(hr == S_OK, "IScriptControl_Eval failed: 0x%08x.\n", hr); + todo_wine ok(V_VT(&var) == VT_I4 && V_I4(&var) == 15, "V_VT(var) = %d, V_I4(var) = %d.\n", V_VT(&var), V_I4(&var)); + SysFreeString(str); + str = SysAllocString(L"sub(10, 5)"); + hr = IScriptControl_Eval(sc, str, &var); + ok(FAILED(hr), "IScriptControl_Eval succeeded: 0x%08x.\n", hr); + SysFreeString(str); + str = SysAllocString(L"vbscript"); hr = IScriptControl_put_Language(sc, str); ok(hr == S_OK, "IScriptControl_put_Language failed: 0x%08x.\n", hr);
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 59 +++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 24 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index b1e455b..1c6eb26 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -259,6 +259,40 @@ static HRESULT start_script(struct ScriptControl *control) return hr; }
+static HRESULT add_script_object(ScriptHost *host, BSTR name, IDispatch *object, DWORD flags) +{ + struct named_item *item; + HRESULT hr; + + if (host_get_named_item(host, name)) + return E_INVALIDARG; + + item = heap_alloc(sizeof(*item)); + if (!item) + return E_OUTOFMEMORY; + + item->name = SysAllocString(name); + if (!item->name) + { + heap_free(item); + return E_OUTOFMEMORY; + } + IDispatch_AddRef(item->disp = object); + list_add_tail(&host->named_items, &item->entry); + + hr = IActiveScript_AddNamedItem(host->script, name, flags); + if (FAILED(hr)) + { + list_remove(&item->entry); + IDispatch_Release(item->disp); + SysFreeString(item->name); + heap_free(item); + return hr; + } + + return hr; +} + static inline ScriptControl *impl_from_IScriptControl(IScriptControl *iface) { return CONTAINING_RECORD(iface, ScriptControl, IScriptControl_iface); @@ -1423,8 +1457,6 @@ static HRESULT WINAPI ScriptControl_AddObject(IScriptControl *iface, BSTR name, { ScriptControl *This = impl_from_IScriptControl(iface); DWORD flags = SCRIPTITEM_ISVISIBLE | SCRIPTITEM_ISSOURCE; - struct named_item *item; - HRESULT hr;
TRACE("(%p)->(%s %p %x)\n", This, debugstr_w(name), object, add_members);
@@ -1434,30 +1466,9 @@ static HRESULT WINAPI ScriptControl_AddObject(IScriptControl *iface, BSTR name, if (!This->host) return E_FAIL;
- if (host_get_named_item(This->host, name)) - return E_INVALIDARG; - - item = heap_alloc(sizeof(*item)); - if (!item) - return E_OUTOFMEMORY; - - item->name = SysAllocString(name); - IDispatch_AddRef(item->disp = object); - list_add_tail(&This->host->named_items, &item->entry); - if (add_members) flags |= SCRIPTITEM_GLOBALMEMBERS; - hr = IActiveScript_AddNamedItem(This->host->script, name, flags); - if (FAILED(hr)) { - list_remove(&item->entry); - IDispatch_Release(item->disp); - SysFreeString(item->name); - heap_free(item); - return hr; - } - - - return hr; + return add_script_object(This->host, name, object, flags); }
static HRESULT WINAPI ScriptControl_Reset(IScriptControl *iface)
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 51 +++++++++- dlls/msscript.ocx/tests/msscript.c | 145 ++++++++++++++++++++++++++--- 2 files changed, 181 insertions(+), 15 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 1c6eb26..8df8c64 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -202,6 +202,11 @@ static void release_typelib(void) ITypeLib_Release(typelib); }
+static inline BOOL is_power_of_2(unsigned x) +{ + return !(x & (x - 1)); +} + static void clear_named_items(ScriptHost *host) { struct named_item *item, *item1; @@ -1014,10 +1019,52 @@ static HRESULT WINAPI ScriptModuleCollection_Add(IScriptModuleCollection *iface, VARIANT *object, IScriptModule **ppmod) { ScriptControl *This = impl_from_IScriptModuleCollection(iface); + struct module *module, *modules; + HRESULT hr;
- FIXME("(%p)->(%s %s %p)\n", This, wine_dbgstr_w(name), wine_dbgstr_variant(object), ppmod); + TRACE("(%p)->(%s %s %p)\n", This, wine_dbgstr_w(name), wine_dbgstr_variant(object), ppmod);
- return E_NOTIMPL; + if (!ppmod) return E_POINTER; + if (!name || V_VT(object) != VT_DISPATCH || find_module(This, name) != ~0) + return E_INVALIDARG; + if (!This->host) return E_FAIL; + + /* See if we need to grow the array */ + if (is_power_of_2(This->num_modules)) + { + modules = heap_realloc(This->modules, This->num_modules * 2 * sizeof(*This->modules)); + if (!modules) return E_OUTOFMEMORY; + This->modules = modules; + } + + module = &This->modules[This->num_modules]; + if (!(module->name = SysAllocString(name))) + return E_OUTOFMEMORY; + module->object = NULL; + + hr = grab_module_object(This, This->num_modules); + if (FAILED(hr)) + { + SysFreeString(module->name); + return hr; + } + + /* If no object, Windows only calls AddNamedItem without adding a NULL object */ + if (V_DISPATCH(object)) + hr = add_script_object(This->host, name, V_DISPATCH(object), 0); + else + hr = IActiveScript_AddNamedItem(This->host->script, name, SCRIPTITEM_CODEONLY); + + if (FAILED(hr)) + { + IScriptModule_Release(&module->object->IScriptModule_iface); + SysFreeString(module->name); + return hr; + } + + *ppmod = &module->object->IScriptModule_iface; + This->num_modules++; + return S_OK; }
static const IScriptModuleCollectionVtbl ScriptModuleCollectionVtbl = { diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index a7b301d..ad2f490 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -2139,6 +2139,7 @@ static void test_IScriptControl_get_Modules(void) IScriptModuleCollection *mods; IScriptModule *mod; IScriptControl *sc; + IUnknown *unknown; VARIANT var; LONG count; HRESULT hr; @@ -2175,33 +2176,33 @@ static void test_IScriptControl_get_Modules(void) V_VT(&var) = VT_EMPTY; str = SysAllocString(L"foobar"); hr = IScriptModuleCollection_Add(mods, str, &var, &mod); - todo_wine ok(hr == E_INVALIDARG, "IScriptModuleCollection_Add returned: 0x%08x.\n", hr); + ok(hr == E_INVALIDARG, "IScriptModuleCollection_Add returned: 0x%08x.\n", hr); hr = IScriptModuleCollection_Add(mods, str, &var, NULL); - todo_wine ok(hr == E_POINTER, "IScriptModuleCollection_Add returned: 0x%08x.\n", hr); + ok(hr == E_POINTER, "IScriptModuleCollection_Add returned: 0x%08x.\n", hr); V_VT(&var) = VT_DISPATCH; V_DISPATCH(&var) = NULL; hr = IScriptModuleCollection_Add(mods, NULL, &var, &mod); - todo_wine ok(hr == E_INVALIDARG, "IScriptModuleCollection_Add returned: 0x%08x.\n", hr); + ok(hr == E_INVALIDARG, "IScriptModuleCollection_Add returned: 0x%08x.\n", hr); hr = IScriptModuleCollection_Add(mods, str, &var, &mod); - todo_wine ok(hr == S_OK, "IScriptModuleCollection_Add failed: 0x%08x.\n", hr); - if (hr == S_OK) IScriptModule_Release(mod); + ok(hr == S_OK, "IScriptModuleCollection_Add failed: 0x%08x.\n", hr); + IScriptModule_Release(mod); SysFreeString(str);
str = SysAllocString(L"some other Module"); hr = IScriptModuleCollection_Add(mods, str, &var, &mod); - todo_wine ok(hr == S_OK, "IScriptModuleCollection_Add failed: 0x%08x.\n", hr); - if (hr == S_OK) IScriptModule_Release(mod); + ok(hr == S_OK, "IScriptModuleCollection_Add failed: 0x%08x.\n", hr); + IScriptModule_Release(mod); SysFreeString(str);
/* Adding a module with the same name is invalid (case insensitive) */ str = SysAllocString(L"FooBar"); hr = IScriptModuleCollection_Add(mods, str, &var, &mod); - todo_wine ok(hr == E_INVALIDARG, "IScriptModuleCollection_Add failed: 0x%08x.\n", hr); + ok(hr == E_INVALIDARG, "IScriptModuleCollection_Add failed: 0x%08x.\n", hr); SysFreeString(str);
hr = IScriptModuleCollection_get_Count(mods, &count); ok(hr == S_OK, "IScriptModuleCollection_get_Count failed: 0x%08x.\n", hr); - todo_wine ok(count == 3, "count is not 3, got %d.\n", count); + ok(count == 3, "count is not 3, got %d.\n", count); V_VT(&var) = VT_I4; V_I4(&var) = count + 1; hr = IScriptModuleCollection_get_Item(mods, var, &mod); @@ -2231,16 +2232,26 @@ static void test_IScriptControl_get_Modules(void) V_VT(&var) = VT_BSTR; V_BSTR(&var) = SysAllocString(L"some other module"); hr = IScriptModuleCollection_get_Item(mods, var, &mod); - todo_wine ok(hr == S_OK, "IScriptModuleCollection_get_Item failed: 0x%08x.\n", hr); + ok(hr == S_OK, "IScriptModuleCollection_get_Item failed: 0x%08x.\n", hr); ok(V_VT(&var) == VT_BSTR, "var type not BSTR, got %d.\n", V_VT(&var)); VariantClear(&var); - if (hr == S_OK) IScriptModule_Release(mod); + hr = IScriptModule_get_Name(mod, &str); + todo_wine ok(hr == S_OK, "IScriptModule_get_Name failed: 0x%08x.\n", hr); + IScriptModule_Release(mod); + if (hr == S_OK) SysFreeString(str);
V_VT(&var) = VT_R8; V_R8(&var) = 2.0; hr = IScriptModuleCollection_get_Item(mods, var, &mod); - todo_wine ok(hr == S_OK, "IScriptModuleCollection_get_Item failed: 0x%08x.\n", hr); - if (hr == S_OK) IScriptModule_Release(mod); + ok(hr == S_OK, "IScriptModuleCollection_get_Item failed: 0x%08x.\n", hr); + hr = IScriptModule_get_Name(mod, &str); + todo_wine ok(hr == S_OK, "IScriptModule_get_Name failed: 0x%08x.\n", hr); + if (hr == S_OK) SysFreeString(str); + str = SysAllocString(L"function sub(a, b) { return a - b; }\n"); + hr = IScriptModule_AddCode(mod, str); + todo_wine ok(hr == S_OK, "IScriptModule_AddCode failed: 0x%08x.\n", hr); + IScriptModule_Release(mod); + SysFreeString(str);
/* The 'Global' module is the same as the script control */ str = SysAllocString(L"add(10, 5)"); @@ -2253,14 +2264,31 @@ static void test_IScriptControl_get_Modules(void) ok(FAILED(hr), "IScriptControl_Eval succeeded: 0x%08x.\n", hr); SysFreeString(str);
+ /* Grab a module ref and change the language to something valid */ + V_VT(&var) = VT_I2; + V_I2(&var) = 3; + hr = IScriptModuleCollection_get_Item(mods, var, &mod); + ok(hr == S_OK, "IScriptModuleCollection_get_Item failed: 0x%08x.\n", hr); str = SysAllocString(L"vbscript"); hr = IScriptControl_put_Language(sc, str); ok(hr == S_OK, "IScriptControl_put_Language failed: 0x%08x.\n", hr); SysFreeString(str);
+ /* The module collection changes and module ref is invalid */ hr = IScriptModuleCollection_get_Count(mods, &count); ok(hr == S_OK, "IScriptModuleCollection_get_Count failed: 0x%08x.\n", hr); ok(count == 1, "count is not 1, got %d.\n", count); + hr = IScriptModule_get_Name(mod, &str); + todo_wine ok(hr == E_FAIL, "IScriptModule_get_Name returned: 0x%08x.\n", hr); + str = SysAllocString(L"function closed() { }\n"); + hr = IScriptModule_AddCode(mod, str); + todo_wine ok(hr == E_FAIL, "IScriptModule_AddCode failed: 0x%08x.\n", hr); + SysFreeString(str); + str = SysAllocString(L"sub closed\nend sub"); + hr = IScriptModule_AddCode(mod, str); + todo_wine ok(hr == E_FAIL, "IScriptModule_AddCode failed: 0x%08x.\n", hr); + IScriptModule_Release(mod); + SysFreeString(str);
IScriptModuleCollection_Release(mods); IScriptControl_Release(sc); @@ -2268,6 +2296,8 @@ static void test_IScriptControl_get_Modules(void) /* custom script engine */ if (have_custom_engine) { + BSTR code_str; + /* A module collection ref keeps the control alive */ hr = CoCreateInstance(&CLSID_ScriptControl, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, &IID_IScriptControl, (void**)&sc); @@ -2298,6 +2328,7 @@ static void test_IScriptControl_get_Modules(void) IScriptModuleCollection_Release(mods); CHECK_CALLED(Close);
+ /* Add a module with a non-null object and add some code to it */ hr = CoCreateInstance(&CLSID_ScriptControl, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, &IID_IScriptControl, (void**)&sc); ok(hr == S_OK, "Failed to create IScriptControl interface: 0x%08x.\n", hr); @@ -2320,6 +2351,36 @@ static void test_IScriptControl_get_Modules(void) hr = IScriptControl_get_Modules(sc, &mods); ok(hr == S_OK, "IScriptControl_get_Modules failed: 0x%08x.\n", hr);
+ SET_EXPECT(AddNamedItem); + str = SysAllocString(L"modname"); + AddNamedItem_expected_name = str; + AddNamedItem_expected_flags = 0; + V_VT(&var) = VT_DISPATCH; + V_DISPATCH(&var) = &testdisp; + hr = IScriptModuleCollection_Add(mods, str, &var, &mod); + ok(hr == S_OK, "IScriptModuleCollection_Add failed: 0x%08x.\n", hr); + VariantClear(&var); + CHECK_CALLED(AddNamedItem); + + unknown = (IUnknown*)0xdeadbeef; + hr = IActiveScriptSite_GetItemInfo(site, str, SCRIPTINFO_IUNKNOWN, &unknown, NULL); + ok(hr == S_OK, "IActiveScriptSite_GetItemInfo failed: 0x%08x.\n", hr); + ok(unknown == (IUnknown*)&testdisp, "Unexpected IUnknown for the item: %p.\n", unknown); + IUnknown_Release(unknown); + + SET_EXPECT(SetScriptState_STARTED); + SET_EXPECT(ParseScriptText); + parse_item_name = str; + parse_flags = SCRIPTTEXT_ISVISIBLE; + code_str = SysAllocString(L"some code"); + hr = IScriptModule_AddCode(mod, code_str); + todo_wine ok(hr == S_OK, "IScriptControl_AddCode failed: 0x%08x.\n", hr); + todo_wine CHECK_CALLED(SetScriptState_STARTED); + todo_wine CHECK_CALLED(ParseScriptText); + SysFreeString(code_str); + SysFreeString(str); + + /* Keep the module ref before changing the language */ SET_EXPECT(Close); hr = IScriptControl_put_Language(sc, NULL); ok(hr == S_OK, "IScriptControl_put_Language failed: 0x%08x.\n", hr); @@ -2327,6 +2388,64 @@ static void test_IScriptControl_get_Modules(void) IScriptModuleCollection_Release(mods); IActiveScriptSite_Release(site); IScriptControl_Release(sc); + IScriptModule_Release(mod); + + /* Now try holding a module ref while closing the script */ + hr = CoCreateInstance(&CLSID_ScriptControl, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, + &IID_IScriptControl, (void**)&sc); + ok(hr == S_OK, "Failed to create IScriptControl interface: 0x%08x.\n", hr); + + SET_EXPECT(CreateInstance); + SET_EXPECT(SetInterfaceSafetyOptions); + SET_EXPECT(SetScriptSite); + SET_EXPECT(QI_IActiveScriptParse); + SET_EXPECT(InitNew); + str = SysAllocString(L"testscript"); + hr = IScriptControl_put_Language(sc, str); + ok(hr == S_OK, "IScriptControl_put_Language failed: 0x%08x.\n", hr); + SysFreeString(str); + CHECK_CALLED(CreateInstance); + CHECK_CALLED(SetInterfaceSafetyOptions); + CHECK_CALLED(SetScriptSite); + CHECK_CALLED(QI_IActiveScriptParse); + CHECK_CALLED(InitNew); + + hr = IScriptControl_get_Modules(sc, &mods); + ok(hr == S_OK, "IScriptControl_get_Modules failed: 0x%08x.\n", hr); + + SET_EXPECT(AddNamedItem); + str = SysAllocString(L"foo"); + AddNamedItem_expected_name = str; + AddNamedItem_expected_flags = SCRIPTITEM_CODEONLY; + V_VT(&var) = VT_DISPATCH; + V_DISPATCH(&var) = NULL; + hr = IScriptModuleCollection_Add(mods, str, &var, &mod); + ok(hr == S_OK, "IScriptModuleCollection_Add failed: 0x%08x.\n", hr); + VariantClear(&var); + CHECK_CALLED(AddNamedItem); + + unknown = (IUnknown*)0xdeadbeef; + hr = IActiveScriptSite_GetItemInfo(site, str, SCRIPTINFO_IUNKNOWN, &unknown, NULL); + ok(hr == TYPE_E_ELEMENTNOTFOUND, "IActiveScriptSite_GetItemInfo returned: 0x%08x.\n", hr); + IScriptModuleCollection_Release(mods); + IActiveScriptSite_Release(site); + IScriptControl_Release(sc); + + SET_EXPECT(SetScriptState_STARTED); + SET_EXPECT(ParseScriptText); + parse_item_name = str; + parse_flags = SCRIPTTEXT_ISVISIBLE; + code_str = SysAllocString(L"code after close"); + hr = IScriptModule_AddCode(mod, code_str); + todo_wine ok(hr == S_OK, "IScriptControl_AddCode failed: 0x%08x.\n", hr); + todo_wine CHECK_CALLED(SetScriptState_STARTED); + todo_wine CHECK_CALLED(ParseScriptText); + SysFreeString(code_str); + SysFreeString(str); + + SET_EXPECT(Close); + IScriptModule_Release(mod); + CHECK_CALLED(Close); } }
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 11 +++++++++-- dlls/msscript.ocx/tests/msscript.c | 19 +++++++++++-------- 2 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 8df8c64..cd0a21b 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -772,10 +772,17 @@ static HRESULT WINAPI ScriptModule_Invoke(IScriptModule *iface, DISPID dispIdMem static HRESULT WINAPI ScriptModule_get_Name(IScriptModule *iface, BSTR *pbstrName) { ScriptModule *This = impl_from_IScriptModule(iface); + BSTR module_name;
- FIXME("(%p)->(%p)\n", This, pbstrName); + TRACE("(%p)->(%p)\n", This, pbstrName);
- return E_NOTIMPL; + if (!pbstrName) return E_POINTER; + if (!This->control) return E_FAIL; + + module_name = This->control->modules[This->idx].name; + + *pbstrName = SysAllocString(module_name ? module_name : L"Global"); + return *pbstrName ? S_OK : E_OUTOFMEMORY; }
static HRESULT WINAPI ScriptModule_get_CodeObject(IScriptModule *iface, IDispatch **ppdispObject) diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index ad2f490..c5e7695 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -2219,10 +2219,11 @@ static void test_IScriptControl_get_Modules(void) hr = IScriptModuleCollection_get_Item(mods, var, &mod); ok(hr == S_OK, "IScriptModuleCollection_get_Item failed: 0x%08x.\n", hr); hr = IScriptModule_get_Name(mod, NULL); - todo_wine ok(hr == E_POINTER, "IScriptModule_get_Name returned: 0x%08x.\n", hr); + ok(hr == E_POINTER, "IScriptModule_get_Name returned: 0x%08x.\n", hr); hr = IScriptModule_get_Name(mod, &str); - todo_wine ok(hr == S_OK, "IScriptModule_get_Name failed: 0x%08x.\n", hr); - if (hr == S_OK) SysFreeString(str); + ok(hr == S_OK, "IScriptModule_get_Name failed: 0x%08x.\n", hr); + ok(!lstrcmpW(str, L"Global"), "got %s.\n", wine_dbgstr_w(str)); + SysFreeString(str); str = SysAllocString(L"function add(a, b) { return a + b; }\n"); hr = IScriptModule_AddCode(mod, str); todo_wine ok(hr == S_OK, "IScriptModule_AddCode failed: 0x%08x.\n", hr); @@ -2236,17 +2237,19 @@ static void test_IScriptControl_get_Modules(void) ok(V_VT(&var) == VT_BSTR, "var type not BSTR, got %d.\n", V_VT(&var)); VariantClear(&var); hr = IScriptModule_get_Name(mod, &str); - todo_wine ok(hr == S_OK, "IScriptModule_get_Name failed: 0x%08x.\n", hr); + ok(hr == S_OK, "IScriptModule_get_Name failed: 0x%08x.\n", hr); + ok(!lstrcmpW(str, L"some other Module"), "got %s.\n", wine_dbgstr_w(str)); IScriptModule_Release(mod); - if (hr == S_OK) SysFreeString(str); + SysFreeString(str);
V_VT(&var) = VT_R8; V_R8(&var) = 2.0; hr = IScriptModuleCollection_get_Item(mods, var, &mod); ok(hr == S_OK, "IScriptModuleCollection_get_Item failed: 0x%08x.\n", hr); hr = IScriptModule_get_Name(mod, &str); - todo_wine ok(hr == S_OK, "IScriptModule_get_Name failed: 0x%08x.\n", hr); - if (hr == S_OK) SysFreeString(str); + ok(hr == S_OK, "IScriptModule_get_Name failed: 0x%08x.\n", hr); + ok(!lstrcmpW(str, L"foobar"), "got %s.\n", wine_dbgstr_w(str)); + SysFreeString(str); str = SysAllocString(L"function sub(a, b) { return a - b; }\n"); hr = IScriptModule_AddCode(mod, str); todo_wine ok(hr == S_OK, "IScriptModule_AddCode failed: 0x%08x.\n", hr); @@ -2279,7 +2282,7 @@ static void test_IScriptControl_get_Modules(void) ok(hr == S_OK, "IScriptModuleCollection_get_Count failed: 0x%08x.\n", hr); ok(count == 1, "count is not 1, got %d.\n", count); hr = IScriptModule_get_Name(mod, &str); - todo_wine ok(hr == E_FAIL, "IScriptModule_get_Name returned: 0x%08x.\n", hr); + ok(hr == E_FAIL, "IScriptModule_get_Name returned: 0x%08x.\n", hr); str = SysAllocString(L"function closed() { }\n"); hr = IScriptModule_AddCode(mod, str); todo_wine ok(hr == E_FAIL, "IScriptModule_AddCode failed: 0x%08x.\n", hr);
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index cd0a21b..d966869 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -68,6 +68,7 @@ struct named_item {
struct module { BSTR name; + IDispatch *script_dispatch; ScriptModule *object; };
@@ -86,7 +87,6 @@ typedef struct ScriptHost {
IActiveScript *script; IActiveScriptParse *parse; - IDispatch *script_dispatch; SCRIPTSTATE script_state; CLSID clsid;
@@ -230,14 +230,15 @@ static struct named_item *host_get_named_item(ScriptHost *host, const WCHAR *nam return NULL; }
-static HRESULT get_script_dispatch(struct ScriptControl *control, IDispatch **disp) +static HRESULT get_script_dispatch(ScriptControl *control, struct module *module, IDispatch **disp) { - if (!control->host->script_dispatch) + if (!module->script_dispatch) { - HRESULT hr = IActiveScript_GetScriptDispatch(control->host->script, NULL, &control->host->script_dispatch); + HRESULT hr = IActiveScript_GetScriptDispatch(control->host->script, + module->name, &module->script_dispatch); if (FAILED(hr)) return hr; } - *disp = control->host->script_dispatch; + *disp = module->script_dispatch; return S_OK; }
@@ -414,10 +415,7 @@ static void release_script_engine(ScriptHost *host)
if (host->parse) IActiveScriptParse_Release(host->parse); - if (host->script_dispatch) - IDispatch_Release(host->script_dispatch);
- host->script_dispatch = NULL; host->parse = NULL; host->script = NULL;
@@ -635,6 +633,8 @@ static void release_modules(ScriptControl *control) module->object->control = NULL; IScriptControl_Release(&control->IScriptControl_iface); } + if (module->script_dispatch) + IDispatch_Release(module->script_dispatch); SysFreeString(module->name); } while (i--);
@@ -1047,6 +1047,7 @@ static HRESULT WINAPI ScriptModuleCollection_Add(IScriptModuleCollection *iface, module = &This->modules[This->num_modules]; if (!(module->name = SysAllocString(name))) return E_OUTOFMEMORY; + module->script_dispatch = NULL; module->object = NULL;
hr = grab_module_object(This, This->num_modules); @@ -1106,7 +1107,6 @@ static HRESULT init_script_host(const CLSID *clsid, ScriptHost **ret) host->ref = 1; host->script = NULL; host->parse = NULL; - host->script_dispatch = NULL; host->clsid = *clsid; list_init(&host->named_items);
@@ -1602,11 +1602,12 @@ static HRESULT WINAPI ScriptControl_Run(IScriptControl *iface, BSTR procedure_na V_VT(res) = VT_EMPTY; if (sa->cDims == 0) return DISP_E_BADINDEX; if (!(sa->fFeatures & FADF_VARIANT)) return DISP_E_BADVARTYPE; + if (!This->modules) return E_FAIL;
hr = start_script(This); if (FAILED(hr)) return hr;
- hr = get_script_dispatch(This, &disp); + hr = get_script_dispatch(This, &This->modules[0], &disp); if (FAILED(hr)) return hr;
hr = IDispatch_GetIDsOfNames(disp, &IID_NULL, &procedure_name, 1, LOCALE_USER_DEFAULT, &dispid);
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
So it's near the other helpers and will be needed for next patch.
dlls/msscript.ocx/msscript.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index d966869..01df485 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -299,6 +299,20 @@ static HRESULT add_script_object(ScriptHost *host, BSTR name, IDispatch *object, return hr; }
+static HRESULT parse_script_text(ScriptControl *control, BSTR script_text, DWORD flag, VARIANT *res) +{ + EXCEPINFO excepinfo; + HRESULT hr; + + hr = start_script(control); + if (FAILED(hr)) return hr; + + hr = IActiveScriptParse_ParseScriptText(control->host->parse, script_text, NULL, + NULL, NULL, 0, 1, flag, res, &excepinfo); + /* FIXME: more error handling */ + return hr; +} + static inline ScriptControl *impl_from_IScriptControl(IScriptControl *iface) { return CONTAINING_RECORD(iface, ScriptControl, IScriptControl_iface); @@ -1538,20 +1552,6 @@ static HRESULT WINAPI ScriptControl_Reset(IScriptControl *iface) return set_script_state(This->host, SCRIPTSTATE_INITIALIZED); }
-static HRESULT parse_script_text(ScriptControl *control, BSTR script_text, DWORD flag, VARIANT *res) -{ - EXCEPINFO excepinfo; - HRESULT hr; - - hr = start_script(control); - if (FAILED(hr)) return hr; - - hr = IActiveScriptParse_ParseScriptText(control->host->parse, script_text, NULL, - NULL, NULL, 0, 1, flag, res, &excepinfo); - /* FIXME: more error handling */ - return hr; -} - static HRESULT WINAPI ScriptControl_AddCode(IScriptControl *iface, BSTR code) { ScriptControl *This = impl_from_IScriptControl(iface);
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 39 +++++++++++++++++++++--------- dlls/msscript.ocx/tests/msscript.c | 24 +++++++++--------- 2 files changed, 40 insertions(+), 23 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 01df485..ab8c551 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -299,7 +299,8 @@ static HRESULT add_script_object(ScriptHost *host, BSTR name, IDispatch *object, return hr; }
-static HRESULT parse_script_text(ScriptControl *control, BSTR script_text, DWORD flag, VARIANT *res) +static HRESULT parse_script_text(ScriptControl *control, struct module *module, BSTR script_text, + DWORD flag, VARIANT *res) { EXCEPINFO excepinfo; HRESULT hr; @@ -307,7 +308,7 @@ static HRESULT parse_script_text(ScriptControl *control, BSTR script_text, DWORD hr = start_script(control); if (FAILED(hr)) return hr;
- hr = IActiveScriptParse_ParseScriptText(control->host->parse, script_text, NULL, + hr = IActiveScriptParse_ParseScriptText(control->host->parse, script_text, module->name, NULL, NULL, 0, 1, flag, res, &excepinfo); /* FIXME: more error handling */ return hr; @@ -821,27 +822,37 @@ static HRESULT WINAPI ScriptModule_AddCode(IScriptModule *iface, BSTR code) { ScriptModule *This = impl_from_IScriptModule(iface);
- FIXME("(%p)->(%s)\n", This, debugstr_w(code)); + TRACE("(%p)->(%s)\n", This, debugstr_w(code));
- return E_NOTIMPL; + if (!This->control) + return E_FAIL; + return parse_script_text(This->control, &This->control->modules[This->idx], code, SCRIPTTEXT_ISVISIBLE, NULL); }
static HRESULT WINAPI ScriptModule_Eval(IScriptModule *iface, BSTR expression, VARIANT *res) { ScriptModule *This = impl_from_IScriptModule(iface);
- FIXME("(%p)->(%s, %p)\n", This, debugstr_w(expression), res); + TRACE("(%p)->(%s, %p)\n", This, debugstr_w(expression), res);
- return E_NOTIMPL; + if (!res) + return E_POINTER; + V_VT(res) = VT_EMPTY; + + if (!This->control) + return E_FAIL; + return parse_script_text(This->control, &This->control->modules[This->idx], expression, SCRIPTTEXT_ISEXPRESSION, res); }
static HRESULT WINAPI ScriptModule_ExecuteStatement(IScriptModule *iface, BSTR statement) { ScriptModule *This = impl_from_IScriptModule(iface);
- FIXME("(%p)->(%s)\n", This, debugstr_w(statement)); + TRACE("(%p)->(%s)\n", This, debugstr_w(statement));
- return E_NOTIMPL; + if (!This->control) + return E_FAIL; + return parse_script_text(This->control, &This->control->modules[This->idx], statement, 0, NULL); }
static HRESULT WINAPI ScriptModule_Run(IScriptModule *iface, BSTR procedure_name, SAFEARRAY **parameters, VARIANT *res) @@ -1558,7 +1569,9 @@ static HRESULT WINAPI ScriptControl_AddCode(IScriptControl *iface, BSTR code)
TRACE("(%p)->(%s).\n", This, debugstr_w(code));
- return parse_script_text(This, code, SCRIPTTEXT_ISVISIBLE, NULL); + if (!This->modules) + return E_FAIL; + return parse_script_text(This, &This->modules[0], code, SCRIPTTEXT_ISVISIBLE, NULL); }
static HRESULT WINAPI ScriptControl_Eval(IScriptControl *iface, BSTR expression, VARIANT *res) @@ -1571,7 +1584,9 @@ static HRESULT WINAPI ScriptControl_Eval(IScriptControl *iface, BSTR expression, return E_POINTER; V_VT(res) = VT_EMPTY;
- return parse_script_text(This, expression, SCRIPTTEXT_ISEXPRESSION, res); + if (!This->modules) + return E_FAIL; + return parse_script_text(This, &This->modules[0], expression, SCRIPTTEXT_ISEXPRESSION, res); }
static HRESULT WINAPI ScriptControl_ExecuteStatement(IScriptControl *iface, BSTR statement) @@ -1580,7 +1595,9 @@ static HRESULT WINAPI ScriptControl_ExecuteStatement(IScriptControl *iface, BSTR
TRACE("(%p)->(%s)\n", This, debugstr_w(statement));
- return parse_script_text(This, statement, 0, NULL); + if (!This->modules) + return E_FAIL; + return parse_script_text(This, &This->modules[0], statement, 0, NULL); }
static HRESULT WINAPI ScriptControl_Run(IScriptControl *iface, BSTR procedure_name, SAFEARRAY **parameters, VARIANT *res) diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index c5e7695..8d2c1b8 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -2226,7 +2226,7 @@ static void test_IScriptControl_get_Modules(void) SysFreeString(str); str = SysAllocString(L"function add(a, b) { return a + b; }\n"); hr = IScriptModule_AddCode(mod, str); - todo_wine ok(hr == S_OK, "IScriptModule_AddCode failed: 0x%08x.\n", hr); + ok(hr == S_OK, "IScriptModule_AddCode failed: 0x%08x.\n", hr); IScriptModule_Release(mod); SysFreeString(str);
@@ -2252,15 +2252,15 @@ static void test_IScriptControl_get_Modules(void) SysFreeString(str); str = SysAllocString(L"function sub(a, b) { return a - b; }\n"); hr = IScriptModule_AddCode(mod, str); - todo_wine ok(hr == S_OK, "IScriptModule_AddCode failed: 0x%08x.\n", hr); + ok(hr == S_OK, "IScriptModule_AddCode failed: 0x%08x.\n", hr); IScriptModule_Release(mod); SysFreeString(str);
/* The 'Global' module is the same as the script control */ str = SysAllocString(L"add(10, 5)"); hr = IScriptControl_Eval(sc, str, &var); - todo_wine ok(hr == S_OK, "IScriptControl_Eval failed: 0x%08x.\n", hr); - todo_wine ok(V_VT(&var) == VT_I4 && V_I4(&var) == 15, "V_VT(var) = %d, V_I4(var) = %d.\n", V_VT(&var), V_I4(&var)); + ok(hr == S_OK, "IScriptControl_Eval failed: 0x%08x.\n", hr); + ok(V_VT(&var) == VT_I4 && V_I4(&var) == 15, "V_VT(var) = %d, V_I4(var) = %d.\n", V_VT(&var), V_I4(&var)); SysFreeString(str); str = SysAllocString(L"sub(10, 5)"); hr = IScriptControl_Eval(sc, str, &var); @@ -2285,11 +2285,11 @@ static void test_IScriptControl_get_Modules(void) ok(hr == E_FAIL, "IScriptModule_get_Name returned: 0x%08x.\n", hr); str = SysAllocString(L"function closed() { }\n"); hr = IScriptModule_AddCode(mod, str); - todo_wine ok(hr == E_FAIL, "IScriptModule_AddCode failed: 0x%08x.\n", hr); + ok(hr == E_FAIL, "IScriptModule_AddCode failed: 0x%08x.\n", hr); SysFreeString(str); str = SysAllocString(L"sub closed\nend sub"); hr = IScriptModule_AddCode(mod, str); - todo_wine ok(hr == E_FAIL, "IScriptModule_AddCode failed: 0x%08x.\n", hr); + ok(hr == E_FAIL, "IScriptModule_AddCode failed: 0x%08x.\n", hr); IScriptModule_Release(mod); SysFreeString(str);
@@ -2377,9 +2377,9 @@ static void test_IScriptControl_get_Modules(void) parse_flags = SCRIPTTEXT_ISVISIBLE; code_str = SysAllocString(L"some code"); hr = IScriptModule_AddCode(mod, code_str); - todo_wine ok(hr == S_OK, "IScriptControl_AddCode failed: 0x%08x.\n", hr); - todo_wine CHECK_CALLED(SetScriptState_STARTED); - todo_wine CHECK_CALLED(ParseScriptText); + ok(hr == S_OK, "IScriptControl_AddCode failed: 0x%08x.\n", hr); + CHECK_CALLED(SetScriptState_STARTED); + CHECK_CALLED(ParseScriptText); SysFreeString(code_str); SysFreeString(str);
@@ -2440,9 +2440,9 @@ static void test_IScriptControl_get_Modules(void) parse_flags = SCRIPTTEXT_ISVISIBLE; code_str = SysAllocString(L"code after close"); hr = IScriptModule_AddCode(mod, code_str); - todo_wine ok(hr == S_OK, "IScriptControl_AddCode failed: 0x%08x.\n", hr); - todo_wine CHECK_CALLED(SetScriptState_STARTED); - todo_wine CHECK_CALLED(ParseScriptText); + ok(hr == S_OK, "IScriptControl_AddCode failed: 0x%08x.\n", hr); + CHECK_CALLED(SetScriptState_STARTED); + CHECK_CALLED(ParseScriptText); SysFreeString(code_str); SysFreeString(str);
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 158 ++++++++++++++++++++++++++++- dlls/msscript.ocx/tests/msscript.c | 56 +++++++++- 2 files changed, 211 insertions(+), 3 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index ab8c551..62560b6 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -72,6 +72,13 @@ struct module { ScriptModule *object; };
+struct module_enum { + IEnumVARIANT IEnumVARIANT_iface; + LONG ref; + UINT pos; + ScriptControl *control; +}; + struct ScriptModule { IScriptModule IScriptModule_iface; LONG ref; @@ -384,6 +391,11 @@ static inline ScriptHost *impl_from_IServiceProvider(IServiceProvider *iface) return CONTAINING_RECORD(iface, ScriptHost, IServiceProvider_iface); }
+static inline struct module_enum *module_enum_from_IEnumVARIANT(IEnumVARIANT *iface) +{ + return CONTAINING_RECORD(iface, struct module_enum, IEnumVARIANT_iface); +} + /* IActiveScriptSite */ static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, REFIID riid, void **ppv) { @@ -901,6 +913,135 @@ static HRESULT grab_module_object(ScriptControl *control, UINT index) return S_OK; }
+static HRESULT WINAPI module_enum_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv) +{ + struct module_enum *This = module_enum_from_IEnumVARIANT(iface); + + if (IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IEnumVARIANT, riid)) + { + *ppv = &This->IEnumVARIANT_iface; + } + else + { + WARN("unsupported interface: (%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI module_enum_AddRef(IEnumVARIANT *iface) +{ + struct module_enum *This = module_enum_from_IEnumVARIANT(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + return ref; +} + +static ULONG WINAPI module_enum_Release(IEnumVARIANT *iface) +{ + struct module_enum *This = module_enum_from_IEnumVARIANT(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + if (!ref) + { + IScriptControl_Release(&This->control->IScriptControl_iface); + heap_free(This); + } + + return ref; +} + +static HRESULT WINAPI module_enum_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched) +{ + struct module_enum *This = module_enum_from_IEnumVARIANT(iface); + UINT i, num; + HRESULT hr; + + TRACE("(%p)->(%u %p %p)\n", This, celt, rgVar, pCeltFetched); + + if (!rgVar) return E_POINTER; + + num = min(celt, This->control->num_modules - This->pos); + for (i = 0; i < num; i++) + { + if (FAILED(hr = grab_module_object(This->control, This->pos))) + { + while (i--) + VariantClear(rgVar + i); + if (pCeltFetched) *pCeltFetched = 0; + return hr; + } + V_VT(rgVar + i) = VT_DISPATCH; + V_DISPATCH(rgVar + i) = (IDispatch*)(&This->control->modules[This->pos].object->IScriptModule_iface); + This->pos++; + } + + if (pCeltFetched) *pCeltFetched = i; + return i == celt ? S_OK : S_FALSE; +} + +static HRESULT WINAPI module_enum_Skip(IEnumVARIANT *iface, ULONG celt) +{ + struct module_enum *This = module_enum_from_IEnumVARIANT(iface); + + TRACE("(%p)->(%u)\n", This, celt); + + if (This->control->num_modules - This->pos < celt) + { + This->pos = This->control->num_modules; + return S_FALSE; + } + This->pos += celt; + return S_OK; +} + +static HRESULT WINAPI module_enum_Reset(IEnumVARIANT *iface) +{ + struct module_enum *This = module_enum_from_IEnumVARIANT(iface); + + TRACE("(%p)\n", This); + + This->pos = 0; + return S_OK; +} + +static HRESULT WINAPI module_enum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum) +{ + struct module_enum *This = module_enum_from_IEnumVARIANT(iface); + struct module_enum *clone; + + TRACE("(%p)->(%p)\n", This, ppEnum); + + if (!ppEnum) return E_POINTER; + + if (!(clone = heap_alloc(sizeof(*clone)))) + return E_OUTOFMEMORY; + + *clone = *This; + clone->ref = 1; + IScriptControl_AddRef(&This->control->IScriptControl_iface); + + *ppEnum = &clone->IEnumVARIANT_iface; + return S_OK; +} + +static const IEnumVARIANTVtbl module_enum_vtbl = { + module_enum_QueryInterface, + module_enum_AddRef, + module_enum_Release, + module_enum_Next, + module_enum_Skip, + module_enum_Reset, + module_enum_Clone +}; + static HRESULT WINAPI ScriptModuleCollection_QueryInterface(IScriptModuleCollection *iface, REFIID riid, void **ppv) { ScriptControl *This = impl_from_IScriptModuleCollection(iface); @@ -997,10 +1138,23 @@ static HRESULT WINAPI ScriptModuleCollection_Invoke(IScriptModuleCollection *ifa static HRESULT WINAPI ScriptModuleCollection_get__NewEnum(IScriptModuleCollection *iface, IUnknown **ppenumContexts) { ScriptControl *This = impl_from_IScriptModuleCollection(iface); + struct module_enum *module_enum;
- FIXME("(%p)->(%p)\n", This, ppenumContexts); + TRACE("(%p)->(%p)\n", This, ppenumContexts);
- return E_NOTIMPL; + if (!ppenumContexts) return E_POINTER; + + if (!(module_enum = heap_alloc(sizeof(*module_enum)))) + return E_OUTOFMEMORY; + + module_enum->IEnumVARIANT_iface.lpVtbl = &module_enum_vtbl; + module_enum->ref = 1; + module_enum->pos = 0; + module_enum->control = This; + IScriptControl_AddRef(&This->IScriptControl_iface); + + *ppenumContexts = (IUnknown*)&module_enum->IEnumVARIANT_iface; + return S_OK; }
static HRESULT WINAPI ScriptModuleCollection_get_Item(IScriptModuleCollection *iface, VARIANT index, diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index 8d2c1b8..35c5141 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -2136,14 +2136,17 @@ static void test_IScriptControl_Run(void)
static void test_IScriptControl_get_Modules(void) { + IEnumVARIANT *enumvar, *enumvar2; IScriptModuleCollection *mods; + VARIANT var, vars[3]; IScriptModule *mod; IScriptControl *sc; IUnknown *unknown; - VARIANT var; + ULONG fetched; LONG count; HRESULT hr; BSTR str; + UINT i;
hr = CoCreateInstance(&CLSID_ScriptControl, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, &IID_IScriptControl, (void**)&sc); @@ -2188,6 +2191,16 @@ static void test_IScriptControl_get_Modules(void) IScriptModule_Release(mod); SysFreeString(str);
+ /* Grab an enumerator before we add another module */ + hr = IScriptModuleCollection_get__NewEnum(mods, NULL); + ok(hr == E_POINTER, "IScriptModuleCollection_get__NewEnum returned: 0x%08x.\n", hr); + hr = IScriptModuleCollection_get__NewEnum(mods, &unknown); + ok(hr == S_OK, "IScriptModuleCollection_get__NewEnum failed: 0x%08x.\n", hr); + hr = IUnknown_QueryInterface(unknown, &IID_IEnumVARIANT, (void**)&enumvar); + ok(hr == S_OK, "Failed to query for IEnumVARIANT: 0x%08x.\n", hr); + ok((char*)unknown == (char*)enumvar, "unknown and enumvar are not the same (%p vs %p).\n", unknown, enumvar); + IUnknown_Release(unknown); + str = SysAllocString(L"some other Module"); hr = IScriptModuleCollection_Add(mods, str, &var, &mod); ok(hr == S_OK, "IScriptModuleCollection_Add failed: 0x%08x.\n", hr); @@ -2256,6 +2269,47 @@ static void test_IScriptControl_get_Modules(void) IScriptModule_Release(mod); SysFreeString(str);
+ /* Test the enumerator, should be updated */ + fetched = 0xdeadbeef; + hr = IEnumVARIANT_Next(enumvar, 0, NULL, NULL); + ok(hr == E_POINTER, "IEnumVARIANT_Next returned: 0x%08x.\n", hr); + hr = IEnumVARIANT_Next(enumvar, 0, NULL, &fetched); + ok(hr == E_POINTER, "IEnumVARIANT_Next failed: 0x%08x.\n", hr); + ok(fetched == 0xdeadbeef, "got %u.\n", fetched); + hr = IEnumVARIANT_Next(enumvar, 0, &var, &fetched); + ok(hr == S_OK, "IEnumVARIANT_Next returned: 0x%08x.\n", hr); + ok(fetched == 0, "got %u.\n", fetched); + hr = IEnumVARIANT_Next(enumvar, 0, &var, NULL); + ok(hr == S_OK, "IEnumVARIANT_Next returned: 0x%08x.\n", hr); + hr = IEnumVARIANT_Clone(enumvar, NULL); + ok(hr == E_POINTER, "IEnumVARIANT_Clone failed: 0x%08x.\n", hr); + + hr = IEnumVARIANT_Next(enumvar, ARRAY_SIZE(vars), vars, &fetched); + ok(hr == S_OK, "IEnumVARIANT_Next failed: 0x%08x.\n", hr); + ok(fetched == ARRAY_SIZE(vars), "got %u.\n", fetched); + hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched); + ok(hr == S_FALSE, "IEnumVARIANT_Next failed: 0x%08x.\n", hr); + ok(fetched == 0, "got %u.\n", fetched); + hr = IEnumVARIANT_Skip(enumvar, 0); + ok(hr == S_OK, "IEnumVARIANT_Skip failed: 0x%08x.\n", hr); + hr = IEnumVARIANT_Skip(enumvar, 1); + ok(hr == S_FALSE, "IEnumVARIANT_Skip failed: 0x%08x.\n", hr); + hr = IEnumVARIANT_Clone(enumvar, &enumvar2); + ok(hr == S_OK, "IEnumVARIANT_Clone failed: 0x%08x.\n", hr); + hr = IEnumVARIANT_Skip(enumvar2, 1); + ok(hr == S_FALSE, "IEnumVARIANT_Skip failed: 0x%08x.\n", hr); + IEnumVARIANT_Release(enumvar2); + IEnumVARIANT_Release(enumvar); + + for (i = 0; i < ARRAY_SIZE(vars); i++) + { + ok(V_VT(&vars[i]) == VT_DISPATCH, "V_VT(vars[%u]) = %d.\n", i, V_VT(&vars[i])); + hr = IDispatch_QueryInterface(V_DISPATCH(&vars[i]), &IID_IScriptModule, (void**)&mod); + ok(hr == S_OK, "Failed to query IScriptModule from vars[%u]: 0x%08x.\n", i, hr); + IScriptModule_Release(mod); + VariantClear(&vars[i]); + } + /* The 'Global' module is the same as the script control */ str = SysAllocString(L"add(10, 5)"); hr = IScriptControl_Eval(sc, str, &var);