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
33 #include "wine/debug.h"
35 #include "msxml_private.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
41 /**********************************************************************
44 typedef struct _xmlelem
46 const IXMLElementVtbl
*lpVtbl
;
51 static inline xmlelem
*impl_from_IXMLElement(IXMLElement
*iface
)
53 return (xmlelem
*)((char*)iface
- FIELD_OFFSET(xmlelem
, lpVtbl
));
56 static HRESULT WINAPI
xmlelem_QueryInterface(IXMLElement
*iface
, REFIID riid
, void** ppvObject
)
58 xmlelem
*This
= impl_from_IXMLElement(iface
);
60 TRACE("%p %s %p\n", This
, debugstr_guid(riid
), ppvObject
);
62 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
63 IsEqualGUID(riid
, &IID_IXMLElement
))
69 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
73 IXMLElement_AddRef(iface
);
78 static ULONG WINAPI
xmlelem_AddRef(IXMLElement
*iface
)
80 xmlelem
*This
= impl_from_IXMLElement(iface
);
82 return InterlockedIncrement(&This
->ref
);
85 static ULONG WINAPI
xmlelem_Release(IXMLElement
*iface
)
87 xmlelem
*This
= impl_from_IXMLElement(iface
);
92 ref
= InterlockedDecrement(&This
->ref
);
95 HeapFree(GetProcessHeap(), 0, This
);
101 static HRESULT WINAPI
xmlelem_GetTypeInfoCount(IXMLElement
*iface
, UINT
* pctinfo
)
107 static HRESULT WINAPI
xmlelem_GetTypeInfo(IXMLElement
*iface
, UINT iTInfo
,
108 LCID lcid
, ITypeInfo
** ppTInfo
)
114 static HRESULT WINAPI
xmlelem_GetIDsOfNames(IXMLElement
*iface
, REFIID riid
,
115 LPOLESTR
* rgszNames
, UINT cNames
,
116 LCID lcid
, DISPID
* rgDispId
)
122 static HRESULT WINAPI
xmlelem_Invoke(IXMLElement
*iface
, DISPID dispIdMember
,
123 REFIID riid
, LCID lcid
, WORD wFlags
,
124 DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
125 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
131 static inline BSTR
str_dup_upper(BSTR str
)
133 INT len
= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
134 BSTR p
= SysAllocStringLen(NULL
, len
);
143 static HRESULT WINAPI
xmlelem_get_tagName(IXMLElement
*iface
, BSTR
*p
)
145 xmlelem
*This
= impl_from_IXMLElement(iface
);
148 TRACE("(%p, %p)\n", iface
, p
);
153 temp
= bstr_from_xmlChar(This
->node
->name
);
154 *p
= str_dup_upper(temp
);
157 TRACE("returning %s\n", debugstr_w(*p
));
162 static HRESULT WINAPI
xmlelem_put_tagName(IXMLElement
*iface
, BSTR p
)
164 FIXME("(%p, %p): stub\n", iface
, p
);
172 static HRESULT WINAPI
xmlelem_get_parent(IXMLElement
*iface
, IXMLElement
**parent
)
174 xmlelem
*This
= impl_from_IXMLElement(iface
);
176 TRACE("(%p, %p)\n", iface
, parent
);
183 if (!This
->node
->parent
)
186 return XMLElement_create((IUnknown
*)iface
, This
->node
->parent
, (LPVOID
*)parent
);
189 static HRESULT WINAPI
xmlelem_setAttribute(IXMLElement
*iface
, BSTR strPropertyName
,
190 VARIANT PropertyValue
)
192 xmlelem
*This
= impl_from_IXMLElement(iface
);
193 xmlChar
*name
, *value
;
196 TRACE("(%p, %s)\n", iface
, debugstr_w(strPropertyName
));
198 if (!strPropertyName
|| V_VT(&PropertyValue
) != VT_BSTR
)
201 name
= xmlChar_from_wchar(strPropertyName
);
202 value
= xmlChar_from_wchar(V_BSTR(&PropertyValue
));
203 attr
= xmlSetProp(This
->node
, name
, value
);
205 HeapFree(GetProcessHeap(), 0, name
);
206 HeapFree(GetProcessHeap(), 0, value
);
207 return (attr
) ? S_OK
: S_FALSE
;
210 static HRESULT WINAPI
xmlelem_getAttribute(IXMLElement
*iface
, BSTR strPropertyName
,
211 VARIANT
*PropertyValue
)
213 xmlelem
*This
= impl_from_IXMLElement(iface
);
214 xmlChar
*val
= NULL
, *name
;
217 TRACE("(%p, %s, %p)\n", iface
, debugstr_w(strPropertyName
), PropertyValue
);
222 VariantInit(PropertyValue
);
223 V_BSTR(PropertyValue
) = NULL
;
225 if (!strPropertyName
)
228 name
= xmlChar_from_wchar(strPropertyName
);
229 ptr
= This
->node
->properties
;
232 if (!lstrcmpiA((LPSTR
)name
, (LPCSTR
)ptr
->name
))
234 val
= xmlNodeListGetString(ptr
->doc
, ptr
->children
, 1);
243 V_VT(PropertyValue
) = VT_BSTR
;
244 V_BSTR(PropertyValue
) = bstr_from_xmlChar(val
);
247 HeapFree(GetProcessHeap(), 0, name
);
249 TRACE("returning %s\n", debugstr_w(V_BSTR(PropertyValue
)));
250 return (val
) ? S_OK
: S_FALSE
;
253 static HRESULT WINAPI
xmlelem_removeAttribute(IXMLElement
*iface
, BSTR strPropertyName
)
255 xmlelem
*This
= impl_from_IXMLElement(iface
);
259 HRESULT hr
= S_FALSE
;
261 TRACE("(%p, %s)\n", iface
, debugstr_w(strPropertyName
));
263 if (!strPropertyName
)
266 name
= xmlChar_from_wchar(strPropertyName
);
267 attr
= xmlHasProp(This
->node
, name
);
271 res
= xmlRemoveProp(attr
);
277 HeapFree(GetProcessHeap(), 0, name
);
281 static HRESULT WINAPI
xmlelem_get_children(IXMLElement
*iface
, IXMLElementCollection
**p
)
283 xmlelem
*This
= impl_from_IXMLElement(iface
);
285 TRACE("(%p, %p)\n", iface
, p
);
290 return XMLElementCollection_create((IUnknown
*)iface
, This
->node
->children
, (LPVOID
*)p
);
293 static long type_libxml_to_msxml(xmlElementType type
)
297 case XML_ELEMENT_NODE
:
298 return XMLELEMTYPE_ELEMENT
;
300 return XMLELEMTYPE_TEXT
;
301 case XML_COMMENT_NODE
:
302 return XMLELEMTYPE_COMMENT
;
303 case XML_DOCUMENT_NODE
:
304 return XMLELEMTYPE_DOCUMENT
;
306 return XMLELEMTYPE_DTD
;
308 return XMLELEMTYPE_PI
;
313 return XMLELEMTYPE_OTHER
;
316 static HRESULT WINAPI
xmlelem_get_type(IXMLElement
*iface
, long *p
)
318 xmlelem
*This
= impl_from_IXMLElement(iface
);
320 TRACE("(%p, %p)\n", This
, p
);
325 *p
= type_libxml_to_msxml(This
->node
->type
);
326 TRACE("returning %ld\n", *p
);
330 static HRESULT WINAPI
xmlelem_get_text(IXMLElement
*iface
, BSTR
*p
)
332 xmlelem
*This
= impl_from_IXMLElement(iface
);
335 TRACE("(%p, %p)\n", iface
, p
);
340 content
= xmlNodeGetContent(This
->node
);
341 *p
= bstr_from_xmlChar(content
);
342 TRACE("returning %s\n", debugstr_w(*p
));
348 static HRESULT WINAPI
xmlelem_put_text(IXMLElement
*iface
, BSTR p
)
350 xmlelem
*This
= impl_from_IXMLElement(iface
);
353 TRACE("(%p, %s)\n", iface
, debugstr_w(p
));
355 /* FIXME: test which types can be used */
356 if (This
->node
->type
== XML_ELEMENT_NODE
)
359 content
= xmlChar_from_wchar(p
);
360 xmlNodeSetContent(This
->node
, content
);
362 HeapFree( GetProcessHeap(), 0, content
);
367 static HRESULT WINAPI
xmlelem_addChild(IXMLElement
*iface
, IXMLElement
*pChildElem
,
368 long lIndex
, long lreserved
)
370 xmlelem
*This
= impl_from_IXMLElement(iface
);
371 xmlelem
*childElem
= impl_from_IXMLElement(pChildElem
);
374 TRACE("(%p, %p, %ld, %ld)\n", iface
, pChildElem
, lIndex
, lreserved
);
377 child
= xmlAddChild(This
->node
, childElem
->node
);
379 child
= xmlAddNextSibling(This
->node
, childElem
->node
->last
);
381 return (child
) ? S_OK
: S_FALSE
;
384 static HRESULT WINAPI
xmlelem_removeChild(IXMLElement
*iface
, IXMLElement
*pChildElem
)
386 FIXME("(%p, %p): stub\n", iface
, pChildElem
);
390 static const struct IXMLElementVtbl xmlelem_vtbl
=
392 xmlelem_QueryInterface
,
395 xmlelem_GetTypeInfoCount
,
397 xmlelem_GetIDsOfNames
,
402 xmlelem_setAttribute
,
403 xmlelem_getAttribute
,
404 xmlelem_removeAttribute
,
405 xmlelem_get_children
,
413 HRESULT
XMLElement_create(IUnknown
*pUnkOuter
, xmlNodePtr node
, LPVOID
*ppObj
)
417 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
424 elem
= HeapAlloc(GetProcessHeap(), 0, sizeof (*elem
));
426 return E_OUTOFMEMORY
;
428 elem
->lpVtbl
= &xmlelem_vtbl
;
432 *ppObj
= &elem
->lpVtbl
;
434 TRACE("returning iface %p\n", *ppObj
);
438 /************************************************************************
439 * IXMLElementCollection
441 typedef struct _xmlelem_collection
443 const IXMLElementCollectionVtbl
*lpVtbl
;
444 const IEnumVARIANTVtbl
*lpvtblIEnumVARIANT
;
449 /* IEnumVARIANT members */
451 } xmlelem_collection
;
453 static inline xmlelem_collection
*impl_from_IXMLElementCollection(IXMLElementCollection
*iface
)
455 return (xmlelem_collection
*)((char*)iface
- FIELD_OFFSET(xmlelem_collection
, lpVtbl
));
458 static inline xmlelem_collection
*impl_from_IEnumVARIANT(IEnumVARIANT
*iface
)
460 return (xmlelem_collection
*)((char*)iface
- FIELD_OFFSET(xmlelem_collection
, lpvtblIEnumVARIANT
));
463 static HRESULT WINAPI
xmlelem_collection_QueryInterface(IXMLElementCollection
*iface
, REFIID riid
, void** ppvObject
)
465 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
467 TRACE("%p %s %p\n", This
, debugstr_guid(riid
), ppvObject
);
469 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
470 IsEqualGUID(riid
, &IID_IXMLElementCollection
))
474 else if (IsEqualGUID(riid
, &IID_IEnumVARIANT
))
476 *ppvObject
= (IEnumVARIANT
*)&(This
->lpvtblIEnumVARIANT
);
480 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
481 return E_NOINTERFACE
;
484 IXMLElementCollection_AddRef(iface
);
489 static ULONG WINAPI
xmlelem_collection_AddRef(IXMLElementCollection
*iface
)
491 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
493 return InterlockedIncrement(&This
->ref
);
496 static ULONG WINAPI
xmlelem_collection_Release(IXMLElementCollection
*iface
)
498 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
503 ref
= InterlockedDecrement(&This
->ref
);
506 HeapFree(GetProcessHeap(), 0, This
);
512 static HRESULT WINAPI
xmlelem_collection_GetTypeInfoCount(IXMLElementCollection
*iface
, UINT
* pctinfo
)
518 static HRESULT WINAPI
xmlelem_collection_GetTypeInfo(IXMLElementCollection
*iface
, UINT iTInfo
,
519 LCID lcid
, ITypeInfo
** ppTInfo
)
525 static HRESULT WINAPI
xmlelem_collection_GetIDsOfNames(IXMLElementCollection
*iface
, REFIID riid
,
526 LPOLESTR
* rgszNames
, UINT cNames
,
527 LCID lcid
, DISPID
* rgDispId
)
533 static HRESULT WINAPI
xmlelem_collection_Invoke(IXMLElementCollection
*iface
, DISPID dispIdMember
,
534 REFIID riid
, LCID lcid
, WORD wFlags
,
535 DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
536 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
542 static HRESULT WINAPI
xmlelem_collection_put_length(IXMLElementCollection
*iface
, long v
)
544 TRACE("(%p, %ld)\n", iface
, v
);
548 static HRESULT WINAPI
xmlelem_collection_get_length(IXMLElementCollection
*iface
, long *p
)
550 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
552 TRACE("(%p, %p)\n", iface
, p
);
561 static HRESULT WINAPI
xmlelem_collection_get__newEnum(IXMLElementCollection
*iface
, IUnknown
**ppUnk
)
563 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
565 TRACE("(%p, %p)\n", iface
, ppUnk
);
570 *ppUnk
= (IUnknown
*)This
;
571 IUnknown_AddRef(*ppUnk
);
575 static HRESULT WINAPI
xmlelem_collection_item(IXMLElementCollection
*iface
, VARIANT var1
,
576 VARIANT var2
, IDispatch
**ppDisp
)
578 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
579 xmlNodePtr ptr
= This
->node
;
582 TRACE("(%p, %p)\n", iface
, ppDisp
);
592 if (index
>= This
->length
)
595 for (i
= 0; i
< index
; i
++)
598 return XMLElement_create((IUnknown
*)iface
, ptr
, (LPVOID
*)ppDisp
);
601 static const struct IXMLElementCollectionVtbl xmlelem_collection_vtbl
=
603 xmlelem_collection_QueryInterface
,
604 xmlelem_collection_AddRef
,
605 xmlelem_collection_Release
,
606 xmlelem_collection_GetTypeInfoCount
,
607 xmlelem_collection_GetTypeInfo
,
608 xmlelem_collection_GetIDsOfNames
,
609 xmlelem_collection_Invoke
,
610 xmlelem_collection_put_length
,
611 xmlelem_collection_get_length
,
612 xmlelem_collection_get__newEnum
,
613 xmlelem_collection_item
616 /************************************************************************
617 * xmlelem_collection implementation of IEnumVARIANT.
619 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_QueryInterface(
620 IEnumVARIANT
*iface
, REFIID riid
, LPVOID
*ppvObj
)
622 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
623 return IXMLDocument_QueryInterface((IXMLDocument
*)this, riid
, ppvObj
);
626 static ULONG WINAPI
xmlelem_collection_IEnumVARIANT_AddRef(
629 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
630 return IXMLDocument_AddRef((IXMLDocument
*)this);
633 static ULONG WINAPI
xmlelem_collection_IEnumVARIANT_Release(
636 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
637 return IXMLDocument_Release((IXMLDocument
*)this);
640 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Next(
641 IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*rgVar
, ULONG
*pCeltFetched
)
643 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
644 xmlNodePtr ptr
= This
->current
;
646 TRACE("(%p, %d, %p, %p)\n", iface
, celt
, rgVar
, pCeltFetched
);
651 /* FIXME: handle celt */
655 This
->current
= This
->current
->next
;
657 V_VT(rgVar
) = VT_DISPATCH
;
658 return XMLElement_create((IUnknown
*)iface
, ptr
, (LPVOID
*)&V_DISPATCH(rgVar
));
661 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Skip(
662 IEnumVARIANT
*iface
, ULONG celt
)
664 FIXME("(%p, %d): stub\n", iface
, celt
);
668 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Reset(
671 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
672 This
->current
= This
->node
;
676 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Clone(
677 IEnumVARIANT
*iface
, IEnumVARIANT
**ppEnum
)
679 FIXME("(%p, %p): stub\n", iface
, ppEnum
);
683 static const struct IEnumVARIANTVtbl xmlelem_collection_IEnumVARIANTvtbl
=
685 xmlelem_collection_IEnumVARIANT_QueryInterface
,
686 xmlelem_collection_IEnumVARIANT_AddRef
,
687 xmlelem_collection_IEnumVARIANT_Release
,
688 xmlelem_collection_IEnumVARIANT_Next
,
689 xmlelem_collection_IEnumVARIANT_Skip
,
690 xmlelem_collection_IEnumVARIANT_Reset
,
691 xmlelem_collection_IEnumVARIANT_Clone
694 HRESULT
XMLElementCollection_create(IUnknown
*pUnkOuter
, xmlNodePtr node
, LPVOID
*ppObj
)
696 xmlelem_collection
*collection
;
699 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
706 collection
= HeapAlloc(GetProcessHeap(), 0, sizeof (*collection
));
708 return E_OUTOFMEMORY
;
710 collection
->lpVtbl
= &xmlelem_collection_vtbl
;
711 collection
->lpvtblIEnumVARIANT
= &xmlelem_collection_IEnumVARIANTvtbl
;
713 collection
->length
= 0;
714 collection
->node
= node
;
715 collection
->current
= node
;
720 collection
->length
++;
724 *ppObj
= &collection
->lpVtbl
;
726 TRACE("returning iface %p\n", *ppObj
);