wined3d: Rename CreateAdditionalSwapChain to CreateSwapChain.
[wine] / dlls / msxml3 / node.c
1 /*
2  *    Node implementation
3  *
4  * Copyright 2005 Mike McCormack
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 #include "config.h"
22
23 #define COBJMACROS
24
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 "msxml2.h"
33
34 #include "msxml_private.h"
35
36 #ifdef HAVE_LIBXSLT
37 # ifdef HAVE_LIBXSLT_PATTERN_H
38 #  include <libxslt/pattern.h>
39 # endif
40 # ifdef HAVE_LIBXSLT_TRANSFORM_H
41 #  include <libxslt/transform.h>
42 # endif
43 # include <libxslt/xsltutils.h>
44 # include <libxslt/xsltInternals.h>
45 #endif
46
47 #ifdef HAVE_LIBXML2
48 # include <libxml/HTMLtree.h>
49 #endif
50
51 #include "wine/debug.h"
52
53 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
54
55 #ifdef HAVE_LIBXML2
56
57 static const WCHAR szBinBase64[]  = {'b','i','n','.','b','a','s','e','6','4',0};
58 static const WCHAR szString[]     = {'s','t','r','i','n','g',0};
59 static const WCHAR szNumber[]     = {'n','u','m','b','e','r',0};
60 static const WCHAR szInt[]        = {'I','n','t',0};
61 static const WCHAR szFixed[]      = {'F','i','x','e','d','.','1','4','.','4',0};
62 static const WCHAR szBoolean[]    = {'B','o','o','l','e','a','n',0};
63 static const WCHAR szDateTime[]   = {'d','a','t','e','T','i','m','e',0};
64 static const WCHAR szDateTimeTZ[] = {'d','a','t','e','T','i','m','e','.','t','z',0};
65 static const WCHAR szDate[]       = {'D','a','t','e',0};
66 static const WCHAR szTime[]       = {'T','i','m','e',0};
67 static const WCHAR szTimeTZ[]     = {'T','i','m','e','.','t','z',0};
68 static const WCHAR szI1[]         = {'i','1',0};
69 static const WCHAR szI2[]         = {'i','2',0};
70 static const WCHAR szI4[]         = {'i','4',0};
71 static const WCHAR szIU1[]        = {'u','i','1',0};
72 static const WCHAR szIU2[]        = {'u','i','2',0};
73 static const WCHAR szIU4[]        = {'u','i','4',0};
74 static const WCHAR szR4[]         = {'r','4',0};
75 static const WCHAR szR8[]         = {'r','8',0};
76 static const WCHAR szFloat[]      = {'f','l','o','a','t',0};
77 static const WCHAR szUUID[]       = {'u','u','i','d',0};
78 static const WCHAR szBinHex[]     = {'b','i','n','.','h','e','x',0};
79
80 static inline xmlnode *impl_from_InternalUnknown( IUnknown *iface )
81 {
82     return (xmlnode *)((char*)iface - FIELD_OFFSET(xmlnode, lpInternalUnkVtbl));
83 }
84
85 xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type )
86 {
87     xmlnode *This;
88
89     if ( !iface )
90         return NULL;
91     This = impl_from_IXMLDOMNode( iface );
92     if ( !This->node )
93         return NULL;
94     if ( type && This->node->type != type )
95         return NULL;
96     return This->node;
97 }
98
99 void attach_xmlnode( IXMLDOMNode *node, xmlNodePtr xml )
100 {
101     xmlnode *This = impl_from_IXMLDOMNode( node );
102
103     if(This->node)
104         xmldoc_release(This->node->doc);
105
106     This->node = xml;
107     if(This->node)
108         xmldoc_add_ref(This->node->doc);
109
110     return;
111 }
112
113 static HRESULT WINAPI xmlnode_QueryInterface(
114     IXMLDOMNode *iface,
115     REFIID riid,
116     void** ppvObject )
117 {
118     xmlnode *This = impl_from_IXMLDOMNode( iface );
119     TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
120
121     return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObject);
122 }
123
124 static ULONG WINAPI xmlnode_AddRef(
125     IXMLDOMNode *iface )
126 {
127     xmlnode *This = impl_from_IXMLDOMNode( iface );
128     return IUnknown_AddRef(This->pUnkOuter);
129 }
130
131 static ULONG WINAPI xmlnode_Release(
132     IXMLDOMNode *iface )
133 {
134     xmlnode *This = impl_from_IXMLDOMNode( iface );
135     return IUnknown_Release(This->pUnkOuter);
136 }
137
138 static HRESULT WINAPI xmlnode_GetTypeInfoCount(
139     IXMLDOMNode *iface,
140     UINT* pctinfo )
141 {
142     xmlnode *This = impl_from_IXMLDOMNode( iface );
143
144     TRACE("(%p)->(%p)\n", This, pctinfo);
145
146     *pctinfo = 1;
147
148     return S_OK;
149 }
150
151 static HRESULT WINAPI xmlnode_GetTypeInfo(
152     IXMLDOMNode *iface,
153     UINT iTInfo,
154     LCID lcid,
155     ITypeInfo** ppTInfo )
156 {
157     xmlnode *This = impl_from_IXMLDOMNode( iface );
158     HRESULT hr;
159
160     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
161
162     hr = get_typeinfo(IXMLDOMNode_tid, ppTInfo);
163
164     return hr;
165 }
166
167 static HRESULT WINAPI xmlnode_GetIDsOfNames(
168     IXMLDOMNode *iface,
169     REFIID riid,
170     LPOLESTR* rgszNames,
171     UINT cNames,
172     LCID lcid,
173     DISPID* rgDispId )
174 {
175     xmlnode *This = impl_from_IXMLDOMNode( iface );
176
177     ITypeInfo *typeinfo;
178     HRESULT hr;
179
180     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
181           lcid, rgDispId);
182
183     if(!rgszNames || cNames == 0 || !rgDispId)
184         return E_INVALIDARG;
185
186     hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
187     if(SUCCEEDED(hr))
188     {
189         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
190         ITypeInfo_Release(typeinfo);
191     }
192
193     return hr;
194 }
195
196 static HRESULT WINAPI xmlnode_Invoke(
197     IXMLDOMNode *iface,
198     DISPID dispIdMember,
199     REFIID riid,
200     LCID lcid,
201     WORD wFlags,
202     DISPPARAMS* pDispParams,
203     VARIANT* pVarResult,
204     EXCEPINFO* pExcepInfo,
205     UINT* puArgErr )
206 {
207     xmlnode *This = impl_from_IXMLDOMNode( iface );
208     ITypeInfo *typeinfo;
209     HRESULT hr;
210
211     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
212           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
213
214     hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
215     if(SUCCEEDED(hr))
216     {
217         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
218                 pVarResult, pExcepInfo, puArgErr);
219         ITypeInfo_Release(typeinfo);
220     }
221
222     return hr;
223 }
224
225 static HRESULT WINAPI xmlnode_get_nodeName(
226     IXMLDOMNode *iface,
227     BSTR* name)
228 {
229     xmlnode *This = impl_from_IXMLDOMNode( iface );
230     const xmlChar *str;
231
232     TRACE("%p\n", This );
233
234     if (!name)
235         return E_INVALIDARG;
236
237     if ( !This->node )
238         return E_FAIL;
239
240     switch( This->node->type )
241     {
242     case XML_CDATA_SECTION_NODE:
243         str = (const xmlChar*) "#cdata-section";
244         break;
245     case XML_COMMENT_NODE:
246         str = (const xmlChar*) "#comment";
247         break;
248     case XML_DOCUMENT_FRAG_NODE:
249         str = (const xmlChar*) "#document-fragment";
250         break;
251     case XML_TEXT_NODE:
252          str = (const xmlChar*) "#text";
253          break;
254     case XML_DOCUMENT_NODE:
255          str = (const xmlChar*) "#document";
256             break;
257         case XML_ATTRIBUTE_NODE:
258         case XML_ELEMENT_NODE:
259         case XML_PI_NODE:
260         str = This->node->name;
261             break;
262     default:
263         FIXME("nodeName not mapped correctly (%d)\n", This->node->type);
264         str = This->node->name;
265         break;
266     }
267
268     *name = bstr_from_xmlChar( str );
269     if (!*name)
270         return S_FALSE;
271
272     return S_OK;
273 }
274
275 BSTR bstr_from_xmlChar( const xmlChar *buf )
276 {
277     DWORD len;
278     LPWSTR str;
279     BSTR bstr;
280
281     if ( !buf )
282         return NULL;
283
284     len = MultiByteToWideChar( CP_UTF8, 0, (LPCSTR) buf, -1, NULL, 0 );
285     str = (LPWSTR) HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
286     if ( !str )
287         return NULL;
288     MultiByteToWideChar( CP_UTF8, 0, (LPCSTR) buf, -1, str, len );
289     bstr = SysAllocString( str );
290     HeapFree( GetProcessHeap(), 0, str );
291     return bstr;
292 }
293
294 static HRESULT WINAPI xmlnode_get_nodeValue(
295     IXMLDOMNode *iface,
296     VARIANT* value)
297 {
298     xmlnode *This = impl_from_IXMLDOMNode( iface );
299     HRESULT r = S_FALSE;
300
301     TRACE("%p %p\n", This, value);
302
303     if(!value)
304         return E_INVALIDARG;
305
306     V_BSTR(value) = NULL;
307     V_VT(value) = VT_NULL;
308
309     switch ( This->node->type )
310     {
311     case XML_CDATA_SECTION_NODE:
312     case XML_COMMENT_NODE:
313     case XML_PI_NODE:
314     case XML_ATTRIBUTE_NODE:
315       {
316         xmlChar *content = xmlNodeGetContent(This->node);
317         V_VT(value) = VT_BSTR;
318         V_BSTR(value) = bstr_from_xmlChar( content );
319         xmlFree(content);
320         r = S_OK;
321         break;
322       }
323     case XML_TEXT_NODE:
324         V_VT(value) = VT_BSTR;
325         V_BSTR(value) = bstr_from_xmlChar( This->node->content );
326         r = S_OK;
327         break;
328     case XML_ELEMENT_NODE:
329     case XML_DOCUMENT_NODE:
330         /* these seem to return NULL */
331         break;
332
333     default:
334         FIXME("node %p type %d\n", This, This->node->type);
335     }
336  
337     TRACE("%p returned %s\n", This, debugstr_w( V_BSTR(value) ) );
338
339     return r;
340 }
341
342 static HRESULT WINAPI xmlnode_put_nodeValue(
343     IXMLDOMNode *iface,
344     VARIANT value)
345 {
346     xmlnode *This = impl_from_IXMLDOMNode( iface );
347     HRESULT hr;
348     xmlChar *str = NULL;
349     VARIANT string_value;
350
351     TRACE("%p type(%d)\n", This, This->node->type);
352
353     VariantInit(&string_value);
354     hr = VariantChangeType(&string_value, &value, 0, VT_BSTR);
355     if(FAILED(hr))
356     {
357         VariantClear(&string_value);
358         WARN("Couldn't convert to VT_BSTR\n");
359         return hr;
360     }
361
362     hr = S_FALSE;
363     /* Document, Document Fragment, Document Type, Element,
364         Entity, Entity Reference, Notation aren't supported. */
365     switch ( This->node->type )
366     {
367     case XML_ATTRIBUTE_NODE:
368     case XML_CDATA_SECTION_NODE:
369     case XML_COMMENT_NODE:
370     case XML_PI_NODE:
371     case XML_TEXT_NODE:
372       {
373         str = xmlChar_from_wchar((WCHAR*)V_BSTR(&string_value));
374         xmlNodeSetContent(This->node, str);
375         HeapFree(GetProcessHeap(),0,str);
376         hr = S_OK;
377         break;
378       }
379     default:
380         /* Do nothing for unsupported types. */
381         break;
382     }
383
384     VariantClear(&string_value);
385
386     return hr;
387 }
388
389 static HRESULT WINAPI xmlnode_get_nodeType(
390     IXMLDOMNode *iface,
391     DOMNodeType* type)
392 {
393     xmlnode *This = impl_from_IXMLDOMNode( iface );
394
395     TRACE("%p %p\n", This, type);
396
397     assert( NODE_ELEMENT == XML_ELEMENT_NODE );
398     assert( NODE_NOTATION == XML_NOTATION_NODE );
399
400     *type = This->node->type;
401
402     return S_OK;
403 }
404
405 static HRESULT get_node(
406     xmlnode *This,
407     const char *name,
408     xmlNodePtr node,
409     IXMLDOMNode **out )
410 {
411     TRACE("%p->%s %p\n", This, name, node );
412
413     if ( !out )
414         return E_INVALIDARG;
415     *out = create_node( node );
416     if (!*out)
417         return S_FALSE;
418     return S_OK;
419 }
420
421 static HRESULT WINAPI xmlnode_get_parentNode(
422     IXMLDOMNode *iface,
423     IXMLDOMNode** parent)
424 {
425     xmlnode *This = impl_from_IXMLDOMNode( iface );
426     return get_node( This, "parent", This->node->parent, parent );
427 }
428
429 static HRESULT WINAPI xmlnode_get_childNodes(
430     IXMLDOMNode *iface,
431     IXMLDOMNodeList** childList)
432 {
433     xmlnode *This = impl_from_IXMLDOMNode( iface );
434
435     TRACE("%p %p\n", This, childList );
436
437     if ( !childList )
438         return E_INVALIDARG;
439
440     *childList = create_children_nodelist(This->node);
441     if (*childList == NULL)
442         return E_OUTOFMEMORY;
443
444     return S_OK;
445 }
446
447 static HRESULT WINAPI xmlnode_get_firstChild(
448     IXMLDOMNode *iface,
449     IXMLDOMNode** firstChild)
450 {
451     xmlnode *This = impl_from_IXMLDOMNode( iface );
452     return get_node( This, "firstChild", This->node->children, firstChild );
453 }
454
455 static HRESULT WINAPI xmlnode_get_lastChild(
456     IXMLDOMNode *iface,
457     IXMLDOMNode** lastChild)
458 {
459     xmlnode *This = impl_from_IXMLDOMNode( iface );
460
461     TRACE("%p\n", This );
462
463     if (!lastChild)
464         return E_INVALIDARG;
465
466     switch( This->node->type )
467     {
468     /* CDATASection, Comment, PI and Text Nodes do not support lastChild */
469     case XML_TEXT_NODE:
470     case XML_CDATA_SECTION_NODE:
471     case XML_PI_NODE:
472     case XML_COMMENT_NODE:
473         *lastChild = NULL;
474         return S_FALSE;
475     default:
476         return get_node( This, "lastChild", This->node->last, lastChild );
477     }
478 }
479
480 static HRESULT WINAPI xmlnode_get_previousSibling(
481     IXMLDOMNode *iface,
482     IXMLDOMNode** previousSibling)
483 {
484     xmlnode *This = impl_from_IXMLDOMNode( iface );
485
486     TRACE("%p\n", This );
487
488     if (!previousSibling)
489         return E_INVALIDARG;
490
491     switch( This->node->type )
492     {
493     /* Attribute, Document and Document Fragment Nodes do not support previousSibling */
494     case XML_DOCUMENT_NODE:
495     case XML_DOCUMENT_FRAG_NODE:
496     case XML_ATTRIBUTE_NODE:
497         *previousSibling = NULL;
498         return S_FALSE;
499     default:
500         return get_node( This, "previous", This->node->prev, previousSibling );
501     }
502 }
503
504 static HRESULT WINAPI xmlnode_get_nextSibling(
505     IXMLDOMNode *iface,
506     IXMLDOMNode** nextSibling)
507 {
508     xmlnode *This = impl_from_IXMLDOMNode( iface );
509
510     TRACE("%p\n", This );
511
512     if (!nextSibling)
513         return E_INVALIDARG;
514
515     switch( This->node->type )
516     {
517     /* Attribute, Document and Document Fragment Nodes do not support nextSibling */
518     case XML_DOCUMENT_NODE:
519     case XML_DOCUMENT_FRAG_NODE:
520     case XML_ATTRIBUTE_NODE:
521         *nextSibling = NULL;
522         return S_FALSE;
523     default:
524         return get_node( This, "next", This->node->next, nextSibling );
525     }
526 }
527
528 static HRESULT WINAPI xmlnode_get_attributes(
529     IXMLDOMNode *iface,
530     IXMLDOMNamedNodeMap** attributeMap)
531 {
532     xmlnode *This = impl_from_IXMLDOMNode( iface );
533     TRACE("%p\n", This);
534
535     if (!attributeMap)
536         return E_INVALIDARG;
537
538     switch( This->node->type )
539     {
540     /* Attribute, CDataSection, Comment, Documents, Documents Fragments,
541        Entity and Text Nodes does not support get_attributes */
542     case XML_ATTRIBUTE_NODE:
543     case XML_CDATA_SECTION_NODE:
544     case XML_COMMENT_NODE:
545     case XML_DOCUMENT_NODE:
546     case XML_DOCUMENT_FRAG_NODE:
547     case XML_ENTITY_NODE:
548     case XML_ENTITY_REF_NODE:
549     case XML_TEXT_NODE:
550         *attributeMap = NULL;
551         return S_FALSE;
552     default:
553         *attributeMap = create_nodemap( iface );
554         return S_OK;
555     }
556 }
557
558 static HRESULT WINAPI xmlnode_insertBefore(
559     IXMLDOMNode *iface,
560     IXMLDOMNode* newChild,
561     VARIANT refChild,
562     IXMLDOMNode** outNewChild)
563 {
564     xmlnode *This = impl_from_IXMLDOMNode( iface );
565     xmlNodePtr before_node, new_child_node;
566     IXMLDOMNode *before = NULL, *new;
567     HRESULT hr;
568
569     TRACE("(%p)->(%p,var,%p)\n",This,newChild,outNewChild);
570
571     if (!newChild)
572         return E_INVALIDARG;
573
574     switch(V_VT(&refChild))
575     {
576     case VT_EMPTY:
577     case VT_NULL:
578         break;
579
580     case VT_UNKNOWN:
581         hr = IUnknown_QueryInterface(V_UNKNOWN(&refChild), &IID_IXMLDOMNode, (LPVOID)&before);
582         if(FAILED(hr)) return hr;
583         break;
584
585     case VT_DISPATCH:
586         hr = IDispatch_QueryInterface(V_DISPATCH(&refChild), &IID_IXMLDOMNode, (LPVOID)&before);
587         if(FAILED(hr)) return hr;
588         break;
589
590     default:
591         FIXME("refChild var type %x\n", V_VT(&refChild));
592         return E_FAIL;
593     }
594
595     IXMLDOMNode_QueryInterface(newChild, &IID_IXMLDOMNode, (LPVOID)&new);
596     new_child_node = impl_from_IXMLDOMNode(new)->node;
597     TRACE("new_child_node %p This->node %p\n", new_child_node, This->node);
598
599     if(!new_child_node->parent)
600         if(xmldoc_remove_orphan(new_child_node->doc, new_child_node) != S_OK)
601             WARN("%p is not an orphan of %p\n", new_child_node, new_child_node->doc);
602
603     if(before)
604     {
605         before_node = impl_from_IXMLDOMNode(before)->node;
606         xmlAddPrevSibling(before_node, new_child_node);
607         IXMLDOMNode_Release(before);
608     }
609     else
610     {
611         xmlAddChild(This->node, new_child_node);
612     }
613
614     IXMLDOMNode_Release(new);
615     IXMLDOMNode_AddRef(newChild);
616     if(outNewChild)
617         *outNewChild = newChild;
618
619     TRACE("ret S_OK\n");
620     return S_OK;
621 }
622
623 static HRESULT WINAPI xmlnode_replaceChild(
624     IXMLDOMNode *iface,
625     IXMLDOMNode* newChild,
626     IXMLDOMNode* oldChild,
627     IXMLDOMNode** outOldChild)
628 {
629     xmlnode *This = impl_from_IXMLDOMNode( iface );
630     xmlNode *old_child_ptr, *new_child_ptr;
631     xmlDocPtr leaving_doc;
632     xmlNode *my_ancestor;
633     IXMLDOMNode *realOldChild;
634     HRESULT hr;
635
636     TRACE("%p->(%p,%p,%p)\n",This,newChild,oldChild,outOldChild);
637
638     /* Do not believe any documentation telling that newChild == NULL
639        means removal. It does certainly *not* apply to msxml3! */
640     if(!newChild || !oldChild)
641         return E_INVALIDARG;
642
643     if(outOldChild)
644         *outOldChild = NULL;
645
646     hr = IXMLDOMNode_QueryInterface(oldChild,&IID_IXMLDOMNode,(LPVOID*)&realOldChild);
647     if(FAILED(hr))
648         return hr;
649
650     old_child_ptr = impl_from_IXMLDOMNode(realOldChild)->node;
651     IXMLDOMNode_Release(realOldChild);
652     if(old_child_ptr->parent != This->node)
653     {
654         WARN("childNode %p is not a child of %p\n", oldChild, iface);
655         return E_INVALIDARG;
656     }
657
658     new_child_ptr = impl_from_IXMLDOMNode(newChild)->node;
659     my_ancestor = This->node;
660     while(my_ancestor)
661     {
662         if(my_ancestor == new_child_ptr)
663         {
664             WARN("tried to create loop\n");
665             return E_FAIL;
666         }
667         my_ancestor = my_ancestor->parent;
668     }
669
670     if(!new_child_ptr->parent)
671         if(xmldoc_remove_orphan(new_child_ptr->doc, new_child_ptr) != S_OK)
672             WARN("%p is not an orphan of %p\n", new_child_ptr, new_child_ptr->doc);
673
674     leaving_doc = new_child_ptr->doc;
675     xmldoc_add_ref(old_child_ptr->doc);
676     xmlReplaceNode(old_child_ptr, new_child_ptr);
677     xmldoc_release(leaving_doc);
678
679     xmldoc_add_orphan(old_child_ptr->doc, old_child_ptr);
680
681     if(outOldChild)
682     {
683         IXMLDOMNode_AddRef(oldChild);
684         *outOldChild = oldChild;
685     }
686
687     return S_OK;
688 }
689
690 static HRESULT WINAPI xmlnode_removeChild(
691     IXMLDOMNode *iface,
692     IXMLDOMNode* childNode,
693     IXMLDOMNode** oldChild)
694 {
695     xmlnode *This = impl_from_IXMLDOMNode( iface );
696     xmlNode *child_node_ptr;
697     HRESULT hr;
698     IXMLDOMNode *child;
699
700     TRACE("%p->(%p, %p)\n", This, childNode, oldChild);
701
702     if(!childNode) return E_INVALIDARG;
703
704     if(oldChild)
705         *oldChild = NULL;
706
707     hr = IXMLDOMNode_QueryInterface(childNode, &IID_IXMLDOMNode, (LPVOID)&child);
708     if(FAILED(hr))
709         return hr;
710
711     child_node_ptr = impl_from_IXMLDOMNode(child)->node;
712     if(child_node_ptr->parent != This->node)
713     {
714         WARN("childNode %p is not a child of %p\n", childNode, iface);
715         IXMLDOMNode_Release(child);
716         return E_INVALIDARG;
717     }
718
719     xmlUnlinkNode(child_node_ptr);
720
721     IXMLDOMNode_Release(child);
722
723     if(oldChild)
724     {
725         IXMLDOMNode_AddRef(childNode);
726         *oldChild = childNode;
727     }
728
729     return S_OK;
730 }
731
732 static HRESULT WINAPI xmlnode_appendChild(
733     IXMLDOMNode *iface,
734     IXMLDOMNode* newChild,
735     IXMLDOMNode** outNewChild)
736 {
737     xmlnode *This = impl_from_IXMLDOMNode( iface );
738     DOMNodeType type;
739     VARIANT var;
740     HRESULT hr;
741
742     TRACE("(%p)->(%p,%p)\n", This, newChild, outNewChild);
743
744     hr = IXMLDOMNode_get_nodeType(newChild, &type);
745     if(FAILED(hr) || type == NODE_ATTRIBUTE) {
746         if(outNewChild) *outNewChild = NULL;
747         return E_FAIL;
748     }
749
750     VariantInit(&var);
751     return IXMLDOMNode_insertBefore(iface, newChild, var, outNewChild);
752 }
753
754 static HRESULT WINAPI xmlnode_hasChildNodes(
755     IXMLDOMNode *iface,
756     VARIANT_BOOL* hasChild)
757 {
758     xmlnode *This = impl_from_IXMLDOMNode( iface );
759
760     TRACE("%p\n", This);
761
762     if (!hasChild)
763         return E_INVALIDARG;
764     if (!This->node->children)
765     {
766         *hasChild = VARIANT_FALSE;
767         return S_FALSE;
768     }
769
770     *hasChild = VARIANT_TRUE;
771     return S_OK;
772 }
773
774 static HRESULT WINAPI xmlnode_get_ownerDocument(
775     IXMLDOMNode *iface,
776     IXMLDOMDocument** DOMDocument)
777 {
778     xmlnode *This = impl_from_IXMLDOMNode( iface );
779
780     TRACE("%p (%p)\n", This, DOMDocument);
781
782     return DOMDocument_create_from_xmldoc(This->node->doc, (IXMLDOMDocument2**)DOMDocument);
783 }
784
785 static HRESULT WINAPI xmlnode_cloneNode(
786     IXMLDOMNode *iface,
787     VARIANT_BOOL deep,
788     IXMLDOMNode** cloneRoot)
789 {
790     xmlnode *This = impl_from_IXMLDOMNode( iface );
791     xmlNodePtr pClone = NULL;
792     IXMLDOMNode *pNode = NULL;
793
794     TRACE("%p (%d)\n", This, deep);
795
796     if(!cloneRoot)
797         return E_INVALIDARG;
798
799     pClone = xmlCopyNode(This->node, deep ? 1 : 2);
800     if(pClone)
801     {
802         pClone->doc = This->node->doc;
803         xmldoc_add_orphan(pClone->doc, pClone);
804
805         pNode = create_node(pClone);
806         if(!pNode)
807         {
808             ERR("Copy failed\n");
809             return E_FAIL;
810         }
811
812         *cloneRoot = pNode;
813     }
814     else
815     {
816         ERR("Copy failed\n");
817         return E_FAIL;
818     }
819
820     return S_OK;
821 }
822
823 static HRESULT WINAPI xmlnode_get_nodeTypeString(
824     IXMLDOMNode *iface,
825     BSTR* xmlnodeType)
826 {
827     xmlnode *This = impl_from_IXMLDOMNode( iface );
828     const xmlChar *str;
829
830     TRACE("%p\n", This );
831
832     if (!xmlnodeType)
833         return E_INVALIDARG;
834
835     if ( !This->node )
836         return E_FAIL;
837
838     switch( This->node->type )
839     {
840     case XML_ATTRIBUTE_NODE:
841         str = (const xmlChar*) "attribute";
842         break;
843     case XML_CDATA_SECTION_NODE:
844         str = (const xmlChar*) "cdatasection";
845         break;
846     case XML_COMMENT_NODE:
847         str = (const xmlChar*) "comment";
848         break;
849     case XML_DOCUMENT_NODE:
850         str = (const xmlChar*) "document";
851         break;
852     case XML_DOCUMENT_FRAG_NODE:
853         str = (const xmlChar*) "documentfragment";
854         break;
855     case XML_ELEMENT_NODE:
856         str = (const xmlChar*) "element";
857         break;
858     case XML_ENTITY_NODE:
859         str = (const xmlChar*) "entity";
860         break;
861     case XML_ENTITY_REF_NODE:
862         str = (const xmlChar*) "entityreference";
863         break;
864     case XML_NOTATION_NODE:
865         str = (const xmlChar*) "notation";
866         break;
867     case XML_PI_NODE:
868         str = (const xmlChar*) "processinginstruction";
869         break;
870     case XML_TEXT_NODE:
871         str = (const xmlChar*) "text";
872         break;
873     default:
874         FIXME("Unknown node type (%d)\n", This->node->type);
875         str = This->node->name;
876         break;
877     }
878
879     *xmlnodeType = bstr_from_xmlChar( str );
880     if (!*xmlnodeType)
881         return S_FALSE;
882
883     return S_OK;
884 }
885
886 static HRESULT WINAPI xmlnode_get_text(
887     IXMLDOMNode *iface,
888     BSTR* text)
889 {
890     xmlnode *This = impl_from_IXMLDOMNode( iface );
891     BSTR str = NULL;
892
893     TRACE("%p\n", This);
894
895     if ( !text )
896         return E_INVALIDARG;
897
898     switch(This->node->type)
899     {
900     case XML_ELEMENT_NODE:
901     case XML_ATTRIBUTE_NODE:
902     {
903         xmlNodePtr child = This->node->children;
904         if ( child && child->type == XML_TEXT_NODE )
905             str = bstr_from_xmlChar( child->content );
906         break;
907     }
908
909     case XML_TEXT_NODE:
910     case XML_CDATA_SECTION_NODE:
911     case XML_PI_NODE:
912     case XML_COMMENT_NODE:
913         str = bstr_from_xmlChar( This->node->content );
914         break;
915
916     default:
917         FIXME("Unhandled node type %d\n", This->node->type);
918     }
919
920     /* Always return a string. */
921     if (!str) str = SysAllocStringLen( NULL, 0 );
922
923     TRACE("%p %s\n", This, debugstr_w(str) );
924     *text = str;
925  
926     return S_OK;
927 }
928
929 static HRESULT WINAPI xmlnode_put_text(
930     IXMLDOMNode *iface,
931     BSTR text)
932 {
933     xmlnode *This = impl_from_IXMLDOMNode( iface );
934     xmlChar *str, *str2, *str3;
935
936     TRACE("%p\n", This);
937
938     switch(This->node->type)
939     {
940     case XML_DOCUMENT_NODE:
941         return E_FAIL;
942     default:
943         break;
944     }
945
946     str = xmlChar_from_wchar((WCHAR*)text);
947
948     /* Escape the string. */
949     str2 = xmlEncodeEntitiesReentrant(This->node->doc, str);
950     HeapFree(GetProcessHeap(), 0, str);
951     str3 = xmlEncodeSpecialChars(This->node->doc, str2);
952     xmlFree(str2);
953
954     xmlNodeSetContent(This->node, str3);
955     xmlFree(str3);
956
957     return S_OK;
958 }
959
960 static HRESULT WINAPI xmlnode_get_specified(
961     IXMLDOMNode *iface,
962     VARIANT_BOOL* isSpecified)
963 {
964     FIXME("\n");
965     return E_NOTIMPL;
966 }
967
968 static HRESULT WINAPI xmlnode_get_definition(
969     IXMLDOMNode *iface,
970     IXMLDOMNode** definitionNode)
971 {
972     FIXME("\n");
973     return E_NOTIMPL;
974 }
975
976 static HRESULT WINAPI xmlnode_get_nodeTypedValue(
977     IXMLDOMNode *iface,
978     VARIANT* typedValue)
979 {
980     xmlnode *This = impl_from_IXMLDOMNode( iface );
981     HRESULT r = S_FALSE;
982
983     FIXME("ignoring data type %p %p\n", This, typedValue);
984
985     if(!typedValue)
986         return E_INVALIDARG;
987
988     V_VT(typedValue) = VT_NULL;
989
990     switch ( This->node->type )
991     {
992     case XML_ELEMENT_NODE:
993     {
994         xmlChar *content = xmlNodeGetContent(This->node);
995         V_VT(typedValue) = VT_BSTR;
996         V_BSTR(typedValue) = bstr_from_xmlChar( content );
997         xmlFree(content);
998         r = S_OK;
999         break;
1000     }
1001     default:
1002         r = xmlnode_get_nodeValue(iface, typedValue);
1003     }
1004
1005     return r;
1006 }
1007
1008 static HRESULT WINAPI xmlnode_put_nodeTypedValue(
1009     IXMLDOMNode *iface,
1010     VARIANT typedValue)
1011 {
1012     FIXME("\n");
1013     return E_NOTIMPL;
1014 }
1015
1016 static HRESULT WINAPI xmlnode_get_dataType(
1017     IXMLDOMNode *iface,
1018     VARIANT* dataTypeName)
1019 {
1020     xmlnode *This = impl_from_IXMLDOMNode( iface );
1021     xmlChar *pVal;
1022
1023     TRACE("iface %p\n", iface);
1024
1025     if(!dataTypeName)
1026         return E_INVALIDARG;
1027
1028     /* Attribute, CDATA Section, Comment, Document, Document Fragment,
1029         Entity, Notation, PI, and Text Node are non-typed. */
1030     V_BSTR(dataTypeName) = NULL;
1031     V_VT(dataTypeName) = VT_NULL;
1032
1033     switch ( This->node->type )
1034     {
1035     case XML_ELEMENT_NODE:
1036         pVal = xmlGetNsProp(This->node, (xmlChar*)"dt",
1037                             (xmlChar*)"urn:schemas-microsoft-com:datatypes");
1038         if (pVal)
1039         {
1040             V_VT(dataTypeName) = VT_BSTR;
1041             V_BSTR(dataTypeName) = bstr_from_xmlChar( pVal );
1042             xmlFree(pVal);
1043         }
1044         break;
1045     case XML_ENTITY_REF_NODE:
1046         FIXME("XML_ENTITY_REF_NODE should return a valid value.\n");
1047         break;
1048     default:
1049         TRACE("Type %d returning NULL\n", This->node->type);
1050     }
1051
1052     /* non-typed nodes return S_FALSE */
1053     if(V_VT(dataTypeName) == VT_NULL)
1054     {
1055         return S_FALSE;
1056     }
1057
1058     return S_OK;
1059 }
1060
1061 static HRESULT WINAPI xmlnode_put_dataType(
1062     IXMLDOMNode *iface,
1063     BSTR dataTypeName)
1064 {
1065     xmlnode *This = impl_from_IXMLDOMNode( iface );
1066     HRESULT hr = E_FAIL;
1067
1068     TRACE("iface %p\n", iface);
1069
1070     if(dataTypeName == NULL)
1071         return E_INVALIDARG;
1072
1073     /* An example of this is. The Text in the node needs to be a 0 or 1 for a boolean type.
1074        This applies to changing types (string->bool) or setting a new one
1075      */
1076     FIXME("Need to Validate the data before allowing a type to be set.\n");
1077
1078     /* Check all supported types. */
1079     if(lstrcmpiW(dataTypeName,szString) == 0  ||
1080        lstrcmpiW(dataTypeName,szNumber) == 0  ||
1081        lstrcmpiW(dataTypeName,szUUID) == 0    ||
1082        lstrcmpiW(dataTypeName,szInt) == 0     ||
1083        lstrcmpiW(dataTypeName,szI4) == 0      ||
1084        lstrcmpiW(dataTypeName,szFixed) == 0   ||
1085        lstrcmpiW(dataTypeName,szBoolean) == 0 ||
1086        lstrcmpiW(dataTypeName,szDateTime) == 0 ||
1087        lstrcmpiW(dataTypeName,szDateTimeTZ) == 0 ||
1088        lstrcmpiW(dataTypeName,szDate) == 0    ||
1089        lstrcmpiW(dataTypeName,szTime) == 0    ||
1090        lstrcmpiW(dataTypeName,szTimeTZ) == 0  ||
1091        lstrcmpiW(dataTypeName,szI1) == 0      ||
1092        lstrcmpiW(dataTypeName,szI2) == 0      ||
1093        lstrcmpiW(dataTypeName,szIU1) == 0     ||
1094        lstrcmpiW(dataTypeName,szIU2) == 0     ||
1095        lstrcmpiW(dataTypeName,szIU4) == 0     ||
1096        lstrcmpiW(dataTypeName,szR4) == 0      ||
1097        lstrcmpiW(dataTypeName,szR8) == 0      ||
1098        lstrcmpiW(dataTypeName,szFloat) == 0   ||
1099        lstrcmpiW(dataTypeName,szBinHex) == 0  ||
1100        lstrcmpiW(dataTypeName,szBinBase64) == 0)
1101     {
1102         xmlNsPtr pNS = NULL;
1103         xmlAttrPtr pAttr = NULL;
1104         xmlChar* str = xmlChar_from_wchar((WCHAR*)dataTypeName);
1105
1106         pAttr = xmlHasNsProp(This->node, (xmlChar*)"dt",
1107                             (xmlChar*)"urn:schemas-microsoft-com:datatypes");
1108         if (pAttr)
1109         {
1110             pAttr = xmlSetNsProp(This->node, pAttr->ns, (xmlChar*)"dt", str);
1111
1112             hr = S_OK;
1113         }
1114         else
1115         {
1116             pNS = xmlNewNs(This->node, (xmlChar*)"urn:schemas-microsoft-com:datatypes", (xmlChar*)"dt");
1117             if(pNS)
1118             {
1119                 pAttr = xmlNewNsProp(This->node, pNS, (xmlChar*)"dt", str);
1120                 if(pAttr)
1121                 {
1122                     xmlAddChild(This->node, (xmlNodePtr)pAttr);
1123
1124                     hr = S_OK;
1125                 }
1126                 else
1127                     ERR("Failed to create Attribute\n");
1128             }
1129             else
1130                 ERR("Failed to Create Namepsace\n");
1131         }
1132         HeapFree( GetProcessHeap(), 0, str );
1133     }
1134
1135     return hr;
1136 }
1137
1138 static BSTR EnsureCorrectEOL(BSTR sInput)
1139 {
1140     static const WCHAR SZ_RETURN[] = {'\n',0};
1141     static const WCHAR SZ_LINEFEED[] = {'\r',0};
1142     int nNum = 0;
1143     BSTR sNew;
1144     int nLen;
1145     int i;
1146
1147     nLen = lstrlenW(sInput);
1148     /* Count line endings */
1149     for(i=0; i < nLen; i++)
1150     {
1151         if(sInput[i] == SZ_RETURN[0])
1152             nNum++;
1153     }
1154
1155     TRACE("len=%d, num=%d\n", nLen, nNum);
1156
1157     /* Add linefeed as needed */
1158     if(nNum > 0)
1159     {
1160         int nPlace = 0;
1161         sNew = SysAllocStringLen(NULL, nLen + nNum+1);
1162         for(i=0; i < nLen; i++)
1163         {
1164             if(sInput[i] == SZ_RETURN[0])
1165             {
1166                 sNew[i+nPlace] = SZ_LINEFEED[0];
1167                 nPlace++;
1168             }
1169             sNew[i+nPlace] = sInput[i];
1170         }
1171
1172         SysFreeString(sInput);
1173     }
1174     else
1175     {
1176         sNew = sInput;
1177     }
1178
1179     TRACE("len %d\n", lstrlenW(sNew));
1180
1181     return sNew;
1182 }
1183
1184 /* Removes encoding information and last character (nullbyte) */
1185 static BSTR EnsureNoEncoding(BSTR sInput)
1186 {
1187     static const WCHAR wszEncoding[] = {'e','n','c','o','d','i','n','g','='};
1188     BSTR sNew;
1189     WCHAR *pBeg, *pEnd;
1190
1191     pBeg = sInput;
1192     while(*pBeg != '\n' && memcmp(pBeg, wszEncoding, sizeof(wszEncoding)))
1193         pBeg++;
1194
1195     if(*pBeg == '\n')
1196     {
1197         SysReAllocStringLen(&sInput, sInput, SysStringLen(sInput)-1);
1198         return sInput;
1199     }
1200     pBeg--;
1201
1202     pEnd = pBeg + sizeof(wszEncoding)/sizeof(WCHAR) + 2;
1203     while(*pEnd != '\"') pEnd++;
1204     pEnd++;
1205
1206     sNew = SysAllocStringLen(NULL,
1207             pBeg-sInput + SysStringLen(sInput)-(pEnd-sInput)-1);
1208     memcpy(sNew, sInput, (pBeg-sInput)*sizeof(WCHAR));
1209     memcpy(&sNew[pBeg-sInput], pEnd, (SysStringLen(sInput)-(pEnd-sInput)-1)*sizeof(WCHAR));
1210
1211     SysFreeString(sInput);
1212     return sNew;
1213 }
1214
1215 /*
1216  * We are trying to replicate the same behaviour as msxml by converting
1217  * line endings to \r\n and using idents as \t. The problem is that msxml
1218  * only formats nodes that have a line ending. Using libxml we cannot
1219  * reproduce behaviour exactly.
1220  *
1221  */
1222 static HRESULT WINAPI xmlnode_get_xml(
1223     IXMLDOMNode *iface,
1224     BSTR* xmlString)
1225 {
1226     xmlnode *This = impl_from_IXMLDOMNode( iface );
1227     xmlBufferPtr pXmlBuf;
1228     int nSize;
1229
1230     TRACE("iface %p %d\n", iface, This->node->type);
1231
1232     if(!xmlString)
1233         return E_INVALIDARG;
1234
1235     *xmlString = NULL;
1236
1237     pXmlBuf = xmlBufferCreate();
1238     if(pXmlBuf)
1239     {
1240         nSize = xmlNodeDump(pXmlBuf, This->node->doc, This->node, 0, 1);
1241         if(nSize > 0)
1242         {
1243             const xmlChar *pContent;
1244             BSTR bstrContent;
1245
1246             /* Attribute Nodes return a space in front of their name */
1247             pContent = xmlBufferContent(pXmlBuf);
1248             if( ((char*)pContent)[0] == ' ')
1249                 bstrContent = bstr_from_xmlChar(pContent+1);
1250             else
1251                 bstrContent = bstr_from_xmlChar(pContent);
1252
1253             switch(This->node->type)
1254             {
1255                 case XML_ELEMENT_NODE:
1256                     *xmlString = EnsureCorrectEOL(bstrContent);
1257                     break;
1258                 case XML_DOCUMENT_NODE:
1259                     *xmlString = EnsureCorrectEOL(bstrContent);
1260                     *xmlString = EnsureNoEncoding(*xmlString);
1261                     break;
1262                 default:
1263                     *xmlString = bstrContent;
1264             }
1265         }
1266
1267         xmlBufferFree(pXmlBuf);
1268     }
1269
1270     /* Always returns a string. */
1271     if(*xmlString == NULL)  *xmlString = SysAllocStringLen( NULL, 0 );
1272
1273     return S_OK;
1274 }
1275
1276 static HRESULT WINAPI xmlnode_transformNode(
1277     IXMLDOMNode *iface,
1278     IXMLDOMNode* styleSheet,
1279     BSTR* xmlString)
1280 {
1281 #ifdef HAVE_LIBXSLT
1282     xmlnode *This = impl_from_IXMLDOMNode( iface );
1283     xmlnode *pStyleSheet = NULL;
1284     xsltStylesheetPtr xsltSS = NULL;
1285     xmlDocPtr result = NULL;
1286     IXMLDOMNode *ssNew;
1287
1288     TRACE("%p %p %p\n", This, styleSheet, xmlString);
1289
1290     if(!styleSheet || !xmlString)
1291         return E_INVALIDARG;
1292
1293     *xmlString = NULL;
1294
1295     if(IXMLDOMNode_QueryInterface(styleSheet, &IID_IXMLDOMNode, (LPVOID)&ssNew) == S_OK)
1296     {
1297         pStyleSheet = impl_from_IXMLDOMNode( ssNew );
1298
1299         xsltSS = xsltParseStylesheetDoc( pStyleSheet->node->doc);
1300         if(xsltSS)
1301         {
1302             result = xsltApplyStylesheet(xsltSS, This->node->doc, NULL);
1303             if(result)
1304             {
1305                 const xmlChar *pContent;
1306
1307                 if(result->type == XML_HTML_DOCUMENT_NODE)
1308                 {
1309                     xmlOutputBufferPtr  pOutput = xmlAllocOutputBuffer(NULL);
1310                     if(pOutput)
1311                     {
1312                         htmlDocContentDumpOutput(pOutput, result->doc, NULL);
1313                         if(pOutput)
1314                         {
1315                             pContent = xmlBufferContent(pOutput->buffer);
1316                             *xmlString = bstr_from_xmlChar(pContent);
1317                         }
1318
1319                         xmlOutputBufferClose(pOutput);
1320                     }
1321                 }
1322                 else
1323                 {
1324                     xmlBufferPtr pXmlBuf;
1325                     int nSize;
1326
1327                     pXmlBuf = xmlBufferCreate();
1328                     if(pXmlBuf)
1329                     {
1330                         nSize = xmlNodeDump(pXmlBuf, NULL, (xmlNodePtr)result, 0, 0);
1331                         if(nSize > 0)
1332                         {
1333                             pContent = xmlBufferContent(pXmlBuf);
1334                             *xmlString = bstr_from_xmlChar(pContent);
1335
1336                             xmlBufferFree(pXmlBuf);
1337                         }
1338                     }
1339                 }
1340             }
1341             xmlFreeDoc(result);
1342         }
1343
1344         /* libxslt "helpfully" frees the XML document the stylesheet was
1345            generated from, too */
1346         xsltSS->doc = NULL;
1347         xsltFreeStylesheet(xsltSS);
1348         IXMLDOMNode_Release(ssNew);
1349     }
1350
1351     if(*xmlString == NULL)
1352         *xmlString = SysAllocStringLen(NULL, 0);
1353
1354     return S_OK;
1355 #else
1356     FIXME("libxslt headers were not found at compile time\n");
1357     return E_NOTIMPL;
1358 #endif
1359 }
1360
1361 static HRESULT WINAPI xmlnode_selectNodes(
1362     IXMLDOMNode *iface,
1363     BSTR queryString,
1364     IXMLDOMNodeList** resultList)
1365 {
1366     xmlnode *This = impl_from_IXMLDOMNode( iface );
1367
1368     TRACE("%p %s %p\n", This, debugstr_w(queryString), resultList );
1369
1370     return queryresult_create( This->node, queryString, resultList );
1371 }
1372
1373 static HRESULT WINAPI xmlnode_selectSingleNode(
1374     IXMLDOMNode *iface,
1375     BSTR queryString,
1376     IXMLDOMNode** resultNode)
1377 {
1378     xmlnode *This = impl_from_IXMLDOMNode( iface );
1379     IXMLDOMNodeList *list;
1380     HRESULT r;
1381
1382     TRACE("%p %s %p\n", This, debugstr_w(queryString), resultNode );
1383
1384     *resultNode = NULL;
1385     r = IXMLDOMNode_selectNodes(iface, queryString, &list);
1386     if(r == S_OK)
1387     {
1388         r = IXMLDOMNodeList_nextNode(list, resultNode);
1389         IXMLDOMNodeList_Release(list);
1390     }
1391     return r;
1392 }
1393
1394 static HRESULT WINAPI xmlnode_get_parsed(
1395     IXMLDOMNode *iface,
1396     VARIANT_BOOL* isParsed)
1397 {
1398     FIXME("\n");
1399     return E_NOTIMPL;
1400 }
1401
1402 static HRESULT WINAPI xmlnode_get_namespaceURI(
1403     IXMLDOMNode *iface,
1404     BSTR* namespaceURI)
1405 {
1406     xmlnode *This = impl_from_IXMLDOMNode( iface );
1407     HRESULT hr = S_FALSE;
1408     xmlNsPtr *pNSList;
1409
1410     TRACE("%p %p\n", This, namespaceURI );
1411
1412     if(!namespaceURI)
1413         return E_INVALIDARG;
1414
1415     *namespaceURI = NULL;
1416
1417     pNSList = xmlGetNsList(This->node->doc, This->node);
1418     if(pNSList)
1419     {
1420         *namespaceURI = bstr_from_xmlChar( pNSList[0]->href );
1421
1422         xmlFree( pNSList );
1423         hr = S_OK;
1424     }
1425
1426     return hr;
1427 }
1428
1429 static HRESULT WINAPI xmlnode_get_prefix(
1430     IXMLDOMNode *iface,
1431     BSTR* prefixString)
1432 {
1433     xmlnode *This = impl_from_IXMLDOMNode( iface );
1434     HRESULT hr = S_FALSE;
1435     xmlNsPtr *pNSList;
1436
1437     TRACE("%p %p\n", This, prefixString );
1438
1439     if(!prefixString)
1440         return E_INVALIDARG;
1441
1442     *prefixString = NULL;
1443
1444     pNSList = xmlGetNsList(This->node->doc, This->node);
1445     if(pNSList)
1446     {
1447         *prefixString = bstr_from_xmlChar( pNSList[0]->prefix );
1448
1449         xmlFree(pNSList);
1450         hr = S_OK;
1451     }
1452
1453     return hr;
1454 }
1455
1456 static HRESULT WINAPI xmlnode_get_baseName(
1457     IXMLDOMNode *iface,
1458     BSTR* nameString)
1459 {
1460     xmlnode *This = impl_from_IXMLDOMNode( iface );
1461     BSTR str = NULL;
1462     HRESULT r = S_FALSE;
1463
1464     TRACE("%p %p\n", This, nameString );
1465
1466     if ( !nameString )
1467         return E_INVALIDARG;
1468
1469     switch ( This->node->type )
1470     {
1471     case XML_ELEMENT_NODE:
1472     case XML_ATTRIBUTE_NODE:
1473         str = bstr_from_xmlChar( This->node->name );
1474         r = S_OK;
1475         break;
1476     case XML_TEXT_NODE:
1477         break;
1478     default:
1479         ERR("Unhandled type %d\n", This->node->type );
1480         break;
1481     }
1482
1483     TRACE("returning %08x str = %s\n", r, debugstr_w( str ) );
1484
1485     *nameString = str;
1486     return r;
1487 }
1488
1489 static HRESULT WINAPI xmlnode_transformNodeToObject(
1490     IXMLDOMNode *iface,
1491     IXMLDOMNode* stylesheet,
1492     VARIANT outputObject)
1493 {
1494     FIXME("\n");
1495     return E_NOTIMPL;
1496 }
1497
1498 static const struct IXMLDOMNodeVtbl xmlnode_vtbl =
1499 {
1500     xmlnode_QueryInterface,
1501     xmlnode_AddRef,
1502     xmlnode_Release,
1503     xmlnode_GetTypeInfoCount,
1504     xmlnode_GetTypeInfo,
1505     xmlnode_GetIDsOfNames,
1506     xmlnode_Invoke,
1507     xmlnode_get_nodeName,
1508     xmlnode_get_nodeValue,
1509     xmlnode_put_nodeValue,
1510     xmlnode_get_nodeType,
1511     xmlnode_get_parentNode,
1512     xmlnode_get_childNodes,
1513     xmlnode_get_firstChild,
1514     xmlnode_get_lastChild,
1515     xmlnode_get_previousSibling,
1516     xmlnode_get_nextSibling,
1517     xmlnode_get_attributes,
1518     xmlnode_insertBefore,
1519     xmlnode_replaceChild,
1520     xmlnode_removeChild,
1521     xmlnode_appendChild,
1522     xmlnode_hasChildNodes,
1523     xmlnode_get_ownerDocument,
1524     xmlnode_cloneNode,
1525     xmlnode_get_nodeTypeString,
1526     xmlnode_get_text,
1527     xmlnode_put_text,
1528     xmlnode_get_specified,
1529     xmlnode_get_definition,
1530     xmlnode_get_nodeTypedValue,
1531     xmlnode_put_nodeTypedValue,
1532     xmlnode_get_dataType,
1533     xmlnode_put_dataType,
1534     xmlnode_get_xml,
1535     xmlnode_transformNode,
1536     xmlnode_selectNodes,
1537     xmlnode_selectSingleNode,
1538     xmlnode_get_parsed,
1539     xmlnode_get_namespaceURI,
1540     xmlnode_get_prefix,
1541     xmlnode_get_baseName,
1542     xmlnode_transformNodeToObject,
1543 };
1544
1545 static HRESULT WINAPI Internal_QueryInterface(
1546     IUnknown *iface,
1547     REFIID riid,
1548     void** ppvObject )
1549 {
1550     xmlnode *This = impl_from_InternalUnknown( iface );
1551
1552     TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
1553
1554
1555     if ( IsEqualGUID( riid, &IID_IUnknown ))
1556         *ppvObject = iface;
1557     else if ( IsEqualGUID( riid, &IID_IDispatch ) ||
1558               IsEqualGUID( riid, &IID_IXMLDOMNode ) )
1559         *ppvObject = &This->lpVtbl;
1560     else
1561     {
1562         FIXME("interface %s not implemented\n", debugstr_guid(riid));
1563         *ppvObject = NULL;
1564         return E_NOINTERFACE;
1565     }
1566
1567     IUnknown_AddRef( (IUnknown*)*ppvObject );
1568
1569     return S_OK;
1570 }
1571
1572 static ULONG WINAPI Internal_AddRef(
1573                  IUnknown *iface )
1574 {
1575     xmlnode *This = impl_from_InternalUnknown( iface );
1576     return InterlockedIncrement( &This->ref );
1577 }
1578
1579 static ULONG WINAPI Internal_Release(
1580     IUnknown *iface )
1581 {
1582     xmlnode *This = impl_from_InternalUnknown( iface );
1583     ULONG ref;
1584
1585     ref = InterlockedDecrement( &This->ref );
1586     if ( ref == 0 )
1587     {
1588         if( This->node )
1589             xmldoc_release( This->node->doc );
1590         HeapFree( GetProcessHeap(), 0, This );
1591     }
1592
1593     return ref;
1594 }
1595
1596 static const struct IUnknownVtbl internal_unk_vtbl =
1597 {
1598     Internal_QueryInterface,
1599     Internal_AddRef,
1600     Internal_Release
1601 };
1602
1603 IUnknown *create_basic_node( xmlNodePtr node, IUnknown *pUnkOuter )
1604 {
1605     xmlnode *This;
1606
1607     This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
1608     if ( !This )
1609         return NULL;
1610
1611     if(node)
1612         xmldoc_add_ref( node->doc );
1613
1614     This->lpVtbl = &xmlnode_vtbl;
1615     This->lpInternalUnkVtbl = &internal_unk_vtbl;
1616
1617     if(pUnkOuter)
1618         This->pUnkOuter = pUnkOuter; /* Don't take a ref on outer Unknown */
1619     else
1620         This->pUnkOuter = (IUnknown *)&This->lpInternalUnkVtbl;
1621
1622     This->ref = 1;
1623     This->node = node;
1624
1625     return (IUnknown*)&This->lpInternalUnkVtbl;
1626 }
1627
1628 IXMLDOMNode *create_node( xmlNodePtr node )
1629 {
1630     IUnknown *pUnk;
1631     IXMLDOMNode *ret;
1632     HRESULT hr;
1633
1634     if ( !node )
1635         return NULL;
1636
1637     TRACE("type %d\n", node->type);
1638     switch(node->type)
1639     {
1640     case XML_ELEMENT_NODE:
1641         pUnk = create_element( node, NULL );
1642         break;
1643     case XML_ATTRIBUTE_NODE:
1644         pUnk = create_attribute( node );
1645         break;
1646     case XML_TEXT_NODE:
1647         pUnk = create_text( node );
1648         break;
1649     case XML_CDATA_SECTION_NODE:
1650         pUnk = create_cdata( node );
1651         break;
1652     case XML_COMMENT_NODE:
1653         pUnk = create_comment( node );
1654         break;
1655     case XML_DOCUMENT_NODE:
1656         pUnk = create_domdoc( node );
1657         break;
1658     default:
1659         FIXME("only creating basic node for type %d\n", node->type);
1660         pUnk = create_basic_node( node, NULL );
1661     }
1662
1663     hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
1664     IUnknown_Release(pUnk);
1665     if(FAILED(hr)) return NULL;
1666     return ret;
1667 }
1668 #endif