830e6721501cf2bae07b168ecfc61b58c7ea9e1c
[reactos.git] / reactos / dll / win32 / msxml3 / xmlelem.c
1 /*
2 * XML Element implementation
3 *
4 * Copyright 2007 James Hawkins
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #define WIN32_NO_STATUS
22 #define _INC_WINDOWS
23
24 #define COBJMACROS
25
26 #include <config.h>
27
28 //#include <stdarg.h>
29 #ifdef HAVE_LIBXML2
30 # include <libxml/parser.h>
31 //# include <libxml/xmlerror.h>
32 #endif
33
34 #include <windef.h>
35 #include <winbase.h>
36 //#include "winuser.h"
37 #include <ole2.h>
38 #include <msxml6.h>
39 //#include "ocidl.h"
40
41 #include <wine/debug.h>
42
43 #include "msxml_private.h"
44
45 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
46
47 #ifdef HAVE_LIBXML2
48
49 static HRESULT XMLElementCollection_create( IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj );
50
51 /**********************************************************************
52 * IXMLElement
53 */
54 typedef struct _xmlelem
55 {
56 IXMLElement IXMLElement_iface;
57 LONG ref;
58 xmlNodePtr node;
59 BOOL own;
60 } xmlelem;
61
62 static inline xmlelem *impl_from_IXMLElement(IXMLElement *iface)
63 {
64 return CONTAINING_RECORD(iface, xmlelem, IXMLElement_iface);
65 }
66
67 static HRESULT WINAPI xmlelem_QueryInterface(IXMLElement *iface, REFIID riid, void** ppvObject)
68 {
69 xmlelem *This = impl_from_IXMLElement(iface);
70
71 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
72
73 if (IsEqualGUID(riid, &IID_IUnknown) ||
74 IsEqualGUID(riid, &IID_IDispatch) ||
75 IsEqualGUID(riid, &IID_IXMLElement))
76 {
77 *ppvObject = iface;
78 }
79 else
80 {
81 FIXME("interface %s not implemented\n", debugstr_guid(riid));
82 *ppvObject = NULL;
83 return E_NOINTERFACE;
84 }
85
86 IXMLElement_AddRef(iface);
87
88 return S_OK;
89 }
90
91 static ULONG WINAPI xmlelem_AddRef(IXMLElement *iface)
92 {
93 xmlelem *This = impl_from_IXMLElement(iface);
94 TRACE("%p\n", This);
95 return InterlockedIncrement(&This->ref);
96 }
97
98 static ULONG WINAPI xmlelem_Release(IXMLElement *iface)
99 {
100 xmlelem *This = impl_from_IXMLElement(iface);
101 LONG ref;
102
103 TRACE("%p\n", This);
104
105 ref = InterlockedDecrement(&This->ref);
106 if (ref == 0)
107 {
108 if (This->own) xmlFreeNode(This->node);
109 heap_free(This);
110 }
111
112 return ref;
113 }
114
115 static HRESULT WINAPI xmlelem_GetTypeInfoCount(IXMLElement *iface, UINT* pctinfo)
116 {
117 xmlelem *This = impl_from_IXMLElement(iface);
118
119 TRACE("(%p)->(%p)\n", This, pctinfo);
120
121 *pctinfo = 1;
122
123 return S_OK;
124 }
125
126 static HRESULT WINAPI xmlelem_GetTypeInfo(IXMLElement *iface, UINT iTInfo,
127 LCID lcid, ITypeInfo** ppTInfo)
128 {
129 xmlelem *This = impl_from_IXMLElement(iface);
130 HRESULT hr;
131
132 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
133
134 hr = get_typeinfo(IXMLElement_tid, ppTInfo);
135
136 return hr;
137 }
138
139 static HRESULT WINAPI xmlelem_GetIDsOfNames(IXMLElement *iface, REFIID riid,
140 LPOLESTR* rgszNames, UINT cNames,
141 LCID lcid, DISPID* rgDispId)
142 {
143 xmlelem *This = impl_from_IXMLElement(iface);
144 ITypeInfo *typeinfo;
145 HRESULT hr;
146
147 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
148 lcid, rgDispId);
149
150 if(!rgszNames || cNames == 0 || !rgDispId)
151 return E_INVALIDARG;
152
153 hr = get_typeinfo(IXMLElement_tid, &typeinfo);
154 if(SUCCEEDED(hr))
155 {
156 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
157 ITypeInfo_Release(typeinfo);
158 }
159
160 return hr;
161 }
162
163 static HRESULT WINAPI xmlelem_Invoke(IXMLElement *iface, DISPID dispIdMember,
164 REFIID riid, LCID lcid, WORD wFlags,
165 DISPPARAMS* pDispParams, VARIANT* pVarResult,
166 EXCEPINFO* pExcepInfo, UINT* puArgErr)
167 {
168 xmlelem *This = impl_from_IXMLElement(iface);
169 ITypeInfo *typeinfo;
170 HRESULT hr;
171
172 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
173 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
174
175 hr = get_typeinfo(IXMLElement_tid, &typeinfo);
176 if(SUCCEEDED(hr))
177 {
178 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLElement_iface, dispIdMember, wFlags, pDispParams,
179 pVarResult, pExcepInfo, puArgErr);
180 ITypeInfo_Release(typeinfo);
181 }
182
183 return hr;
184 }
185
186 static HRESULT WINAPI xmlelem_get_tagName(IXMLElement *iface, BSTR *p)
187 {
188 xmlelem *This = impl_from_IXMLElement(iface);
189
190 TRACE("(%p)->(%p)\n", This, p);
191
192 if (!p)
193 return E_INVALIDARG;
194
195 *p = bstr_from_xmlChar(This->node->name);
196 CharUpperBuffW(*p, SysStringLen(*p));
197
198 TRACE("returning %s\n", debugstr_w(*p));
199
200 return S_OK;
201 }
202
203 static HRESULT WINAPI xmlelem_put_tagName(IXMLElement *iface, BSTR p)
204 {
205 xmlelem *This = impl_from_IXMLElement(iface);
206
207 FIXME("(%p)->(%s): stub\n", This, debugstr_w(p));
208
209 if (!p)
210 return E_INVALIDARG;
211
212 return E_NOTIMPL;
213 }
214
215 static HRESULT WINAPI xmlelem_get_parent(IXMLElement *iface, IXMLElement **parent)
216 {
217 xmlelem *This = impl_from_IXMLElement(iface);
218
219 TRACE("(%p)->(%p)\n", This, parent);
220
221 if (!parent)
222 return E_INVALIDARG;
223
224 *parent = NULL;
225
226 if (!This->node->parent)
227 return S_FALSE;
228
229 return XMLElement_create((IUnknown *)iface, This->node->parent, (LPVOID *)parent, FALSE);
230 }
231
232 static HRESULT WINAPI xmlelem_setAttribute(IXMLElement *iface, BSTR strPropertyName,
233 VARIANT PropertyValue)
234 {
235 xmlelem *This = impl_from_IXMLElement(iface);
236 xmlChar *name, *value;
237 xmlAttrPtr attr;
238
239 TRACE("(%p)->(%s %s)\n", This, debugstr_w(strPropertyName), debugstr_variant(&PropertyValue));
240
241 if (!strPropertyName || V_VT(&PropertyValue) != VT_BSTR)
242 return E_INVALIDARG;
243
244 name = xmlchar_from_wchar(strPropertyName);
245 value = xmlchar_from_wchar(V_BSTR(&PropertyValue));
246 attr = xmlSetProp(This->node, name, value);
247
248 heap_free(name);
249 heap_free(value);
250 return (attr) ? S_OK : S_FALSE;
251 }
252
253 static HRESULT WINAPI xmlelem_getAttribute(IXMLElement *iface, BSTR name,
254 VARIANT *value)
255 {
256 static const WCHAR xmllangW[] = { 'x','m','l',':','l','a','n','g',0 };
257 xmlelem *This = impl_from_IXMLElement(iface);
258 xmlChar *val = NULL;
259
260 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(name), value);
261
262 if (!value)
263 return E_INVALIDARG;
264
265 VariantInit(value);
266 V_BSTR(value) = NULL;
267
268 if (!name)
269 return E_INVALIDARG;
270
271 /* case for xml:lang attribute */
272 if (!lstrcmpiW(name, xmllangW))
273 {
274 xmlNsPtr ns;
275 ns = xmlSearchNs(This->node->doc, This->node, (xmlChar*)"xml");
276 val = xmlGetNsProp(This->node, (xmlChar*)"lang", ns->href);
277 }
278 else
279 {
280 xmlAttrPtr attr;
281 xmlChar *xml_name;
282
283 xml_name = xmlchar_from_wchar(name);
284 attr = This->node->properties;
285 while (attr)
286 {
287 BSTR attr_name;
288
289 attr_name = bstr_from_xmlChar(attr->name);
290 if (!lstrcmpiW(name, attr_name))
291 {
292 val = xmlNodeListGetString(attr->doc, attr->children, 1);
293 SysFreeString(attr_name);
294 break;
295 }
296
297 attr = attr->next;
298 SysFreeString(attr_name);
299 }
300
301 heap_free(xml_name);
302 }
303
304 if (val)
305 {
306 V_VT(value) = VT_BSTR;
307 V_BSTR(value) = bstr_from_xmlChar(val);
308 }
309
310 xmlFree(val);
311 TRACE("returning %s\n", debugstr_w(V_BSTR(value)));
312 return (val) ? S_OK : S_FALSE;
313 }
314
315 static HRESULT WINAPI xmlelem_removeAttribute(IXMLElement *iface, BSTR strPropertyName)
316 {
317 xmlelem *This = impl_from_IXMLElement(iface);
318 xmlChar *name;
319 xmlAttrPtr attr;
320 int res;
321 HRESULT hr = S_FALSE;
322
323 TRACE("(%p)->(%s)\n", This, debugstr_w(strPropertyName));
324
325 if (!strPropertyName)
326 return E_INVALIDARG;
327
328 name = xmlchar_from_wchar(strPropertyName);
329 attr = xmlHasProp(This->node, name);
330 if (!attr)
331 goto done;
332
333 res = xmlRemoveProp(attr);
334
335 if (res == 0)
336 hr = S_OK;
337
338 done:
339 heap_free(name);
340 return hr;
341 }
342
343 static HRESULT WINAPI xmlelem_get_children(IXMLElement *iface, IXMLElementCollection **p)
344 {
345 xmlelem *This = impl_from_IXMLElement(iface);
346
347 TRACE("(%p)->(%p)\n", This, p);
348
349 if (!p)
350 return E_INVALIDARG;
351
352 return XMLElementCollection_create((IUnknown *)iface, This->node, (LPVOID *)p);
353 }
354
355 static LONG type_libxml_to_msxml(xmlElementType type)
356 {
357 switch (type)
358 {
359 case XML_ELEMENT_NODE:
360 return XMLELEMTYPE_ELEMENT;
361 case XML_TEXT_NODE:
362 return XMLELEMTYPE_TEXT;
363 case XML_COMMENT_NODE:
364 return XMLELEMTYPE_COMMENT;
365 case XML_DOCUMENT_NODE:
366 return XMLELEMTYPE_DOCUMENT;
367 case XML_DTD_NODE:
368 return XMLELEMTYPE_DTD;
369 case XML_PI_NODE:
370 return XMLELEMTYPE_PI;
371 default:
372 break;
373 }
374
375 return XMLELEMTYPE_OTHER;
376 }
377
378 static HRESULT WINAPI xmlelem_get_type(IXMLElement *iface, LONG *p)
379 {
380 xmlelem *This = impl_from_IXMLElement(iface);
381
382 TRACE("(%p)->(%p)\n", This, p);
383
384 if (!p)
385 return E_INVALIDARG;
386
387 *p = type_libxml_to_msxml(This->node->type);
388 TRACE("returning %d\n", *p);
389 return S_OK;
390 }
391
392 static HRESULT WINAPI xmlelem_get_text(IXMLElement *iface, BSTR *p)
393 {
394 xmlelem *This = impl_from_IXMLElement(iface);
395 xmlChar *content;
396
397 TRACE("(%p)->(%p)\n", This, p);
398
399 if (!p)
400 return E_INVALIDARG;
401
402 content = xmlNodeGetContent(This->node);
403 *p = bstr_from_xmlChar(content);
404 TRACE("returning %s\n", debugstr_w(*p));
405
406 xmlFree(content);
407 return S_OK;
408 }
409
410 static HRESULT WINAPI xmlelem_put_text(IXMLElement *iface, BSTR p)
411 {
412 xmlelem *This = impl_from_IXMLElement(iface);
413 xmlChar *content;
414
415 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
416
417 /* FIXME: test which types can be used */
418 if (This->node->type == XML_ELEMENT_NODE)
419 return E_NOTIMPL;
420
421 content = xmlchar_from_wchar(p);
422 xmlNodeSetContent(This->node, content);
423
424 heap_free(content);
425
426 return S_OK;
427 }
428
429 static HRESULT WINAPI xmlelem_addChild(IXMLElement *iface, IXMLElement *pChildElem,
430 LONG lIndex, LONG lreserved)
431 {
432 xmlelem *This = impl_from_IXMLElement(iface);
433 xmlelem *childElem = impl_from_IXMLElement(pChildElem);
434 xmlNodePtr child;
435
436 TRACE("(%p)->(%p %d %d)\n", This, pChildElem, lIndex, lreserved);
437
438 if (lIndex == 0)
439 child = xmlAddChild(This->node, childElem->node);
440 else
441 child = xmlAddNextSibling(This->node, childElem->node->last);
442
443 /* parent is responsible for child data */
444 if (child) childElem->own = FALSE;
445
446 return (child) ? S_OK : S_FALSE;
447 }
448
449 static HRESULT WINAPI xmlelem_removeChild(IXMLElement *iface, IXMLElement *pChildElem)
450 {
451 xmlelem *This = impl_from_IXMLElement(iface);
452 xmlelem *childElem = impl_from_IXMLElement(pChildElem);
453
454 TRACE("(%p)->(%p)\n", This, childElem);
455
456 if (!pChildElem)
457 return E_INVALIDARG;
458
459 /* only supported for This is childElem parent case */
460 if (This->node != childElem->node->parent)
461 return E_INVALIDARG;
462
463 xmlUnlinkNode(childElem->node);
464 /* standalone element now */
465 childElem->own = TRUE;
466
467 return S_OK;
468 }
469
470 static const struct IXMLElementVtbl xmlelem_vtbl =
471 {
472 xmlelem_QueryInterface,
473 xmlelem_AddRef,
474 xmlelem_Release,
475 xmlelem_GetTypeInfoCount,
476 xmlelem_GetTypeInfo,
477 xmlelem_GetIDsOfNames,
478 xmlelem_Invoke,
479 xmlelem_get_tagName,
480 xmlelem_put_tagName,
481 xmlelem_get_parent,
482 xmlelem_setAttribute,
483 xmlelem_getAttribute,
484 xmlelem_removeAttribute,
485 xmlelem_get_children,
486 xmlelem_get_type,
487 xmlelem_get_text,
488 xmlelem_put_text,
489 xmlelem_addChild,
490 xmlelem_removeChild
491 };
492
493 HRESULT XMLElement_create(IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj, BOOL own)
494 {
495 xmlelem *elem;
496
497 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
498
499 if (!ppObj)
500 return E_INVALIDARG;
501
502 *ppObj = NULL;
503
504 elem = heap_alloc(sizeof (*elem));
505 if(!elem)
506 return E_OUTOFMEMORY;
507
508 elem->IXMLElement_iface.lpVtbl = &xmlelem_vtbl;
509 elem->ref = 1;
510 elem->node = node;
511 elem->own = own;
512
513 *ppObj = &elem->IXMLElement_iface;
514
515 TRACE("returning iface %p\n", *ppObj);
516 return S_OK;
517 }
518
519 /************************************************************************
520 * IXMLElementCollection
521 */
522 typedef struct _xmlelem_collection
523 {
524 IXMLElementCollection IXMLElementCollection_iface;
525 IEnumVARIANT IEnumVARIANT_iface;
526 LONG ref;
527 LONG length;
528 xmlNodePtr node;
529
530 /* IEnumVARIANT members */
531 xmlNodePtr current;
532 } xmlelem_collection;
533
534 static inline LONG xmlelem_collection_updatelength(xmlelem_collection *collection)
535 {
536 xmlNodePtr ptr = collection->node->children;
537
538 collection->length = 0;
539 while (ptr)
540 {
541 collection->length++;
542 ptr = ptr->next;
543 }
544 return collection->length;
545 }
546
547 static inline xmlelem_collection *impl_from_IXMLElementCollection(IXMLElementCollection *iface)
548 {
549 return CONTAINING_RECORD(iface, xmlelem_collection, IXMLElementCollection_iface);
550 }
551
552 static inline xmlelem_collection *impl_from_IEnumVARIANT(IEnumVARIANT *iface)
553 {
554 return CONTAINING_RECORD(iface, xmlelem_collection, IEnumVARIANT_iface);
555 }
556
557 static HRESULT WINAPI xmlelem_collection_QueryInterface(IXMLElementCollection *iface, REFIID riid, void** ppvObject)
558 {
559 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
560
561 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
562
563 if (IsEqualGUID(riid, &IID_IUnknown) ||
564 IsEqualGUID(riid, &IID_IXMLElementCollection))
565 {
566 *ppvObject = iface;
567 }
568 else if (IsEqualGUID(riid, &IID_IEnumVARIANT))
569 {
570 *ppvObject = &This->IEnumVARIANT_iface;
571 }
572 else
573 {
574 FIXME("interface %s not implemented\n", debugstr_guid(riid));
575 return E_NOINTERFACE;
576 }
577
578 IXMLElementCollection_AddRef(iface);
579
580 return S_OK;
581 }
582
583 static ULONG WINAPI xmlelem_collection_AddRef(IXMLElementCollection *iface)
584 {
585 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
586 TRACE("(%p)\n", This);
587 return InterlockedIncrement(&This->ref);
588 }
589
590 static ULONG WINAPI xmlelem_collection_Release(IXMLElementCollection *iface)
591 {
592 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
593 LONG ref;
594
595 TRACE("(%p)\n", This);
596
597 ref = InterlockedDecrement(&This->ref);
598 if (ref == 0)
599 {
600 heap_free(This);
601 }
602
603 return ref;
604 }
605
606 static HRESULT WINAPI xmlelem_collection_GetTypeInfoCount(IXMLElementCollection *iface, UINT* pctinfo)
607 {
608 FIXME("\n");
609 return E_NOTIMPL;
610 }
611
612 static HRESULT WINAPI xmlelem_collection_GetTypeInfo(IXMLElementCollection *iface, UINT iTInfo,
613 LCID lcid, ITypeInfo** ppTInfo)
614 {
615 FIXME("\n");
616 return E_NOTIMPL;
617 }
618
619 static HRESULT WINAPI xmlelem_collection_GetIDsOfNames(IXMLElementCollection *iface, REFIID riid,
620 LPOLESTR* rgszNames, UINT cNames,
621 LCID lcid, DISPID* rgDispId)
622 {
623 FIXME("\n");
624 return E_NOTIMPL;
625 }
626
627 static HRESULT WINAPI xmlelem_collection_Invoke(IXMLElementCollection *iface, DISPID dispIdMember,
628 REFIID riid, LCID lcid, WORD wFlags,
629 DISPPARAMS* pDispParams, VARIANT* pVarResult,
630 EXCEPINFO* pExcepInfo, UINT* puArgErr)
631 {
632 FIXME("\n");
633 return E_NOTIMPL;
634 }
635
636 static HRESULT WINAPI xmlelem_collection_put_length(IXMLElementCollection *iface, LONG v)
637 {
638 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
639 TRACE("(%p)->(%d)\n", This, v);
640 return E_FAIL;
641 }
642
643 static HRESULT WINAPI xmlelem_collection_get_length(IXMLElementCollection *iface, LONG *p)
644 {
645 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
646
647 TRACE("(%p)->(%p)\n", This, p);
648
649 if (!p)
650 return E_INVALIDARG;
651
652 *p = xmlelem_collection_updatelength(This);
653 return S_OK;
654 }
655
656 static HRESULT WINAPI xmlelem_collection_get__newEnum(IXMLElementCollection *iface, IUnknown **ppUnk)
657 {
658 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
659
660 TRACE("(%p)->(%p)\n", This, ppUnk);
661
662 if (!ppUnk)
663 return E_INVALIDARG;
664
665 *ppUnk = (IUnknown *)This;
666 IUnknown_AddRef(*ppUnk);
667 return S_OK;
668 }
669
670 static HRESULT WINAPI xmlelem_collection_item(IXMLElementCollection *iface, VARIANT var1,
671 VARIANT var2, IDispatch **ppDisp)
672 {
673 xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
674 xmlNodePtr ptr = This->node->children;
675 int index, i;
676
677 TRACE("(%p)->(%s %s %p)\n", This, debugstr_variant(&var1), debugstr_variant(&var2), ppDisp);
678
679 if (!ppDisp)
680 return E_INVALIDARG;
681
682 *ppDisp = NULL;
683
684 index = V_I4(&var1);
685 if (index < 0)
686 return E_INVALIDARG;
687
688 xmlelem_collection_updatelength(This);
689 if (index >= This->length)
690 return E_FAIL;
691
692 for (i = 0; i < index; i++)
693 ptr = ptr->next;
694
695 return XMLElement_create((IUnknown *)iface, ptr, (LPVOID *)ppDisp, FALSE);
696 }
697
698 static const struct IXMLElementCollectionVtbl xmlelem_collection_vtbl =
699 {
700 xmlelem_collection_QueryInterface,
701 xmlelem_collection_AddRef,
702 xmlelem_collection_Release,
703 xmlelem_collection_GetTypeInfoCount,
704 xmlelem_collection_GetTypeInfo,
705 xmlelem_collection_GetIDsOfNames,
706 xmlelem_collection_Invoke,
707 xmlelem_collection_put_length,
708 xmlelem_collection_get_length,
709 xmlelem_collection_get__newEnum,
710 xmlelem_collection_item
711 };
712
713 /************************************************************************
714 * xmlelem_collection implementation of IEnumVARIANT.
715 */
716 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_QueryInterface(
717 IEnumVARIANT *iface, REFIID riid, LPVOID *ppvObj)
718 {
719 xmlelem_collection *this = impl_from_IEnumVARIANT(iface);
720 return IXMLDocument_QueryInterface((IXMLDocument *)this, riid, ppvObj);
721 }
722
723 static ULONG WINAPI xmlelem_collection_IEnumVARIANT_AddRef(
724 IEnumVARIANT *iface)
725 {
726 xmlelem_collection *this = impl_from_IEnumVARIANT(iface);
727 return IXMLDocument_AddRef((IXMLDocument *)this);
728 }
729
730 static ULONG WINAPI xmlelem_collection_IEnumVARIANT_Release(
731 IEnumVARIANT *iface)
732 {
733 xmlelem_collection *this = impl_from_IEnumVARIANT(iface);
734 return IXMLDocument_Release((IXMLDocument *)this);
735 }
736
737 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Next(
738 IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *fetched)
739 {
740 xmlelem_collection *This = impl_from_IEnumVARIANT(iface);
741 xmlNodePtr ptr = This->current;
742
743 TRACE("(%p)->(%d %p %p)\n", This, celt, rgVar, fetched);
744
745 if (!rgVar)
746 return E_INVALIDARG;
747
748 /* FIXME: handle celt */
749 if (fetched)
750 *fetched = 1;
751
752 if (This->current)
753 This->current = This->current->next;
754 else
755 {
756 V_VT(rgVar) = VT_EMPTY;
757 if (fetched) *fetched = 0;
758 return S_FALSE;
759 }
760
761 V_VT(rgVar) = VT_DISPATCH;
762 return XMLElement_create((IUnknown *)iface, ptr, (LPVOID *)&V_DISPATCH(rgVar), FALSE);
763 }
764
765 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Skip(
766 IEnumVARIANT *iface, ULONG celt)
767 {
768 xmlelem_collection *This = impl_from_IEnumVARIANT(iface);
769 FIXME("(%p)->(%d): stub\n", This, celt);
770 return E_NOTIMPL;
771 }
772
773 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Reset(
774 IEnumVARIANT *iface)
775 {
776 xmlelem_collection *This = impl_from_IEnumVARIANT(iface);
777 TRACE("(%p)\n", This);
778 This->current = This->node->children;
779 return S_OK;
780 }
781
782 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Clone(
783 IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
784 {
785 xmlelem_collection *This = impl_from_IEnumVARIANT(iface);
786 FIXME("(%p)->(%p): stub\n", This, ppEnum);
787 return E_NOTIMPL;
788 }
789
790 static const struct IEnumVARIANTVtbl xmlelem_collection_IEnumVARIANTvtbl =
791 {
792 xmlelem_collection_IEnumVARIANT_QueryInterface,
793 xmlelem_collection_IEnumVARIANT_AddRef,
794 xmlelem_collection_IEnumVARIANT_Release,
795 xmlelem_collection_IEnumVARIANT_Next,
796 xmlelem_collection_IEnumVARIANT_Skip,
797 xmlelem_collection_IEnumVARIANT_Reset,
798 xmlelem_collection_IEnumVARIANT_Clone
799 };
800
801 static HRESULT XMLElementCollection_create(IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj)
802 {
803 xmlelem_collection *collection;
804
805 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
806
807 *ppObj = NULL;
808
809 if (!node->children)
810 return S_FALSE;
811
812 collection = heap_alloc(sizeof (*collection));
813 if(!collection)
814 return E_OUTOFMEMORY;
815
816 collection->IXMLElementCollection_iface.lpVtbl = &xmlelem_collection_vtbl;
817 collection->IEnumVARIANT_iface.lpVtbl = &xmlelem_collection_IEnumVARIANTvtbl;
818 collection->ref = 1;
819 collection->length = 0;
820 collection->node = node;
821 collection->current = node->children;
822 xmlelem_collection_updatelength(collection);
823
824 *ppObj = &collection->IXMLElementCollection_iface;
825
826 TRACE("returning iface %p\n", *ppObj);
827 return S_OK;
828 }
829
830 #endif