Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlstylesheet.c | 152 ++++++++++++++++++++++++++++++++++- dlls/mshtml/tests/dom.c | 27 +++++++ 2 files changed, 177 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlstylesheet.c b/dlls/mshtml/htmlstylesheet.c index 2d16f4a..2d76e37 100644 --- a/dlls/mshtml/htmlstylesheet.c +++ b/dlls/mshtml/htmlstylesheet.c @@ -50,6 +50,15 @@ struct HTMLStyleSheetsCollection { nsIDOMStyleSheetList *nslist; };
+typedef struct { + IEnumVARIANT IEnumVARIANT_iface; + + LONG ref; + + ULONG iter; + HTMLStyleSheetsCollection *col; +} HTMLStyleSheetsCollectionEnum; + struct HTMLStyleSheetRulesCollection { DispatchEx dispex; IHTMLStyleSheetRulesCollection IHTMLStyleSheetRulesCollection_iface; @@ -479,6 +488,130 @@ static HRESULT create_style_sheet_rules_collection(nsIDOMCSSRuleList *nslist, co return S_OK; }
+static inline HTMLStyleSheetsCollectionEnum *HTMLStyleSheetsCollectionEnum_from_IEnumVARIANT(IEnumVARIANT *iface) +{ + return CONTAINING_RECORD(iface, HTMLStyleSheetsCollectionEnum, IEnumVARIANT_iface); +} + +static HRESULT WINAPI HTMLStyleSheetsCollectionEnum_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv) +{ + HTMLStyleSheetsCollectionEnum *This = HTMLStyleSheetsCollectionEnum_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 HTMLStyleSheetsCollectionEnum_AddRef(IEnumVARIANT *iface) +{ + HTMLStyleSheetsCollectionEnum *This = HTMLStyleSheetsCollectionEnum_from_IEnumVARIANT(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%ld\n", This, ref); + + return ref; +} + +static ULONG WINAPI HTMLStyleSheetsCollectionEnum_Release(IEnumVARIANT *iface) +{ + HTMLStyleSheetsCollectionEnum *This = HTMLStyleSheetsCollectionEnum_from_IEnumVARIANT(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%ld\n", This, ref); + + if(!ref) { + IHTMLStyleSheetsCollection_Release(&This->col->IHTMLStyleSheetsCollection_iface); + heap_free(This); + } + + return ref; +} + +static HRESULT WINAPI HTMLStyleSheetsCollectionEnum_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched) +{ + HTMLStyleSheetsCollectionEnum *This = HTMLStyleSheetsCollectionEnum_from_IEnumVARIANT(iface); + VARIANT index; + HRESULT hres; + ULONG num, i; + UINT32 len; + + TRACE("(%p)->(%lu %p %p)\n", This, celt, rgVar, pCeltFetched); + + nsIDOMStyleSheetList_GetLength(This->col->nslist, &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 = IHTMLStyleSheetsCollection_item(&This->col->IHTMLStyleSheetsCollection_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 HTMLStyleSheetsCollectionEnum_Skip(IEnumVARIANT *iface, ULONG celt) +{ + HTMLStyleSheetsCollectionEnum *This = HTMLStyleSheetsCollectionEnum_from_IEnumVARIANT(iface); + UINT32 len; + + TRACE("(%p)->(%lu)\n", This, celt); + + nsIDOMStyleSheetList_GetLength(This->col->nslist, &len); + if(This->iter + celt > len) { + This->iter = len; + return S_FALSE; + } + + This->iter += celt; + return S_OK; +} + +static HRESULT WINAPI HTMLStyleSheetsCollectionEnum_Reset(IEnumVARIANT *iface) +{ + HTMLStyleSheetsCollectionEnum *This = HTMLStyleSheetsCollectionEnum_from_IEnumVARIANT(iface); + + TRACE("(%p)->()\n", This); + + This->iter = 0; + return S_OK; +} + +static HRESULT WINAPI HTMLStyleSheetsCollectionEnum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum) +{ + HTMLStyleSheetsCollectionEnum *This = HTMLStyleSheetsCollectionEnum_from_IEnumVARIANT(iface); + FIXME("(%p)->(%p)\n", This, ppEnum); + return E_NOTIMPL; +} + +static const IEnumVARIANTVtbl HTMLStyleSheetsCollectionEnumVtbl = { + HTMLStyleSheetsCollectionEnum_QueryInterface, + HTMLStyleSheetsCollectionEnum_AddRef, + HTMLStyleSheetsCollectionEnum_Release, + HTMLStyleSheetsCollectionEnum_Next, + HTMLStyleSheetsCollectionEnum_Skip, + HTMLStyleSheetsCollectionEnum_Reset, + HTMLStyleSheetsCollectionEnum_Clone +}; + static inline HTMLStyleSheetsCollection *impl_from_IHTMLStyleSheetsCollection(IHTMLStyleSheetsCollection *iface) { return CONTAINING_RECORD(iface, HTMLStyleSheetsCollection, IHTMLStyleSheetsCollection_iface); @@ -586,8 +719,23 @@ static HRESULT WINAPI HTMLStyleSheetsCollection_get__newEnum(IHTMLStyleSheetsCol IUnknown **p) { HTMLStyleSheetsCollection *This = impl_from_IHTMLStyleSheetsCollection(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + HTMLStyleSheetsCollectionEnum *ret; + + TRACE("(%p)->(%p)\n", This, p); + + ret = heap_alloc(sizeof(*ret)); + if(!ret) + return E_OUTOFMEMORY; + + ret->IEnumVARIANT_iface.lpVtbl = &HTMLStyleSheetsCollectionEnumVtbl; + ret->ref = 1; + ret->iter = 0; + + HTMLStyleSheetsCollection_AddRef(&This->IHTMLStyleSheetsCollection_iface); + ret->col = This; + + *p = (IUnknown*)&ret->IEnumVARIANT_iface; + return S_OK; }
static HRESULT WINAPI HTMLStyleSheetsCollection_item(IHTMLStyleSheetsCollection *iface, diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index 4af0e9b..73b9831 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -8577,7 +8577,10 @@ static void test_stylesheet(IDispatch *disp) static void test_stylesheets(IHTMLDocument2 *doc) { IHTMLStyleSheetsCollection *col = NULL; + IEnumVARIANT *enum_var; + IUnknown *enum_unk; VARIANT idx, res; + ULONG fetched; LONG len = 0; HRESULT hres;
@@ -8611,6 +8614,30 @@ static void test_stylesheets(IHTMLDocument2 *doc) ok(V_VT(&res) == VT_EMPTY, "V_VT(res) = %d\n", V_VT(&res)); VariantClear(&res);
+ hres = IHTMLStyleSheetsCollection_get__newEnum(col, &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(&res) = VT_ERROR; + hres = IEnumVARIANT_Next(enum_var, 1, &res, &fetched); + ok(hres == S_OK, "Next failed: %08lx\n", hres); + ok(fetched == 1, "fetched = %lu\n", fetched); + ok(V_VT(&res) == VT_DISPATCH, "V_VT(res) = %d\n", V_VT(&res)); + ok(V_DISPATCH(&res) != NULL, "V_DISPATCH(&res) == NULL\n"); + test_disp2((IUnknown*)V_DISPATCH(&res), &DIID_DispHTMLStyleSheet, &IID_IHTMLStyleSheet, NULL, L"[object]"); + VariantClear(&res); + + fetched = 0; + V_VT(&res) = VT_ERROR; + hres = IEnumVARIANT_Next(enum_var, 1, &res, &fetched); + ok(hres == S_FALSE, "Next failed: %08lx\n", hres); + ok(fetched == 0, "fetched = %lu\n", fetched); + IEnumVARIANT_Release(enum_var); + IHTMLStyleSheetsCollection_Release(col); }