wininet: Fix invalid memory access in HTTP_QUERY_RAW_HEADERS (Valgrind).
[wine/multimedia.git] / dlls / mshtml / htmlelemcol.c
blob8fd61edd2bfab89162add54efbc02a7b2df10ebe
1 /*
2 * Copyright 2006-2008 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
21 #define COBJMACROS
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "ole2.h"
28 #include "wine/debug.h"
30 #include "mshtml_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
34 typedef struct {
35 DispatchEx dispex;
36 IHTMLElementCollection IHTMLElementCollection_iface;
38 HTMLElement **elems;
39 DWORD len;
41 LONG ref;
42 } HTMLElementCollection;
44 typedef struct {
45 IEnumVARIANT IEnumVARIANT_iface;
47 LONG ref;
49 ULONG iter;
50 HTMLElementCollection *col;
51 } HTMLElementCollectionEnum;
53 typedef struct {
54 HTMLElement **buf;
55 DWORD len;
56 DWORD size;
57 } elem_vector_t;
59 /* FIXME: Handle it better way */
60 static inline HTMLElement *elem_from_HTMLDOMNode(HTMLDOMNode *iface)
62 return CONTAINING_RECORD(iface, HTMLElement, node);
65 static IHTMLElementCollection *HTMLElementCollection_Create(HTMLElement **elems, DWORD len);
67 static void elem_vector_add(elem_vector_t *buf, HTMLElement *elem)
69 if(buf->len == buf->size) {
70 buf->size <<= 1;
71 buf->buf = heap_realloc(buf->buf, buf->size*sizeof(HTMLElement*));
74 buf->buf[buf->len++] = elem;
77 static void elem_vector_normalize(elem_vector_t *buf)
79 if(!buf->len) {
80 heap_free(buf->buf);
81 buf->buf = NULL;
82 }else if(buf->size > buf->len) {
83 buf->buf = heap_realloc(buf->buf, buf->len*sizeof(HTMLElement*));
86 buf->size = buf->len;
89 static inline BOOL is_elem_node(nsIDOMNode *node)
91 UINT16 type=0;
93 nsIDOMNode_GetNodeType(node, &type);
95 return type == ELEMENT_NODE || type == COMMENT_NODE;
98 static inline HTMLElementCollectionEnum *impl_from_IEnumVARIANT(IEnumVARIANT *iface)
100 return CONTAINING_RECORD(iface, HTMLElementCollectionEnum, IEnumVARIANT_iface);
103 static HRESULT WINAPI HTMLElementCollectionEnum_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv)
105 HTMLElementCollectionEnum *This = impl_from_IEnumVARIANT(iface);
107 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
109 if(IsEqualGUID(riid, &IID_IUnknown)) {
110 *ppv = &This->IEnumVARIANT_iface;
111 }else if(IsEqualGUID(riid, &IID_IEnumVARIANT)) {
112 *ppv = &This->IEnumVARIANT_iface;
113 }else {
114 FIXME("Unsupported iface %s\n", debugstr_mshtml_guid(riid));
115 *ppv = NULL;
116 return E_NOINTERFACE;
119 IUnknown_AddRef((IUnknown*)*ppv);
120 return S_OK;
123 static ULONG WINAPI HTMLElementCollectionEnum_AddRef(IEnumVARIANT *iface)
125 HTMLElementCollectionEnum *This = impl_from_IEnumVARIANT(iface);
126 LONG ref = InterlockedIncrement(&This->ref);
128 TRACE("(%p) ref=%d\n", This, ref);
130 return ref;
133 static ULONG WINAPI HTMLElementCollectionEnum_Release(IEnumVARIANT *iface)
135 HTMLElementCollectionEnum *This = impl_from_IEnumVARIANT(iface);
136 LONG ref = InterlockedDecrement(&This->ref);
138 TRACE("(%p) ref=%d\n", This, ref);
140 if(!ref) {
141 IHTMLElementCollection_Release(&This->col->IHTMLElementCollection_iface);
142 heap_free(This);
145 return ref;
148 static HRESULT WINAPI HTMLElementCollectionEnum_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
150 HTMLElementCollectionEnum *This = impl_from_IEnumVARIANT(iface);
151 ULONG fetched = 0;
153 TRACE("(%p)->(%d %p %p)\n", This, celt, rgVar, pCeltFetched);
155 while(This->iter+fetched < This->col->len && fetched < celt) {
156 V_VT(rgVar+fetched) = VT_DISPATCH;
157 V_DISPATCH(rgVar+fetched) = (IDispatch*)&This->col->elems[This->iter+fetched]->IHTMLElement_iface;
158 IDispatch_AddRef(V_DISPATCH(rgVar+fetched));
159 fetched++;
162 This->iter += fetched;
163 if(pCeltFetched)
164 *pCeltFetched = fetched;
165 return fetched == celt ? S_OK : S_FALSE;
168 static HRESULT WINAPI HTMLElementCollectionEnum_Skip(IEnumVARIANT *iface, ULONG celt)
170 HTMLElementCollectionEnum *This = impl_from_IEnumVARIANT(iface);
172 TRACE("(%p)->(%d)\n", This, celt);
174 if(This->iter + celt > This->col->len) {
175 This->iter = This->col->len;
176 return S_FALSE;
179 This->iter += celt;
180 return S_OK;
183 static HRESULT WINAPI HTMLElementCollectionEnum_Reset(IEnumVARIANT *iface)
185 HTMLElementCollectionEnum *This = impl_from_IEnumVARIANT(iface);
187 TRACE("(%p)->()\n", This);
189 This->iter = 0;
190 return S_OK;
193 static HRESULT WINAPI HTMLElementCollectionEnum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
195 HTMLElementCollectionEnum *This = impl_from_IEnumVARIANT(iface);
196 FIXME("(%p)->(%p)\n", This, ppEnum);
197 return E_NOTIMPL;
200 static const IEnumVARIANTVtbl HTMLElementCollectionEnumVtbl = {
201 HTMLElementCollectionEnum_QueryInterface,
202 HTMLElementCollectionEnum_AddRef,
203 HTMLElementCollectionEnum_Release,
204 HTMLElementCollectionEnum_Next,
205 HTMLElementCollectionEnum_Skip,
206 HTMLElementCollectionEnum_Reset,
207 HTMLElementCollectionEnum_Clone
210 static inline HTMLElementCollection *impl_from_IHTMLElementCollection(IHTMLElementCollection *iface)
212 return CONTAINING_RECORD(iface, HTMLElementCollection, IHTMLElementCollection_iface);
215 static HRESULT WINAPI HTMLElementCollection_QueryInterface(IHTMLElementCollection *iface,
216 REFIID riid, void **ppv)
218 HTMLElementCollection *This = impl_from_IHTMLElementCollection(iface);
220 if(IsEqualGUID(&IID_IUnknown, riid)) {
221 *ppv = &This->IHTMLElementCollection_iface;
222 }else if(IsEqualGUID(&IID_IHTMLElementCollection, riid)) {
223 *ppv = &This->IHTMLElementCollection_iface;
224 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
225 return *ppv ? S_OK : E_NOINTERFACE;
226 }else {
227 *ppv = NULL;
228 FIXME("Unsupported iface %s\n", debugstr_mshtml_guid(riid));
229 return E_NOINTERFACE;
232 IHTMLElementCollection_AddRef(&This->IHTMLElementCollection_iface);
233 return S_OK;
236 static ULONG WINAPI HTMLElementCollection_AddRef(IHTMLElementCollection *iface)
238 HTMLElementCollection *This = impl_from_IHTMLElementCollection(iface);
239 LONG ref = InterlockedIncrement(&This->ref);
241 TRACE("(%p) ref=%d\n", This, ref);
243 return ref;
246 static ULONG WINAPI HTMLElementCollection_Release(IHTMLElementCollection *iface)
248 HTMLElementCollection *This = impl_from_IHTMLElementCollection(iface);
249 LONG ref = InterlockedDecrement(&This->ref);
251 TRACE("(%p) ref=%d\n", This, ref);
253 if(!ref) {
254 unsigned i;
256 for(i=0; i < This->len; i++)
257 node_release(&This->elems[i]->node);
258 heap_free(This->elems);
260 release_dispex(&This->dispex);
261 heap_free(This);
264 return ref;
267 static HRESULT WINAPI HTMLElementCollection_GetTypeInfoCount(IHTMLElementCollection *iface,
268 UINT *pctinfo)
270 HTMLElementCollection *This = impl_from_IHTMLElementCollection(iface);
271 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
274 static HRESULT WINAPI HTMLElementCollection_GetTypeInfo(IHTMLElementCollection *iface,
275 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
277 HTMLElementCollection *This = impl_from_IHTMLElementCollection(iface);
278 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
281 static HRESULT WINAPI HTMLElementCollection_GetIDsOfNames(IHTMLElementCollection *iface,
282 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
284 HTMLElementCollection *This = impl_from_IHTMLElementCollection(iface);
285 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
286 lcid, rgDispId);
289 static HRESULT WINAPI HTMLElementCollection_Invoke(IHTMLElementCollection *iface,
290 DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
291 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
293 HTMLElementCollection *This = impl_from_IHTMLElementCollection(iface);
294 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
295 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
298 static HRESULT WINAPI HTMLElementCollection_toString(IHTMLElementCollection *iface,
299 BSTR *String)
301 HTMLElementCollection *This = impl_from_IHTMLElementCollection(iface);
302 FIXME("(%p)->(%p)\n", This, String);
303 return E_NOTIMPL;
306 static HRESULT WINAPI HTMLElementCollection_put_length(IHTMLElementCollection *iface,
307 LONG v)
309 HTMLElementCollection *This = impl_from_IHTMLElementCollection(iface);
310 FIXME("(%p)->(%d)\n", This, v);
311 return E_NOTIMPL;
314 static HRESULT WINAPI HTMLElementCollection_get_length(IHTMLElementCollection *iface,
315 LONG *p)
317 HTMLElementCollection *This = impl_from_IHTMLElementCollection(iface);
319 TRACE("(%p)->(%p)\n", This, p);
321 *p = This->len;
322 return S_OK;
325 static HRESULT WINAPI HTMLElementCollection_get__newEnum(IHTMLElementCollection *iface,
326 IUnknown **p)
328 HTMLElementCollection *This = impl_from_IHTMLElementCollection(iface);
329 HTMLElementCollectionEnum *ret;
331 TRACE("(%p)->(%p)\n", This, p);
333 ret = heap_alloc(sizeof(*ret));
334 if(!ret)
335 return E_OUTOFMEMORY;
337 ret->IEnumVARIANT_iface.lpVtbl = &HTMLElementCollectionEnumVtbl;
338 ret->ref = 1;
339 ret->iter = 0;
341 IHTMLElementCollection_AddRef(&This->IHTMLElementCollection_iface);
342 ret->col = This;
344 *p = (IUnknown*)&ret->IEnumVARIANT_iface;
345 return S_OK;
348 static BOOL is_elem_id(HTMLElement *elem, LPCWSTR name)
350 BSTR elem_id;
351 HRESULT hres;
353 hres = IHTMLElement_get_id(&elem->IHTMLElement_iface, &elem_id);
354 if(FAILED(hres)){
355 WARN("IHTMLElement_get_id failed: 0x%08x\n", hres);
356 return FALSE;
359 if(elem_id && !strcmpW(elem_id, name)) {
360 SysFreeString(elem_id);
361 return TRUE;
364 SysFreeString(elem_id);
365 return FALSE;
368 static BOOL is_elem_name(HTMLElement *elem, LPCWSTR name)
370 const PRUnichar *str;
371 nsAString nsstr;
372 BOOL ret = FALSE;
373 nsresult nsres;
375 static const PRUnichar nameW[] = {'n','a','m','e',0};
377 if(!elem->nselem)
378 return FALSE;
380 nsAString_Init(&nsstr, NULL);
381 nsIDOMHTMLElement_GetId(elem->nselem, &nsstr);
382 nsAString_GetData(&nsstr, &str);
383 if(!strcmpiW(str, name)) {
384 nsAString_Finish(&nsstr);
385 return TRUE;
388 nsres = get_elem_attr_value(elem->nselem, nameW, &nsstr, &str);
389 if(NS_SUCCEEDED(nsres)) {
390 ret = !strcmpiW(str, name);
391 nsAString_Finish(&nsstr);
394 return ret;
397 static HRESULT get_item_idx(HTMLElementCollection *This, UINT idx, IDispatch **ret)
399 if(idx < This->len) {
400 *ret = (IDispatch*)This->elems[idx];
401 IDispatch_AddRef(*ret);
404 return S_OK;
407 static HRESULT WINAPI HTMLElementCollection_item(IHTMLElementCollection *iface,
408 VARIANT name, VARIANT index, IDispatch **pdisp)
410 HTMLElementCollection *This = impl_from_IHTMLElementCollection(iface);
411 HRESULT hres = S_OK;
413 TRACE("(%p)->(%s %s %p)\n", This, debugstr_variant(&name), debugstr_variant(&index), pdisp);
415 *pdisp = NULL;
417 switch(V_VT(&name)) {
418 case VT_I4:
419 if(V_I4(&name) < 0)
420 return E_INVALIDARG;
421 hres = get_item_idx(This, V_I4(&name), pdisp);
422 break;
424 case VT_UINT:
425 hres = get_item_idx(This, V_UINT(&name), pdisp);
426 break;
428 case VT_BSTR: {
429 DWORD i;
431 if(V_VT(&index) == VT_I4) {
432 LONG idx = V_I4(&index);
434 if(idx < 0)
435 return E_INVALIDARG;
437 for(i=0; i<This->len; i++) {
438 if(is_elem_name(This->elems[i], V_BSTR(&name)) && !idx--)
439 break;
442 if(i != This->len) {
443 *pdisp = (IDispatch*)&This->elems[i]->IHTMLElement_iface;
444 IDispatch_AddRef(*pdisp);
446 }else {
447 elem_vector_t buf = {NULL, 0, 8};
449 buf.buf = heap_alloc(buf.size*sizeof(HTMLElement*));
451 for(i=0; i<This->len; i++) {
452 if(is_elem_name(This->elems[i], V_BSTR(&name))) {
453 node_addref(&This->elems[i]->node);
454 elem_vector_add(&buf, This->elems[i]);
458 if(buf.len > 1) {
459 elem_vector_normalize(&buf);
460 *pdisp = (IDispatch*)HTMLElementCollection_Create(buf.buf, buf.len);
461 }else {
462 if(buf.len == 1) {
463 /* Already AddRef-ed */
464 *pdisp = (IDispatch*)&buf.buf[0]->IHTMLElement_iface;
467 heap_free(buf.buf);
470 break;
473 default:
474 FIXME("Unsupported name %s\n", debugstr_variant(&name));
475 hres = E_NOTIMPL;
478 if(SUCCEEDED(hres))
479 TRACE("returning %p\n", *pdisp);
480 return hres;
483 static HRESULT WINAPI HTMLElementCollection_tags(IHTMLElementCollection *iface,
484 VARIANT tagName, IDispatch **pdisp)
486 HTMLElementCollection *This = impl_from_IHTMLElementCollection(iface);
487 DWORD i;
488 nsAString tag_str;
489 const PRUnichar *tag;
490 elem_vector_t buf = {NULL, 0, 8};
492 if(V_VT(&tagName) != VT_BSTR) {
493 WARN("Invalid arg\n");
494 return DISP_E_MEMBERNOTFOUND;
497 TRACE("(%p)->(%s %p)\n", This, debugstr_w(V_BSTR(&tagName)), pdisp);
499 buf.buf = heap_alloc(buf.size*sizeof(HTMLElement*));
501 nsAString_Init(&tag_str, NULL);
503 for(i=0; i<This->len; i++) {
504 if(!This->elems[i]->nselem)
505 continue;
507 nsIDOMHTMLElement_GetTagName(This->elems[i]->nselem, &tag_str);
508 nsAString_GetData(&tag_str, &tag);
510 if(CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, tag, -1,
511 V_BSTR(&tagName), -1) == CSTR_EQUAL) {
512 node_addref(&This->elems[i]->node);
513 elem_vector_add(&buf, This->elems[i]);
517 nsAString_Finish(&tag_str);
518 elem_vector_normalize(&buf);
520 TRACE("fount %d tags\n", buf.len);
522 *pdisp = (IDispatch*)HTMLElementCollection_Create(buf.buf, buf.len);
523 return S_OK;
526 static const IHTMLElementCollectionVtbl HTMLElementCollectionVtbl = {
527 HTMLElementCollection_QueryInterface,
528 HTMLElementCollection_AddRef,
529 HTMLElementCollection_Release,
530 HTMLElementCollection_GetTypeInfoCount,
531 HTMLElementCollection_GetTypeInfo,
532 HTMLElementCollection_GetIDsOfNames,
533 HTMLElementCollection_Invoke,
534 HTMLElementCollection_toString,
535 HTMLElementCollection_put_length,
536 HTMLElementCollection_get_length,
537 HTMLElementCollection_get__newEnum,
538 HTMLElementCollection_item,
539 HTMLElementCollection_tags
542 static inline HTMLElementCollection *impl_from_DispatchEx(DispatchEx *iface)
544 return CONTAINING_RECORD(iface, HTMLElementCollection, dispex);
547 #define DISPID_ELEMCOL_0 MSHTML_DISPID_CUSTOM_MIN
549 static HRESULT HTMLElementCollection_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid)
551 HTMLElementCollection *This = impl_from_DispatchEx(dispex);
552 WCHAR *ptr;
553 DWORD idx=0;
555 if(!*name)
556 return DISP_E_UNKNOWNNAME;
558 for(ptr = name; *ptr && isdigitW(*ptr); ptr++)
559 idx = idx*10 + (*ptr-'0');
561 if(*ptr) {
562 /* the name contains alpha characters, so search by name & id */
563 for(idx = 0; idx < This->len; ++idx) {
564 if(is_elem_id(This->elems[idx], name) ||
565 is_elem_name(This->elems[idx], name))
566 break;
570 if(idx >= This->len)
571 return DISP_E_UNKNOWNNAME;
573 *dispid = DISPID_ELEMCOL_0 + idx;
574 TRACE("ret %x\n", *dispid);
575 return S_OK;
578 static HRESULT HTMLElementCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
579 VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
581 HTMLElementCollection *This = impl_from_DispatchEx(dispex);
582 DWORD idx;
584 TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller);
586 idx = id - DISPID_ELEMCOL_0;
587 if(idx >= This->len)
588 return DISP_E_UNKNOWNNAME;
590 switch(flags) {
591 case DISPATCH_PROPERTYGET:
592 V_VT(res) = VT_DISPATCH;
593 V_DISPATCH(res) = (IDispatch*)&This->elems[idx]->IHTMLElement_iface;
594 IHTMLElement_AddRef(&This->elems[idx]->IHTMLElement_iface);
595 break;
596 default:
597 FIXME("unimplemented flags %x\n", flags);
598 return E_NOTIMPL;
601 return S_OK;
604 static const dispex_static_data_vtbl_t HTMLElementColection_dispex_vtbl = {
605 NULL,
606 HTMLElementCollection_get_dispid,
607 HTMLElementCollection_invoke,
608 NULL
611 static const tid_t HTMLElementCollection_iface_tids[] = {
612 IHTMLElementCollection_tid,
616 static dispex_static_data_t HTMLElementCollection_dispex = {
617 &HTMLElementColection_dispex_vtbl,
618 DispHTMLElementCollection_tid,
619 NULL,
620 HTMLElementCollection_iface_tids
623 static void create_all_list(HTMLDocumentNode *doc, HTMLDOMNode *elem, elem_vector_t *buf)
625 nsIDOMNodeList *nsnode_list;
626 nsIDOMNode *iter;
627 UINT32 list_len = 0, i;
628 nsresult nsres;
629 HRESULT hres;
631 nsres = nsIDOMNode_GetChildNodes(elem->nsnode, &nsnode_list);
632 if(NS_FAILED(nsres)) {
633 ERR("GetChildNodes failed: %08x\n", nsres);
634 return;
637 nsIDOMNodeList_GetLength(nsnode_list, &list_len);
638 if(!list_len)
639 return;
641 for(i=0; i<list_len; i++) {
642 nsres = nsIDOMNodeList_Item(nsnode_list, i, &iter);
643 if(NS_FAILED(nsres)) {
644 ERR("Item failed: %08x\n", nsres);
645 continue;
648 if(is_elem_node(iter)) {
649 HTMLDOMNode *node;
651 hres = get_node(doc, iter, TRUE, &node);
652 if(FAILED(hres)) {
653 FIXME("get_node failed: %08x\n", hres);
654 continue;
657 elem_vector_add(buf, elem_from_HTMLDOMNode(node));
658 create_all_list(doc, node, buf);
663 IHTMLElementCollection *create_all_collection(HTMLDOMNode *node, BOOL include_root)
665 elem_vector_t buf = {NULL, 0, 8};
667 buf.buf = heap_alloc(buf.size*sizeof(HTMLElement*));
669 if(include_root) {
670 node_addref(node);
671 elem_vector_add(&buf, elem_from_HTMLDOMNode(node));
673 create_all_list(node->doc, node, &buf);
674 elem_vector_normalize(&buf);
676 return HTMLElementCollection_Create(buf.buf, buf.len);
679 IHTMLElementCollection *create_collection_from_nodelist(HTMLDocumentNode *doc, nsIDOMNodeList *nslist)
681 UINT32 length = 0, i;
682 HTMLDOMNode *node;
683 elem_vector_t buf;
684 HRESULT hres;
686 nsIDOMNodeList_GetLength(nslist, &length);
688 buf.len = 0;
689 buf.size = length;
690 if(length) {
691 nsIDOMNode *nsnode;
693 buf.buf = heap_alloc(buf.size*sizeof(HTMLElement*));
695 for(i=0; i<length; i++) {
696 nsIDOMNodeList_Item(nslist, i, &nsnode);
697 if(is_elem_node(nsnode)) {
698 hres = get_node(doc, nsnode, TRUE, &node);
699 if(FAILED(hres))
700 continue;
701 buf.buf[buf.len++] = elem_from_HTMLDOMNode(node);
703 nsIDOMNode_Release(nsnode);
706 elem_vector_normalize(&buf);
707 }else {
708 buf.buf = NULL;
711 return HTMLElementCollection_Create(buf.buf, buf.len);
714 IHTMLElementCollection *create_collection_from_htmlcol(HTMLDocumentNode *doc, nsIDOMHTMLCollection *nscol)
716 UINT32 length = 0, i;
717 elem_vector_t buf;
718 HTMLDOMNode *node;
719 HRESULT hres = S_OK;
721 nsIDOMHTMLCollection_GetLength(nscol, &length);
723 buf.len = buf.size = length;
724 if(buf.len) {
725 nsIDOMNode *nsnode;
727 buf.buf = heap_alloc(buf.size*sizeof(HTMLElement*));
729 for(i=0; i<length; i++) {
730 nsIDOMHTMLCollection_Item(nscol, i, &nsnode);
731 hres = get_node(doc, nsnode, TRUE, &node);
732 nsIDOMNode_Release(nsnode);
733 if(FAILED(hres))
734 break;
735 buf.buf[i] = elem_from_HTMLDOMNode(node);
737 }else {
738 buf.buf = NULL;
741 if(FAILED(hres)) {
742 heap_free(buf.buf);
743 return NULL;
746 return HTMLElementCollection_Create(buf.buf, buf.len);
749 static IHTMLElementCollection *HTMLElementCollection_Create(HTMLElement **elems, DWORD len)
751 HTMLElementCollection *ret = heap_alloc_zero(sizeof(HTMLElementCollection));
753 ret->IHTMLElementCollection_iface.lpVtbl = &HTMLElementCollectionVtbl;
754 ret->ref = 1;
755 ret->elems = elems;
756 ret->len = len;
758 init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLElementCollection_iface,
759 &HTMLElementCollection_dispex);
761 TRACE("ret=%p len=%d\n", ret, len);
763 return &ret->IHTMLElementCollection_iface;