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