diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c
index 47c18279689..9ed22495058 100644
--- a/dlls/mshtml/htmlelem.c
+++ b/dlls/mshtml/htmlelem.c
@@ -781,6 +781,139 @@ typedef struct {
nsIDOMClientRectList *rect_list;
} HTMLRectCollection;
+typedef struct {
+ IEnumVARIANT IEnumVARIANT_iface;
+
+ LONG ref;
+
+ ULONG iter;
+ HTMLRectCollection *col;
+} HTMLRectCollectionEnum;
+
+static inline HTMLRectCollectionEnum *HTMLRectCollectionEnum_from_IEnumVARIANT(IEnumVARIANT *iface)
+{
+ return CONTAINING_RECORD(iface, HTMLRectCollectionEnum, IEnumVARIANT_iface);
+}
+
+static HRESULT WINAPI HTMLRectCollectionEnum_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv)
+{
+ HTMLRectCollectionEnum *This = HTMLRectCollectionEnum_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 HTMLRectCollectionEnum_AddRef(IEnumVARIANT *iface)
+{
+ HTMLRectCollectionEnum *This = HTMLRectCollectionEnum_from_IEnumVARIANT(iface);
+ LONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) ref=%ld\n", This, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI HTMLRectCollectionEnum_Release(IEnumVARIANT *iface)
+{
+ HTMLRectCollectionEnum *This = HTMLRectCollectionEnum_from_IEnumVARIANT(iface);
+ LONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) ref=%ld\n", This, ref);
+
+ if(!ref) {
+ IHTMLRectCollection_Release(&This->col->IHTMLRectCollection_iface);
+ heap_free(This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI HTMLRectCollectionEnum_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
+{
+ HTMLRectCollectionEnum *This = HTMLRectCollectionEnum_from_IEnumVARIANT(iface);
+ VARIANT index;
+ HRESULT hres;
+ ULONG num, i;
+ UINT32 len;
+
+ TRACE("(%p)->(%lu %p %p)\n", This, celt, rgVar, pCeltFetched);
+
+ nsIDOMClientRectList_GetLength(This->col->rect_list, &len);
+ num = min(len - This->iter, celt);
+ V_VT(&index) = VT_I4;
+
+ for(i = 0; i < num; i++) {
+ V_I4(&index) = This->iter + i;
+ hres = IHTMLRectCollection_item(&This->col->IHTMLRectCollection_iface, &index, &rgVar[i]);
+ if(FAILED(hres)) {
+ while(i--)
+ VariantClear(&rgVar[i]);
+ return hres;
+ }
+ }
+
+ This->iter += num;
+ if(pCeltFetched)
+ *pCeltFetched = num;
+ return num == celt ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI HTMLRectCollectionEnum_Skip(IEnumVARIANT *iface, ULONG celt)
+{
+ HTMLRectCollectionEnum *This = HTMLRectCollectionEnum_from_IEnumVARIANT(iface);
+ UINT32 len;
+
+ TRACE("(%p)->(%lu)\n", This, celt);
+
+ nsIDOMClientRectList_GetLength(This->col->rect_list, &len);
+ if(This->iter + celt > len) {
+ This->iter = len;
+ return S_FALSE;
+ }
+
+ This->iter += celt;
+ return S_OK;
+}
+
+static HRESULT WINAPI HTMLRectCollectionEnum_Reset(IEnumVARIANT *iface)
+{
+ HTMLRectCollectionEnum *This = HTMLRectCollectionEnum_from_IEnumVARIANT(iface);
+
+ TRACE("(%p)->()\n", This);
+
+ This->iter = 0;
+ return S_OK;
+}
+
+static HRESULT WINAPI HTMLRectCollectionEnum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
+{
+ HTMLRectCollectionEnum *This = HTMLRectCollectionEnum_from_IEnumVARIANT(iface);
+ FIXME("(%p)->(%p)\n", This, ppEnum);
+ return E_NOTIMPL;
+}
+
+static const IEnumVARIANTVtbl HTMLRectCollectionEnumVtbl = {
+ HTMLRectCollectionEnum_QueryInterface,
+ HTMLRectCollectionEnum_AddRef,
+ HTMLRectCollectionEnum_Release,
+ HTMLRectCollectionEnum_Next,
+ HTMLRectCollectionEnum_Skip,
+ HTMLRectCollectionEnum_Reset,
+ HTMLRectCollectionEnum_Clone
+};
+
static inline HTMLRectCollection *impl_from_IHTMLRectCollection(IHTMLRectCollection *iface)
{
return CONTAINING_RECORD(iface, HTMLRectCollection, IHTMLRectCollection_iface);
@@ -883,8 +1016,23 @@ static HRESULT WINAPI HTMLRectCollection_get_length(IHTMLRectCollection *iface,
static HRESULT WINAPI HTMLRectCollection_get__newEnum(IHTMLRectCollection *iface, IUnknown **p)
{
HTMLRectCollection *This = impl_from_IHTMLRectCollection(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ HTMLRectCollectionEnum *ret;
+
+ TRACE("(%p)->(%p)\n", This, p);
+
+ ret = heap_alloc(sizeof(*ret));
+ if(!ret)
+ return E_OUTOFMEMORY;
+
+ ret->IEnumVARIANT_iface.lpVtbl = &HTMLRectCollectionEnumVtbl;
+ ret->ref = 1;
+ ret->iter = 0;
+
+ HTMLRectCollection_AddRef(&This->IHTMLRectCollection_iface);
+ ret->col = This;
+
+ *p = (IUnknown*)&ret->IEnumVARIANT_iface;
+ return S_OK;
}
static HRESULT WINAPI HTMLRectCollection_item(IHTMLRectCollection *iface, VARIANT *index, VARIANT *result)
diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c
index 73b983174d5..00c15773f96 100644
--- a/dlls/mshtml/tests/dom.c
+++ b/dlls/mshtml/tests/dom.c
@@ -5229,8 +5229,11 @@ static void test_elem_bounding_client_rect(IUnknown *unk)
{
IHTMLRectCollection *rects;
IHTMLRect *rect, *rect2;
+ IEnumVARIANT *enum_var;
IHTMLElement2 *elem2;
+ IUnknown *enum_unk;
VARIANT v, index;
+ ULONG fetched;
LONG l;
HRESULT hres;
@@ -5285,6 +5288,30 @@ static void test_elem_bounding_client_rect(IUnknown *unk)
test_disp((IUnknown*)V_DISPATCH(&v), &IID_IHTMLRect, NULL, L"[object]");
VariantClear(&v);
+ hres = IHTMLRectCollection_get__newEnum(rects, &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), &IID_IHTMLRect, NULL, L"[object]");
+ 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);
+
IHTMLRectCollection_Release(rects);
IHTMLElement2_Release(elem2);
}