From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 46 +++++++--- dlls/mshtml/htmlelem.c | 169 ++++++----------------------------- dlls/mshtml/mshtml_private.h | 4 + 3 files changed, 65 insertions(+), 154 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 88d2e3e37ba..97c0f311362 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -2958,20 +2958,36 @@ static HRESULT WINAPI CollectionEnum_Next(IEnumVARIANT *iface, ULONG celt, VARIA
TRACE("(%p)->(%ld %p %p)\n", This, celt, rgVar, pCeltFetched);
- len = This->vtbl->get_length(col); + if(This->vtbl->next_item) { + while(fetched < celt) { + hres = This->vtbl->next_item(col, &iter, &V_DISPATCH(rgVar + fetched)); + if(hres == S_FALSE) + break; + if(FAILED(hres)) { + while(fetched--) + VariantClear(rgVar + fetched); + return hres; + } + V_VT(rgVar + fetched) = V_DISPATCH(rgVar + fetched) ? VT_DISPATCH : VT_NULL; + fetched++; + } + }else { + len = This->vtbl->get_length(col);
- while(iter + fetched < len && fetched < celt) { - hres = This->vtbl->get_item(col, iter + fetched, &V_DISPATCH(rgVar + fetched)); - if(FAILED(hres)) { - while(fetched--) - VariantClear(rgVar + fetched); - return hres; + while(iter + fetched < len && fetched < celt) { + hres = This->vtbl->get_item(col, iter + fetched, &V_DISPATCH(rgVar + fetched)); + if(FAILED(hres)) { + while(fetched--) + VariantClear(rgVar + fetched); + return hres; + } + V_VT(rgVar + fetched) = V_DISPATCH(rgVar + fetched) ? VT_DISPATCH : VT_NULL; + fetched++; } - V_VT(rgVar + fetched) = V_DISPATCH(rgVar + fetched) ? VT_DISPATCH : VT_NULL; - fetched++; + iter += fetched; }
- This->iter = iter + fetched; + This->iter = iter; if(pCeltFetched) *pCeltFetched = fetched; return fetched == celt ? S_OK : S_FALSE; @@ -2984,6 +3000,12 @@ static HRESULT WINAPI CollectionEnum_Skip(IEnumVARIANT *iface, ULONG celt)
TRACE("(%p)->(%ld)\n", This, celt);
+ if(!celt) + return S_OK; + + if(This->vtbl->skip_items) + return This->vtbl->skip_items(This->collection, &This->iter, celt); + len = This->vtbl->get_length(This->collection);
if(This->iter + celt > len) { @@ -3001,7 +3023,7 @@ static HRESULT WINAPI CollectionEnum_Reset(IEnumVARIANT *iface)
TRACE("(%p)->()\n", This);
- This->iter = 0; + This->iter = This->vtbl->initial_iter_value; return S_OK; }
@@ -3034,7 +3056,7 @@ HRESULT CollectionEnum_create(DispatchEx *collection, const CollectionEnum_vtbl colenum->vtbl = vtbl; colenum->IEnumVARIANT_iface.lpVtbl = &CollectionEnumVtbl; colenum->ref = 1; - colenum->iter = 0; + colenum->iter = vtbl->initial_iter_value; colenum->collection = collection; DispatchEx_AddRef(&collection->IWineJSDispatchHost_iface);
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index e12b032dfb8..bff7a65fd5e 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -7798,154 +7798,57 @@ static inline HRESULT get_domattr(HTMLAttributeCollection *This, DISPID id, LONG return S_OK; }
-typedef struct { - IEnumVARIANT IEnumVARIANT_iface; - - LONG ref; - - DISPID iter_dispid; - HTMLAttributeCollection *col; -} HTMLAttributeCollectionEnum; - -static inline HTMLAttributeCollectionEnum *HTMLAttributeCollectionEnum_from_IEnumVARIANT(IEnumVARIANT *iface) -{ - return CONTAINING_RECORD(iface, HTMLAttributeCollectionEnum, IEnumVARIANT_iface); -} - -static HRESULT WINAPI HTMLAttributeCollectionEnum_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv) -{ - HTMLAttributeCollectionEnum *This = HTMLAttributeCollectionEnum_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 HTMLAttributeCollectionEnum_AddRef(IEnumVARIANT *iface) -{ - HTMLAttributeCollectionEnum *This = HTMLAttributeCollectionEnum_from_IEnumVARIANT(iface); - LONG ref = InterlockedIncrement(&This->ref); - - TRACE("(%p) ref=%ld\n", This, ref); - - return ref; -} - -static ULONG WINAPI HTMLAttributeCollectionEnum_Release(IEnumVARIANT *iface) +static inline HTMLAttributeCollection *HTMLAttributeCollection_from_DispatchEx(DispatchEx *iface) { - HTMLAttributeCollectionEnum *This = HTMLAttributeCollectionEnum_from_IEnumVARIANT(iface); - LONG ref = InterlockedDecrement(&This->ref); - - TRACE("(%p) ref=%ld\n", This, ref); - - if(!ref) { - IHTMLAttributeCollection_Release(&This->col->IHTMLAttributeCollection_iface); - free(This); - } - - return ref; + return CONTAINING_RECORD(iface, HTMLAttributeCollection, dispex); }
-static HRESULT WINAPI HTMLAttributeCollectionEnum_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched) +static HRESULT HTMLAttributeCollectionEnum_next_item(DispatchEx *dispex, ULONG *iter, IDispatch **p) { - HTMLAttributeCollectionEnum *This = HTMLAttributeCollectionEnum_from_IEnumVARIANT(iface); - DISPID tmp, dispid = This->iter_dispid; + HTMLAttributeCollection *col = HTMLAttributeCollection_from_DispatchEx(dispex); HTMLDOMAttribute *attr; + DISPID dispid = *iter; LONG rel_index = 0; HRESULT hres; - ULONG i; - - TRACE("(%p)->(%lu %p %p)\n", This, celt, rgVar, pCeltFetched); - - for(i = 0; i < celt; i++) { - hres = get_attr_dispid_by_relative_idx(This->col, &rel_index, dispid, &tmp); - if(SUCCEEDED(hres)) { - dispid = tmp; - hres = get_domattr(This->col, dispid, NULL, &attr); - } - else if(hres == DISP_E_UNKNOWNNAME) - break; - - if(FAILED(hres)) { - while(i--) - VariantClear(&rgVar[i]); - return hres; - }
- V_VT(&rgVar[i]) = VT_DISPATCH; - V_DISPATCH(&rgVar[i]) = (IDispatch*)&attr->IHTMLDOMAttribute_iface; + hres = get_attr_dispid_by_relative_idx(col, &rel_index, dispid, &dispid); + if(SUCCEEDED(hres)) + hres = get_domattr(col, dispid, NULL, &attr); + else if(hres == DISP_E_UNKNOWNNAME) + return S_FALSE; + if(SUCCEEDED(hres)) { + *iter = dispid; + *p = (IDispatch*)&attr->IHTMLDOMAttribute_iface; } - - This->iter_dispid = dispid; - if(pCeltFetched) - *pCeltFetched = i; - return i == celt ? S_OK : S_FALSE; + return hres; }
-static HRESULT WINAPI HTMLAttributeCollectionEnum_Skip(IEnumVARIANT *iface, ULONG celt) +static HRESULT HTMLAttributeCollectionEnum_skip_items(DispatchEx *dispex, ULONG *iter, ULONG skip) { - HTMLAttributeCollectionEnum *This = HTMLAttributeCollectionEnum_from_IEnumVARIANT(iface); - LONG remaining, rel_index; + HTMLAttributeCollection *col = HTMLAttributeCollection_from_DispatchEx(dispex); + LONG remaining, rel_index = -1; DISPID dispid; HRESULT hres;
- TRACE("(%p)->(%lu)\n", This, celt); - - if(!celt) - return S_OK; - - rel_index = -1; - hres = get_attr_dispid_by_relative_idx(This->col, &rel_index, This->iter_dispid, NULL); + hres = get_attr_dispid_by_relative_idx(col, &rel_index, *iter, NULL); if(FAILED(hres)) return hres; - remaining = min(celt, rel_index); + remaining = min(skip, rel_index);
if(remaining) { rel_index = remaining - 1; - hres = get_attr_dispid_by_relative_idx(This->col, &rel_index, This->iter_dispid, &dispid); + hres = get_attr_dispid_by_relative_idx(col, &rel_index, *iter, &dispid); if(FAILED(hres)) return hres; - This->iter_dispid = dispid; + *iter = dispid; } - return celt > remaining ? S_FALSE : S_OK; + return skip > remaining ? S_FALSE : S_OK; }
-static HRESULT WINAPI HTMLAttributeCollectionEnum_Reset(IEnumVARIANT *iface) -{ - HTMLAttributeCollectionEnum *This = HTMLAttributeCollectionEnum_from_IEnumVARIANT(iface); - - TRACE("(%p)->()\n", This); - - This->iter_dispid = DISPID_STARTENUM; - return S_OK; -} - -static HRESULT WINAPI HTMLAttributeCollectionEnum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum) -{ - HTMLAttributeCollectionEnum *This = HTMLAttributeCollectionEnum_from_IEnumVARIANT(iface); - FIXME("(%p)->(%p)\n", This, ppEnum); - return E_NOTIMPL; -} - -static const IEnumVARIANTVtbl HTMLAttributeCollectionEnumVtbl = { - HTMLAttributeCollectionEnum_QueryInterface, - HTMLAttributeCollectionEnum_AddRef, - HTMLAttributeCollectionEnum_Release, - HTMLAttributeCollectionEnum_Next, - HTMLAttributeCollectionEnum_Skip, - HTMLAttributeCollectionEnum_Reset, - HTMLAttributeCollectionEnum_Clone +static const CollectionEnum_vtbl HTMLAttributeCollectionEnum_vtbl = { + .initial_iter_value = DISPID_STARTENUM, + .next_item = HTMLAttributeCollectionEnum_next_item, + .skip_items = HTMLAttributeCollectionEnum_skip_items, };
/* interface IHTMLAttributeCollection */ @@ -7972,23 +7875,10 @@ static HRESULT WINAPI HTMLAttributeCollection_get_length(IHTMLAttributeCollectio static HRESULT WINAPI HTMLAttributeCollection__newEnum(IHTMLAttributeCollection *iface, IUnknown **p) { HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection(iface); - HTMLAttributeCollectionEnum *ret;
TRACE("(%p)->(%p)\n", This, p);
- ret = malloc(sizeof(*ret)); - if(!ret) - return E_OUTOFMEMORY; - - ret->IEnumVARIANT_iface.lpVtbl = &HTMLAttributeCollectionEnumVtbl; - ret->ref = 1; - ret->iter_dispid = DISPID_STARTENUM; - - HTMLAttributeCollection_AddRef(&This->IHTMLAttributeCollection_iface); - ret->col = This; - - *p = (IUnknown*)&ret->IEnumVARIANT_iface; - return S_OK; + return CollectionEnum_create(&This->dispex, &HTMLAttributeCollectionEnum_vtbl, p); }
static HRESULT WINAPI HTMLAttributeCollection_item(IHTMLAttributeCollection *iface, VARIANT *name, IDispatch **ppItem) @@ -8310,11 +8200,6 @@ static const IHTMLAttributeCollection4Vtbl HTMLAttributeCollection4Vtbl = { HTMLAttributeCollection4_get_length };
-static inline HTMLAttributeCollection *HTMLAttributeCollection_from_DispatchEx(DispatchEx *iface) -{ - return CONTAINING_RECORD(iface, HTMLAttributeCollection, dispex); -} - static void *HTMLAttributeCollection_query_interface(DispatchEx *dispex, REFIID riid) { HTMLAttributeCollection *This = HTMLAttributeCollection_from_DispatchEx(dispex); diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 0966b294e46..85bd5f8cd23 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -613,6 +613,10 @@ struct DispatchEx { typedef struct { ULONG (*get_length)(DispatchEx*); HRESULT (*get_item)(DispatchEx*,ULONG,IDispatch**); + HRESULT (*next_item)(DispatchEx*,ULONG*,IDispatch**); + HRESULT (*skip_items)(DispatchEx*,ULONG*,ULONG); + + ULONG initial_iter_value; } CollectionEnum_vtbl;
struct CollectionEnum {