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