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 df63220..bc1811b 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); @@ -1392,8 +1426,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);
@@ -1403,30 +1435,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 | 70 ++++++++++++++++++++++++++++-- dlls/msscript.ocx/tests/msscript.c | 61 +++++++++++++++++++++----- 2 files changed, 117 insertions(+), 14 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index bc1811b..6960598 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; @@ -650,6 +656,7 @@ static ULONG WINAPI ScriptModule_Release(IScriptModule *iface) { detach_script_host(This->host); IActiveScriptSite_Release(&This->host->IActiveScriptSite_iface); + SysFreeString(This->name); heap_free(This); }
@@ -797,7 +804,7 @@ static const IScriptModuleVtbl ScriptModuleVtbl = { ScriptModule_Run };
-static ScriptModule *create_module(ScriptHost *host) +static ScriptModule *create_module(ScriptHost *host, BSTR name) { ScriptModule *module;
@@ -805,6 +812,12 @@ static ScriptModule *create_module(ScriptHost *host)
module->IScriptModule_iface.lpVtbl = &ScriptModuleVtbl; module->ref = 1; + module->name = NULL; + if (name && !(module->name = SysAllocString(name))) + { + heap_free(module); + return NULL; + } module->host = host; IActiveScriptSite_AddRef(&host->IActiveScriptSite_iface); return module; @@ -820,6 +833,21 @@ static void release_modules(ScriptControl *control) heap_free(control->modules); }
+static ScriptModule *find_module(ScriptControl *control, BSTR name) +{ + unsigned int i; + + if (!wcsicmp(name, L"Global")) + return control->modules[0]; + + for (i = 1; i < control->host->module_count; i++) + { + if (!wcsicmp(name, control->modules[i]->name)) + return control->modules[i]; + } + return NULL; +} + static HRESULT WINAPI ScriptModuleCollection_QueryInterface(IScriptModuleCollection *iface, REFIID riid, void **ppv) { ScriptControl *This = impl_from_IScriptModuleCollection(iface); @@ -949,10 +977,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(This, name)) return E_INVALIDARG; + + /* See if we need to grow the array */ + if (is_power_of_2(host->module_count)) + { + modules = heap_realloc(This->modules, host->module_count * 2 * sizeof(*This->modules)); + if (!modules) return E_OUTOFMEMORY; + This->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; + } + This->modules[host->module_count++] = module; + + *ppmod = &module->IScriptModule_iface; + IScriptModule_AddRef(*ppmod); + return S_OK; }
static const IScriptModuleCollectionVtbl ScriptModuleCollectionVtbl = { @@ -1230,7 +1292,7 @@ static HRESULT WINAPI ScriptControl_put_Language(IScriptControl *iface, BSTR lan /* Alloc global module */ This->modules = heap_alloc_zero(sizeof(*This->modules)); if (This->modules) { - This->modules[0] = create_module(This->host); + This->modules[0] = create_module(This->host, NULL); if (!This->modules[0]) { heap_free(This->modules); This->modules = NULL; diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index b6a5209..8945186 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); @@ -2419,6 +2420,12 @@ 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_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); @@ -2429,6 +2436,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); @@ -2459,6 +2468,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); @@ -2481,13 +2491,44 @@ 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); - CHECK_CALLED(Close); + todo_wine CHECK_CALLED(Close); IScriptModuleCollection_Release(mods); IActiveScriptSite_Release(site); IScriptControl_Release(sc); + IScriptModule_Release(mod); } }
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 28 +++++++++++++- dlls/msscript.ocx/tests/msscript.c | 60 +++++++++++++++++++++++++----- 2 files changed, 76 insertions(+), 12 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 6960598..9783c77 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -954,10 +954,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, 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->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 8945186..701363a 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -2341,9 +2341,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"); @@ -2378,34 +2378,69 @@ 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"); 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)"); + 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); + + /* 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); @@ -2414,12 +2449,17 @@ static void test_IScriptControl_get_Modules(void) 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); + IScriptModule_Release(mod);
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); + 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); V_VT(&var) = VT_DISPATCH; V_DISPATCH(&var) = NULL; str = SysAllocString(L"module_name");
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 26 ++++++++--- dlls/msscript.ocx/tests/msscript.c | 70 +++++++++++++++++++++++++++++- 2 files changed, 88 insertions(+), 8 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 9783c77..5f3993b 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -615,6 +615,17 @@ static void detach_script_host(ScriptHost *host) host->script = NULL; }
+static void detach_module(ScriptModule *module) +{ + ScriptHost *host = module->host; + + if (host) { + module->host = NULL; + detach_script_host(host); + IActiveScriptSite_Release(&host->IActiveScriptSite_iface); + } +} + static HRESULT WINAPI ScriptModule_QueryInterface(IScriptModule *iface, REFIID riid, void **ppv) { ScriptModule *This = impl_from_IScriptModule(iface); @@ -654,8 +665,7 @@ static ULONG WINAPI ScriptModule_Release(IScriptModule *iface)
if (!ref) { - detach_script_host(This->host); - IActiveScriptSite_Release(&This->host->IActiveScriptSite_iface); + detach_module(This); SysFreeString(This->name); heap_free(This); } @@ -823,12 +833,14 @@ static ScriptModule *create_module(ScriptHost *host, BSTR name) return module; }
-static void release_modules(ScriptControl *control) +static void release_modules(ScriptControl *control, BOOL force_detach) { - unsigned int i; + unsigned int i, module_count = control->host->module_count;
- for (i = 0; i < control->host->module_count; i++) + for (i = 0; i < module_count; i++) { + if (force_detach) detach_module(control->modules[i]); IScriptModule_Release(&control->modules[i]->IScriptModule_iface); + }
heap_free(control->modules); } @@ -1200,7 +1212,7 @@ static ULONG WINAPI ScriptControl_Release(IScriptControl *iface) IOleClientSite_Release(This->site); if (This->host) { - release_modules(This); + release_modules(This, FALSE); IActiveScriptSite_Release(&This->host->IActiveScriptSite_iface); } heap_free(This); @@ -1301,7 +1313,7 @@ static HRESULT WINAPI ScriptControl_put_Language(IScriptControl *iface, BSTR lan return CTL_E_INVALIDPROPERTYVALUE;
if (This->host) { - release_modules(This); + release_modules(This, TRUE); IActiveScriptSite_Release(&This->host->IActiveScriptSite_iface); This->host = NULL; } diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c index 701363a..35ab1ba 100644 --- a/dlls/msscript.ocx/tests/msscript.c +++ b/dlls/msscript.ocx/tests/msscript.c @@ -2446,10 +2446,21 @@ static void test_IScriptControl_get_Modules(void) 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); @@ -2564,11 +2575,68 @@ static void test_IScriptControl_get_Modules(void) SET_EXPECT(Close); hr = IScriptControl_put_Language(sc, NULL); ok(hr == S_OK, "IScriptControl_put_Language failed: 0x%08x.\n", hr); - todo_wine CHECK_CALLED(Close); + CHECK_CALLED(Close); 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: Jacek Caban jacek@codeweavers.com
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 5f3993b..e55fec9 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -738,9 +738,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: Jacek Caban jacek@codeweavers.com
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 e55fec9..e8c0f0a 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; }
@@ -607,10 +608,7 @@ static void detach_script_host(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; } @@ -667,6 +665,8 @@ static ULONG WINAPI ScriptModule_Release(IScriptModule *iface) { detach_module(This); SysFreeString(This->name); + if (This->script_dispatch) + IDispatch_Release(This->script_dispatch); heap_free(This); }
@@ -833,6 +833,7 @@ static ScriptModule *create_module(ScriptHost *host, BSTR name) return NULL; } module->host = host; + module->script_dispatch = NULL; IActiveScriptSite_AddRef(&host->IActiveScriptSite_iface); return 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; host->module_count = 1; list_init(&host->named_items); @@ -1633,7 +1633,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->modules[0], &disp); if (FAILED(hr)) return hr;
hr = IDispatch_GetIDsOfNames(disp, &IID_NULL, &procedure_name, 1, LOCALE_USER_DEFAULT, &dispid);
Signed-off-by: Jacek Caban jacek@codeweavers.com
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 e8c0f0a..4460afc 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); @@ -1555,20 +1569,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: Jacek Caban jacek@codeweavers.com
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 4460afc..7fc7b95 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -291,15 +291,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; @@ -783,27 +783,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) @@ -1578,7 +1590,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->modules[0], code, SCRIPTTEXT_ISVISIBLE, NULL); }
static HRESULT WINAPI ScriptControl_Eval(IScriptControl *iface, BSTR expression, VARIANT *res) @@ -1593,7 +1605,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->modules[0], expression, SCRIPTTEXT_ISEXPRESSION, res); }
static HRESULT WINAPI ScriptControl_ExecuteStatement(IScriptControl *iface, BSTR statement) @@ -1605,7 +1617,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->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: Jacek Caban jacek@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/msscript.ocx/msscript.c | 163 ++++++++++++++++++++++++++++- dlls/msscript.ocx/tests/msscript.c | 134 +++++++++++++++++++++++- 2 files changed, 294 insertions(+), 3 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index 7fc7b95..352bcab 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -66,6 +66,15 @@ 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; @@ -375,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) { @@ -844,6 +858,135 @@ 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); + unsigned int i, num; + + TRACE("(%p)->(%u %p %p)\n", This, celt, rgVar, pCeltFetched); + + if (!rgVar) return E_POINTER; + if (This->host != This->control->host) return E_FAIL; + + num = min(celt, This->host->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->host != This->control->host) return E_FAIL; + + if (This->host->module_count - This->pos < celt) + { + This->pos = This->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 != This->control->host) 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 != This->control->host) 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; @@ -987,10 +1130,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); } }
Hi Gabriel,
On 25.06.2020 16:59, Gabriel Ivăncescu wrote:
+struct module_enum {
- IEnumVARIANT IEnumVARIANT_iface;
- LONG ref;
- UINT pos;
- ScriptHost *host;
- ScriptControl *control;
+};
Do you need host reference if you already have control reference?
Thanks,
Jacek
Hi Jacek,
On 29/06/2020 19:01, Jacek Caban wrote:
Hi Gabriel,
On 25.06.2020 16:59, Gabriel Ivăncescu wrote:
+struct module_enum { + IEnumVARIANT IEnumVARIANT_iface; + LONG ref;
+ UINT pos; + ScriptHost *host; + ScriptControl *control; +};
Do you need host reference if you already have control reference?
Thanks,
Jacek
Unfortunately yeah, because the enumerator becomes invalid when the host is detached. However, it still keeps the script control alive, and I have tests for both (the script control test is at the end of the test).
Please see the comment in the test `The enumerator is also invalid' for this behavior.
The way I do it right now is I compare the original host held by the enumerator to the control's host—if they don't match, it was detached.
I know it's not pretty, but I couldn't find a better way. If you have a better idea please let me know.
Thanks, Gabriel