 
            From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 140 +++++++++++++++++++++++++++++++ dlls/mshtml/htmlelemcol.c | 154 +++++------------------------------ dlls/mshtml/mshtml_private.h | 15 ++++ 3 files changed, 174 insertions(+), 135 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index cd256dba677..1514a59b225 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -2901,6 +2901,146 @@ static IWineJSDispatchHostVtbl JSDispatchHostVtbl = { JSDispatchHost_ToString, };
+static inline CollectionEnum *CollectionEnum_from_IEnumVARIANT(IEnumVARIANT *iface) +{ + return CONTAINING_RECORD(iface, CollectionEnum, IEnumVARIANT_iface); +} + +static HRESULT WINAPI CollectionEnum_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv) +{ + CollectionEnum *This = CollectionEnum_from_IEnumVARIANT(iface); + + TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv); + + if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IEnumVARIANT)) + *ppv = &This->IEnumVARIANT_iface; + else { + FIXME("Unsupported iface %s\n", debugstr_mshtml_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI CollectionEnum_AddRef(IEnumVARIANT *iface) +{ + CollectionEnum *This = CollectionEnum_from_IEnumVARIANT(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%ld\n", This, ref); + + return ref; +} + +static ULONG WINAPI CollectionEnum_Release(IEnumVARIANT *iface) +{ + CollectionEnum *This = CollectionEnum_from_IEnumVARIANT(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%ld\n", This, ref); + + if(!ref) { + DispatchEx_Release(&This->collection->IWineJSDispatchHost_iface); + free(This); + } + + return ref; +} + +static HRESULT WINAPI CollectionEnum_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched) +{ + CollectionEnum *This = CollectionEnum_from_IEnumVARIANT(iface); + ULONG iter = This->iter, len, fetched = 0; + DispatchEx *col = This->collection; + HRESULT hres; + + TRACE("(%p)->(%ld %p %p)\n", This, celt, rgVar, pCeltFetched); + + len = col->info->vtbl->collection_len(col); + + while(iter + fetched < len && fetched < celt) { + hres = col->info->vtbl->collection_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++; + } + + This->iter = iter + fetched; + if(pCeltFetched) + *pCeltFetched = fetched; + return fetched == celt ? S_OK : S_FALSE; +} + +static HRESULT WINAPI CollectionEnum_Skip(IEnumVARIANT *iface, ULONG celt) +{ + CollectionEnum *This = CollectionEnum_from_IEnumVARIANT(iface); + ULONG len; + + TRACE("(%p)->(%ld)\n", This, celt); + + len = This->collection->info->vtbl->collection_len(This->collection); + + if(This->iter + celt > len) { + This->iter = len; + return S_FALSE; + } + + This->iter += celt; + return S_OK; +} + +static HRESULT WINAPI CollectionEnum_Reset(IEnumVARIANT *iface) +{ + CollectionEnum *This = CollectionEnum_from_IEnumVARIANT(iface); + + TRACE("(%p)->()\n", This); + + This->iter = 0; + return S_OK; +} + +static HRESULT WINAPI CollectionEnum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum) +{ + CollectionEnum *This = CollectionEnum_from_IEnumVARIANT(iface); + + FIXME("(%p)->(%p)\n", This, ppEnum); + + return E_NOTIMPL; +} + +static const IEnumVARIANTVtbl CollectionEnumVtbl = { + CollectionEnum_QueryInterface, + CollectionEnum_AddRef, + CollectionEnum_Release, + CollectionEnum_Next, + CollectionEnum_Skip, + CollectionEnum_Reset, + CollectionEnum_Clone +}; + +HRESULT CollectionEnum_create(DispatchEx *collection, IUnknown **ret) +{ + CollectionEnum *colenum = malloc(sizeof(*colenum)); + + if(!colenum) + return E_OUTOFMEMORY; + + colenum->IEnumVARIANT_iface.lpVtbl = &CollectionEnumVtbl; + colenum->ref = 1; + colenum->iter = 0; + colenum->collection = collection; + DispatchEx_AddRef(&collection->IWineJSDispatchHost_iface); + + *ret = (IUnknown*)&colenum->IEnumVARIANT_iface; + return S_OK; +} + HRESULT dispex_builtin_props_to_json(DispatchEx *dispex, HTMLInnerWindow *window, VARIANT *ret) { func_info_t *func, *end; diff --git a/dlls/mshtml/htmlelemcol.c b/dlls/mshtml/htmlelemcol.c index 5b3d9b56310..050047ec15a 100644 --- a/dlls/mshtml/htmlelemcol.c +++ b/dlls/mshtml/htmlelemcol.c @@ -39,15 +39,6 @@ typedef struct { DWORD len; } HTMLElementCollection;
-typedef struct { - IEnumVARIANT IEnumVARIANT_iface; - - LONG ref; - - ULONG iter; - HTMLElementCollection *col; -} HTMLElementCollectionEnum; - typedef struct { HTMLElement **buf; DWORD len; @@ -93,118 +84,6 @@ static inline BOOL is_elem_node(nsIDOMNode *node) return type == ELEMENT_NODE || type == COMMENT_NODE; }
-static inline HTMLElementCollectionEnum *impl_from_IEnumVARIANT(IEnumVARIANT *iface) -{ - return CONTAINING_RECORD(iface, HTMLElementCollectionEnum, IEnumVARIANT_iface); -} - -static HRESULT WINAPI HTMLElementCollectionEnum_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv) -{ - HTMLElementCollectionEnum *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("Unsupported iface %s\n", debugstr_mshtml_guid(riid)); - *ppv = NULL; - return E_NOINTERFACE; - } - - IUnknown_AddRef((IUnknown*)*ppv); - return S_OK; -} - -static ULONG WINAPI HTMLElementCollectionEnum_AddRef(IEnumVARIANT *iface) -{ - HTMLElementCollectionEnum *This = impl_from_IEnumVARIANT(iface); - LONG ref = InterlockedIncrement(&This->ref); - - TRACE("(%p) ref=%ld\n", This, ref); - - return ref; -} - -static ULONG WINAPI HTMLElementCollectionEnum_Release(IEnumVARIANT *iface) -{ - HTMLElementCollectionEnum *This = impl_from_IEnumVARIANT(iface); - LONG ref = InterlockedDecrement(&This->ref); - - TRACE("(%p) ref=%ld\n", This, ref); - - if(!ref) { - IHTMLElementCollection_Release(&This->col->IHTMLElementCollection_iface); - free(This); - } - - return ref; -} - -static HRESULT WINAPI HTMLElementCollectionEnum_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched) -{ - HTMLElementCollectionEnum *This = impl_from_IEnumVARIANT(iface); - ULONG fetched = 0; - - TRACE("(%p)->(%ld %p %p)\n", This, celt, rgVar, pCeltFetched); - - while(This->iter+fetched < This->col->len && fetched < celt) { - V_VT(rgVar+fetched) = VT_DISPATCH; - V_DISPATCH(rgVar+fetched) = (IDispatch*)&This->col->elems[This->iter+fetched]->IHTMLElement_iface; - IDispatch_AddRef(V_DISPATCH(rgVar+fetched)); - fetched++; - } - - This->iter += fetched; - if(pCeltFetched) - *pCeltFetched = fetched; - return fetched == celt ? S_OK : S_FALSE; -} - -static HRESULT WINAPI HTMLElementCollectionEnum_Skip(IEnumVARIANT *iface, ULONG celt) -{ - HTMLElementCollectionEnum *This = impl_from_IEnumVARIANT(iface); - - TRACE("(%p)->(%ld)\n", This, celt); - - if(This->iter + celt > This->col->len) { - This->iter = This->col->len; - return S_FALSE; - } - - This->iter += celt; - return S_OK; -} - -static HRESULT WINAPI HTMLElementCollectionEnum_Reset(IEnumVARIANT *iface) -{ - HTMLElementCollectionEnum *This = impl_from_IEnumVARIANT(iface); - - TRACE("(%p)->()\n", This); - - This->iter = 0; - return S_OK; -} - -static HRESULT WINAPI HTMLElementCollectionEnum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum) -{ - HTMLElementCollectionEnum *This = impl_from_IEnumVARIANT(iface); - FIXME("(%p)->(%p)\n", This, ppEnum); - return E_NOTIMPL; -} - -static const IEnumVARIANTVtbl HTMLElementCollectionEnumVtbl = { - HTMLElementCollectionEnum_QueryInterface, - HTMLElementCollectionEnum_AddRef, - HTMLElementCollectionEnum_Release, - HTMLElementCollectionEnum_Next, - HTMLElementCollectionEnum_Skip, - HTMLElementCollectionEnum_Reset, - HTMLElementCollectionEnum_Clone -}; - static inline HTMLElementCollection *impl_from_IHTMLElementCollection(IHTMLElementCollection *iface) { return CONTAINING_RECORD(iface, HTMLElementCollection, IHTMLElementCollection_iface); @@ -246,23 +125,10 @@ static HRESULT WINAPI HTMLElementCollection_get__newEnum(IHTMLElementCollection IUnknown **p) { HTMLElementCollection *This = impl_from_IHTMLElementCollection(iface); - HTMLElementCollectionEnum *ret;
TRACE("(%p)->(%p)\n", This, p);
- ret = malloc(sizeof(*ret)); - if(!ret) - return E_OUTOFMEMORY; - - ret->IEnumVARIANT_iface.lpVtbl = &HTMLElementCollectionEnumVtbl; - ret->ref = 1; - ret->iter = 0; - - IHTMLElementCollection_AddRef(&This->IHTMLElementCollection_iface); - ret->col = This; - - *p = (IUnknown*)&ret->IEnumVARIANT_iface; - return S_OK; + return CollectionEnum_create(&This->dispex, p); }
static BOOL is_elem_id(HTMLElement *elem, LPCWSTR name) @@ -559,6 +425,22 @@ static HRESULT HTMLElementCollection_invoke(DispatchEx *dispex, DISPID id, LCID return S_OK; }
+static ULONG HTMLElementCollection_collection_len(DispatchEx *dispex) +{ + HTMLElementCollection *This = impl_from_DispatchEx(dispex); + + return This->len; +} + +static HRESULT HTMLElementCollection_collection_item(DispatchEx *dispex, ULONG index, IDispatch **p) +{ + HTMLElementCollection *This = impl_from_DispatchEx(dispex); + + *p = (IDispatch*)&This->elems[index]->IHTMLElement_iface; + IDispatch_AddRef(*p); + return S_OK; +} + static const dispex_static_data_vtbl_t HTMLElementColection_dispex_vtbl = { .query_interface = HTMLElementCollection_query_interface, .destructor = HTMLElementCollection_destructor, @@ -567,6 +449,8 @@ static const dispex_static_data_vtbl_t HTMLElementColection_dispex_vtbl = { .get_dispid = HTMLElementCollection_get_dispid, .get_prop_desc = dispex_index_prop_desc, .invoke = HTMLElementCollection_invoke, + .collection_len = HTMLElementCollection_collection_len, + .collection_item = HTMLElementCollection_collection_item, };
static const tid_t HTMLCollection_iface_tids[] = { diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 6e4a58aee55..ddb4e68fb74 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -360,6 +360,7 @@ typedef struct dispex_dynamic_data_t dispex_dynamic_data_t; #define MSHTML_CUSTOM_DISPID_CNT (MSHTML_DISPID_CUSTOM_MAX-MSHTML_DISPID_CUSTOM_MIN)
typedef struct DispatchEx DispatchEx; +typedef struct CollectionEnum CollectionEnum; typedef struct nsCycleCollectionTraversalCallback nsCycleCollectionTraversalCallback; typedef struct dispex_static_data_t dispex_static_data_t;
@@ -420,6 +421,10 @@ typedef struct {
/* Used by objects that want to return a custom name instead of the one in the dispex static data */ const char *(*get_name)(DispatchEx*); + + /* Used by objects that have a collection of items, required by enumerators */ + ULONG (*collection_len)(DispatchEx*); + HRESULT (*collection_item)(DispatchEx*,ULONG,IDispatch**); } dispex_static_data_vtbl_t;
#define ALL_OBJECTS \ @@ -609,6 +614,16 @@ struct DispatchEx { } \ DISPEX_IDISPATCH_NOUNK_IMPL(prefix, iface_name, dispex)
+struct CollectionEnum { + IEnumVARIANT IEnumVARIANT_iface; + LONG ref; + + DispatchEx *collection; + ULONG iter; +}; + +HRESULT CollectionEnum_create(DispatchEx*,IUnknown**); + typedef struct { void *vtbl; int ref_flags;