From a328ac5bc946e87cbfc5362f815ad2b17960de90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Iv=C4=83ncescu?= Date: Thu, 25 Jun 2020 17:59:22 +0300 Subject: [PATCH] msscript.ocx: Implement IScriptModuleCollection::Add. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gabriel Ivăncescu Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- 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 bc1811b4c2a..696059897f7 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 b6a5209fa13..8945186b876 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); } }