From: "Gabriel Ivăncescu" Subject: [PATCH 12/13] msscript.ocx: Implement ScriptModule enumerator. Message-Id: Date: Thu, 9 Apr 2020 17:34:39 +0300 In-Reply-To: <311c32ff785fcd554c8d64166530bcc63090f724.1586442574.git.gabrielopcode@gmail.com> References: <311c32ff785fcd554c8d64166530bcc63090f724.1586442574.git.gabrielopcode@gmail.com> Signed-off-by: Gabriel Ivăncescu --- dlls/msscript.ocx/msscript.c | 150 ++++++++++++++++++++++++++++++++++- 1 file changed, 148 insertions(+), 2 deletions(-) diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c index f0a4853..a691413 100644 --- a/dlls/msscript.ocx/msscript.c +++ b/dlls/msscript.ocx/msscript.c @@ -65,6 +65,13 @@ struct named_item { IDispatch *disp; }; +struct script_mod_enum { + IEnumVARIANT IEnumVARIANT_iface; + LONG ref; + UINT pos; + ScriptControl *control; +}; + typedef struct ScriptModule { IScriptModule IScriptModule_iface; LONG ref; @@ -430,6 +437,11 @@ static inline ScriptHost *impl_from_IServiceProvider(IServiceProvider *iface) return CONTAINING_RECORD(iface, ScriptHost, IServiceProvider_iface); } +static inline struct script_mod_enum *script_mod_enum_from_IEnumVARIANT(IEnumVARIANT *iface) +{ + return CONTAINING_RECORD(iface, struct script_mod_enum, IEnumVARIANT_iface); +} + /* IActiveScriptSite */ static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, REFIID riid, void **ppv) { @@ -935,6 +947,127 @@ static const IScriptModuleVtbl ScriptModuleVtbl = { ScriptModule_Run }; +static HRESULT WINAPI script_mod_enum_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv) +{ + struct script_mod_enum *This = script_mod_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 script_mod_enum_AddRef(IEnumVARIANT *iface) +{ + struct script_mod_enum *This = script_mod_enum_from_IEnumVARIANT(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + return ref; +} + +static ULONG WINAPI script_mod_enum_Release(IEnumVARIANT *iface) +{ + struct script_mod_enum *This = script_mod_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 script_mod_enum_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched) +{ + struct script_mod_enum *This = script_mod_enum_from_IEnumVARIANT(iface); + UINT i, num; + + 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++) + { + V_VT(rgVar + i) = VT_DISPATCH; + V_DISPATCH(rgVar + i) = (IDispatch*)(&This->control->modules[This->pos++]->IScriptModule_iface); + IDispatch_AddRef(V_DISPATCH(rgVar + i)); + } + + if (pCeltFetched) *pCeltFetched = i; + return i == celt ? S_OK : S_FALSE; +} + +static HRESULT WINAPI script_mod_enum_Skip(IEnumVARIANT *iface, ULONG celt) +{ + struct script_mod_enum *This = script_mod_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 script_mod_enum_Reset(IEnumVARIANT *iface) +{ + struct script_mod_enum *This = script_mod_enum_from_IEnumVARIANT(iface); + + TRACE("(%p)\n", This); + + This->pos = 0; + return S_OK; +} + +static HRESULT WINAPI script_mod_enum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum) +{ + struct script_mod_enum *This = script_mod_enum_from_IEnumVARIANT(iface); + struct script_mod_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 script_mod_enum_vtbl = { + script_mod_enum_QueryInterface, + script_mod_enum_AddRef, + script_mod_enum_Release, + script_mod_enum_Next, + script_mod_enum_Skip, + script_mod_enum_Reset, + script_mod_enum_Clone +}; + static ScriptModule *alloc_module(ScriptControl *control, BSTR name) { ScriptModule *module = heap_alloc_zero(sizeof(*module)); @@ -1049,10 +1182,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 script_mod_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 = &script_mod_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, -- 2.21.0