msxml3: Don't crash on null pointer when doing ::Next() on a last child.
[wine/multimedia.git] / dlls / msxml3 / xmlelem.c
blobc0671794283084b73e3275a22f792ed7a41376a2
1 /*
2 * XML Element implementation
4 * Copyright 2007 James Hawkins
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include "config.h"
25 #include <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "ole2.h"
30 #include "msxml2.h"
31 #include "ocidl.h"
33 #include "wine/debug.h"
35 #include "msxml_private.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
39 #ifdef HAVE_LIBXML2
41 static HRESULT XMLElementCollection_create( IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj );
43 /**********************************************************************
44 * IXMLElement
46 typedef struct _xmlelem
48 const IXMLElementVtbl *lpVtbl;
49 LONG ref;
50 xmlNodePtr node;
51 BOOL own;
52 } xmlelem;
54 static inline xmlelem *impl_from_IXMLElement(IXMLElement *iface)
56 return (xmlelem *)((char*)iface - FIELD_OFFSET(xmlelem, lpVtbl));
59 static HRESULT WINAPI xmlelem_QueryInterface(IXMLElement *iface, REFIID riid, void** ppvObject)
61 xmlelem *This = impl_from_IXMLElement(iface);
63 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
65 if (IsEqualGUID(riid, &IID_IUnknown) ||
66 IsEqualGUID(riid, &IID_IXMLElement))
68 *ppvObject = iface;
70 else
72 FIXME("interface %s not implemented\n", debugstr_guid(riid));
73 return E_NOINTERFACE;
76 IXMLElement_AddRef(iface);
78 return S_OK;
81 static ULONG WINAPI xmlelem_AddRef(IXMLElement *iface)
83 xmlelem *This = impl_from_IXMLElement(iface);
84 TRACE("%p\n", This);
85 return InterlockedIncrement(&This->ref);
88 static ULONG WINAPI xmlelem_Release(IXMLElement *iface)
90 xmlelem *This = impl_from_IXMLElement(iface);
91 LONG ref;
93 TRACE("%p\n", This);
95 ref = InterlockedDecrement(&This->ref);
96 if (ref == 0)
98 if (This->own) xmlFreeNode(This->node);
99 heap_free(This);
102 return ref;
105 static HRESULT WINAPI xmlelem_GetTypeInfoCount(IXMLElement *iface, UINT* pctinfo)
107 xmlelem *This = impl_from_IXMLElement(iface);
109 TRACE("(%p)->(%p)\n", This, pctinfo);
111 *pctinfo = 1;
113 return S_OK;
116 static HRESULT WINAPI xmlelem_GetTypeInfo(IXMLElement *iface, UINT iTInfo,
117 LCID lcid, ITypeInfo** ppTInfo)
119 xmlelem *This = impl_from_IXMLElement(iface);
120 HRESULT hr;
122 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
124 hr = get_typeinfo(IXMLElement_tid, ppTInfo);
126 return hr;
129 static HRESULT WINAPI xmlelem_GetIDsOfNames(IXMLElement *iface, REFIID riid,
130 LPOLESTR* rgszNames, UINT cNames,
131 LCID lcid, DISPID* rgDispId)
133 xmlelem *This = impl_from_IXMLElement(iface);
134 ITypeInfo *typeinfo;
135 HRESULT hr;
137 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
138 lcid, rgDispId);
140 if(!rgszNames || cNames == 0 || !rgDispId)
141 return E_INVALIDARG;
143 hr = get_typeinfo(IXMLElement_tid, &typeinfo);
144 if(SUCCEEDED(hr))
146 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
147 ITypeInfo_Release(typeinfo);
150 return hr;
153 static HRESULT WINAPI xmlelem_Invoke(IXMLElement *iface, DISPID dispIdMember,
154 REFIID riid, LCID lcid, WORD wFlags,
155 DISPPARAMS* pDispParams, VARIANT* pVarResult,
156 EXCEPINFO* pExcepInfo, UINT* puArgErr)
158 xmlelem *This = impl_from_IXMLElement(iface);
159 ITypeInfo *typeinfo;
160 HRESULT hr;
162 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
163 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
165 hr = get_typeinfo(IXMLElement_tid, &typeinfo);
166 if(SUCCEEDED(hr))
168 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
169 pVarResult, pExcepInfo, puArgErr);
170 ITypeInfo_Release(typeinfo);
173 return hr;
176 static HRESULT WINAPI xmlelem_get_tagName(IXMLElement *iface, BSTR *p)
178 xmlelem *This = impl_from_IXMLElement(iface);
180 TRACE("(%p, %p)\n", iface, p);
182 if (!p)
183 return E_INVALIDARG;
185 *p = bstr_from_xmlChar(This->node->name);
186 CharUpperBuffW(*p, SysStringLen(*p));
188 TRACE("returning %s\n", debugstr_w(*p));
190 return S_OK;
193 static HRESULT WINAPI xmlelem_put_tagName(IXMLElement *iface, BSTR p)
195 FIXME("(%p, %p): stub\n", iface, p);
197 if (!p)
198 return E_INVALIDARG;
200 return E_NOTIMPL;
203 static HRESULT WINAPI xmlelem_get_parent(IXMLElement *iface, IXMLElement **parent)
205 xmlelem *This = impl_from_IXMLElement(iface);
207 TRACE("(%p, %p)\n", iface, parent);
209 if (!parent)
210 return E_INVALIDARG;
212 *parent = NULL;
214 if (!This->node->parent)
215 return S_FALSE;
217 return XMLElement_create((IUnknown *)iface, This->node->parent, (LPVOID *)parent, FALSE);
220 static HRESULT WINAPI xmlelem_setAttribute(IXMLElement *iface, BSTR strPropertyName,
221 VARIANT PropertyValue)
223 xmlelem *This = impl_from_IXMLElement(iface);
224 xmlChar *name, *value;
225 xmlAttrPtr attr;
227 TRACE("(%p, %s)\n", iface, debugstr_w(strPropertyName));
229 if (!strPropertyName || V_VT(&PropertyValue) != VT_BSTR)
230 return E_INVALIDARG;
232 name = xmlChar_from_wchar(strPropertyName);
233 value = xmlChar_from_wchar(V_BSTR(&PropertyValue));
234 attr = xmlSetProp(This->node, name, value);
236 heap_free(name);
237 heap_free(value);
238 return (attr) ? S_OK : S_FALSE;
241 static HRESULT WINAPI xmlelem_getAttribute(IXMLElement *iface, BSTR name,
242 VARIANT *value)
244 static const WCHAR xmllangW[] = { 'x','m','l',':','l','a','n','g',0 };
245 xmlelem *This = impl_from_IXMLElement(iface);
246 xmlChar *val = NULL;
248 TRACE("(%p, %s, %p)\n", iface, debugstr_w(name), value);
250 if (!value)
251 return E_INVALIDARG;
253 VariantInit(value);
254 V_BSTR(value) = NULL;
256 if (!name)
257 return E_INVALIDARG;
259 /* case for xml:lang attribute */
260 if (!lstrcmpiW(name, xmllangW))
262 xmlNsPtr ns;
263 ns = xmlSearchNs(This->node->doc, This->node, (xmlChar*)"xml");
264 val = xmlGetNsProp(This->node, (xmlChar*)"lang", ns->href);
265 xmlFree(ns);
267 else
269 xmlAttrPtr attr;
270 xmlChar *xml_name;
272 xml_name = xmlChar_from_wchar(name);
273 attr = This->node->properties;
274 while (attr)
276 BSTR attr_name;
278 attr_name = bstr_from_xmlChar(attr->name);
279 if (!lstrcmpiW(name, attr_name))
281 val = xmlNodeListGetString(attr->doc, attr->children, 1);
282 SysFreeString(attr_name);
283 break;
286 attr = attr->next;
287 SysFreeString(attr_name);
290 heap_free(xml_name);
293 if (val)
295 V_VT(value) = VT_BSTR;
296 V_BSTR(value) = bstr_from_xmlChar(val);
299 xmlFree(val);
300 TRACE("returning %s\n", debugstr_w(V_BSTR(value)));
301 return (val) ? S_OK : S_FALSE;
304 static HRESULT WINAPI xmlelem_removeAttribute(IXMLElement *iface, BSTR strPropertyName)
306 xmlelem *This = impl_from_IXMLElement(iface);
307 xmlChar *name;
308 xmlAttrPtr attr;
309 int res;
310 HRESULT hr = S_FALSE;
312 TRACE("(%p, %s)\n", iface, debugstr_w(strPropertyName));
314 if (!strPropertyName)
315 return E_INVALIDARG;
317 name = xmlChar_from_wchar(strPropertyName);
318 attr = xmlHasProp(This->node, name);
319 if (!attr)
320 goto done;
322 res = xmlRemoveProp(attr);
324 if (res == 0)
325 hr = S_OK;
327 done:
328 heap_free(name);
329 return hr;
332 static HRESULT WINAPI xmlelem_get_children(IXMLElement *iface, IXMLElementCollection **p)
334 xmlelem *This = impl_from_IXMLElement(iface);
336 TRACE("(%p, %p)\n", iface, p);
338 if (!p)
339 return E_INVALIDARG;
341 return XMLElementCollection_create((IUnknown *)iface, This->node, (LPVOID *)p);
344 static LONG type_libxml_to_msxml(xmlElementType type)
346 switch (type)
348 case XML_ELEMENT_NODE:
349 return XMLELEMTYPE_ELEMENT;
350 case XML_TEXT_NODE:
351 return XMLELEMTYPE_TEXT;
352 case XML_COMMENT_NODE:
353 return XMLELEMTYPE_COMMENT;
354 case XML_DOCUMENT_NODE:
355 return XMLELEMTYPE_DOCUMENT;
356 case XML_DTD_NODE:
357 return XMLELEMTYPE_DTD;
358 case XML_PI_NODE:
359 return XMLELEMTYPE_PI;
360 default:
361 break;
364 return XMLELEMTYPE_OTHER;
367 static HRESULT WINAPI xmlelem_get_type(IXMLElement *iface, LONG *p)
369 xmlelem *This = impl_from_IXMLElement(iface);
371 TRACE("(%p, %p)\n", This, p);
373 if (!p)
374 return E_INVALIDARG;
376 *p = type_libxml_to_msxml(This->node->type);
377 TRACE("returning %d\n", *p);
378 return S_OK;
381 static HRESULT WINAPI xmlelem_get_text(IXMLElement *iface, BSTR *p)
383 xmlelem *This = impl_from_IXMLElement(iface);
384 xmlChar *content;
386 TRACE("(%p, %p)\n", iface, p);
388 if (!p)
389 return E_INVALIDARG;
391 content = xmlNodeGetContent(This->node);
392 *p = bstr_from_xmlChar(content);
393 TRACE("returning %s\n", debugstr_w(*p));
395 xmlFree(content);
396 return S_OK;
399 static HRESULT WINAPI xmlelem_put_text(IXMLElement *iface, BSTR p)
401 xmlelem *This = impl_from_IXMLElement(iface);
402 xmlChar *content;
404 TRACE("(%p, %s)\n", iface, debugstr_w(p));
406 /* FIXME: test which types can be used */
407 if (This->node->type == XML_ELEMENT_NODE)
408 return E_NOTIMPL;
410 content = xmlChar_from_wchar(p);
411 xmlNodeSetContent(This->node, content);
413 heap_free(content);
415 return S_OK;
418 static HRESULT WINAPI xmlelem_addChild(IXMLElement *iface, IXMLElement *pChildElem,
419 LONG lIndex, LONG lreserved)
421 xmlelem *This = impl_from_IXMLElement(iface);
422 xmlelem *childElem = impl_from_IXMLElement(pChildElem);
423 xmlNodePtr child;
425 TRACE("(%p, %p, %d, %d)\n", iface, pChildElem, lIndex, lreserved);
427 if (lIndex == 0)
428 child = xmlAddChild(This->node, childElem->node);
429 else
430 child = xmlAddNextSibling(This->node, childElem->node->last);
432 /* parent is responsible for child data */
433 if (child) childElem->own = FALSE;
435 return (child) ? S_OK : S_FALSE;
438 static HRESULT WINAPI xmlelem_removeChild(IXMLElement *iface, IXMLElement *pChildElem)
440 xmlelem *This = impl_from_IXMLElement(iface);
441 xmlelem *childElem = impl_from_IXMLElement(pChildElem);
443 TRACE("(%p, %p)\n", This, childElem);
445 if (!pChildElem)
446 return E_INVALIDARG;
448 /* only supported for This is childElem parent case */
449 if (This->node != childElem->node->parent)
450 return E_INVALIDARG;
452 xmlUnlinkNode(childElem->node);
453 /* standalone element now */
454 childElem->own = TRUE;
456 return S_OK;
459 static const struct IXMLElementVtbl xmlelem_vtbl =
461 xmlelem_QueryInterface,
462 xmlelem_AddRef,
463 xmlelem_Release,
464 xmlelem_GetTypeInfoCount,
465 xmlelem_GetTypeInfo,
466 xmlelem_GetIDsOfNames,
467 xmlelem_Invoke,
468 xmlelem_get_tagName,
469 xmlelem_put_tagName,
470 xmlelem_get_parent,
471 xmlelem_setAttribute,
472 xmlelem_getAttribute,
473 xmlelem_removeAttribute,
474 xmlelem_get_children,
475 xmlelem_get_type,
476 xmlelem_get_text,
477 xmlelem_put_text,
478 xmlelem_addChild,
479 xmlelem_removeChild
482 HRESULT XMLElement_create(IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj, BOOL own)
484 xmlelem *elem;
486 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
488 if (!ppObj)
489 return E_INVALIDARG;
491 *ppObj = NULL;
493 elem = heap_alloc(sizeof (*elem));
494 if(!elem)
495 return E_OUTOFMEMORY;
497 elem->lpVtbl = &xmlelem_vtbl;
498 elem->ref = 1;
499 elem->node = node;
500 elem->own = own;
502 *ppObj = &elem->lpVtbl;
504 TRACE("returning iface %p\n", *ppObj);
505 return S_OK;
508 /************************************************************************
509 * IXMLElementCollection
511 typedef struct _xmlelem_collection
513 const IXMLElementCollectionVtbl *lpVtbl;
514 const IEnumVARIANTVtbl *lpvtblIEnumVARIANT;
515 LONG ref;
516 LONG length;
517 xmlNodePtr node;
519 /* IEnumVARIANT members */
520 xmlNodePtr current;
521 } xmlelem_collection;
523 static inline LONG xmlelem_collection_updatelength(xmlelem_collection *collection)
525 xmlNodePtr ptr = collection->node->children;
527 collection->length = 0;
528 while (ptr)
530 collection->length++;
531 ptr = ptr->next;
533 return collection->length;
536 static inline xmlelem_collection *impl_from_IXMLElementCollection(IXMLElementCollection *iface)
538 return (xmlelem_collection *)((char*)iface - FIELD_OFFSET(xmlelem_collection, lpVtbl));
541 static inline xmlelem_collection *impl_from_IEnumVARIANT(IEnumVARIANT *iface)
543 return (xmlelem_collection *)((char*)iface - FIELD_OFFSET(xmlelem_collection, lpvtblIEnumVARIANT));
546 static HRESULT WINAPI xmlelem_collection_QueryInterface(IXMLElementCollection *iface, REFIID riid, void** ppvObject)
548 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
550 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
552 if (IsEqualGUID(riid, &IID_IUnknown) ||
553 IsEqualGUID(riid, &IID_IXMLElementCollection))
555 *ppvObject = iface;
557 else if (IsEqualGUID(riid, &IID_IEnumVARIANT))
559 *ppvObject = &(This->lpvtblIEnumVARIANT);
561 else
563 FIXME("interface %s not implemented\n", debugstr_guid(riid));
564 return E_NOINTERFACE;
567 IXMLElementCollection_AddRef(iface);
569 return S_OK;
572 static ULONG WINAPI xmlelem_collection_AddRef(IXMLElementCollection *iface)
574 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
575 TRACE("%p\n", This);
576 return InterlockedIncrement(&This->ref);
579 static ULONG WINAPI xmlelem_collection_Release(IXMLElementCollection *iface)
581 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
582 LONG ref;
584 TRACE("%p\n", This);
586 ref = InterlockedDecrement(&This->ref);
587 if (ref == 0)
589 heap_free(This);
592 return ref;
595 static HRESULT WINAPI xmlelem_collection_GetTypeInfoCount(IXMLElementCollection *iface, UINT* pctinfo)
597 FIXME("\n");
598 return E_NOTIMPL;
601 static HRESULT WINAPI xmlelem_collection_GetTypeInfo(IXMLElementCollection *iface, UINT iTInfo,
602 LCID lcid, ITypeInfo** ppTInfo)
604 FIXME("\n");
605 return E_NOTIMPL;
608 static HRESULT WINAPI xmlelem_collection_GetIDsOfNames(IXMLElementCollection *iface, REFIID riid,
609 LPOLESTR* rgszNames, UINT cNames,
610 LCID lcid, DISPID* rgDispId)
612 FIXME("\n");
613 return E_NOTIMPL;
616 static HRESULT WINAPI xmlelem_collection_Invoke(IXMLElementCollection *iface, DISPID dispIdMember,
617 REFIID riid, LCID lcid, WORD wFlags,
618 DISPPARAMS* pDispParams, VARIANT* pVarResult,
619 EXCEPINFO* pExcepInfo, UINT* puArgErr)
621 FIXME("\n");
622 return E_NOTIMPL;
625 static HRESULT WINAPI xmlelem_collection_put_length(IXMLElementCollection *iface, LONG v)
627 TRACE("(%p, %d)\n", iface, v);
628 return E_FAIL;
631 static HRESULT WINAPI xmlelem_collection_get_length(IXMLElementCollection *iface, LONG *p)
633 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
635 TRACE("(%p, %p)\n", iface, p);
637 if (!p)
638 return E_INVALIDARG;
640 *p = xmlelem_collection_updatelength(This);
641 return S_OK;
644 static HRESULT WINAPI xmlelem_collection_get__newEnum(IXMLElementCollection *iface, IUnknown **ppUnk)
646 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
648 TRACE("(%p, %p)\n", iface, ppUnk);
650 if (!ppUnk)
651 return E_INVALIDARG;
653 *ppUnk = (IUnknown *)This;
654 IUnknown_AddRef(*ppUnk);
655 return S_OK;
658 static HRESULT WINAPI xmlelem_collection_item(IXMLElementCollection *iface, VARIANT var1,
659 VARIANT var2, IDispatch **ppDisp)
661 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
662 xmlNodePtr ptr = This->node->children;
663 int index, i;
665 TRACE("(%p, %p)\n", iface, ppDisp);
667 if (!ppDisp)
668 return E_INVALIDARG;
670 *ppDisp = NULL;
672 index = V_I4(&var1);
673 if (index < 0)
674 return E_INVALIDARG;
676 xmlelem_collection_updatelength(This);
677 if (index >= This->length)
678 return E_FAIL;
680 for (i = 0; i < index; i++)
681 ptr = ptr->next;
683 return XMLElement_create((IUnknown *)iface, ptr, (LPVOID *)ppDisp, FALSE);
686 static const struct IXMLElementCollectionVtbl xmlelem_collection_vtbl =
688 xmlelem_collection_QueryInterface,
689 xmlelem_collection_AddRef,
690 xmlelem_collection_Release,
691 xmlelem_collection_GetTypeInfoCount,
692 xmlelem_collection_GetTypeInfo,
693 xmlelem_collection_GetIDsOfNames,
694 xmlelem_collection_Invoke,
695 xmlelem_collection_put_length,
696 xmlelem_collection_get_length,
697 xmlelem_collection_get__newEnum,
698 xmlelem_collection_item
701 /************************************************************************
702 * xmlelem_collection implementation of IEnumVARIANT.
704 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_QueryInterface(
705 IEnumVARIANT *iface, REFIID riid, LPVOID *ppvObj)
707 xmlelem_collection *this = impl_from_IEnumVARIANT(iface);
708 return IXMLDocument_QueryInterface((IXMLDocument *)this, riid, ppvObj);
711 static ULONG WINAPI xmlelem_collection_IEnumVARIANT_AddRef(
712 IEnumVARIANT *iface)
714 xmlelem_collection *this = impl_from_IEnumVARIANT(iface);
715 return IXMLDocument_AddRef((IXMLDocument *)this);
718 static ULONG WINAPI xmlelem_collection_IEnumVARIANT_Release(
719 IEnumVARIANT *iface)
721 xmlelem_collection *this = impl_from_IEnumVARIANT(iface);
722 return IXMLDocument_Release((IXMLDocument *)this);
725 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Next(
726 IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *fetched)
728 xmlelem_collection *This = impl_from_IEnumVARIANT(iface);
729 xmlNodePtr ptr = This->current;
731 TRACE("(%p, %d, %p, %p)\n", iface, celt, rgVar, fetched);
733 if (!rgVar)
734 return E_INVALIDARG;
736 /* FIXME: handle celt */
737 if (fetched)
738 *fetched = 1;
740 if (This->current)
741 This->current = This->current->next;
742 else
744 V_VT(rgVar) = VT_EMPTY;
745 if (fetched) *fetched = 0;
746 return S_FALSE;
749 V_VT(rgVar) = VT_DISPATCH;
750 return XMLElement_create((IUnknown *)iface, ptr, (LPVOID *)&V_DISPATCH(rgVar), FALSE);
753 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Skip(
754 IEnumVARIANT *iface, ULONG celt)
756 FIXME("(%p, %d): stub\n", iface, celt);
757 return E_NOTIMPL;
760 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Reset(
761 IEnumVARIANT *iface)
763 xmlelem_collection *This = impl_from_IEnumVARIANT(iface);
764 This->current = This->node->children;
765 return S_OK;
768 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Clone(
769 IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
771 FIXME("(%p, %p): stub\n", iface, ppEnum);
772 return E_NOTIMPL;
775 static const struct IEnumVARIANTVtbl xmlelem_collection_IEnumVARIANTvtbl =
777 xmlelem_collection_IEnumVARIANT_QueryInterface,
778 xmlelem_collection_IEnumVARIANT_AddRef,
779 xmlelem_collection_IEnumVARIANT_Release,
780 xmlelem_collection_IEnumVARIANT_Next,
781 xmlelem_collection_IEnumVARIANT_Skip,
782 xmlelem_collection_IEnumVARIANT_Reset,
783 xmlelem_collection_IEnumVARIANT_Clone
786 static HRESULT XMLElementCollection_create(IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj)
788 xmlelem_collection *collection;
790 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
792 *ppObj = NULL;
794 if (!node->children)
795 return S_FALSE;
797 collection = heap_alloc(sizeof (*collection));
798 if(!collection)
799 return E_OUTOFMEMORY;
801 collection->lpVtbl = &xmlelem_collection_vtbl;
802 collection->lpvtblIEnumVARIANT = &xmlelem_collection_IEnumVARIANTvtbl;
803 collection->ref = 1;
804 collection->length = 0;
805 collection->node = node;
806 collection->current = node->children;
807 xmlelem_collection_updatelength(collection);
809 *ppObj = &collection->lpVtbl;
811 TRACE("returning iface %p\n", *ppObj);
812 return S_OK;
815 #endif