include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / msxml3 / xmlelem.c
blob218603c1c92e7dbde3a813418a0adeaaebf281c4
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 <stdarg.h>
24 #include <libxml/parser.h>
25 #include <libxml/xmlerror.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "ole2.h"
31 #include "msxml6.h"
32 #include "ocidl.h"
34 #include "wine/debug.h"
36 #include "msxml_private.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
40 static HRESULT XMLElementCollection_create( xmlNodePtr node, LPVOID *ppObj );
42 /**********************************************************************
43 * IXMLElement
45 typedef struct _xmlelem
47 IXMLElement IXMLElement_iface;
48 LONG ref;
49 xmlNodePtr node;
50 BOOL own;
51 } xmlelem;
53 static inline xmlelem *impl_from_IXMLElement(IXMLElement *iface)
55 return CONTAINING_RECORD(iface, xmlelem, IXMLElement_iface);
58 static HRESULT WINAPI xmlelem_QueryInterface(IXMLElement *iface, REFIID riid, void** ppvObject)
60 xmlelem *This = impl_from_IXMLElement(iface);
62 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
64 if (IsEqualGUID(riid, &IID_IUnknown) ||
65 IsEqualGUID(riid, &IID_IDispatch) ||
66 IsEqualGUID(riid, &IID_IXMLElement))
68 *ppvObject = iface;
70 else
72 FIXME("interface %s not implemented\n", debugstr_guid(riid));
73 *ppvObject = NULL;
74 return E_NOINTERFACE;
77 IXMLElement_AddRef(iface);
79 return S_OK;
82 static ULONG WINAPI xmlelem_AddRef(IXMLElement *iface)
84 xmlelem *This = impl_from_IXMLElement(iface);
85 TRACE("%p\n", This);
86 return InterlockedIncrement(&This->ref);
89 static ULONG WINAPI xmlelem_Release(IXMLElement *iface)
91 xmlelem *This = impl_from_IXMLElement(iface);
92 LONG ref;
94 TRACE("%p\n", This);
96 ref = InterlockedDecrement(&This->ref);
97 if (ref == 0)
99 if (This->own) xmlFreeNode(This->node);
100 free(This);
103 return ref;
106 static HRESULT WINAPI xmlelem_GetTypeInfoCount(IXMLElement *iface, UINT* pctinfo)
108 xmlelem *This = impl_from_IXMLElement(iface);
110 TRACE("(%p)->(%p)\n", This, pctinfo);
112 *pctinfo = 1;
114 return S_OK;
117 static HRESULT WINAPI xmlelem_GetTypeInfo(IXMLElement *iface, UINT iTInfo,
118 LCID lcid, ITypeInfo** ppTInfo)
120 TRACE("%p, %u, %lx, %p.\n", iface, iTInfo, lcid, ppTInfo);
122 return get_typeinfo(IXMLElement_tid, ppTInfo);
125 static HRESULT WINAPI xmlelem_GetIDsOfNames(IXMLElement *iface, REFIID riid,
126 LPOLESTR* rgszNames, UINT cNames,
127 LCID lcid, DISPID* rgDispId)
129 ITypeInfo *typeinfo;
130 HRESULT hr;
132 TRACE("%p, %s, %p, %u, %lx, %p.\n", iface, debugstr_guid(riid), rgszNames, cNames,
133 lcid, rgDispId);
135 if(!rgszNames || cNames == 0 || !rgDispId)
136 return E_INVALIDARG;
138 hr = get_typeinfo(IXMLElement_tid, &typeinfo);
139 if(SUCCEEDED(hr))
141 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
142 ITypeInfo_Release(typeinfo);
145 return hr;
148 static HRESULT WINAPI xmlelem_Invoke(IXMLElement *iface, DISPID dispIdMember,
149 REFIID riid, LCID lcid, WORD wFlags,
150 DISPPARAMS* pDispParams, VARIANT* pVarResult,
151 EXCEPINFO* pExcepInfo, UINT* puArgErr)
153 ITypeInfo *typeinfo;
154 HRESULT hr;
156 TRACE("%p, %ld, %s, %lx, %d, %p, %p, %p, %p.\n", iface, dispIdMember, debugstr_guid(riid),
157 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
159 hr = get_typeinfo(IXMLElement_tid, &typeinfo);
160 if(SUCCEEDED(hr))
162 hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
163 ITypeInfo_Release(typeinfo);
166 return hr;
169 static HRESULT WINAPI xmlelem_get_tagName(IXMLElement *iface, BSTR *p)
171 xmlelem *This = impl_from_IXMLElement(iface);
173 TRACE("(%p)->(%p)\n", This, p);
175 if (!p)
176 return E_INVALIDARG;
178 if (*This->node->name) {
179 *p = bstr_from_xmlChar(This->node->name);
180 CharUpperBuffW(*p, SysStringLen(*p));
181 }else {
182 *p = NULL;
185 TRACE("returning %s\n", debugstr_w(*p));
187 return S_OK;
190 static HRESULT WINAPI xmlelem_put_tagName(IXMLElement *iface, BSTR p)
192 xmlelem *This = impl_from_IXMLElement(iface);
194 FIXME("(%p)->(%s): stub\n", This, debugstr_w(p));
196 if (!p)
197 return E_INVALIDARG;
199 return E_NOTIMPL;
202 static HRESULT WINAPI xmlelem_get_parent(IXMLElement *iface, IXMLElement **parent)
204 xmlelem *This = impl_from_IXMLElement(iface);
206 TRACE("(%p)->(%p)\n", This, parent);
208 if (!parent)
209 return E_INVALIDARG;
211 *parent = NULL;
213 if (!This->node->parent)
214 return S_FALSE;
216 return XMLElement_create(This->node->parent, (LPVOID *)parent, FALSE);
219 static HRESULT WINAPI xmlelem_setAttribute(IXMLElement *iface, BSTR strPropertyName,
220 VARIANT PropertyValue)
222 xmlelem *This = impl_from_IXMLElement(iface);
223 xmlChar *name, *value;
224 xmlAttrPtr attr;
226 TRACE("(%p)->(%s %s)\n", This, debugstr_w(strPropertyName), debugstr_variant(&PropertyValue));
228 if (!strPropertyName || V_VT(&PropertyValue) != VT_BSTR)
229 return E_INVALIDARG;
231 name = xmlchar_from_wchar(strPropertyName);
232 value = xmlchar_from_wchar(V_BSTR(&PropertyValue));
233 attr = xmlSetProp(This->node, name, value);
235 free(name);
236 free(value);
237 return (attr) ? S_OK : S_FALSE;
240 static HRESULT WINAPI xmlelem_getAttribute(IXMLElement *iface, BSTR name,
241 VARIANT *value)
243 static const WCHAR xmllangW[] = { 'x','m','l',':','l','a','n','g',0 };
244 xmlelem *This = impl_from_IXMLElement(iface);
245 xmlChar *val = NULL;
247 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(name), value);
249 if (!value)
250 return E_INVALIDARG;
252 VariantInit(value);
253 V_BSTR(value) = NULL;
255 if (!name)
256 return E_INVALIDARG;
258 /* case for xml:lang attribute */
259 if (!lstrcmpiW(name, xmllangW))
261 xmlNsPtr ns;
262 ns = xmlSearchNs(This->node->doc, This->node, (xmlChar*)"xml");
263 val = xmlGetNsProp(This->node, (xmlChar*)"lang", ns->href);
265 else
267 xmlAttrPtr attr;
268 xmlChar *xml_name;
270 xml_name = xmlchar_from_wchar(name);
271 attr = This->node->properties;
272 while (attr)
274 BSTR attr_name;
276 attr_name = bstr_from_xmlChar(attr->name);
277 if (!lstrcmpiW(name, attr_name))
279 val = xmlNodeListGetString(attr->doc, attr->children, 1);
280 SysFreeString(attr_name);
281 break;
284 attr = attr->next;
285 SysFreeString(attr_name);
288 free(xml_name);
291 if (val)
293 V_VT(value) = VT_BSTR;
294 V_BSTR(value) = bstr_from_xmlChar(val);
297 xmlFree(val);
298 TRACE("returning %s\n", debugstr_w(V_BSTR(value)));
299 return (val) ? S_OK : S_FALSE;
302 static HRESULT WINAPI xmlelem_removeAttribute(IXMLElement *iface, BSTR strPropertyName)
304 xmlelem *This = impl_from_IXMLElement(iface);
305 xmlChar *name;
306 xmlAttrPtr attr;
307 int res;
308 HRESULT hr = S_FALSE;
310 TRACE("(%p)->(%s)\n", This, debugstr_w(strPropertyName));
312 if (!strPropertyName)
313 return E_INVALIDARG;
315 name = xmlchar_from_wchar(strPropertyName);
316 attr = xmlHasProp(This->node, name);
317 if (!attr)
318 goto done;
320 res = xmlRemoveProp(attr);
322 if (res == 0)
323 hr = S_OK;
325 done:
326 free(name);
327 return hr;
330 static HRESULT WINAPI xmlelem_get_children(IXMLElement *iface, IXMLElementCollection **p)
332 xmlelem *This = impl_from_IXMLElement(iface);
334 TRACE("(%p)->(%p)\n", This, p);
336 if (!p)
337 return E_INVALIDARG;
339 return XMLElementCollection_create(This->node, (LPVOID *)p);
342 static LONG type_libxml_to_msxml(xmlElementType type)
344 switch (type)
346 case XML_ELEMENT_NODE:
347 return XMLELEMTYPE_ELEMENT;
348 case XML_TEXT_NODE:
349 return XMLELEMTYPE_TEXT;
350 case XML_COMMENT_NODE:
351 return XMLELEMTYPE_COMMENT;
352 case XML_DOCUMENT_NODE:
353 return XMLELEMTYPE_DOCUMENT;
354 case XML_DTD_NODE:
355 return XMLELEMTYPE_DTD;
356 case XML_PI_NODE:
357 return XMLELEMTYPE_PI;
358 default:
359 break;
362 return XMLELEMTYPE_OTHER;
365 static HRESULT WINAPI xmlelem_get_type(IXMLElement *iface, LONG *p)
367 xmlelem *This = impl_from_IXMLElement(iface);
369 TRACE("(%p)->(%p)\n", This, p);
371 if (!p)
372 return E_INVALIDARG;
374 *p = type_libxml_to_msxml(This->node->type);
375 TRACE("returning %ld\n", *p);
376 return S_OK;
379 static HRESULT WINAPI xmlelem_get_text(IXMLElement *iface, BSTR *p)
381 xmlelem *This = impl_from_IXMLElement(iface);
382 xmlChar *content;
384 TRACE("(%p)->(%p)\n", This, p);
386 if (!p)
387 return E_INVALIDARG;
389 content = xmlNodeGetContent(This->node);
390 *p = bstr_from_xmlChar(content);
391 TRACE("returning %s\n", debugstr_w(*p));
393 xmlFree(content);
394 return S_OK;
397 static HRESULT WINAPI xmlelem_put_text(IXMLElement *iface, BSTR p)
399 xmlelem *This = impl_from_IXMLElement(iface);
400 xmlChar *content;
402 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
404 /* FIXME: test which types can be used */
405 if (This->node->type == XML_ELEMENT_NODE)
406 return E_NOTIMPL;
408 content = xmlchar_from_wchar(p);
409 xmlNodeSetContent(This->node, content);
411 free(content);
413 return S_OK;
416 static HRESULT WINAPI xmlelem_addChild(IXMLElement *iface, IXMLElement *pChildElem,
417 LONG lIndex, LONG lreserved)
419 xmlelem *This = impl_from_IXMLElement(iface);
420 xmlelem *childElem = impl_from_IXMLElement(pChildElem);
421 xmlNodePtr child;
423 TRACE("%p, %p, %ld, %ld.\n", iface, pChildElem, lIndex, lreserved);
425 if (lIndex == 0)
426 child = xmlAddChild(This->node, childElem->node);
427 else
428 child = xmlAddNextSibling(This->node, childElem->node->last);
430 /* parent is responsible for child data */
431 if (child) childElem->own = FALSE;
433 return (child) ? S_OK : S_FALSE;
436 static HRESULT WINAPI xmlelem_removeChild(IXMLElement *iface, IXMLElement *pChildElem)
438 xmlelem *This = impl_from_IXMLElement(iface);
439 xmlelem *childElem = impl_from_IXMLElement(pChildElem);
441 TRACE("(%p)->(%p)\n", This, childElem);
443 if (!pChildElem)
444 return E_INVALIDARG;
446 /* only supported for This is childElem parent case */
447 if (This->node != childElem->node->parent)
448 return E_INVALIDARG;
450 xmlUnlinkNode(childElem->node);
451 /* standalone element now */
452 childElem->own = TRUE;
454 return S_OK;
457 static const struct IXMLElementVtbl xmlelem_vtbl =
459 xmlelem_QueryInterface,
460 xmlelem_AddRef,
461 xmlelem_Release,
462 xmlelem_GetTypeInfoCount,
463 xmlelem_GetTypeInfo,
464 xmlelem_GetIDsOfNames,
465 xmlelem_Invoke,
466 xmlelem_get_tagName,
467 xmlelem_put_tagName,
468 xmlelem_get_parent,
469 xmlelem_setAttribute,
470 xmlelem_getAttribute,
471 xmlelem_removeAttribute,
472 xmlelem_get_children,
473 xmlelem_get_type,
474 xmlelem_get_text,
475 xmlelem_put_text,
476 xmlelem_addChild,
477 xmlelem_removeChild
480 HRESULT XMLElement_create(xmlNodePtr node, LPVOID *ppObj, BOOL own)
482 xmlelem *elem;
484 TRACE("(%p)\n", ppObj);
486 if (!ppObj)
487 return E_INVALIDARG;
489 *ppObj = NULL;
491 elem = malloc(sizeof(*elem));
492 if(!elem)
493 return E_OUTOFMEMORY;
495 elem->IXMLElement_iface.lpVtbl = &xmlelem_vtbl;
496 elem->ref = 1;
497 elem->node = node;
498 elem->own = own;
500 *ppObj = &elem->IXMLElement_iface;
502 TRACE("returning iface %p\n", *ppObj);
503 return S_OK;
506 /************************************************************************
507 * IXMLElementCollection
509 typedef struct _xmlelem_collection
511 IXMLElementCollection IXMLElementCollection_iface;
512 IEnumVARIANT IEnumVARIANT_iface;
513 LONG ref;
514 LONG length;
515 xmlNodePtr node;
517 /* IEnumVARIANT members */
518 xmlNodePtr current;
519 } xmlelem_collection;
521 static inline LONG xmlelem_collection_updatelength(xmlelem_collection *collection)
523 xmlNodePtr ptr = collection->node->children;
525 collection->length = 0;
526 while (ptr)
528 collection->length++;
529 ptr = ptr->next;
531 return collection->length;
534 static inline xmlelem_collection *impl_from_IXMLElementCollection(IXMLElementCollection *iface)
536 return CONTAINING_RECORD(iface, xmlelem_collection, IXMLElementCollection_iface);
539 static inline xmlelem_collection *impl_from_IEnumVARIANT(IEnumVARIANT *iface)
541 return CONTAINING_RECORD(iface, xmlelem_collection, IEnumVARIANT_iface);
544 static HRESULT WINAPI xmlelem_collection_QueryInterface(IXMLElementCollection *iface, REFIID riid, void** ppvObject)
546 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
548 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
550 if (IsEqualGUID(riid, &IID_IUnknown) ||
551 IsEqualGUID(riid, &IID_IXMLElementCollection))
553 *ppvObject = iface;
555 else if (IsEqualGUID(riid, &IID_IEnumVARIANT))
557 *ppvObject = &This->IEnumVARIANT_iface;
559 else
561 FIXME("interface %s not implemented\n", debugstr_guid(riid));
562 *ppvObject = NULL;
563 return E_NOINTERFACE;
566 IXMLElementCollection_AddRef(iface);
568 return S_OK;
571 static ULONG WINAPI xmlelem_collection_AddRef(IXMLElementCollection *iface)
573 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
574 TRACE("(%p)\n", This);
575 return InterlockedIncrement(&This->ref);
578 static ULONG WINAPI xmlelem_collection_Release(IXMLElementCollection *iface)
580 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
581 LONG ref;
583 TRACE("(%p)\n", This);
585 ref = InterlockedDecrement(&This->ref);
586 if (ref == 0)
588 free(This);
591 return ref;
594 static HRESULT WINAPI xmlelem_collection_GetTypeInfoCount(IXMLElementCollection *iface, UINT* pctinfo)
596 FIXME("\n");
597 return E_NOTIMPL;
600 static HRESULT WINAPI xmlelem_collection_GetTypeInfo(IXMLElementCollection *iface, UINT iTInfo,
601 LCID lcid, ITypeInfo** ppTInfo)
603 FIXME("\n");
604 return E_NOTIMPL;
607 static HRESULT WINAPI xmlelem_collection_GetIDsOfNames(IXMLElementCollection *iface, REFIID riid,
608 LPOLESTR* rgszNames, UINT cNames,
609 LCID lcid, DISPID* rgDispId)
611 FIXME("\n");
612 return E_NOTIMPL;
615 static HRESULT WINAPI xmlelem_collection_Invoke(IXMLElementCollection *iface, DISPID dispIdMember,
616 REFIID riid, LCID lcid, WORD wFlags,
617 DISPPARAMS* pDispParams, VARIANT* pVarResult,
618 EXCEPINFO* pExcepInfo, UINT* puArgErr)
620 FIXME("\n");
621 return E_NOTIMPL;
624 static HRESULT WINAPI xmlelem_collection_put_length(IXMLElementCollection *iface, LONG v)
626 TRACE("%p, %ld.\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", This, 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", This, ppUnk);
650 if (!ppUnk)
651 return E_INVALIDARG;
653 IXMLElementCollection_AddRef(iface);
654 *ppUnk = (IUnknown *)&This->IEnumVARIANT_iface;
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)->(%s %s %p)\n", This, debugstr_variant(&var1), debugstr_variant(&var2), 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(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);
709 TRACE("(%p)->(%s %p)\n", this, debugstr_guid(riid), ppvObj);
711 if (IsEqualGUID(riid, &IID_IUnknown) ||
712 IsEqualGUID(riid, &IID_IEnumVARIANT))
714 *ppvObj = iface;
715 IEnumVARIANT_AddRef(iface);
716 return S_OK;
719 FIXME("interface %s not implemented\n", debugstr_guid(riid));
720 *ppvObj = NULL;
721 return E_NOINTERFACE;
724 static ULONG WINAPI xmlelem_collection_IEnumVARIANT_AddRef(
725 IEnumVARIANT *iface)
727 xmlelem_collection *this = impl_from_IEnumVARIANT(iface);
728 return IXMLElementCollection_AddRef(&this->IXMLElementCollection_iface);
731 static ULONG WINAPI xmlelem_collection_IEnumVARIANT_Release(
732 IEnumVARIANT *iface)
734 xmlelem_collection *this = impl_from_IEnumVARIANT(iface);
735 return IXMLElementCollection_Release(&this->IXMLElementCollection_iface);
738 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Next(
739 IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *fetched)
741 xmlelem_collection *This = impl_from_IEnumVARIANT(iface);
742 HRESULT hr;
744 TRACE("%p, %lu, %p, %p.\n", iface, celt, rgVar, fetched);
746 if (!rgVar)
747 return E_INVALIDARG;
749 if (fetched) *fetched = 0;
751 if (!This->current)
753 V_VT(rgVar) = VT_EMPTY;
754 return S_FALSE;
757 while (celt > 0 && This->current)
759 V_VT(rgVar) = VT_DISPATCH;
760 hr = XMLElement_create(This->current, (void **)&V_DISPATCH(rgVar), FALSE);
761 if (FAILED(hr)) return hr;
762 This->current = This->current->next;
763 if (fetched) ++*fetched;
764 rgVar++;
765 celt--;
767 if (!celt) return S_OK;
768 V_VT(rgVar) = VT_EMPTY;
769 return S_FALSE;
772 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Skip(
773 IEnumVARIANT *iface, ULONG celt)
775 FIXME("%p, %lu: stub\n", iface, celt);
776 return E_NOTIMPL;
779 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Reset(
780 IEnumVARIANT *iface)
782 xmlelem_collection *This = impl_from_IEnumVARIANT(iface);
783 TRACE("(%p)\n", This);
784 This->current = This->node->children;
785 return S_OK;
788 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Clone(
789 IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
791 xmlelem_collection *This = impl_from_IEnumVARIANT(iface);
792 FIXME("(%p)->(%p): stub\n", This, ppEnum);
793 return E_NOTIMPL;
796 static const struct IEnumVARIANTVtbl xmlelem_collection_IEnumVARIANTvtbl =
798 xmlelem_collection_IEnumVARIANT_QueryInterface,
799 xmlelem_collection_IEnumVARIANT_AddRef,
800 xmlelem_collection_IEnumVARIANT_Release,
801 xmlelem_collection_IEnumVARIANT_Next,
802 xmlelem_collection_IEnumVARIANT_Skip,
803 xmlelem_collection_IEnumVARIANT_Reset,
804 xmlelem_collection_IEnumVARIANT_Clone
807 static HRESULT XMLElementCollection_create(xmlNodePtr node, LPVOID *ppObj)
809 xmlelem_collection *collection;
811 TRACE("(%p)\n", ppObj);
813 *ppObj = NULL;
815 if (!node->children)
816 return S_FALSE;
818 collection = malloc(sizeof(*collection));
819 if(!collection)
820 return E_OUTOFMEMORY;
822 collection->IXMLElementCollection_iface.lpVtbl = &xmlelem_collection_vtbl;
823 collection->IEnumVARIANT_iface.lpVtbl = &xmlelem_collection_IEnumVARIANTvtbl;
824 collection->ref = 1;
825 collection->length = 0;
826 collection->node = node;
827 collection->current = node->children;
828 xmlelem_collection_updatelength(collection);
830 *ppObj = &collection->IXMLElementCollection_iface;
832 TRACE("returning iface %p\n", *ppObj);
833 return S_OK;