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