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:
parent
523f9d2a4f
commit
a328ac5bc9
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue