[PATCH v2 11/11] msscript.ocx: Implement the ScriptModule enumerator.
Gabriel Ivăncescu
gabrielopcode at gmail.com
Mon Jun 1 11:14:43 CDT 2020
Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
dlls/msscript.ocx/msscript.c | 160 ++++++++++++++++++++++++++++-
dlls/msscript.ocx/tests/msscript.c | 56 +++++++++-
2 files changed, 213 insertions(+), 3 deletions(-)
diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c
index 469fa5d..8ac062d 100644
--- a/dlls/msscript.ocx/msscript.c
+++ b/dlls/msscript.ocx/msscript.c
@@ -72,6 +72,13 @@ struct module {
ScriptModule *object;
};
+struct module_enum {
+ IEnumVARIANT IEnumVARIANT_iface;
+ LONG ref;
+ UINT pos;
+ ScriptControl *control;
+};
+
struct ScriptModule {
IScriptModule IScriptModule_iface;
LONG ref;
@@ -385,6 +392,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)
{
@@ -897,6 +909,137 @@ static HRESULT grab_module_object(ScriptControl *control, struct module *module)
return S_OK;
}
+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)
+ {
+ 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);
+ UINT i, num;
+ HRESULT hr;
+
+ TRACE("(%p)->(%u %p %p)\n", This, celt, rgVar, pCeltFetched);
+
+ if (!rgVar) return E_POINTER;
+
+ num = min(celt, This->control->num_modules - This->pos);
+ for (i = 0; i < num; i++)
+ {
+ struct module *module = &This->control->modules[This->pos];
+
+ if (FAILED(hr = grab_module_object(This->control, module)))
+ {
+ while (i--)
+ IDispatch_Release(V_DISPATCH(rgVar + i));
+ if (pCeltFetched) *pCeltFetched = 0;
+ return hr;
+ }
+ V_VT(rgVar + i) = VT_DISPATCH;
+ V_DISPATCH(rgVar + i) = (IDispatch*)(&module->object->IScriptModule_iface);
+ This->pos++;
+ }
+
+ 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->control->num_modules - This->pos < celt)
+ {
+ This->pos = This->control->num_modules;
+ 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);
+
+ 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 (!(clone = heap_alloc(sizeof(*clone))))
+ return E_OUTOFMEMORY;
+
+ *clone = *This;
+ clone->ref = 1;
+ 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 HRESULT WINAPI ScriptModuleCollection_QueryInterface(IScriptModuleCollection *iface, REFIID riid, void **ppv)
{
ScriptControl *This = impl_from_IScriptModuleCollection(iface);
@@ -993,10 +1136,23 @@ 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 *mod_enum;
- FIXME("(%p)->(%p)\n", This, ppenumContexts);
+ TRACE("(%p)->(%p)\n", This, ppenumContexts);
- return E_NOTIMPL;
+ if (!ppenumContexts) return E_POINTER;
+
+ if (!(mod_enum = heap_alloc(sizeof(*mod_enum))))
+ return E_OUTOFMEMORY;
+
+ mod_enum->IEnumVARIANT_iface.lpVtbl = &module_enum_vtbl;
+ mod_enum->ref = 1;
+ mod_enum->pos = 0;
+ mod_enum->control = This;
+ IScriptControl_AddRef(&This->IScriptControl_iface);
+
+ *ppenumContexts = (IUnknown*)&mod_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 8d2c1b8..35c5141 100644
--- a/dlls/msscript.ocx/tests/msscript.c
+++ b/dlls/msscript.ocx/tests/msscript.c
@@ -2136,14 +2136,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);
@@ -2188,6 +2191,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);
@@ -2256,6 +2269,47 @@ 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);
+ IEnumVARIANT_Release(enumvar);
+
+ 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);
--
2.21.0
More information about the wine-devel
mailing list