Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 57 +++++++++++++++--------------- dlls/msscript.ocx/tests/msscript.c | 9 +++++ 2 files changed, 38 insertions(+), 28 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 8fb127e..7385ce1 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -82,6 +82,9 @@ typedef struct ScriptHost { SCRIPTSTATE script_state; CLSID clsid;
+ unsigned int module_count; + ScriptModule **modules; + struct list named_items; } ScriptHost;
@@ -94,6 +97,7 @@ struct ScriptControl { IViewObjectEx IViewObjectEx_iface; IPointerInactive IPointerInactive_iface; IConnectionPointContainer IConnectionPointContainer_iface; + IScriptModuleCollection IScriptModuleCollection_iface; LONG ref; IOleClientSite *site; SIZEL extent; @@ -110,11 +114,6 @@ struct ScriptControl { IAdviseSink *view_sink; DWORD view_sink_flags;
- /* modules */ - unsigned int module_count; - ScriptModule **modules; - IScriptModuleCollection IScriptModuleCollection_iface; - ScriptHost *host; };
@@ -766,15 +765,15 @@ static ScriptModule *create_module(void) return module; }
-static void release_modules(ScriptControl *control) +static void release_modules(ScriptHost *host) { unsigned int i;
- for (i = 0; i < control->module_count; i++) - IScriptModule_Release(&control->modules[i]->IScriptModule_iface); + for (i = 0; i < host->module_count; i++) + IScriptModule_Release(&host->modules[i]->IScriptModule_iface);
- control->module_count = 0; - heap_free(control->modules); + host->module_count = 0; + heap_free(host->modules); }
static HRESULT WINAPI ScriptModuleCollection_QueryInterface(IScriptModuleCollection *iface, REFIID riid, void **ppv) @@ -896,8 +895,9 @@ static HRESULT WINAPI ScriptModuleCollection_get_Count(IScriptModuleCollection * TRACE("(%p)->(%p)\n", This, plCount);
if (!plCount) return E_POINTER; + if (!This->host) return E_FAIL;
- *plCount = This->module_count; + *plCount = This->host->module_count; return S_OK; }
@@ -947,6 +947,18 @@ static HRESULT init_script_host(const CLSID *clsid, ScriptHost **ret) host->clsid = *clsid; list_init(&host->named_items);
+ /* Alloc global module */ + host->modules = heap_alloc_zero(sizeof(*host->modules)); + if (!host->modules) return E_OUTOFMEMORY; + + host->modules[0] = create_module(); + if (!host->modules[0]) { + heap_free(host->modules); + heap_free(host); + return E_OUTOFMEMORY; + } + host->module_count = 1; + hr = CoCreateInstance(&host->clsid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, &IID_IActiveScript, (void**)&host->script); if (FAILED(hr)) { @@ -990,6 +1002,7 @@ static HRESULT init_script_host(const CLSID *clsid, ScriptHost **ret) return S_OK;
failed: + release_modules(host); release_script_engine(host); return hr; } @@ -1068,8 +1081,10 @@ static ULONG WINAPI ScriptControl_Release(IScriptControl *iface) if (This->site) IOleClientSite_Release(This->site); if (This->host) + { + release_modules(This->host); release_script_engine(This->host); - release_modules(This); + } heap_free(This); }
@@ -1159,7 +1174,6 @@ 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); - ScriptModule **modules; CLSID clsid;
TRACE("(%p)->(%s)\n", This, debugstr_w(language)); @@ -1167,25 +1181,12 @@ 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; - - modules[0] = create_module(); - if (!modules[0]) { - heap_free(modules); - return E_OUTOFMEMORY; - } - if (This->host) { + release_modules(This->host); release_script_engine(This->host); This->host = NULL; }
- release_modules(This); - This->modules = modules; - This->module_count = 1; - if (!language) return S_OK;
@@ -1332,7 +1333,7 @@ static HRESULT WINAPI ScriptControl_get_Modules(IScriptControl *iface, IScriptMo
TRACE("(%p)->(%p)\n", This, p);
- if (!This->module_count) return E_FAIL; + if (!This->host) return E_FAIL;
*p = &This->IScriptModuleCollection_iface; IScriptControl_AddRef(iface); diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index fbbe831..b6a5209 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -2414,7 +2414,16 @@ 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 = IScriptControl_put_Language(sc, NULL); + ok(hr == S_OK, "IScriptControl_put_Language failed: 0x%08x.\n", hr); + + hr = IScriptModuleCollection_get_Count(mods, &count); + ok(hr == E_FAIL, "IScriptModuleCollection_get_Count returned: 0x%08x.\n", hr); + IScriptModuleCollection_Release(mods); + hr = IScriptControl_get_Modules(sc, &mods); + ok(hr == E_FAIL, "IScriptControl_get_Modules returned: 0x%08x.\n", hr); + IScriptControl_Release(sc);
/* custom script engine */
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 88 +++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 37 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 7385ce1..3d65067 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -51,6 +51,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msscript);
struct ScriptControl; typedef struct ConnectionPoint ConnectionPoint; +typedef struct ScriptHost ScriptHost;
struct ConnectionPoint { IConnectionPoint IConnectionPoint_iface; @@ -68,9 +69,11 @@ struct named_item { typedef struct { IScriptModule IScriptModule_iface; LONG ref; + + ScriptHost *host; } ScriptModule;
-typedef struct ScriptHost { +struct ScriptHost { IActiveScriptSite IActiveScriptSite_iface; IActiveScriptSiteWindow IActiveScriptSiteWindow_iface; IServiceProvider IServiceProvider_iface; @@ -86,7 +89,7 @@ typedef struct ScriptHost { ScriptModule **modules;
struct list named_items; -} ScriptHost; +};
struct ScriptControl { IScriptControl IScriptControl_iface; @@ -353,25 +356,6 @@ static ULONG WINAPI ActiveScriptSite_AddRef(IActiveScriptSite *iface) return ref; }
-static void release_script_engine(ScriptHost *host) -{ - if (host->script) { - IActiveScript_Close(host->script); - IActiveScript_Release(host->script); - } - - if (host->parse) - IActiveScriptParse_Release(host->parse); - if (host->script_dispatch) - IDispatch_Release(host->script_dispatch); - - host->script_dispatch = NULL; - host->parse = NULL; - host->script = NULL; - - IActiveScriptSite_Release(&host->IActiveScriptSite_iface); -} - static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface) { ScriptHost *This = impl_from_IActiveScriptSite(iface); @@ -570,6 +554,32 @@ static const IServiceProviderVtbl ServiceProviderVtbl = { ServiceProvider_QueryService };
+static void detach_module(ScriptModule *module) +{ + ScriptHost *host = module->host; + + module->host = NULL; + + if (--host->module_count) + return; + + if (host->script) { + IActiveScript_Close(host->script); + IActiveScript_Release(host->script); + } + + 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; + + IActiveScriptSite_Release(&host->IActiveScriptSite_iface); +} + static HRESULT WINAPI ScriptModule_QueryInterface(IScriptModule *iface, REFIID riid, void **ppv) { ScriptModule *This = impl_from_IScriptModule(iface); @@ -608,7 +618,11 @@ static ULONG WINAPI ScriptModule_Release(IScriptModule *iface) TRACE("(%p) ref=%d\n", This, ref);
if (!ref) + { + if (This->host) + detach_module(This); heap_free(This); + }
return ref; } @@ -754,7 +768,7 @@ static const IScriptModuleVtbl ScriptModuleVtbl = { ScriptModule_Run };
-static ScriptModule *create_module(void) +static ScriptModule *create_module(ScriptHost *host) { ScriptModule *module;
@@ -762,18 +776,23 @@ static ScriptModule *create_module(void)
module->IScriptModule_iface.lpVtbl = &ScriptModuleVtbl; module->ref = 1; + module->host = host; return module; }
-static void release_modules(ScriptHost *host) +static void release_modules(ScriptHost *host, BOOL force_detach) { - unsigned int i; + /* Releasing the modules might destroy the host, so keep copies */ + unsigned int i, module_count = host->module_count; + ScriptModule **modules = host->modules;
- for (i = 0; i < host->module_count; i++) - IScriptModule_Release(&host->modules[i]->IScriptModule_iface); + for (i = 0; i < module_count; i++) + { + if (force_detach) detach_module(modules[i]); + IScriptModule_Release(&modules[i]->IScriptModule_iface); + }
- host->module_count = 0; - heap_free(host->modules); + heap_free(modules); }
static HRESULT WINAPI ScriptModuleCollection_QueryInterface(IScriptModuleCollection *iface, REFIID riid, void **ppv) @@ -951,7 +970,7 @@ static HRESULT init_script_host(const CLSID *clsid, ScriptHost **ret) host->modules = heap_alloc_zero(sizeof(*host->modules)); if (!host->modules) return E_OUTOFMEMORY;
- host->modules[0] = create_module(); + host->modules[0] = create_module(host); if (!host->modules[0]) { heap_free(host->modules); heap_free(host); @@ -1002,8 +1021,7 @@ static HRESULT init_script_host(const CLSID *clsid, ScriptHost **ret) return S_OK;
failed: - release_modules(host); - release_script_engine(host); + release_modules(host, FALSE); return hr; }
@@ -1081,10 +1099,7 @@ static ULONG WINAPI ScriptControl_Release(IScriptControl *iface) if (This->site) IOleClientSite_Release(This->site); if (This->host) - { - release_modules(This->host); - release_script_engine(This->host); - } + release_modules(This->host, FALSE); heap_free(This); }
@@ -1182,8 +1197,7 @@ static HRESULT WINAPI ScriptControl_put_Language(IScriptControl *iface, BSTR lan return CTL_E_INVALIDPROPERTYVALUE;
if (This->host) { - release_modules(This->host); - release_script_engine(This->host); + release_modules(This->host, TRUE); This->host = NULL; }
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 39 ++++++++++++++++++++++++++++-- dlls/msscript.ocx/tests/msscript.c | 36 ++++++++++++++++++++++----- 2 files changed, 67 insertions(+), 8 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 3d65067..9a0cbcd 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -795,6 +795,17 @@ static void release_modules(ScriptHost *host, BOOL force_detach) heap_free(modules); }
+static ScriptModule *find_module(ScriptHost *host, BSTR name) +{ + unsigned int len = SysStringLen(name); + + if (len == sizeof("Global") - 1 && !wcsicmp(name, L"Global")) + return host->modules[0]; + + /* FIXME: Look for other modules when they can be added */ + return NULL; +} + static HRESULT WINAPI ScriptModuleCollection_QueryInterface(IScriptModuleCollection *iface, REFIID riid, void **ppv) { ScriptControl *This = impl_from_IScriptModuleCollection(iface); @@ -901,10 +912,34 @@ static HRESULT WINAPI ScriptModuleCollection_get_Item(IScriptModuleCollection *i IScriptModule **ppmod) { ScriptControl *This = impl_from_IScriptModuleCollection(iface); + ScriptModule *module; + unsigned int i; + HRESULT hr;
- 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 (!This->host) return E_FAIL; + + if (V_VT(&index) == VT_BSTR) + { + module = find_module(This->host, V_BSTR(&index)); + if (!module) 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->host->module_count) return 0x800a0009; + + module = This->host->modules[i]; + } + + *ppmod = &module->IScriptModule_iface; + IScriptModule_AddRef(*ppmod); + 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 b6a5209..9ffb957 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -2340,9 +2340,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"); @@ -2377,19 +2377,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"); @@ -2405,6 +2414,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); @@ -2419,6 +2439,10 @@ static void test_IScriptControl_get_Modules(void)
hr = IScriptModuleCollection_get_Count(mods, &count); ok(hr == E_FAIL, "IScriptModuleCollection_get_Count returned: 0x%08x.\n", hr); + V_VT(&var) = VT_I4; + V_I4(&var) = 1; + hr = IScriptModuleCollection_get_Item(mods, var, &mod); + ok(hr == E_FAIL, "IScriptModuleCollection_get_Item returned: 0x%08x.\n", hr);
IScriptModuleCollection_Release(mods); hr = IScriptControl_get_Modules(sc, &mods);
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 9a0cbcd..bb76c5a 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -249,6 +249,40 @@ static HRESULT start_script(ScriptHost *host) 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); @@ -1421,8 +1455,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);
@@ -1432,30 +1464,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 | 66 +++++++++++-- dlls/msscript.ocx/tests/msscript.c | 151 ++++++++++++++++++++++++++--- 2 files changed, 198 insertions(+), 19 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index bb76c5a..20eea45 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -70,6 +70,7 @@ typedef struct { IScriptModule IScriptModule_iface; LONG ref;
+ BSTR name; ScriptHost *host; } ScriptModule;
@@ -195,6 +196,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; @@ -655,6 +661,7 @@ static ULONG WINAPI ScriptModule_Release(IScriptModule *iface) { if (This->host) detach_module(This); + SysFreeString(This->name); heap_free(This); }
@@ -802,7 +809,7 @@ static const IScriptModuleVtbl ScriptModuleVtbl = { ScriptModule_Run };
-static ScriptModule *create_module(ScriptHost *host) +static ScriptModule *create_module(ScriptHost *host, BSTR name) { ScriptModule *module;
@@ -810,7 +817,13 @@ static ScriptModule *create_module(ScriptHost *host)
module->IScriptModule_iface.lpVtbl = &ScriptModuleVtbl; module->ref = 1; + module->name = NULL; module->host = host; + if (name && !(module->name = SysAllocString(name))) + { + heap_free(module); + return NULL; + } return module; }
@@ -831,12 +844,19 @@ static void release_modules(ScriptHost *host, BOOL force_detach)
static ScriptModule *find_module(ScriptHost *host, BSTR name) { - unsigned int len = SysStringLen(name); + unsigned int i, len = SysStringLen(name);
if (len == sizeof("Global") - 1 && !wcsicmp(name, L"Global")) return host->modules[0];
- /* FIXME: Look for other modules when they can be added */ + for (i = 1; i < host->module_count; i++) + { + BSTR module_name = host->modules[i]->name; + + if (len == SysStringLen(module_name) && !wcsicmp(name, module_name)) + return host->modules[i]; + } + return NULL; }
@@ -993,10 +1013,44 @@ static HRESULT WINAPI ScriptModuleCollection_Add(IScriptModuleCollection *iface, VARIANT *object, IScriptModule **ppmod) { ScriptControl *This = impl_from_IScriptModuleCollection(iface); + ScriptModule *module, **modules; + ScriptHost *host = This->host; + 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) return E_INVALIDARG; + if (!host) return E_FAIL; + if (find_module(host, name)) return E_INVALIDARG; + + /* See if we need to grow the array */ + if (is_power_of_2(host->module_count)) + { + modules = heap_realloc(host->modules, host->module_count * 2 * sizeof(*host->modules)); + if (!modules) return E_OUTOFMEMORY; + host->modules = modules; + } + + if (!(module = create_module(host, name))) + return E_OUTOFMEMORY; + + /* If no object, Windows only calls AddNamedItem without adding a NULL object */ + if (V_DISPATCH(object)) + hr = add_script_object(host, name, V_DISPATCH(object), 0); + else + hr = IActiveScript_AddNamedItem(host->script, name, SCRIPTITEM_CODEONLY); + + if (FAILED(hr)) + { + IScriptModule_Release(&module->IScriptModule_iface); + return hr; + } + host->modules[host->module_count++] = module; + + *ppmod = &module->IScriptModule_iface; + IScriptModule_AddRef(*ppmod); + return S_OK; }
static const IScriptModuleCollectionVtbl ScriptModuleCollectionVtbl = { @@ -1039,7 +1093,7 @@ static HRESULT init_script_host(const CLSID *clsid, ScriptHost **ret) host->modules = heap_alloc_zero(sizeof(*host->modules)); if (!host->modules) return E_OUTOFMEMORY;
- host->modules[0] = create_module(host); + host->modules[0] = create_module(host, NULL); if (!host->modules[0]) { heap_free(host->modules); heap_free(host); diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index 9ffb957..35ab1ba 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -2310,6 +2310,7 @@ static void test_IScriptControl_get_Modules(void) IScriptModuleCollection *mods; IScriptModule *mod; IScriptControl *sc; + IUnknown *unknown; VARIANT var; LONG count; HRESULT hr; @@ -2347,33 +2348,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); @@ -2403,16 +2404,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)"); @@ -2425,14 +2436,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);
hr = IScriptControl_put_Language(sc, NULL); ok(hr == S_OK, "IScriptControl_put_Language failed: 0x%08x.\n", hr); @@ -2443,6 +2471,12 @@ static void test_IScriptControl_get_Modules(void) V_I4(&var) = 1; hr = IScriptModuleCollection_get_Item(mods, var, &mod); ok(hr == E_FAIL, "IScriptModuleCollection_get_Item returned: 0x%08x.\n", hr); + V_VT(&var) = VT_DISPATCH; + V_DISPATCH(&var) = NULL; + str = SysAllocString(L"module_name"); + hr = IScriptModuleCollection_Add(mods, str, &var, &mod); + ok(hr == E_FAIL, "IScriptModuleCollection_Add returned: 0x%08x.\n", hr); + SysFreeString(str);
IScriptModuleCollection_Release(mods); hr = IScriptControl_get_Modules(sc, &mods); @@ -2453,6 +2487,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); @@ -2483,6 +2519,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); @@ -2505,6 +2542,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); @@ -2512,6 +2579,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 | 8 ++++++-- dlls/msscript.ocx/tests/msscript.c | 19 +++++++++++-------- 2 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 20eea45..f58f517 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -733,9 +733,13 @@ static HRESULT WINAPI ScriptModule_get_Name(IScriptModule *iface, BSTR *pbstrNam { ScriptModule *This = impl_from_IScriptModule(iface);
- FIXME("(%p)->(%p)\n", This, pbstrName); + TRACE("(%p)->(%p)\n", This, pbstrName);
- return E_NOTIMPL; + if (!pbstrName) return E_POINTER; + if (!This->host) return E_FAIL; + + *pbstrName = SysAllocString(This->name ? This->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 35ab1ba..871ff51 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -2391,10 +2391,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); @@ -2408,17 +2409,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); @@ -2451,7 +2454,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 | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index f58f517..6693f0d 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -72,6 +72,7 @@ typedef struct {
BSTR name; ScriptHost *host; + IDispatch *script_dispatch; } ScriptModule;
struct ScriptHost { @@ -82,7 +83,6 @@ struct ScriptHost {
IActiveScript *script; IActiveScriptParse *parse; - IDispatch *script_dispatch; SCRIPTSTATE script_state; CLSID clsid;
@@ -224,14 +224,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(ScriptModule *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(module->host->script, + module->name, &module->script_dispatch); if (FAILED(hr)) return hr; } - *disp = control->host->script_dispatch; + *disp = module->script_dispatch; return S_OK; }
@@ -610,10 +611,7 @@ static void detach_module(ScriptModule *module)
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;
@@ -659,6 +657,8 @@ static ULONG WINAPI ScriptModule_Release(IScriptModule *iface)
if (!ref) { + if (This->script_dispatch) + IDispatch_Release(This->script_dispatch); if (This->host) detach_module(This); SysFreeString(This->name); @@ -823,6 +823,7 @@ static ScriptModule *create_module(ScriptHost *host, BSTR name) module->ref = 1; module->name = NULL; module->host = host; + module->script_dispatch = NULL; if (name && !(module->name = SysAllocString(name))) { heap_free(module); @@ -1089,7 +1090,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);
@@ -1618,7 +1618,7 @@ static HRESULT WINAPI ScriptControl_Run(IScriptControl *iface, BSTR procedure_na hr = start_script(This->host); if (FAILED(hr)) return hr;
- hr = get_script_dispatch(This, &disp); + hr = get_script_dispatch(This->host->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 6693f0d..659ebd6 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -290,6 +290,20 @@ static HRESULT add_script_object(ScriptHost *host, BSTR name, IDispatch *object, return hr; }
+static HRESULT parse_script_text(ScriptHost *host, BSTR script_text, DWORD flag, VARIANT *res) +{ + EXCEPINFO excepinfo; + HRESULT hr; + + hr = start_script(host); + if (FAILED(hr)) return hr; + + hr = IActiveScriptParse_ParseScriptText(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); @@ -1540,20 +1554,6 @@ static HRESULT WINAPI ScriptControl_Reset(IScriptControl *iface) return set_script_state(This->host, SCRIPTSTATE_INITIALIZED); }
-static HRESULT parse_script_text(ScriptHost *host, BSTR script_text, DWORD flag, VARIANT *res) -{ - EXCEPINFO excepinfo; - HRESULT hr; - - hr = start_script(host); - if (FAILED(hr)) return hr; - - hr = IActiveScriptParse_ParseScriptText(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 | 36 ++++++++++++++++++++---------- dlls/msscript.ocx/tests/msscript.c | 24 ++++++++++---------- 2 files changed, 36 insertions(+), 24 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 659ebd6..c662651 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -290,15 +290,15 @@ static HRESULT add_script_object(ScriptHost *host, BSTR name, IDispatch *object, return hr; }
-static HRESULT parse_script_text(ScriptHost *host, BSTR script_text, DWORD flag, VARIANT *res) +static HRESULT parse_script_text(ScriptModule *module, BSTR script_text, DWORD flag, VARIANT *res) { EXCEPINFO excepinfo; HRESULT hr;
- hr = start_script(host); + hr = start_script(module->host); if (FAILED(hr)) return hr;
- hr = IActiveScriptParse_ParseScriptText(host->parse, script_text, NULL, + hr = IActiveScriptParse_ParseScriptText(module->host->parse, script_text, module->name, NULL, NULL, 0, 1, flag, res, &excepinfo); /* FIXME: more error handling */ return hr; @@ -778,27 +778,39 @@ 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->host) + return E_FAIL; + + return parse_script_text(This, 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->host) + return E_FAIL; + + return parse_script_text(This, 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)); + + if (!This->host) + return E_FAIL;
- return E_NOTIMPL; + return parse_script_text(This, statement, 0, NULL); }
static HRESULT WINAPI ScriptModule_Run(IScriptModule *iface, BSTR procedure_name, SAFEARRAY **parameters, VARIANT *res) @@ -1563,7 +1575,7 @@ static HRESULT WINAPI ScriptControl_AddCode(IScriptControl *iface, BSTR code) if (!This->host) return E_FAIL;
- return parse_script_text(This->host, code, SCRIPTTEXT_ISVISIBLE, NULL); + return parse_script_text(This->host->modules[0], code, SCRIPTTEXT_ISVISIBLE, NULL); }
static HRESULT WINAPI ScriptControl_Eval(IScriptControl *iface, BSTR expression, VARIANT *res) @@ -1578,7 +1590,7 @@ static HRESULT WINAPI ScriptControl_Eval(IScriptControl *iface, BSTR expression, if (!This->host) return E_FAIL;
- return parse_script_text(This->host, expression, SCRIPTTEXT_ISEXPRESSION, res); + return parse_script_text(This->host->modules[0], expression, SCRIPTTEXT_ISEXPRESSION, res); }
static HRESULT WINAPI ScriptControl_ExecuteStatement(IScriptControl *iface, BSTR statement) @@ -1590,7 +1602,7 @@ static HRESULT WINAPI ScriptControl_ExecuteStatement(IScriptControl *iface, BSTR if (!This->host) return E_FAIL;
- return parse_script_text(This->host, statement, 0, NULL); + return parse_script_text(This->host->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 871ff51..807f82e 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -2398,7 +2398,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);
@@ -2424,15 +2424,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); @@ -2457,11 +2457,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);
@@ -2568,9 +2568,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);
@@ -2631,9 +2631,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 | 165 ++++++++++++++++++++++++++++- dlls/msscript.ocx/tests/msscript.c | 134 ++++++++++++++++++++++- 2 files changed, 296 insertions(+), 3 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index c662651..d8f56d5 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -66,6 +66,14 @@ struct named_item { IDispatch *disp; };
+struct module_enum { + IEnumVARIANT IEnumVARIANT_iface; + LONG ref; + UINT pos; + ScriptHost *host; + ScriptControl *control; +}; + typedef struct { IScriptModule IScriptModule_iface; LONG ref; @@ -374,6 +382,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) { @@ -839,6 +852,137 @@ static const IScriptModuleVtbl ScriptModuleVtbl = { ScriptModule_Run };
+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) + { + IActiveScriptSite_Release(&This->host->IActiveScriptSite_iface); + 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); + ScriptHost *host = This->host; + unsigned int i, num; + + TRACE("(%p)->(%u %p %p)\n", This, celt, rgVar, pCeltFetched); + + if (!rgVar) return E_POINTER; + if (!host->modules) return E_FAIL; + + num = min(celt, host->module_count - This->pos); + for (i = 0; i < num; i++) + { + V_VT(rgVar + i) = VT_DISPATCH; + V_DISPATCH(rgVar + i) = (IDispatch*)(&host->modules[This->pos++]->IScriptModule_iface); + IDispatch_AddRef(V_DISPATCH(rgVar + i)); + } + + 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); + ScriptHost *host = This->host; + + TRACE("(%p)->(%u)\n", This, celt); + + if (!host->modules) return E_FAIL; + + if (host->module_count - This->pos < celt) + { + This->pos = host->module_count; + 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); + + if (!This->host->modules) return E_FAIL; + + 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 (!This->host->modules) return E_FAIL; + + if (!(clone = heap_alloc(sizeof(*clone)))) + return E_OUTOFMEMORY; + + *clone = *This; + clone->ref = 1; + IActiveScriptSite_AddRef(&This->host->IActiveScriptSite_iface); + 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 ScriptModule *create_module(ScriptHost *host, BSTR name) { ScriptModule *module; @@ -864,6 +1008,7 @@ static void release_modules(ScriptHost *host, BOOL force_detach) unsigned int i, module_count = host->module_count; ScriptModule **modules = host->modules;
+ host->modules = NULL; for (i = 0; i < module_count; i++) { if (force_detach) detach_module(modules[i]); @@ -987,10 +1132,26 @@ 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 (!This->host) return E_FAIL; + + 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->host = This->host; + module_enum->control = This; + IActiveScriptSite_AddRef(&This->host->IActiveScriptSite_iface); + 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 807f82e..9986fbf 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -2307,14 +2307,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); @@ -2360,6 +2363,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); @@ -2428,6 +2441,46 @@ 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); + + 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); @@ -2465,6 +2518,17 @@ static void test_IScriptControl_get_Modules(void) IScriptModule_Release(mod); SysFreeString(str);
+ /* The enumerator is also invalid */ + hr = IEnumVARIANT_Reset(enumvar); + ok(hr == E_FAIL, "IEnumVARIANT_Skip returned: 0x%08x.\n", hr); + hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched); + ok(hr == E_FAIL, "IEnumVARIANT_Next returned: 0x%08x.\n", hr); + hr = IEnumVARIANT_Skip(enumvar, 0); + ok(hr == E_FAIL, "IEnumVARIANT_Skip returned: 0x%08x.\n", hr); + hr = IEnumVARIANT_Clone(enumvar, &enumvar2); + ok(hr == E_FAIL, "IEnumVARIANT_Clone returned: 0x%08x.\n", hr); + IEnumVARIANT_Release(enumvar); + hr = IScriptControl_put_Language(sc, NULL); ok(hr == S_OK, "IScriptControl_put_Language failed: 0x%08x.\n", hr);
@@ -2480,6 +2544,8 @@ static void test_IScriptControl_get_Modules(void) hr = IScriptModuleCollection_Add(mods, str, &var, &mod); ok(hr == E_FAIL, "IScriptModuleCollection_Add returned: 0x%08x.\n", hr); SysFreeString(str); + hr = IScriptModuleCollection_get__NewEnum(mods, &unknown); + ok(hr == E_FAIL, "IScriptModuleCollection_get__NewEnum returned: 0x%08x.\n", hr);
IScriptModuleCollection_Release(mods); hr = IScriptControl_get_Modules(sc, &mods); @@ -2640,6 +2706,72 @@ static void test_IScriptControl_get_Modules(void) SET_EXPECT(Close); IScriptModule_Release(mod); CHECK_CALLED(Close); + + /* Hold an enumerator while releasing the script control */ + 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); + IScriptControl_Release(sc); + + SET_EXPECT(AddNamedItem); + str = SysAllocString(L"bar"); + 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); + IScriptModule_Release(mod); + VariantClear(&var); + SysFreeString(str); + CHECK_CALLED(AddNamedItem); + + 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); + IUnknown_Release(unknown); + + IScriptModuleCollection_Release(mods); + IActiveScriptSite_Release(site); + + hr = IEnumVARIANT_Next(enumvar, ARRAY_SIZE(vars), vars, &fetched); + ok(hr == S_FALSE, "IEnumVARIANT_Next failed: 0x%08x.\n", hr); + ok(fetched == 2, "got %u.\n", fetched); + for (i = 0; i < fetched; 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); + hr = IScriptModule_get_Name(mod, &str); + ok(hr == S_OK, "IScriptModule_get_Name failed for vars[%u]: 0x%08x.\n", i, hr); + ok(!lstrcmpW(str, i ? L"bar" : L"Global"), "wrong name for vars[%u]: %s.\n", i, wine_dbgstr_w(str)); + IScriptModule_Release(mod); + VariantClear(&vars[i]); + SysFreeString(str); + } + + SET_EXPECT(Close); + IEnumVARIANT_Release(enumvar); + CHECK_CALLED(Close); } }