[PATCH v7 2/9] msscript.ocx: Implement IScriptModuleCollection::Add.
Gabriel Ivăncescu
gabrielopcode at gmail.com
Thu Jun 25 09:59:22 CDT 2020
Signed-off-by: Gabriel Ivăncescu <gabrielopcode at 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);
}
}
--
2.21.0
More information about the wine-devel
mailing list