msscript.ocx: Implement IScriptModuleCollection::Add.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Gabriel Ivăncescu 2020-06-25 17:59:22 +03:00 committed by Alexandre Julliard
parent 523f9d2a4f
commit a328ac5bc9
2 changed files with 117 additions and 14 deletions

View File

@ -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;

View File

@ -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);
}
}