Extend get_nodeName add testcases for it.
[wine/multimedia.git] / dlls / msxml3 / node.c
blobc957d4eb1056f459252d0aa01ee1be75219632e9
1 /*
2 * Node implementation
4 * Copyright 2005 Mike McCormack
6 * iface 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 * iface 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
23 #define COBJMACROS
25 #include <stdarg.h>
26 #include <assert.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "winnls.h"
31 #include "ole2.h"
32 #include "ocidl.h"
33 #include "msxml.h"
34 #include "xmldom.h"
35 #include "msxml.h"
37 #include "msxml_private.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
43 #ifdef HAVE_LIBXML2
45 typedef struct _xmlnode
47 const struct IXMLDOMNodeVtbl *lpVtbl;
48 LONG ref;
49 xmlNodePtr node;
50 } xmlnode;
52 static inline xmlnode *impl_from_IXMLDOMNode( IXMLDOMNode *iface )
54 return (xmlnode *)((char*)iface - FIELD_OFFSET(xmlnode, lpVtbl));
57 xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type )
59 xmlnode *This;
61 if ( !iface )
62 return NULL;
63 This = impl_from_IXMLDOMNode( iface );
64 if ( !This->node )
65 return NULL;
66 if ( type && This->node->type != type )
67 return NULL;
68 return This->node;
71 static HRESULT WINAPI xmlnode_QueryInterface(
72 IXMLDOMNode *iface,
73 REFIID riid,
74 void** ppvObject )
76 TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
78 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
79 IsEqualGUID( riid, &IID_IDispatch ) ||
80 IsEqualGUID( riid, &IID_IXMLDOMNode ) )
82 *ppvObject = iface;
84 else
85 return E_NOINTERFACE;
87 IXMLDOMElement_AddRef( iface );
89 return S_OK;
92 static ULONG WINAPI xmlnode_AddRef(
93 IXMLDOMNode *iface )
95 xmlnode *This = impl_from_IXMLDOMNode( iface );
96 return InterlockedIncrement( &This->ref );
99 static ULONG WINAPI xmlnode_Release(
100 IXMLDOMNode *iface )
102 xmlnode *This = impl_from_IXMLDOMNode( iface );
103 ULONG ref;
105 ref = InterlockedDecrement( &This->ref );
106 if ( ref == 0 )
108 if( This->node->type == XML_DOCUMENT_NODE )
110 xmlFreeDoc( (xmlDocPtr) This->node );
112 else
114 IXMLDOMNode *root;
115 assert( This->node->doc );
116 root = This->node->doc->_private;
117 assert( root );
118 IXMLDOMNode_Release( root );
119 This->node->_private = NULL;
121 HeapFree( GetProcessHeap(), 0, This );
124 return ref;
127 static HRESULT WINAPI xmlnode_GetTypeInfoCount(
128 IXMLDOMNode *iface,
129 UINT* pctinfo )
131 FIXME("\n");
132 return E_NOTIMPL;
135 static HRESULT WINAPI xmlnode_GetTypeInfo(
136 IXMLDOMNode *iface,
137 UINT iTInfo,
138 LCID lcid,
139 ITypeInfo** ppTInfo )
141 FIXME("\n");
142 return E_NOTIMPL;
145 static HRESULT WINAPI xmlnode_GetIDsOfNames(
146 IXMLDOMNode *iface,
147 REFIID riid,
148 LPOLESTR* rgszNames,
149 UINT cNames,
150 LCID lcid,
151 DISPID* rgDispId )
153 FIXME("\n");
154 return E_NOTIMPL;
157 static HRESULT WINAPI xmlnode_Invoke(
158 IXMLDOMNode *iface,
159 DISPID dispIdMember,
160 REFIID riid,
161 LCID lcid,
162 WORD wFlags,
163 DISPPARAMS* pDispParams,
164 VARIANT* pVarResult,
165 EXCEPINFO* pExcepInfo,
166 UINT* puArgErr )
168 FIXME("\n");
169 return E_NOTIMPL;
172 static HRESULT WINAPI xmlnode_get_nodeName(
173 IXMLDOMNode *iface,
174 BSTR* name)
176 xmlnode *This = impl_from_IXMLDOMNode( iface );
177 const xmlChar *str;
179 TRACE("%p\n", This );
181 if (!name)
182 return E_INVALIDARG;
184 if ( !This->node )
185 return E_FAIL;
187 switch( This->node->type )
189 case XML_TEXT_NODE:
190 str = (const xmlChar*) "#text";
191 break;
192 case XML_DOCUMENT_NODE:
193 str = (const xmlChar*) "#document";
194 break;
195 default:
196 str = This->node->name;
197 break;
200 *name = bstr_from_xmlChar( str );
201 if (!*name)
202 return S_FALSE;
204 return S_OK;
207 BSTR bstr_from_xmlChar( const xmlChar *buf )
209 DWORD len;
210 LPWSTR str;
211 BSTR bstr;
213 if ( !buf )
214 return NULL;
216 len = MultiByteToWideChar( CP_UTF8, 0, (LPCSTR) buf, -1, NULL, 0 );
217 str = (LPWSTR) HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
218 if ( !str )
219 return NULL;
220 MultiByteToWideChar( CP_UTF8, 0, (LPCSTR) buf, -1, str, len );
221 bstr = SysAllocString( str );
222 HeapFree( GetProcessHeap(), 0, str );
223 return bstr;
226 static HRESULT WINAPI xmlnode_get_nodeValue(
227 IXMLDOMNode *iface,
228 VARIANT* value)
230 xmlnode *This = impl_from_IXMLDOMNode( iface );
231 HRESULT r = S_FALSE;
233 TRACE("%p %p\n", This, value);
235 V_BSTR(value) = NULL;
236 V_VT(value) = VT_NULL;
238 switch ( This->node->type )
240 case XML_ATTRIBUTE_NODE:
241 V_VT(value) = VT_BSTR;
242 V_BSTR(value) = bstr_from_xmlChar( This->node->name );
243 r = S_OK;
244 break;
245 case XML_TEXT_NODE:
246 V_VT(value) = VT_BSTR;
247 V_BSTR(value) = bstr_from_xmlChar( This->node->content );
248 r = S_OK;
249 break;
250 case XML_ELEMENT_NODE:
251 case XML_DOCUMENT_NODE:
252 /* these seem to return NULL */
253 break;
254 case XML_PI_NODE:
255 default:
256 FIXME("node %p type %d\n", This, This->node->type);
259 TRACE("%p returned %s\n", This, debugstr_w( V_BSTR(value) ) );
261 return r;
264 static HRESULT WINAPI xmlnode_put_nodeValue(
265 IXMLDOMNode *iface,
266 VARIANT value)
268 FIXME("\n");
269 return E_NOTIMPL;
272 static HRESULT WINAPI xmlnode_get_nodeType(
273 IXMLDOMNode *iface,
274 DOMNodeType* type)
276 xmlnode *This = impl_from_IXMLDOMNode( iface );
278 TRACE("%p %p\n", This, type);
280 assert( NODE_ELEMENT == XML_ELEMENT_NODE );
281 assert( NODE_NOTATION == XML_NOTATION_NODE );
283 *type = This->node->type;
285 return S_OK;
288 static HRESULT get_node(
289 xmlnode *This,
290 const char *name,
291 xmlNodePtr node,
292 IXMLDOMNode **out )
294 TRACE("%p->%s %p\n", This, name, node );
296 if ( !out )
297 return E_INVALIDARG;
298 *out = create_node( node );
299 if (!*out)
300 return S_FALSE;
301 return S_OK;
304 static HRESULT WINAPI xmlnode_get_parentNode(
305 IXMLDOMNode *iface,
306 IXMLDOMNode** parent)
308 xmlnode *This = impl_from_IXMLDOMNode( iface );
309 return get_node( This, "parent", This->node->parent, parent );
312 static HRESULT WINAPI xmlnode_get_childNodes(
313 IXMLDOMNode *iface,
314 IXMLDOMNodeList** childList)
316 xmlnode *This = impl_from_IXMLDOMNode( iface );
318 TRACE("%p %p\n", This, childList );
320 if ( !childList )
321 return E_INVALIDARG;
322 *childList = create_nodelist( This->node->children );
323 if (!*childList)
324 return S_FALSE;
325 return S_OK;
328 static HRESULT WINAPI xmlnode_get_firstChild(
329 IXMLDOMNode *iface,
330 IXMLDOMNode** firstChild)
332 xmlnode *This = impl_from_IXMLDOMNode( iface );
333 return get_node( This, "firstChild", This->node->children, firstChild );
336 static HRESULT WINAPI xmlnode_get_lastChild(
337 IXMLDOMNode *iface,
338 IXMLDOMNode** lastChild)
340 xmlnode *This = impl_from_IXMLDOMNode( iface );
341 return get_node( This, "lastChild", This->node->last, lastChild );
344 static HRESULT WINAPI xmlnode_get_previousSibling(
345 IXMLDOMNode *iface,
346 IXMLDOMNode** previousSibling)
348 xmlnode *This = impl_from_IXMLDOMNode( iface );
349 return get_node( This, "previous", This->node->prev, previousSibling );
352 static HRESULT WINAPI xmlnode_get_nextSibling(
353 IXMLDOMNode *iface,
354 IXMLDOMNode** nextSibling)
356 xmlnode *This = impl_from_IXMLDOMNode( iface );
357 return get_node( This, "next", This->node->next, nextSibling );
360 static HRESULT WINAPI xmlnode_get_attributes(
361 IXMLDOMNode *iface,
362 IXMLDOMNamedNodeMap** attributeMap)
364 xmlnode *This = impl_from_IXMLDOMNode( iface );
365 TRACE("%p\n", This);
366 *attributeMap = create_nodemap( iface );
367 return S_OK;
370 static HRESULT WINAPI xmlnode_insertBefore(
371 IXMLDOMNode *iface,
372 IXMLDOMNode* newChild,
373 VARIANT refChild,
374 IXMLDOMNode** outNewChild)
376 FIXME("\n");
377 return E_NOTIMPL;
380 static HRESULT WINAPI xmlnode_replaceChild(
381 IXMLDOMNode *iface,
382 IXMLDOMNode* newChild,
383 IXMLDOMNode* oldChild,
384 IXMLDOMNode** outOldChild)
386 FIXME("\n");
387 return E_NOTIMPL;
390 static HRESULT WINAPI xmlnode_removeChild(
391 IXMLDOMNode *iface,
392 IXMLDOMNode* childNode,
393 IXMLDOMNode** oldChild)
395 FIXME("\n");
396 return E_NOTIMPL;
399 static HRESULT WINAPI xmlnode_appendChild(
400 IXMLDOMNode *iface,
401 IXMLDOMNode* newChild,
402 IXMLDOMNode** outNewChild)
404 FIXME("\n");
405 return E_NOTIMPL;
408 static HRESULT WINAPI xmlnode_hasChildNodes(
409 IXMLDOMNode *iface,
410 VARIANT_BOOL* hasChild)
412 xmlnode *This = impl_from_IXMLDOMNode( iface );
414 TRACE("%p\n", This);
416 if (!hasChild)
417 return E_INVALIDARG;
418 if (!This->node->children)
420 *hasChild = VARIANT_FALSE;
421 return S_FALSE;
424 *hasChild = VARIANT_TRUE;
425 return S_OK;
428 static HRESULT WINAPI xmlnode_get_ownerDocument(
429 IXMLDOMNode *iface,
430 IXMLDOMDocument** DOMDocument)
432 FIXME("\n");
433 return E_NOTIMPL;
436 static HRESULT WINAPI xmlnode_cloneNode(
437 IXMLDOMNode *iface,
438 VARIANT_BOOL deep,
439 IXMLDOMNode** cloneRoot)
441 FIXME("\n");
442 return E_NOTIMPL;
445 static HRESULT WINAPI xmlnode_get_nodeTypeString(
446 IXMLDOMNode *iface,
447 BSTR* xmlnodeType)
449 FIXME("\n");
450 return E_NOTIMPL;
453 static HRESULT WINAPI xmlnode_get_text(
454 IXMLDOMNode *iface,
455 BSTR* text)
457 xmlnode *This = impl_from_IXMLDOMNode( iface );
458 xmlNodePtr child;
459 BSTR str = NULL;
461 TRACE("%p\n", This);
463 if ( !text )
464 return E_INVALIDARG;
466 child = This->node->children;
467 if ( child && child->type == XML_TEXT_NODE )
468 str = bstr_from_xmlChar( child->content );
470 TRACE("%p %s\n", This, debugstr_w(str) );
471 *text = str;
473 return S_OK;
476 static HRESULT WINAPI xmlnode_put_text(
477 IXMLDOMNode *iface,
478 BSTR text)
480 FIXME("\n");
481 return E_NOTIMPL;
484 static HRESULT WINAPI xmlnode_get_specified(
485 IXMLDOMNode *iface,
486 VARIANT_BOOL* isSpecified)
488 FIXME("\n");
489 return E_NOTIMPL;
492 static HRESULT WINAPI xmlnode_get_definition(
493 IXMLDOMNode *iface,
494 IXMLDOMNode** definitionNode)
496 FIXME("\n");
497 return E_NOTIMPL;
500 static HRESULT WINAPI xmlnode_get_nodeTypedValue(
501 IXMLDOMNode *iface,
502 VARIANT* typedValue)
504 FIXME("\n");
505 return E_NOTIMPL;
508 static HRESULT WINAPI xmlnode_put_nodeTypedValue(
509 IXMLDOMNode *iface,
510 VARIANT typedValue)
512 FIXME("\n");
513 return E_NOTIMPL;
516 static HRESULT WINAPI xmlnode_get_dataType(
517 IXMLDOMNode *iface,
518 VARIANT* dataTypeName)
520 FIXME("\n");
521 return E_NOTIMPL;
524 static HRESULT WINAPI xmlnode_put_dataType(
525 IXMLDOMNode *iface,
526 BSTR dataTypeName)
528 FIXME("\n");
529 return E_NOTIMPL;
532 static HRESULT WINAPI xmlnode_get_xml(
533 IXMLDOMNode *iface,
534 BSTR* xmlString)
536 FIXME("\n");
537 return E_NOTIMPL;
540 static HRESULT WINAPI xmlnode_transformNode(
541 IXMLDOMNode *iface,
542 IXMLDOMNode* styleSheet,
543 BSTR* xmlString)
545 FIXME("\n");
546 return E_NOTIMPL;
549 static HRESULT WINAPI xmlnode_selectNodes(
550 IXMLDOMNode *iface,
551 BSTR queryString,
552 IXMLDOMNodeList** resultList)
554 xmlnode *This = impl_from_IXMLDOMNode( iface );
555 xmlChar *str = NULL;
556 HRESULT r = E_FAIL;
558 TRACE("%p %s %p\n", This, debugstr_w(queryString), resultList );
560 str = xmlChar_from_wchar( queryString );
561 if (!str)
562 return r;
564 *resultList = create_filtered_nodelist( This->node->children, str );
565 HeapFree( GetProcessHeap(), 0, str );
566 return S_OK;
569 static HRESULT WINAPI xmlnode_selectSingleNode(
570 IXMLDOMNode *iface,
571 BSTR queryString,
572 IXMLDOMNode** resultNode)
574 FIXME("\n");
575 return E_NOTIMPL;
578 static HRESULT WINAPI xmlnode_get_parsed(
579 IXMLDOMNode *iface,
580 VARIANT_BOOL* isParsed)
582 FIXME("\n");
583 return E_NOTIMPL;
586 static HRESULT WINAPI xmlnode_get_namespaceURI(
587 IXMLDOMNode *iface,
588 BSTR* namespaceURI)
590 FIXME("\n");
591 return E_NOTIMPL;
594 static HRESULT WINAPI xmlnode_get_prefix(
595 IXMLDOMNode *iface,
596 BSTR* prefixString)
598 FIXME("\n");
599 return E_NOTIMPL;
602 static HRESULT WINAPI xmlnode_get_baseName(
603 IXMLDOMNode *iface,
604 BSTR* nameString)
606 xmlnode *This = impl_from_IXMLDOMNode( iface );
607 BSTR str = NULL;
608 HRESULT r = S_FALSE;
610 TRACE("%p %p\n", This, nameString );
612 if ( !nameString )
613 return E_INVALIDARG;
615 switch ( This->node->type )
617 case XML_ELEMENT_NODE:
618 case XML_ATTRIBUTE_NODE:
619 str = bstr_from_xmlChar( This->node->name );
620 r = S_OK;
621 break;
622 case XML_TEXT_NODE:
623 break;
624 default:
625 ERR("Unhandled type %d\n", This->node->type );
626 break;
629 TRACE("returning %08lx str = %s\n", r, debugstr_w( str ) );
631 *nameString = str;
632 return r;
635 static HRESULT WINAPI xmlnode_transformNodeToObject(
636 IXMLDOMNode *iface,
637 IXMLDOMNode* stylesheet,
638 VARIANT outputObject)
640 FIXME("\n");
641 return E_NOTIMPL;
644 static const struct IXMLDOMNodeVtbl xmlnode_vtbl =
646 xmlnode_QueryInterface,
647 xmlnode_AddRef,
648 xmlnode_Release,
649 xmlnode_GetTypeInfoCount,
650 xmlnode_GetTypeInfo,
651 xmlnode_GetIDsOfNames,
652 xmlnode_Invoke,
653 xmlnode_get_nodeName,
654 xmlnode_get_nodeValue,
655 xmlnode_put_nodeValue,
656 xmlnode_get_nodeType,
657 xmlnode_get_parentNode,
658 xmlnode_get_childNodes,
659 xmlnode_get_firstChild,
660 xmlnode_get_lastChild,
661 xmlnode_get_previousSibling,
662 xmlnode_get_nextSibling,
663 xmlnode_get_attributes,
664 xmlnode_insertBefore,
665 xmlnode_replaceChild,
666 xmlnode_removeChild,
667 xmlnode_appendChild,
668 xmlnode_hasChildNodes,
669 xmlnode_get_ownerDocument,
670 xmlnode_cloneNode,
671 xmlnode_get_nodeTypeString,
672 xmlnode_get_text,
673 xmlnode_put_text,
674 xmlnode_get_specified,
675 xmlnode_get_definition,
676 xmlnode_get_nodeTypedValue,
677 xmlnode_put_nodeTypedValue,
678 xmlnode_get_dataType,
679 xmlnode_put_dataType,
680 xmlnode_get_xml,
681 xmlnode_transformNode,
682 xmlnode_selectNodes,
683 xmlnode_selectSingleNode,
684 xmlnode_get_parsed,
685 xmlnode_get_namespaceURI,
686 xmlnode_get_prefix,
687 xmlnode_get_baseName,
688 xmlnode_transformNodeToObject,
691 IXMLDOMNode *create_node( xmlNodePtr node )
693 xmlnode *This;
695 if ( !node )
696 return NULL;
698 assert( node->doc );
700 /* if an interface already exists for this node, return it */
701 if ( node->_private )
703 IXMLDOMNode *n = node->_private;
704 IXMLDOMNode_AddRef( n );
705 return n;
709 * Try adding a reference to the IXMLDOMNode implementation
710 * containing the document's root element.
712 if ( node->type != XML_DOCUMENT_NODE )
714 IXMLDOMNode *root = NULL;
716 root = node->doc->_private;
717 assert( root );
718 IXMLDOMNode_AddRef( root );
720 else
721 assert( node->doc == (xmlDocPtr) node );
723 This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
724 if ( !This )
725 return NULL;
727 This->lpVtbl = &xmlnode_vtbl;
728 This->ref = 1;
729 This->node = node;
731 /* remember which interface we associated with this node */
732 node->_private = This;
734 return (IXMLDOMNode*) &This->lpVtbl;
737 #endif