Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 7 +++++-- dlls/msscript.ocx/tests/msscript.c | 12 ++++++------ 2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index e397044..8fb127e 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -893,9 +893,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->module_count; + return S_OK; }
static HRESULT WINAPI ScriptModuleCollection_Add(IScriptModuleCollection *iface, BSTR name, diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index 6a07303..fbbe831 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -2331,11 +2331,11 @@ static void test_IScriptControl_get_Modules(void) ok(hr == S_OK, "IScriptControl_get_Modules failed: 0x%08x.\n", hr);
hr = IScriptModuleCollection_get_Count(mods, NULL); - todo_wine ok(hr == E_POINTER, "IScriptModuleCollection_get_Count returned: 0x%08x.\n", hr); + ok(hr == E_POINTER, "IScriptModuleCollection_get_Count returned: 0x%08x.\n", hr); count = 0; hr = IScriptModuleCollection_get_Count(mods, &count); - todo_wine ok(hr == S_OK, "IScriptModuleCollection_get_Count failed: 0x%08x.\n", hr); - todo_wine ok(count == 1, "count is not 1, got %d.\n", 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; @@ -2372,7 +2372,7 @@ static void test_IScriptControl_get_Modules(void) SysFreeString(str);
hr = IScriptModuleCollection_get_Count(mods, &count); - todo_wine ok(hr == S_OK, "IScriptModuleCollection_get_Count failed: 0x%08x.\n", hr); + 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; @@ -2411,8 +2411,8 @@ static void test_IScriptControl_get_Modules(void) SysFreeString(str);
hr = IScriptModuleCollection_get_Count(mods, &count); - todo_wine ok(hr == S_OK, "IScriptModuleCollection_get_Count failed: 0x%08x.\n", hr); - todo_wine ok(count == 1, "count is not 1, got %d.\n", 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);
Modules must keep refs to the script engine, because the script is closed only when the last non-detached module is released, even if the control is not held anymore. put_Language, however, still releases the engine.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 8fb127e..fdf7e7d 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -369,8 +369,6 @@ static void release_script_engine(ScriptHost *host) host->script_dispatch = NULL; host->parse = NULL; host->script = NULL; - - IActiveScriptSite_Release(&host->IActiveScriptSite_iface); }
static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface) @@ -381,6 +379,7 @@ static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface) TRACE("(%p) ref=%d\n", This, ref);
if(!ref) { + release_script_engine(This); clear_named_items(This); heap_free(This); } @@ -990,7 +989,7 @@ static HRESULT init_script_host(const CLSID *clsid, ScriptHost **ret) return S_OK;
failed: - release_script_engine(host); + IActiveScriptSite_Release(&host->IActiveScriptSite_iface); return hr; }
@@ -1068,7 +1067,7 @@ static ULONG WINAPI ScriptControl_Release(IScriptControl *iface) if (This->site) IOleClientSite_Release(This->site); if (This->host) - release_script_engine(This->host); + IActiveScriptSite_Release(&This->host->IActiveScriptSite_iface); release_modules(This); heap_free(This); } @@ -1179,6 +1178,7 @@ static HRESULT WINAPI ScriptControl_put_Language(IScriptControl *iface, BSTR lan
if (This->host) { release_script_engine(This->host); + IActiveScriptSite_Release(&This->host->IActiveScriptSite_iface); This->host = NULL; }
On 15.06.2020 15:00, Gabriel Ivăncescu wrote:
Modules must keep refs to the script engine, because the script is closed only when the last non-detached module is released, even if the control is not held anymore. put_Language, however, still releases the engine.
While I agree that we need to change how release_script_engine() works for modules, this doesn't seem right. There is likely a circular dependency between script engine and script host because script host implements IActiveScriptSite. This is fine, because script control guarantees that it will close script engine at some point, breaking the cycle. With your patch, you depend on ref count to close the engine, so in practice it will leak. See the attached hack for a quick test. It passes on Windows and unpatched Wine.
I think that it may be a good idea to just store number of modules alive in script host (maybe even move it from control). You'd then change release_script_engine to something like:
void detach_script_module(ScriptHost *host)
{
if(--host->module_count) return;
// code closing the engine
}
Thanks,
Jacek
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 38 ++++++++++++++++++++++++++++-- dlls/msscript.ocx/tests/msscript.c | 32 ++++++++++++++++++++----- 2 files changed, 62 insertions(+), 8 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index fdf7e7d..376af3c 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -776,6 +776,17 @@ static void release_modules(ScriptControl *control) heap_free(control->modules); }
+static ScriptModule *find_module(ScriptControl *control, BSTR name) +{ + unsigned int len = SysStringLen(name); + + if (len == sizeof("Global") - 1 && !wcsicmp(name, L"Global")) + return control->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); @@ -882,10 +893,33 @@ static HRESULT WINAPI ScriptModuleCollection_get_Item(IScriptModuleCollection *i IScriptModule **ppmod) { ScriptControl *This = impl_from_IScriptModuleCollection(iface); + ScriptModule *module; + 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) + { + module = find_module(This, 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->module_count) return 0x800a0009; + + module = This->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 fbbe831..7297b8e 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);
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 376af3c..74d33fc 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; @@ -83,7 +86,7 @@ typedef struct ScriptHost { CLSID clsid;
struct list named_items; -} ScriptHost; +};
struct ScriptControl { IScriptControl IScriptControl_iface; @@ -608,7 +611,11 @@ static ULONG WINAPI ScriptModule_Release(IScriptModule *iface) TRACE("(%p) ref=%d\n", This, ref);
if (!ref) + { + if (This->host) + IActiveScriptSite_Release(&This->host->IActiveScriptSite_iface); heap_free(This); + }
return ref; } @@ -762,6 +769,7 @@ static ScriptModule *create_module(void)
module->IScriptModule_iface.lpVtbl = &ScriptModuleVtbl; module->ref = 1; + module->host = NULL; return module; }
@@ -1193,7 +1201,9 @@ static HRESULT WINAPI ScriptControl_put_Language(IScriptControl *iface, BSTR lan { ScriptControl *This = impl_from_IScriptControl(iface); ScriptModule **modules; + unsigned int i; CLSID clsid; + HRESULT hr;
TRACE("(%p)->(%s)\n", This, debugstr_w(language));
@@ -1214,6 +1224,12 @@ static HRESULT WINAPI ScriptControl_put_Language(IScriptControl *iface, BSTR lan release_script_engine(This->host); IActiveScriptSite_Release(&This->host->IActiveScriptSite_iface); This->host = NULL; + + for (i = 0; i < This->module_count; i++) + { + IActiveScriptSite_Release(&This->modules[i]->host->IActiveScriptSite_iface); + This->modules[i]->host = NULL; + } }
release_modules(This); @@ -1223,7 +1239,12 @@ static HRESULT WINAPI ScriptControl_put_Language(IScriptControl *iface, BSTR lan if (!language) return S_OK;
- return init_script_host(&clsid, &This->host); + hr = init_script_host(&clsid, &This->host); + if (FAILED(hr)) return hr; + + modules[0]->host = This->host; + IActiveScriptSite_AddRef(&modules[0]->host->IActiveScriptSite_iface); + return S_OK; }
static HRESULT WINAPI ScriptControl_get_State(IScriptControl *iface, ScriptControlStates *p)
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 74d33fc..2b19785 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -250,6 +250,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); @@ -1426,8 +1460,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);
@@ -1437,30 +1469,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 | 68 ++++++++++++-- dlls/msscript.ocx/tests/msscript.c | 145 ++++++++++++++++++++++++++--- 2 files changed, 194 insertions(+), 19 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 2b19785..b2e6cf2 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;
@@ -196,6 +197,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; @@ -648,6 +654,7 @@ static ULONG WINAPI ScriptModule_Release(IScriptModule *iface) { if (This->host) IActiveScriptSite_Release(&This->host->IActiveScriptSite_iface); + SysFreeString(This->name); heap_free(This); }
@@ -795,7 +802,7 @@ static const IScriptModuleVtbl ScriptModuleVtbl = { ScriptModule_Run };
-static ScriptModule *create_module(void) +static ScriptModule *create_module(BSTR name) { ScriptModule *module;
@@ -803,7 +810,13 @@ static ScriptModule *create_module(void)
module->IScriptModule_iface.lpVtbl = &ScriptModuleVtbl; module->ref = 1; + module->name = NULL; module->host = NULL; + if (name && !(module->name = SysAllocString(name))) + { + heap_free(module); + return NULL; + } return module; }
@@ -820,12 +833,18 @@ static void release_modules(ScriptControl *control)
static ScriptModule *find_module(ScriptControl *control, BSTR name) { - unsigned int len = SysStringLen(name); + unsigned int i, len = SysStringLen(name);
if (len == sizeof("Global") - 1 && !wcsicmp(name, L"Global")) return control->modules[0];
- /* FIXME: Look for other modules when they can be added */ + for (i = 1; i < control->module_count; i++) + { + BSTR module_name = control->modules[i]->name; + if (SysStringLen(module_name) == len && !wcsicmp(name, module_name)) + return control->modules[i]; + } + return NULL; }
@@ -980,10 +999,47 @@ static HRESULT WINAPI ScriptModuleCollection_Add(IScriptModuleCollection *iface, VARIANT *object, IScriptModule **ppmod) { ScriptControl *This = impl_from_IScriptModuleCollection(iface); + ScriptModule *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)) + return E_INVALIDARG; + if (!This->host) return E_FAIL; + + /* See if we need to grow the array */ + if (is_power_of_2(This->module_count)) + { + modules = heap_realloc(This->modules, This->module_count * 2 * sizeof(*This->modules)); + if (!modules) return E_OUTOFMEMORY; + This->modules = modules; + } + + if (!(module = create_module(name))) + return E_OUTOFMEMORY; + + /* 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->IScriptModule_iface); + return hr; + } + + module->host = This->host; + IActiveScriptSite_AddRef(&module->host->IActiveScriptSite_iface); + + This->modules[This->module_count++] = module; + + *ppmod = &module->IScriptModule_iface; + IScriptModule_AddRef(*ppmod); + return S_OK; }
static const IScriptModuleCollectionVtbl ScriptModuleCollectionVtbl = { @@ -1248,7 +1304,7 @@ static HRESULT WINAPI ScriptControl_put_Language(IScriptControl *iface, BSTR lan modules = heap_alloc_zero(sizeof(*modules)); if (!modules) return E_OUTOFMEMORY;
- modules[0] = create_module(); + modules[0] = create_module(NULL); if (!modules[0]) { heap_free(modules); return E_OUTOFMEMORY; diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index 7297b8e..64a4520 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);
IScriptModuleCollection_Release(mods); IScriptControl_Release(sc); @@ -2440,6 +2468,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); @@ -2470,6 +2500,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); @@ -2492,6 +2523,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); @@ -2499,6 +2560,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 b2e6cf2..499a105 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -726,9 +726,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 64a4520..6940d4e 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 | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 499a105..3b56599 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;
@@ -225,14 +225,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; }
@@ -406,10 +407,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; } @@ -654,6 +652,8 @@ static ULONG WINAPI ScriptModule_Release(IScriptModule *iface) { if (This->host) IActiveScriptSite_Release(&This->host->IActiveScriptSite_iface); + if (This->script_dispatch) + IDispatch_Release(This->script_dispatch); SysFreeString(This->name); heap_free(This); } @@ -816,6 +816,7 @@ static ScriptModule *create_module(BSTR name) module->ref = 1; module->name = NULL; module->host = NULL; + module->script_dispatch = NULL; if (name && !(module->name = SysAllocString(name))) { heap_free(module); @@ -1078,7 +1079,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);
@@ -1620,12 +1620,12 @@ static HRESULT WINAPI ScriptControl_Run(IScriptControl *iface, BSTR procedure_na if (sa->cDims == 0) return DISP_E_BADINDEX; if (!(sa->fFeatures & FADF_VARIANT)) return DISP_E_BADVARTYPE;
- + if (!This->modules) return E_FAIL; if (!This->host) return E_FAIL; hr = start_script(This->host); if (FAILED(hr)) return hr;
- hr = get_script_dispatch(This, &disp); + hr = get_script_dispatch(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 3b56599..52e339c 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -291,6 +291,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); @@ -1547,20 +1561,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, 33 insertions(+), 27 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 52e339c..eb4f1f5 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -291,15 +291,17 @@ 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); + if (!module->host) return E_FAIL; + + 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; @@ -771,27 +773,31 @@ 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; + 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; + + 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));
- 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) @@ -1567,10 +1573,10 @@ static HRESULT WINAPI ScriptControl_AddCode(IScriptControl *iface, BSTR code)
TRACE("(%p)->(%s).\n", This, debugstr_w(code));
- if (!This->host) + if (!This->modules) return E_FAIL;
- return parse_script_text(This->host, code, SCRIPTTEXT_ISVISIBLE, NULL); + return parse_script_text(This->modules[0], code, SCRIPTTEXT_ISVISIBLE, NULL); }
static HRESULT WINAPI ScriptControl_Eval(IScriptControl *iface, BSTR expression, VARIANT *res) @@ -1582,10 +1588,10 @@ static HRESULT WINAPI ScriptControl_Eval(IScriptControl *iface, BSTR expression, if (!res) return E_POINTER; V_VT(res) = VT_EMPTY; - if (!This->host) + if (!This->modules) return E_FAIL;
- return parse_script_text(This->host, expression, SCRIPTTEXT_ISEXPRESSION, res); + return parse_script_text(This->modules[0], expression, SCRIPTTEXT_ISEXPRESSION, res); }
static HRESULT WINAPI ScriptControl_ExecuteStatement(IScriptControl *iface, BSTR statement) @@ -1594,10 +1600,10 @@ static HRESULT WINAPI ScriptControl_ExecuteStatement(IScriptControl *iface, BSTR
TRACE("(%p)->(%s)\n", This, debugstr_w(statement));
- if (!This->host) + if (!This->modules) return E_FAIL;
- return parse_script_text(This->host, statement, 0, NULL); + return parse_script_text(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 6940d4e..935aca6 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);
@@ -2549,9 +2549,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);
@@ -2612,9 +2612,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 | 157 ++++++++++++++++++++++++++++- dlls/msscript.ocx/tests/msscript.c | 56 +++++++++- 2 files changed, 210 insertions(+), 3 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index eb4f1f5..a55f928 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -66,6 +66,13 @@ struct named_item { IDispatch *disp; };
+struct module_enum { + IEnumVARIANT IEnumVARIANT_iface; + LONG ref; + UINT pos; + ScriptControl *control; +}; + typedef struct { IScriptModule IScriptModule_iface; LONG ref; @@ -377,6 +384,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) { @@ -826,6 +838,134 @@ 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) + { + 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); + unsigned int i, num; + + TRACE("(%p)->(%u %p %p)\n", This, celt, rgVar, pCeltFetched); + + if (!rgVar) return E_POINTER; + + if (This->control->module_count <= This->pos) + num = 0; + else + num = min(celt, This->control->module_count - This->pos); + + for (i = 0; i < num; i++) + { + V_VT(rgVar + i) = VT_DISPATCH; + V_DISPATCH(rgVar + i) = (IDispatch*)(&This->control->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); + + TRACE("(%p)->(%u)\n", This, celt); + + if (This->control->module_count < This->pos) + return S_FALSE; + + if (This->control->module_count - This->pos < celt) + { + This->pos = This->control->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); + + 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 ScriptModule *create_module(BSTR name) { ScriptModule *module; @@ -969,10 +1109,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 935aca6..dd46b5a 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,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);