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 static HRESULT
XMLElementCollection_create( IUnknown
*pUnkOuter
, xmlNodePtr node
, LPVOID
*ppObj
);
43 /**********************************************************************
46 typedef struct _xmlelem
48 const IXMLElementVtbl
*lpVtbl
;
53 static inline xmlelem
*impl_from_IXMLElement(IXMLElement
*iface
)
55 return (xmlelem
*)((char*)iface
- FIELD_OFFSET(xmlelem
, lpVtbl
));
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_IXMLElement
))
71 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
75 IXMLElement_AddRef(iface
);
80 static ULONG WINAPI
xmlelem_AddRef(IXMLElement
*iface
)
82 xmlelem
*This
= impl_from_IXMLElement(iface
);
84 return InterlockedIncrement(&This
->ref
);
87 static ULONG WINAPI
xmlelem_Release(IXMLElement
*iface
)
89 xmlelem
*This
= impl_from_IXMLElement(iface
);
94 ref
= InterlockedDecrement(&This
->ref
);
97 HeapFree(GetProcessHeap(), 0, This
);
103 static HRESULT WINAPI
xmlelem_GetTypeInfoCount(IXMLElement
*iface
, UINT
* pctinfo
)
105 xmlelem
*This
= impl_from_IXMLElement(iface
);
107 TRACE("(%p)->(%p)\n", This
, pctinfo
);
114 static HRESULT WINAPI
xmlelem_GetTypeInfo(IXMLElement
*iface
, UINT iTInfo
,
115 LCID lcid
, ITypeInfo
** ppTInfo
)
117 xmlelem
*This
= impl_from_IXMLElement(iface
);
120 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
122 hr
= get_typeinfo(IXMLElement_tid
, ppTInfo
);
127 static HRESULT WINAPI
xmlelem_GetIDsOfNames(IXMLElement
*iface
, REFIID riid
,
128 LPOLESTR
* rgszNames
, UINT cNames
,
129 LCID lcid
, DISPID
* rgDispId
)
131 xmlelem
*This
= impl_from_IXMLElement(iface
);
135 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
138 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
141 hr
= get_typeinfo(IXMLElement_tid
, &typeinfo
);
144 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
145 ITypeInfo_Release(typeinfo
);
151 static HRESULT WINAPI
xmlelem_Invoke(IXMLElement
*iface
, DISPID dispIdMember
,
152 REFIID riid
, LCID lcid
, WORD wFlags
,
153 DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
154 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
156 xmlelem
*This
= impl_from_IXMLElement(iface
);
160 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
161 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
163 hr
= get_typeinfo(IXMLElement_tid
, &typeinfo
);
166 hr
= ITypeInfo_Invoke(typeinfo
, &(This
->lpVtbl
), dispIdMember
, wFlags
, pDispParams
,
167 pVarResult
, pExcepInfo
, puArgErr
);
168 ITypeInfo_Release(typeinfo
);
174 static HRESULT WINAPI
xmlelem_get_tagName(IXMLElement
*iface
, BSTR
*p
)
176 xmlelem
*This
= impl_from_IXMLElement(iface
);
178 TRACE("(%p, %p)\n", iface
, p
);
183 *p
= bstr_from_xmlChar(This
->node
->name
);
184 CharUpperBuffW(*p
, SysStringLen(*p
));
186 TRACE("returning %s\n", debugstr_w(*p
));
191 static HRESULT WINAPI
xmlelem_put_tagName(IXMLElement
*iface
, BSTR p
)
193 FIXME("(%p, %p): stub\n", iface
, p
);
201 static HRESULT WINAPI
xmlelem_get_parent(IXMLElement
*iface
, IXMLElement
**parent
)
203 xmlelem
*This
= impl_from_IXMLElement(iface
);
205 TRACE("(%p, %p)\n", iface
, parent
);
212 if (!This
->node
->parent
)
215 return XMLElement_create((IUnknown
*)iface
, This
->node
->parent
, (LPVOID
*)parent
);
218 static HRESULT WINAPI
xmlelem_setAttribute(IXMLElement
*iface
, BSTR strPropertyName
,
219 VARIANT PropertyValue
)
221 xmlelem
*This
= impl_from_IXMLElement(iface
);
222 xmlChar
*name
, *value
;
225 TRACE("(%p, %s)\n", iface
, debugstr_w(strPropertyName
));
227 if (!strPropertyName
|| V_VT(&PropertyValue
) != VT_BSTR
)
230 name
= xmlChar_from_wchar(strPropertyName
);
231 value
= xmlChar_from_wchar(V_BSTR(&PropertyValue
));
232 attr
= xmlSetProp(This
->node
, name
, value
);
234 HeapFree(GetProcessHeap(), 0, name
);
235 HeapFree(GetProcessHeap(), 0, value
);
236 return (attr
) ? S_OK
: S_FALSE
;
239 static HRESULT WINAPI
xmlelem_getAttribute(IXMLElement
*iface
, BSTR strPropertyName
,
240 VARIANT
*PropertyValue
)
242 xmlelem
*This
= impl_from_IXMLElement(iface
);
243 xmlChar
*val
= NULL
, *name
;
246 TRACE("(%p, %s, %p)\n", iface
, debugstr_w(strPropertyName
), PropertyValue
);
251 VariantInit(PropertyValue
);
252 V_BSTR(PropertyValue
) = NULL
;
254 if (!strPropertyName
)
257 name
= xmlChar_from_wchar(strPropertyName
);
258 ptr
= This
->node
->properties
;
261 if (!lstrcmpiA((LPSTR
)name
, (LPCSTR
)ptr
->name
))
263 val
= xmlNodeListGetString(ptr
->doc
, ptr
->children
, 1);
272 V_VT(PropertyValue
) = VT_BSTR
;
273 V_BSTR(PropertyValue
) = bstr_from_xmlChar(val
);
276 HeapFree(GetProcessHeap(), 0, name
);
278 TRACE("returning %s\n", debugstr_w(V_BSTR(PropertyValue
)));
279 return (val
) ? S_OK
: S_FALSE
;
282 static HRESULT WINAPI
xmlelem_removeAttribute(IXMLElement
*iface
, BSTR strPropertyName
)
284 xmlelem
*This
= impl_from_IXMLElement(iface
);
288 HRESULT hr
= S_FALSE
;
290 TRACE("(%p, %s)\n", iface
, debugstr_w(strPropertyName
));
292 if (!strPropertyName
)
295 name
= xmlChar_from_wchar(strPropertyName
);
296 attr
= xmlHasProp(This
->node
, name
);
300 res
= xmlRemoveProp(attr
);
306 HeapFree(GetProcessHeap(), 0, name
);
310 static HRESULT WINAPI
xmlelem_get_children(IXMLElement
*iface
, IXMLElementCollection
**p
)
312 xmlelem
*This
= impl_from_IXMLElement(iface
);
314 TRACE("(%p, %p)\n", iface
, p
);
319 return XMLElementCollection_create((IUnknown
*)iface
, This
->node
->children
, (LPVOID
*)p
);
322 static LONG
type_libxml_to_msxml(xmlElementType type
)
326 case XML_ELEMENT_NODE
:
327 return XMLELEMTYPE_ELEMENT
;
329 return XMLELEMTYPE_TEXT
;
330 case XML_COMMENT_NODE
:
331 return XMLELEMTYPE_COMMENT
;
332 case XML_DOCUMENT_NODE
:
333 return XMLELEMTYPE_DOCUMENT
;
335 return XMLELEMTYPE_DTD
;
337 return XMLELEMTYPE_PI
;
342 return XMLELEMTYPE_OTHER
;
345 static HRESULT WINAPI
xmlelem_get_type(IXMLElement
*iface
, LONG
*p
)
347 xmlelem
*This
= impl_from_IXMLElement(iface
);
349 TRACE("(%p, %p)\n", This
, p
);
354 *p
= type_libxml_to_msxml(This
->node
->type
);
355 TRACE("returning %d\n", *p
);
359 static HRESULT WINAPI
xmlelem_get_text(IXMLElement
*iface
, BSTR
*p
)
361 xmlelem
*This
= impl_from_IXMLElement(iface
);
364 TRACE("(%p, %p)\n", iface
, p
);
369 content
= xmlNodeGetContent(This
->node
);
370 *p
= bstr_from_xmlChar(content
);
371 TRACE("returning %s\n", debugstr_w(*p
));
377 static HRESULT WINAPI
xmlelem_put_text(IXMLElement
*iface
, BSTR p
)
379 xmlelem
*This
= impl_from_IXMLElement(iface
);
382 TRACE("(%p, %s)\n", iface
, debugstr_w(p
));
384 /* FIXME: test which types can be used */
385 if (This
->node
->type
== XML_ELEMENT_NODE
)
388 content
= xmlChar_from_wchar(p
);
389 xmlNodeSetContent(This
->node
, content
);
391 HeapFree( GetProcessHeap(), 0, content
);
396 static HRESULT WINAPI
xmlelem_addChild(IXMLElement
*iface
, IXMLElement
*pChildElem
,
397 LONG lIndex
, LONG lreserved
)
399 xmlelem
*This
= impl_from_IXMLElement(iface
);
400 xmlelem
*childElem
= impl_from_IXMLElement(pChildElem
);
403 TRACE("(%p, %p, %d, %d)\n", iface
, pChildElem
, lIndex
, lreserved
);
406 child
= xmlAddChild(This
->node
, childElem
->node
);
408 child
= xmlAddNextSibling(This
->node
, childElem
->node
->last
);
410 return (child
) ? S_OK
: S_FALSE
;
413 static HRESULT WINAPI
xmlelem_removeChild(IXMLElement
*iface
, IXMLElement
*pChildElem
)
415 xmlelem
*This
= impl_from_IXMLElement(iface
);
416 xmlelem
*childElem
= impl_from_IXMLElement(pChildElem
);
418 TRACE("(%p, %p)\n", This
, childElem
);
423 /* only supported for This is childElem parent case */
424 if (This
->node
!= childElem
->node
->parent
)
427 xmlUnlinkNode(childElem
->node
);
432 static const struct IXMLElementVtbl xmlelem_vtbl
=
434 xmlelem_QueryInterface
,
437 xmlelem_GetTypeInfoCount
,
439 xmlelem_GetIDsOfNames
,
444 xmlelem_setAttribute
,
445 xmlelem_getAttribute
,
446 xmlelem_removeAttribute
,
447 xmlelem_get_children
,
455 HRESULT
XMLElement_create(IUnknown
*pUnkOuter
, xmlNodePtr node
, LPVOID
*ppObj
)
459 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
466 elem
= HeapAlloc(GetProcessHeap(), 0, sizeof (*elem
));
468 return E_OUTOFMEMORY
;
470 elem
->lpVtbl
= &xmlelem_vtbl
;
474 *ppObj
= &elem
->lpVtbl
;
476 TRACE("returning iface %p\n", *ppObj
);
480 /************************************************************************
481 * IXMLElementCollection
483 typedef struct _xmlelem_collection
485 const IXMLElementCollectionVtbl
*lpVtbl
;
486 const IEnumVARIANTVtbl
*lpvtblIEnumVARIANT
;
491 /* IEnumVARIANT members */
493 } xmlelem_collection
;
495 static inline xmlelem_collection
*impl_from_IXMLElementCollection(IXMLElementCollection
*iface
)
497 return (xmlelem_collection
*)((char*)iface
- FIELD_OFFSET(xmlelem_collection
, lpVtbl
));
500 static inline xmlelem_collection
*impl_from_IEnumVARIANT(IEnumVARIANT
*iface
)
502 return (xmlelem_collection
*)((char*)iface
- FIELD_OFFSET(xmlelem_collection
, lpvtblIEnumVARIANT
));
505 static HRESULT WINAPI
xmlelem_collection_QueryInterface(IXMLElementCollection
*iface
, REFIID riid
, void** ppvObject
)
507 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
509 TRACE("%p %s %p\n", This
, debugstr_guid(riid
), ppvObject
);
511 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
512 IsEqualGUID(riid
, &IID_IXMLElementCollection
))
516 else if (IsEqualGUID(riid
, &IID_IEnumVARIANT
))
518 *ppvObject
= &(This
->lpvtblIEnumVARIANT
);
522 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
523 return E_NOINTERFACE
;
526 IXMLElementCollection_AddRef(iface
);
531 static ULONG WINAPI
xmlelem_collection_AddRef(IXMLElementCollection
*iface
)
533 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
535 return InterlockedIncrement(&This
->ref
);
538 static ULONG WINAPI
xmlelem_collection_Release(IXMLElementCollection
*iface
)
540 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
545 ref
= InterlockedDecrement(&This
->ref
);
548 HeapFree(GetProcessHeap(), 0, This
);
554 static HRESULT WINAPI
xmlelem_collection_GetTypeInfoCount(IXMLElementCollection
*iface
, UINT
* pctinfo
)
560 static HRESULT WINAPI
xmlelem_collection_GetTypeInfo(IXMLElementCollection
*iface
, UINT iTInfo
,
561 LCID lcid
, ITypeInfo
** ppTInfo
)
567 static HRESULT WINAPI
xmlelem_collection_GetIDsOfNames(IXMLElementCollection
*iface
, REFIID riid
,
568 LPOLESTR
* rgszNames
, UINT cNames
,
569 LCID lcid
, DISPID
* rgDispId
)
575 static HRESULT WINAPI
xmlelem_collection_Invoke(IXMLElementCollection
*iface
, DISPID dispIdMember
,
576 REFIID riid
, LCID lcid
, WORD wFlags
,
577 DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
578 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
584 static HRESULT WINAPI
xmlelem_collection_put_length(IXMLElementCollection
*iface
, LONG v
)
586 TRACE("(%p, %d)\n", iface
, v
);
590 static HRESULT WINAPI
xmlelem_collection_get_length(IXMLElementCollection
*iface
, LONG
*p
)
592 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
594 TRACE("(%p, %p)\n", iface
, p
);
603 static HRESULT WINAPI
xmlelem_collection_get__newEnum(IXMLElementCollection
*iface
, IUnknown
**ppUnk
)
605 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
607 TRACE("(%p, %p)\n", iface
, ppUnk
);
612 *ppUnk
= (IUnknown
*)This
;
613 IUnknown_AddRef(*ppUnk
);
617 static HRESULT WINAPI
xmlelem_collection_item(IXMLElementCollection
*iface
, VARIANT var1
,
618 VARIANT var2
, IDispatch
**ppDisp
)
620 xmlelem_collection
*This
= impl_from_IXMLElementCollection(iface
);
621 xmlNodePtr ptr
= This
->node
;
624 TRACE("(%p, %p)\n", iface
, ppDisp
);
634 if (index
>= This
->length
)
637 for (i
= 0; i
< index
; i
++)
640 return XMLElement_create((IUnknown
*)iface
, ptr
, (LPVOID
*)ppDisp
);
643 static const struct IXMLElementCollectionVtbl xmlelem_collection_vtbl
=
645 xmlelem_collection_QueryInterface
,
646 xmlelem_collection_AddRef
,
647 xmlelem_collection_Release
,
648 xmlelem_collection_GetTypeInfoCount
,
649 xmlelem_collection_GetTypeInfo
,
650 xmlelem_collection_GetIDsOfNames
,
651 xmlelem_collection_Invoke
,
652 xmlelem_collection_put_length
,
653 xmlelem_collection_get_length
,
654 xmlelem_collection_get__newEnum
,
655 xmlelem_collection_item
658 /************************************************************************
659 * xmlelem_collection implementation of IEnumVARIANT.
661 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_QueryInterface(
662 IEnumVARIANT
*iface
, REFIID riid
, LPVOID
*ppvObj
)
664 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
665 return IXMLDocument_QueryInterface((IXMLDocument
*)this, riid
, ppvObj
);
668 static ULONG WINAPI
xmlelem_collection_IEnumVARIANT_AddRef(
671 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
672 return IXMLDocument_AddRef((IXMLDocument
*)this);
675 static ULONG WINAPI
xmlelem_collection_IEnumVARIANT_Release(
678 xmlelem_collection
*this = impl_from_IEnumVARIANT(iface
);
679 return IXMLDocument_Release((IXMLDocument
*)this);
682 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Next(
683 IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*rgVar
, ULONG
*pCeltFetched
)
685 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
686 xmlNodePtr ptr
= This
->current
;
688 TRACE("(%p, %d, %p, %p)\n", iface
, celt
, rgVar
, pCeltFetched
);
693 /* FIXME: handle celt */
697 This
->current
= This
->current
->next
;
699 V_VT(rgVar
) = VT_DISPATCH
;
700 return XMLElement_create((IUnknown
*)iface
, ptr
, (LPVOID
*)&V_DISPATCH(rgVar
));
703 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Skip(
704 IEnumVARIANT
*iface
, ULONG celt
)
706 FIXME("(%p, %d): stub\n", iface
, celt
);
710 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Reset(
713 xmlelem_collection
*This
= impl_from_IEnumVARIANT(iface
);
714 This
->current
= This
->node
;
718 static HRESULT WINAPI
xmlelem_collection_IEnumVARIANT_Clone(
719 IEnumVARIANT
*iface
, IEnumVARIANT
**ppEnum
)
721 FIXME("(%p, %p): stub\n", iface
, ppEnum
);
725 static const struct IEnumVARIANTVtbl xmlelem_collection_IEnumVARIANTvtbl
=
727 xmlelem_collection_IEnumVARIANT_QueryInterface
,
728 xmlelem_collection_IEnumVARIANT_AddRef
,
729 xmlelem_collection_IEnumVARIANT_Release
,
730 xmlelem_collection_IEnumVARIANT_Next
,
731 xmlelem_collection_IEnumVARIANT_Skip
,
732 xmlelem_collection_IEnumVARIANT_Reset
,
733 xmlelem_collection_IEnumVARIANT_Clone
736 static HRESULT
XMLElementCollection_create(IUnknown
*pUnkOuter
, xmlNodePtr node
, LPVOID
*ppObj
)
738 xmlelem_collection
*collection
;
741 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
748 collection
= HeapAlloc(GetProcessHeap(), 0, sizeof (*collection
));
750 return E_OUTOFMEMORY
;
752 collection
->lpVtbl
= &xmlelem_collection_vtbl
;
753 collection
->lpvtblIEnumVARIANT
= &xmlelem_collection_IEnumVARIANTvtbl
;
755 collection
->length
= 0;
756 collection
->node
= node
;
757 collection
->current
= node
;
762 collection
->length
++;
766 *ppObj
= &collection
->lpVtbl
;
768 TRACE("returning iface %p\n", *ppObj
);