2 * Node map implementation
4 * Copyright 2005 Mike McCormack
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
27 # include <libxml/parser.h>
28 # include <libxml/xmlerror.h>
38 #include "msxml_private.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
46 typedef struct _xmlnodemap
48 IXMLDOMNamedNodeMap IXMLDOMNamedNodeMap_iface;
49 ISupportErrorInfo ISupportErrorInfo_iface;
55 static inline xmlnodemap *impl_from_IXMLDOMNamedNodeMap( IXMLDOMNamedNodeMap *iface )
57 return CONTAINING_RECORD(iface, xmlnodemap, IXMLDOMNamedNodeMap_iface);
60 static inline xmlnodemap *impl_from_ISupportErrorInfo( ISupportErrorInfo *iface )
62 return CONTAINING_RECORD(iface, xmlnodemap, ISupportErrorInfo_iface);
65 static HRESULT WINAPI xmlnodemap_QueryInterface(
66 IXMLDOMNamedNodeMap *iface,
67 REFIID riid, void** ppvObject )
69 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
70 TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppvObject);
72 if( IsEqualGUID( riid, &IID_IUnknown ) ||
73 IsEqualGUID( riid, &IID_IDispatch ) ||
74 IsEqualGUID( riid, &IID_IXMLDOMNamedNodeMap ) )
78 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
80 *ppvObject = &This->ISupportErrorInfo_iface;
84 FIXME("interface %s not implemented\n", debugstr_guid(riid));
88 IXMLDOMElement_AddRef( iface );
93 static ULONG WINAPI xmlnodemap_AddRef(
94 IXMLDOMNamedNodeMap *iface )
96 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
97 return InterlockedIncrement( &This->ref );
100 static ULONG WINAPI xmlnodemap_Release(
101 IXMLDOMNamedNodeMap *iface )
103 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
106 ref = InterlockedDecrement( &This->ref );
109 IXMLDOMNode_Release( This->node );
116 static HRESULT WINAPI xmlnodemap_GetTypeInfoCount(
117 IXMLDOMNamedNodeMap *iface,
120 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
122 TRACE("(%p)->(%p)\n", This, pctinfo);
129 static HRESULT WINAPI xmlnodemap_GetTypeInfo(
130 IXMLDOMNamedNodeMap *iface,
131 UINT iTInfo, LCID lcid,
132 ITypeInfo** ppTInfo )
134 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
135 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
136 return get_typeinfo(IXMLDOMNamedNodeMap_tid, ppTInfo);
139 static HRESULT WINAPI xmlnodemap_GetIDsOfNames(
140 IXMLDOMNamedNodeMap *iface,
141 REFIID riid, LPOLESTR* rgszNames,
142 UINT cNames, LCID lcid, DISPID* rgDispId )
144 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
148 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
151 if(!rgszNames || cNames == 0 || !rgDispId)
154 hr = get_typeinfo(IXMLDOMNamedNodeMap_tid, &typeinfo);
157 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
158 ITypeInfo_Release(typeinfo);
164 static HRESULT WINAPI xmlnodemap_Invoke(
165 IXMLDOMNamedNodeMap *iface,
166 DISPID dispIdMember, REFIID riid, LCID lcid,
167 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
168 EXCEPINFO* pExcepInfo, UINT* puArgErr )
170 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
174 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
175 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
177 hr = get_typeinfo(IXMLDOMNamedNodeMap_tid, &typeinfo);
180 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMNamedNodeMap_iface, dispIdMember, wFlags,
181 pDispParams, pVarResult, pExcepInfo, puArgErr);
182 ITypeInfo_Release(typeinfo);
188 xmlChar *xmlChar_from_wchar( LPCWSTR str )
193 len = WideCharToMultiByte( CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL );
194 xmlstr = heap_alloc( len );
196 WideCharToMultiByte( CP_UTF8, 0, str, -1, (LPSTR) xmlstr, len, NULL, NULL );
200 static HRESULT WINAPI xmlnodemap_getNamedItem(
201 IXMLDOMNamedNodeMap *iface,
203 IXMLDOMNode** namedItem)
205 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
206 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), namedItem );
207 return IXMLDOMNamedNodeMap_getQualifiedItem(iface, name, NULL, namedItem);
210 static HRESULT WINAPI xmlnodemap_setNamedItem(
211 IXMLDOMNamedNodeMap *iface,
212 IXMLDOMNode* newItem,
213 IXMLDOMNode** namedItem)
215 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
220 TRACE("(%p)->(%p %p)\n", This, newItem, namedItem );
225 if(namedItem) *namedItem = NULL;
227 node = xmlNodePtr_from_domnode( This->node, 0 );
231 /* Must be an Attribute */
232 ThisNew = get_node_obj( newItem );
234 FIXME("ThisNew is not our node implementation\n");
238 if(ThisNew->node->type != XML_ATTRIBUTE_NODE)
241 if(!ThisNew->node->parent)
242 if(xmldoc_remove_orphan(ThisNew->node->doc, ThisNew->node) != S_OK)
243 WARN("%p is not an orphan of %p\n", ThisNew->node, ThisNew->node->doc);
245 nodeNew = xmlAddChild(node, ThisNew->node);
248 *namedItem = create_node( nodeNew );
252 static HRESULT WINAPI xmlnodemap_removeNamedItem(
253 IXMLDOMNamedNodeMap *iface,
255 IXMLDOMNode** namedItem)
257 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
258 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), namedItem );
259 return IXMLDOMNamedNodeMap_removeQualifiedItem(iface, name, NULL, namedItem);
262 static HRESULT WINAPI xmlnodemap_get_item(
263 IXMLDOMNamedNodeMap *iface,
265 IXMLDOMNode** listItem)
267 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
272 TRACE("(%p)->(%d %p)\n", This, index, listItem);
279 node = xmlNodePtr_from_domnode( This->node, 0 );
280 curr = node->properties;
282 for (attrIndex = 0; attrIndex < index; attrIndex++) {
283 if (curr->next == NULL)
289 *listItem = create_node( (xmlNodePtr) curr );
294 static HRESULT WINAPI xmlnodemap_get_length(
295 IXMLDOMNamedNodeMap *iface,
303 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
305 TRACE("(%p)->(%p)\n", This, listLength);
310 node = xmlNodePtr_from_domnode( This->node, 0 );
314 first = node->properties;
326 *listLength = attrCount;
331 static HRESULT WINAPI xmlnodemap_getQualifiedItem(
332 IXMLDOMNamedNodeMap *iface,
335 IXMLDOMNode** qualifiedItem)
337 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
343 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(baseName), debugstr_w(namespaceURI), qualifiedItem);
345 if (!baseName || !qualifiedItem) return E_INVALIDARG;
347 node = xmlNodePtr_from_domnode(This->node, XML_ELEMENT_NODE);
351 if (namespaceURI && *namespaceURI)
353 href = xmlChar_from_wchar(namespaceURI);
354 if (!href) return E_OUTOFMEMORY;
359 name = xmlChar_from_wchar(baseName);
363 return E_OUTOFMEMORY;
366 attr = xmlHasNsProp(node, name, href);
373 *qualifiedItem = NULL;
377 *qualifiedItem = create_node((xmlNodePtr)attr);
382 static HRESULT WINAPI xmlnodemap_removeQualifiedItem(
383 IXMLDOMNamedNodeMap *iface,
386 IXMLDOMNode** qualifiedItem)
388 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
394 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(baseName), debugstr_w(namespaceURI), qualifiedItem);
396 if (!baseName) return E_INVALIDARG;
398 node = xmlNodePtr_from_domnode( This->node, XML_ELEMENT_NODE );
402 if (namespaceURI && *namespaceURI)
404 href = xmlChar_from_wchar(namespaceURI);
405 if (!href) return E_OUTOFMEMORY;
410 name = xmlChar_from_wchar(baseName);
414 return E_OUTOFMEMORY;
417 attr = xmlHasNsProp( node, name, href );
424 if (qualifiedItem) *qualifiedItem = NULL;
430 xmlUnlinkNode( (xmlNodePtr) attr );
431 xmldoc_add_orphan( attr->doc, (xmlNodePtr) attr );
432 *qualifiedItem = create_node( (xmlNodePtr) attr );
436 if (xmlRemoveProp(attr) == -1)
437 ERR("xmlRemoveProp failed\n");
443 static HRESULT WINAPI xmlnodemap_nextNode(
444 IXMLDOMNamedNodeMap *iface,
445 IXMLDOMNode** nextItem)
447 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
452 TRACE("(%p)->(%p: %d)\n", This, nextItem, This->iterator);
456 node = xmlNodePtr_from_domnode( This->node, 0 );
457 curr = node->properties;
459 for (attrIndex = 0; attrIndex < This->iterator; attrIndex++) {
460 if (curr->next == NULL)
468 *nextItem = create_node( (xmlNodePtr) curr );
473 static HRESULT WINAPI xmlnodemap_reset(
474 IXMLDOMNamedNodeMap *iface )
476 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
478 TRACE("(%p: %d)\n", This, This->iterator);
485 static HRESULT WINAPI xmlnodemap__newEnum(
486 IXMLDOMNamedNodeMap *iface,
489 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
490 FIXME("(%p)->(%p)\n", This, ppUnk);
494 static const struct IXMLDOMNamedNodeMapVtbl xmlnodemap_vtbl =
496 xmlnodemap_QueryInterface,
499 xmlnodemap_GetTypeInfoCount,
500 xmlnodemap_GetTypeInfo,
501 xmlnodemap_GetIDsOfNames,
503 xmlnodemap_getNamedItem,
504 xmlnodemap_setNamedItem,
505 xmlnodemap_removeNamedItem,
507 xmlnodemap_get_length,
508 xmlnodemap_getQualifiedItem,
509 xmlnodemap_removeQualifiedItem,
515 static HRESULT WINAPI support_error_QueryInterface(
516 ISupportErrorInfo *iface,
517 REFIID riid, void** ppvObject )
519 xmlnodemap *This = impl_from_ISupportErrorInfo( iface );
520 TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
521 return IXMLDOMNamedNodeMap_QueryInterface(&This->IXMLDOMNamedNodeMap_iface, riid, ppvObject);
524 static ULONG WINAPI support_error_AddRef(
525 ISupportErrorInfo *iface )
527 xmlnodemap *This = impl_from_ISupportErrorInfo( iface );
528 return IXMLDOMNamedNodeMap_AddRef(&This->IXMLDOMNamedNodeMap_iface);
531 static ULONG WINAPI support_error_Release(
532 ISupportErrorInfo *iface )
534 xmlnodemap *This = impl_from_ISupportErrorInfo( iface );
535 return IXMLDOMNamedNodeMap_Release(&This->IXMLDOMNamedNodeMap_iface);
538 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
539 ISupportErrorInfo *iface,
542 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
546 static const struct ISupportErrorInfoVtbl support_error_vtbl =
548 support_error_QueryInterface,
549 support_error_AddRef,
550 support_error_Release,
551 support_error_InterfaceSupportsErrorInfo
554 IXMLDOMNamedNodeMap *create_nodemap( IXMLDOMNode *node )
558 nodemap = heap_alloc( sizeof *nodemap );
562 nodemap->IXMLDOMNamedNodeMap_iface.lpVtbl = &xmlnodemap_vtbl;
563 nodemap->ISupportErrorInfo_iface.lpVtbl = &support_error_vtbl;
564 nodemap->node = node;
566 nodemap->iterator = 0;
568 IXMLDOMNode_AddRef( node );
569 /* Since we AddRef a node here, we don't need to call xmldoc_add_ref() */
571 return &nodemap->IXMLDOMNamedNodeMap_iface;