[PATCH 07/10] mshtml: Implement enumerator for HTMLFormElement.
Gabriel Ivăncescu
gabrielopcode at gmail.com
Tue Apr 12 09:47:36 CDT 2022
Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
dlls/mshtml/htmlform.c | 157 +++++++++++++++++++++++++++++++++++++++-
dlls/mshtml/tests/dom.c | 39 +++++++++-
2 files changed, 193 insertions(+), 3 deletions(-)
diff --git a/dlls/mshtml/htmlform.c b/dlls/mshtml/htmlform.c
index 45ff19a..18b56ae 100644
--- a/dlls/mshtml/htmlform.c
+++ b/dlls/mshtml/htmlform.c
@@ -41,6 +41,15 @@ struct HTMLFormElement {
nsIDOMHTMLFormElement *nsform;
};
+typedef struct {
+ IEnumVARIANT IEnumVARIANT_iface;
+
+ LONG ref;
+
+ ULONG iter;
+ HTMLFormElement *elem;
+} HTMLFormElementEnum;
+
HRESULT return_nsform(nsresult nsres, nsIDOMHTMLFormElement *form, IHTMLFormElement **p)
{
nsIDOMNode *form_node;
@@ -108,6 +117,135 @@ static HRESULT htmlform_item(HTMLFormElement *This, int i, IDispatch **ret)
return S_OK;
}
+static inline HTMLFormElementEnum *impl_from_IEnumVARIANT(IEnumVARIANT *iface)
+{
+ return CONTAINING_RECORD(iface, HTMLFormElementEnum, IEnumVARIANT_iface);
+}
+
+static HRESULT WINAPI HTMLFormElementEnum_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv)
+{
+ HTMLFormElementEnum *This = impl_from_IEnumVARIANT(iface);
+
+ TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
+
+ if(IsEqualGUID(riid, &IID_IUnknown)) {
+ *ppv = &This->IEnumVARIANT_iface;
+ }else if(IsEqualGUID(riid, &IID_IEnumVARIANT)) {
+ *ppv = &This->IEnumVARIANT_iface;
+ }else {
+ FIXME("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI HTMLFormElementEnum_AddRef(IEnumVARIANT *iface)
+{
+ HTMLFormElementEnum *This = impl_from_IEnumVARIANT(iface);
+ LONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) ref=%ld\n", This, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI HTMLFormElementEnum_Release(IEnumVARIANT *iface)
+{
+ HTMLFormElementEnum *This = impl_from_IEnumVARIANT(iface);
+ LONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) ref=%ld\n", This, ref);
+
+ if(!ref) {
+ IHTMLFormElement_Release(&This->elem->IHTMLFormElement_iface);
+ heap_free(This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI HTMLFormElementEnum_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
+{
+ HTMLFormElementEnum *This = impl_from_IEnumVARIANT(iface);
+ nsresult nsres;
+ HRESULT hres;
+ ULONG num, i;
+ LONG len;
+
+ TRACE("(%p)->(%lu %p %p)\n", This, celt, rgVar, pCeltFetched);
+
+ nsres = nsIDOMHTMLFormElement_GetLength(This->elem->nsform, &len);
+ if(NS_FAILED(nsres))
+ return E_FAIL;
+ num = min(len - This->iter, celt);
+
+ for(i = 0; i < num; i++) {
+ hres = htmlform_item(This->elem, This->iter + i, &V_DISPATCH(&rgVar[i]));
+ if(FAILED(hres)) {
+ while(i--)
+ VariantClear(&rgVar[i]);
+ return hres;
+ }
+ V_VT(&rgVar[i]) = VT_DISPATCH;
+ }
+
+ This->iter += num;
+ if(pCeltFetched)
+ *pCeltFetched = num;
+ return num == celt ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI HTMLFormElementEnum_Skip(IEnumVARIANT *iface, ULONG celt)
+{
+ HTMLFormElementEnum *This = impl_from_IEnumVARIANT(iface);
+ nsresult nsres;
+ LONG len;
+
+ TRACE("(%p)->(%lu)\n", This, celt);
+
+ nsres = nsIDOMHTMLFormElement_GetLength(This->elem->nsform, &len);
+ if(NS_FAILED(nsres))
+ return E_FAIL;
+
+ if(This->iter + celt > len) {
+ This->iter = len;
+ return S_FALSE;
+ }
+
+ This->iter += celt;
+ return S_OK;
+}
+
+static HRESULT WINAPI HTMLFormElementEnum_Reset(IEnumVARIANT *iface)
+{
+ HTMLFormElementEnum *This = impl_from_IEnumVARIANT(iface);
+
+ TRACE("(%p)->()\n", This);
+
+ This->iter = 0;
+ return S_OK;
+}
+
+static HRESULT WINAPI HTMLFormElementEnum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
+{
+ HTMLFormElementEnum *This = impl_from_IEnumVARIANT(iface);
+ FIXME("(%p)->(%p)\n", This, ppEnum);
+ return E_NOTIMPL;
+}
+
+static const IEnumVARIANTVtbl HTMLFormElementEnumVtbl = {
+ HTMLFormElementEnum_QueryInterface,
+ HTMLFormElementEnum_AddRef,
+ HTMLFormElementEnum_Release,
+ HTMLFormElementEnum_Next,
+ HTMLFormElementEnum_Skip,
+ HTMLFormElementEnum_Reset,
+ HTMLFormElementEnum_Clone
+};
+
static inline HTMLFormElement *impl_from_IHTMLFormElement(IHTMLFormElement *iface)
{
return CONTAINING_RECORD(iface, HTMLFormElement, IHTMLFormElement_iface);
@@ -545,8 +683,23 @@ static HRESULT WINAPI HTMLFormElement_get_length(IHTMLFormElement *iface, LONG *
static HRESULT WINAPI HTMLFormElement__newEnum(IHTMLFormElement *iface, IUnknown **p)
{
HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ HTMLFormElementEnum *ret;
+
+ TRACE("(%p)->(%p)\n", This, p);
+
+ ret = heap_alloc(sizeof(*ret));
+ if(!ret)
+ return E_OUTOFMEMORY;
+
+ ret->IEnumVARIANT_iface.lpVtbl = &HTMLFormElementEnumVtbl;
+ ret->ref = 1;
+ ret->iter = 0;
+
+ HTMLFormElement_AddRef(&This->IHTMLFormElement_iface);
+ ret->elem = This;
+
+ *p = (IUnknown*)&ret->IEnumVARIANT_iface;
+ return S_OK;
}
static HRESULT WINAPI HTMLFormElement_item(IHTMLFormElement *iface, VARIANT name,
diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c
index 00c1577..bd4b772 100644
--- a/dlls/mshtml/tests/dom.c
+++ b/dlls/mshtml/tests/dom.c
@@ -5504,7 +5504,10 @@ static void test_form_item(IHTMLElement *elem)
{
IHTMLFormElement *form = get_form_iface((IUnknown*)elem);
IDispatch *disp, *disp2;
- VARIANT name, index;
+ IEnumVARIANT *enum_var;
+ VARIANT name, index, v;
+ IUnknown *enum_unk;
+ ULONG fetched;
HRESULT hres;
V_VT(&index) = VT_EMPTY;
@@ -5543,6 +5546,40 @@ static void test_form_item(IHTMLElement *elem)
ok(iface_cmp((IUnknown*)disp, (IUnknown*)disp2), "disp != disp2\n");
IDispatch_Release(disp2);
IDispatch_Release(disp);
+
+ hres = IHTMLFormElement_get__newEnum(form, &enum_unk);
+ ok(hres == S_OK, "_newEnum failed: %08lx\n", hres);
+
+ hres = IUnknown_QueryInterface(enum_unk, &IID_IEnumVARIANT, (void**)&enum_var);
+ IUnknown_Release(enum_unk);
+ ok(hres == S_OK, "Could not get IEnumVARIANT iface: %08lx\n", hres);
+
+ fetched = 0;
+ V_VT(&v) = VT_ERROR;
+ hres = IEnumVARIANT_Next(enum_var, 1, &v, &fetched);
+ ok(hres == S_OK, "Next failed: %08lx\n", hres);
+ ok(fetched == 1, "fetched = %lu\n", fetched);
+ ok(V_VT(&v) == VT_DISPATCH, "V_VT(v) = %d\n", V_VT(&v));
+ ok(V_DISPATCH(&v) != NULL, "V_DISPATCH(&v) == NULL\n");
+ test_disp((IUnknown*)V_DISPATCH(&v), &DIID_DispHTMLTextAreaElement, &CLSID_HTMLTextAreaElement, NULL);
+ VariantClear(&v);
+
+ fetched = 0;
+ V_VT(&v) = VT_ERROR;
+ hres = IEnumVARIANT_Next(enum_var, 1, &v, &fetched);
+ ok(hres == S_OK, "Next failed: %08lx\n", hres);
+ ok(fetched == 1, "fetched = %lu\n", fetched);
+ ok(V_VT(&v) == VT_DISPATCH, "V_VT(v) = %d\n", V_VT(&v));
+ ok(V_DISPATCH(&v) != NULL, "V_DISPATCH(&v) == NULL\n");
+ test_disp((IUnknown*)V_DISPATCH(&v), &DIID_DispHTMLInputElement, &CLSID_HTMLInputElement, NULL);
+ VariantClear(&v);
+
+ fetched = 0;
+ V_VT(&v) = VT_ERROR;
+ hres = IEnumVARIANT_Next(enum_var, 1, &v, &fetched);
+ ok(hres == S_FALSE, "Next failed: %08lx\n", hres);
+ ok(fetched == 0, "fetched = %lu\n", fetched);
+ IEnumVARIANT_Release(enum_var);
}
static void test_create_option_elem(IHTMLDocument2 *doc)
--
2.34.1
More information about the wine-devel
mailing list