msxml3: Don't use xmlnode's IXMLDOMNode iface in get_childNode implementations.
[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 "msxml6.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 static const IID IID_xmlnode = {0x4f2f4ba2,0xb822,0x11df,{0x8b,0x8a,0x68,0x50,0xdf,0xd7,0x20,0x85}};
70
71 xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type )
72 {
73     xmlnode *This;
74
75     if ( !iface )
76         return NULL;
77     This = get_node_obj( iface );
78     if ( !This || !This->node )
79         return NULL;
80     if ( type && This->node->type != type )
81         return NULL;
82     return This->node;
83 }
84
85 BOOL node_query_interface(xmlnode *This, REFIID riid, void **ppv)
86 {
87     if(IsEqualGUID(&IID_xmlnode, riid)) {
88         TRACE("(%p)->(IID_xmlnode %p)\n", This, ppv);
89         *ppv = This;
90         return TRUE;
91     }
92
93     if(This->dispex.outer)
94         return dispex_query_interface(&This->dispex, riid, ppv);
95
96     return FALSE;
97 }
98
99 xmlnode *get_node_obj(IXMLDOMNode *node)
100 {
101     xmlnode *obj;
102     HRESULT hres;
103
104     hres = IXMLDOMNode_QueryInterface(node, &IID_xmlnode, (void**)&obj);
105     return SUCCEEDED(hres) ? obj : NULL;
106 }
107
108 static inline xmlnode *impl_from_IXMLDOMNode( IXMLDOMNode *iface )
109 {
110     return (xmlnode *)((char*)iface - FIELD_OFFSET(xmlnode, lpVtbl));
111 }
112
113 static HRESULT WINAPI xmlnode_QueryInterface(
114     IXMLDOMNode *iface,
115     REFIID riid,
116     void** ppvObject )
117 {
118     ERR("Should not be called\n");
119     return E_NOINTERFACE;
120 }
121
122 static ULONG WINAPI xmlnode_AddRef(
123     IXMLDOMNode *iface )
124 {
125     ERR("Should not be called\n");
126     return 2;
127 }
128
129 static ULONG WINAPI xmlnode_Release(
130     IXMLDOMNode *iface )
131 {
132     ERR("Should not be called\n");
133     return 1;
134 }
135
136 static HRESULT WINAPI xmlnode_GetTypeInfoCount(
137     IXMLDOMNode *iface,
138     UINT* pctinfo )
139 {
140     ERR("Should not be called\n");
141     return E_NOTIMPL;
142 }
143
144 static HRESULT WINAPI xmlnode_GetTypeInfo(
145     IXMLDOMNode *iface,
146     UINT iTInfo,
147     LCID lcid,
148     ITypeInfo** ppTInfo )
149 {
150     ERR("Should not be called\n");
151     return E_NOTIMPL;
152 }
153
154 static HRESULT WINAPI xmlnode_GetIDsOfNames(
155     IXMLDOMNode *iface,
156     REFIID riid,
157     LPOLESTR* rgszNames,
158     UINT cNames,
159     LCID lcid,
160     DISPID* rgDispId )
161 {
162     ERR("Should not be called\n");
163     return E_NOTIMPL;
164 }
165
166 static HRESULT WINAPI xmlnode_Invoke(
167     IXMLDOMNode *iface,
168     DISPID dispIdMember,
169     REFIID riid,
170     LCID lcid,
171     WORD wFlags,
172     DISPPARAMS* pDispParams,
173     VARIANT* pVarResult,
174     EXCEPINFO* pExcepInfo,
175     UINT* puArgErr )
176 {
177     ERR("Should not be called\n");
178     return E_NOTIMPL;
179 }
180
181 HRESULT node_get_nodeName(xmlnode *This, BSTR *name)
182 {
183     if (!name)
184         return E_INVALIDARG;
185
186     *name = bstr_from_xmlChar(This->node->name);
187     if (!*name)
188         return S_FALSE;
189
190     return S_OK;
191 }
192
193 static HRESULT WINAPI xmlnode_get_nodeName(
194     IXMLDOMNode *iface,
195     BSTR* name)
196 {
197     ERR("Should not be called\n");
198     return E_NOTIMPL;
199 }
200
201 HRESULT node_get_content(xmlnode *This, VARIANT *value)
202 {
203     xmlChar *content;
204
205     if(!value)
206         return E_INVALIDARG;
207
208     content = xmlNodeGetContent(This->node);
209     V_VT(value) = VT_BSTR;
210     V_BSTR(value) = bstr_from_xmlChar( content );
211     xmlFree(content);
212
213     TRACE("%p returned %s\n", This, debugstr_w(V_BSTR(value)));
214     return S_OK;
215 }
216
217 static HRESULT WINAPI xmlnode_get_nodeValue(
218     IXMLDOMNode *iface,
219     VARIANT* value)
220 {
221     ERR("Should not be called\n");
222     return E_NOTIMPL;
223 }
224
225 HRESULT node_put_value(xmlnode *This, VARIANT *value)
226 {
227     VARIANT string_value;
228     xmlChar *str;
229     HRESULT hr;
230
231     VariantInit(&string_value);
232     hr = VariantChangeType(&string_value, value, 0, VT_BSTR);
233     if(FAILED(hr)) {
234         WARN("Couldn't convert to VT_BSTR\n");
235         return hr;
236     }
237
238     str = xmlChar_from_wchar(V_BSTR(&string_value));
239     VariantClear(&string_value);
240
241     xmlNodeSetContent(This->node, str);
242     heap_free(str);
243     return S_OK;
244 }
245
246 static HRESULT WINAPI xmlnode_put_nodeValue(
247     IXMLDOMNode *iface,
248     VARIANT value)
249 {
250     ERR("Should not be called\n");
251     return E_NOTIMPL;
252 }
253
254 static HRESULT WINAPI xmlnode_get_nodeType(
255     IXMLDOMNode *iface,
256     DOMNodeType* type)
257 {
258     ERR("Should not be called\n");
259     return E_NOTIMPL;
260 }
261
262 static HRESULT get_node(
263     xmlnode *This,
264     const char *name,
265     xmlNodePtr node,
266     IXMLDOMNode **out )
267 {
268     TRACE("(%p)->(%s %p %p)\n", This, name, node, out );
269
270     if ( !out )
271         return E_INVALIDARG;
272
273     /* if we don't have a doc, use our parent. */
274     if(node && !node->doc && node->parent)
275         node->doc = node->parent->doc;
276
277     *out = create_node( node );
278     if (!*out)
279         return S_FALSE;
280     return S_OK;
281 }
282
283 HRESULT node_get_parent(xmlnode *This, IXMLDOMNode **parent)
284 {
285     return get_node( This, "parent", This->node->parent, parent );
286 }
287
288 static HRESULT WINAPI xmlnode_get_parentNode(
289     IXMLDOMNode *iface,
290     IXMLDOMNode** parent)
291 {
292     ERR("Should not be called\n");
293     return E_NOTIMPL;
294 }
295
296 HRESULT node_get_child_nodes(xmlnode *This, IXMLDOMNodeList **ret)
297 {
298     if(!ret)
299         return E_INVALIDARG;
300
301     *ret = create_children_nodelist(This->node);
302     if(!*ret)
303         return E_OUTOFMEMORY;
304
305     return S_OK;
306 }
307
308 static HRESULT WINAPI xmlnode_get_childNodes(
309     IXMLDOMNode *iface,
310     IXMLDOMNodeList** childList)
311 {
312     ERR("Should not be called\n");
313     return E_NOTIMPL;
314 }
315
316 static HRESULT WINAPI xmlnode_get_firstChild(
317     IXMLDOMNode *iface,
318     IXMLDOMNode** firstChild)
319 {
320     xmlnode *This = impl_from_IXMLDOMNode( iface );
321     TRACE("(%p)->(%p)\n", This, firstChild);
322     return get_node( This, "firstChild", This->node->children, firstChild );
323 }
324
325 static HRESULT WINAPI xmlnode_get_lastChild(
326     IXMLDOMNode *iface,
327     IXMLDOMNode** lastChild)
328 {
329     xmlnode *This = impl_from_IXMLDOMNode( iface );
330
331     TRACE("(%p)->(%p)\n", This, lastChild );
332
333     if (!lastChild)
334         return E_INVALIDARG;
335
336     switch( This->node->type )
337     {
338     /* CDATASection, Comment, PI and Text Nodes do not support lastChild */
339     case XML_TEXT_NODE:
340     case XML_CDATA_SECTION_NODE:
341     case XML_PI_NODE:
342     case XML_COMMENT_NODE:
343         *lastChild = NULL;
344         return S_FALSE;
345     default:
346         return get_node( This, "lastChild", This->node->last, lastChild );
347     }
348 }
349
350 static HRESULT WINAPI xmlnode_get_previousSibling(
351     IXMLDOMNode *iface,
352     IXMLDOMNode** previousSibling)
353 {
354     xmlnode *This = impl_from_IXMLDOMNode( iface );
355
356     TRACE("(%p)->(%p)\n", This, previousSibling );
357
358     if (!previousSibling)
359         return E_INVALIDARG;
360
361     switch( This->node->type )
362     {
363     /* Attribute, Document and Document Fragment Nodes do not support previousSibling */
364     case XML_DOCUMENT_NODE:
365     case XML_DOCUMENT_FRAG_NODE:
366     case XML_ATTRIBUTE_NODE:
367         *previousSibling = NULL;
368         return S_FALSE;
369     default:
370         return get_node( This, "previous", This->node->prev, previousSibling );
371     }
372 }
373
374 static HRESULT WINAPI xmlnode_get_nextSibling(
375     IXMLDOMNode *iface,
376     IXMLDOMNode** nextSibling)
377 {
378     xmlnode *This = impl_from_IXMLDOMNode( iface );
379
380     TRACE("(%p)->(%p)\n", This, nextSibling );
381
382     if (!nextSibling)
383         return E_INVALIDARG;
384
385     switch( This->node->type )
386     {
387     /* Attribute, Document and Document Fragment Nodes do not support nextSibling */
388     case XML_DOCUMENT_NODE:
389     case XML_DOCUMENT_FRAG_NODE:
390     case XML_ATTRIBUTE_NODE:
391         *nextSibling = NULL;
392         return S_FALSE;
393     default:
394         return get_node( This, "next", This->node->next, nextSibling );
395     }
396 }
397
398 static HRESULT WINAPI xmlnode_get_attributes(
399     IXMLDOMNode *iface,
400     IXMLDOMNamedNodeMap** attributeMap)
401 {
402     xmlnode *This = impl_from_IXMLDOMNode( iface );
403     TRACE("(%p)->(%p)\n", This, attributeMap);
404
405     if (!attributeMap)
406         return E_INVALIDARG;
407
408     switch( This->node->type )
409     {
410     /* Attribute, CDataSection, Comment, Documents, Documents Fragments,
411        Entity and Text Nodes does not support get_attributes */
412     case XML_ATTRIBUTE_NODE:
413     case XML_CDATA_SECTION_NODE:
414     case XML_COMMENT_NODE:
415     case XML_DOCUMENT_NODE:
416     case XML_DOCUMENT_FRAG_NODE:
417     case XML_ENTITY_NODE:
418     case XML_ENTITY_REF_NODE:
419     case XML_TEXT_NODE:
420         *attributeMap = NULL;
421         return S_FALSE;
422     default:
423         *attributeMap = create_nodemap( This->iface );
424         return S_OK;
425     }
426 }
427
428 static HRESULT WINAPI xmlnode_insertBefore(
429     IXMLDOMNode *iface,
430     IXMLDOMNode* newChild,
431     VARIANT refChild,
432     IXMLDOMNode** outNewChild)
433 {
434     xmlnode *This = impl_from_IXMLDOMNode( iface );
435     xmlNodePtr before_node, new_child_node;
436     IXMLDOMNode *before = NULL;
437     xmlnode *node_obj;
438     HRESULT hr;
439
440     TRACE("(%p)->(%p var %p)\n",This,newChild,outNewChild);
441
442     if (!newChild)
443         return E_INVALIDARG;
444
445     switch(V_VT(&refChild))
446     {
447     case VT_EMPTY:
448     case VT_NULL:
449         break;
450
451     case VT_UNKNOWN:
452         hr = IUnknown_QueryInterface(V_UNKNOWN(&refChild), &IID_IXMLDOMNode, (LPVOID)&before);
453         if(FAILED(hr)) return hr;
454         break;
455
456     case VT_DISPATCH:
457         hr = IDispatch_QueryInterface(V_DISPATCH(&refChild), &IID_IXMLDOMNode, (LPVOID)&before);
458         if(FAILED(hr)) return hr;
459         break;
460
461     default:
462         FIXME("refChild var type %x\n", V_VT(&refChild));
463         return E_FAIL;
464     }
465
466     node_obj = get_node_obj(newChild);
467     if(!node_obj) {
468         FIXME("newChild is not our node implementation\n");
469         return E_FAIL;
470     }
471
472     new_child_node = node_obj->node;
473     TRACE("new_child_node %p This->node %p\n", new_child_node, This->node);
474
475     if(!new_child_node->parent)
476         if(xmldoc_remove_orphan(new_child_node->doc, new_child_node) != S_OK)
477             WARN("%p is not an orphan of %p\n", new_child_node, new_child_node->doc);
478
479     if(before)
480     {
481         node_obj = get_node_obj(before);
482         IXMLDOMNode_Release(before);
483         if(!node_obj) {
484             FIXME("before node is not our node implementation\n");
485             return E_FAIL;
486         }
487
488         before_node = node_obj->node;
489         xmlAddPrevSibling(before_node, new_child_node);
490     }
491     else
492     {
493         xmlAddChild(This->node, new_child_node);
494     }
495
496     IXMLDOMNode_AddRef(newChild);
497     if(outNewChild)
498         *outNewChild = newChild;
499
500     TRACE("ret S_OK\n");
501     return S_OK;
502 }
503
504 static HRESULT WINAPI xmlnode_replaceChild(
505     IXMLDOMNode *iface,
506     IXMLDOMNode* newChild,
507     IXMLDOMNode* oldChild,
508     IXMLDOMNode** outOldChild)
509 {
510     xmlnode *This = impl_from_IXMLDOMNode( iface );
511     xmlnode *old_child, *new_child;
512     xmlDocPtr leaving_doc;
513     xmlNode *my_ancestor;
514
515     TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
516
517     /* Do not believe any documentation telling that newChild == NULL
518        means removal. It does certainly *not* apply to msxml3! */
519     if(!newChild || !oldChild)
520         return E_INVALIDARG;
521
522     if(outOldChild)
523         *outOldChild = NULL;
524
525     old_child = get_node_obj(oldChild);
526     if(!old_child) {
527         FIXME("oldChild is not our node implementation\n");
528         return E_FAIL;
529     }
530
531     if(old_child->node->parent != This->node)
532     {
533         WARN("childNode %p is not a child of %p\n", oldChild, iface);
534         return E_INVALIDARG;
535     }
536
537     new_child = get_node_obj(newChild);
538     if(!new_child) {
539         FIXME("newChild is not our node implementation\n");
540         return E_FAIL;
541     }
542
543     my_ancestor = This->node;
544     while(my_ancestor)
545     {
546         if(my_ancestor == new_child->node)
547         {
548             WARN("tried to create loop\n");
549             return E_FAIL;
550         }
551         my_ancestor = my_ancestor->parent;
552     }
553
554     if(!new_child->node->parent)
555         if(xmldoc_remove_orphan(new_child->node->doc, new_child->node) != S_OK)
556             WARN("%p is not an orphan of %p\n", new_child->node, new_child->node->doc);
557
558     leaving_doc = new_child->node->doc;
559     xmldoc_add_ref(old_child->node->doc);
560     xmlReplaceNode(old_child->node, new_child->node);
561     xmldoc_release(leaving_doc);
562
563     xmldoc_add_orphan(old_child->node->doc, old_child->node);
564
565     if(outOldChild)
566     {
567         IXMLDOMNode_AddRef(oldChild);
568         *outOldChild = oldChild;
569     }
570
571     return S_OK;
572 }
573
574 static HRESULT WINAPI xmlnode_removeChild(
575     IXMLDOMNode *iface,
576     IXMLDOMNode* childNode,
577     IXMLDOMNode** oldChild)
578 {
579     xmlnode *This = impl_from_IXMLDOMNode( iface );
580     xmlnode *child_node;
581
582     TRACE("(%p)->(%p %p)\n", This, childNode, oldChild);
583
584     if(!childNode) return E_INVALIDARG;
585
586     if(oldChild)
587         *oldChild = NULL;
588
589     child_node = get_node_obj(childNode);
590     if(!child_node) {
591         FIXME("childNode is not our node implementation\n");
592         return E_FAIL;
593     }
594
595     if(child_node->node->parent != This->node)
596     {
597         WARN("childNode %p is not a child of %p\n", childNode, iface);
598         return E_INVALIDARG;
599     }
600
601     xmlUnlinkNode(child_node->node);
602
603     if(oldChild)
604     {
605         IXMLDOMNode_AddRef(childNode);
606         *oldChild = childNode;
607     }
608
609     return S_OK;
610 }
611
612 static HRESULT WINAPI xmlnode_appendChild(
613     IXMLDOMNode *iface,
614     IXMLDOMNode* newChild,
615     IXMLDOMNode** outNewChild)
616 {
617     xmlnode *This = impl_from_IXMLDOMNode( iface );
618     DOMNodeType type;
619     VARIANT var;
620     HRESULT hr;
621
622     TRACE("(%p)->(%p %p)\n", This, newChild, outNewChild);
623
624     hr = IXMLDOMNode_get_nodeType(newChild, &type);
625     if(FAILED(hr) || type == NODE_ATTRIBUTE) {
626         if(outNewChild) *outNewChild = NULL;
627         return E_FAIL;
628     }
629
630     VariantInit(&var);
631     return IXMLDOMNode_insertBefore(This->iface, newChild, var, outNewChild);
632 }
633
634 static HRESULT WINAPI xmlnode_hasChildNodes(
635     IXMLDOMNode *iface,
636     VARIANT_BOOL* hasChild)
637 {
638     xmlnode *This = impl_from_IXMLDOMNode( iface );
639
640     TRACE("(%p)->(%p)\n", This, hasChild);
641
642     if (!hasChild)
643         return E_INVALIDARG;
644     if (!This->node->children)
645     {
646         *hasChild = VARIANT_FALSE;
647         return S_FALSE;
648     }
649
650     *hasChild = VARIANT_TRUE;
651     return S_OK;
652 }
653
654 static HRESULT WINAPI xmlnode_get_ownerDocument(
655     IXMLDOMNode *iface,
656     IXMLDOMDocument** DOMDocument)
657 {
658     xmlnode *This = impl_from_IXMLDOMNode( iface );
659
660     TRACE("(%p)->(%p)\n", This, DOMDocument);
661
662     return DOMDocument_create_from_xmldoc(This->node->doc, (IXMLDOMDocument3**)DOMDocument);
663 }
664
665 static HRESULT WINAPI xmlnode_cloneNode(
666     IXMLDOMNode *iface,
667     VARIANT_BOOL deep,
668     IXMLDOMNode** cloneRoot)
669 {
670     xmlnode *This = impl_from_IXMLDOMNode( iface );
671     xmlNodePtr pClone = NULL;
672     IXMLDOMNode *pNode = NULL;
673
674     TRACE("(%p)->(%d %p)\n", This, deep, cloneRoot);
675
676     if(!cloneRoot)
677         return E_INVALIDARG;
678
679     pClone = xmlCopyNode(This->node, deep ? 1 : 2);
680     if(pClone)
681     {
682         pClone->doc = This->node->doc;
683         xmldoc_add_orphan(pClone->doc, pClone);
684
685         pNode = create_node(pClone);
686         if(!pNode)
687         {
688             ERR("Copy failed\n");
689             return E_FAIL;
690         }
691
692         *cloneRoot = pNode;
693     }
694     else
695     {
696         ERR("Copy failed\n");
697         return E_FAIL;
698     }
699
700     return S_OK;
701 }
702
703 static HRESULT WINAPI xmlnode_get_nodeTypeString(
704     IXMLDOMNode *iface,
705     BSTR* xmlnodeType)
706 {
707     xmlnode *This = impl_from_IXMLDOMNode( iface );
708     const xmlChar *str;
709
710     TRACE("(%p)->(%p)\n", This, xmlnodeType );
711
712     if (!xmlnodeType)
713         return E_INVALIDARG;
714
715     if ( !This->node )
716         return E_FAIL;
717
718     switch( This->node->type )
719     {
720     case XML_ATTRIBUTE_NODE:
721         str = (const xmlChar*) "attribute";
722         break;
723     case XML_CDATA_SECTION_NODE:
724         str = (const xmlChar*) "cdatasection";
725         break;
726     case XML_COMMENT_NODE:
727         str = (const xmlChar*) "comment";
728         break;
729     case XML_DOCUMENT_NODE:
730         str = (const xmlChar*) "document";
731         break;
732     case XML_DOCUMENT_FRAG_NODE:
733         str = (const xmlChar*) "documentfragment";
734         break;
735     case XML_ELEMENT_NODE:
736         str = (const xmlChar*) "element";
737         break;
738     case XML_ENTITY_NODE:
739         str = (const xmlChar*) "entity";
740         break;
741     case XML_ENTITY_REF_NODE:
742         str = (const xmlChar*) "entityreference";
743         break;
744     case XML_NOTATION_NODE:
745         str = (const xmlChar*) "notation";
746         break;
747     case XML_PI_NODE:
748         str = (const xmlChar*) "processinginstruction";
749         break;
750     case XML_TEXT_NODE:
751         str = (const xmlChar*) "text";
752         break;
753     default:
754         FIXME("Unknown node type (%d)\n", This->node->type);
755         str = This->node->name;
756         break;
757     }
758
759     *xmlnodeType = bstr_from_xmlChar( str );
760     if (!*xmlnodeType)
761         return S_FALSE;
762
763     return S_OK;
764 }
765
766 static HRESULT WINAPI xmlnode_get_text(
767     IXMLDOMNode *iface,
768     BSTR* text)
769 {
770     xmlnode *This = impl_from_IXMLDOMNode( iface );
771     BSTR str = NULL;
772     xmlChar *pContent;
773
774     TRACE("(%p, type %d)->(%p)\n", This, This->node->type, text);
775
776     if ( !text )
777         return E_INVALIDARG;
778
779     pContent = xmlNodeGetContent((xmlNodePtr)This->node);
780     if(pContent)
781     {
782         str = bstr_from_xmlChar(pContent);
783         xmlFree(pContent);
784     }
785
786     /* Always return a string. */
787     if (!str) str = SysAllocStringLen( NULL, 0 );
788
789     TRACE("%p %s\n", This, debugstr_w(str) );
790     *text = str;
791  
792     return S_OK;
793 }
794
795 static HRESULT WINAPI xmlnode_put_text(
796     IXMLDOMNode *iface,
797     BSTR text)
798 {
799     xmlnode *This = impl_from_IXMLDOMNode( iface );
800     xmlChar *str, *str2;
801
802     TRACE("(%p)->(%s)\n", This, debugstr_w(text));
803
804     switch(This->node->type)
805     {
806     case XML_DOCUMENT_NODE:
807         return E_FAIL;
808     default:
809         break;
810     }
811
812     str = xmlChar_from_wchar(text);
813
814     /* Escape the string. */
815     str2 = xmlEncodeEntitiesReentrant(This->node->doc, str);
816     heap_free(str);
817
818     xmlNodeSetContent(This->node, str2);
819     xmlFree(str2);
820
821     return S_OK;
822 }
823
824 static HRESULT WINAPI xmlnode_get_specified(
825     IXMLDOMNode *iface,
826     VARIANT_BOOL* isSpecified)
827 {
828     xmlnode *This = impl_from_IXMLDOMNode( iface );
829     FIXME("(%p)->(%p) stub!\n", This, isSpecified);
830     *isSpecified = VARIANT_TRUE;
831     return S_OK;
832 }
833
834 static HRESULT WINAPI xmlnode_get_definition(
835     IXMLDOMNode *iface,
836     IXMLDOMNode** definitionNode)
837 {
838     xmlnode *This = impl_from_IXMLDOMNode( iface );
839     FIXME("(%p)->(%p)\n", This, definitionNode);
840     return E_NOTIMPL;
841 }
842
843 static inline BYTE hex_to_byte(xmlChar c)
844 {
845     if(c <= '9') return c-'0';
846     if(c <= 'F') return c-'A'+10;
847     return c-'a'+10;
848 }
849
850 static inline BYTE base64_to_byte(xmlChar c)
851 {
852     if(c == '+') return 62;
853     if(c == '/') return 63;
854     if(c <= '9') return c-'0'+52;
855     if(c <= 'Z') return c-'A';
856     return c-'a'+26;
857 }
858
859 static inline HRESULT VARIANT_from_xmlChar(xmlChar *str, VARIANT *v, BSTR type)
860 {
861     if(!type || !lstrcmpiW(type, szString) ||
862             !lstrcmpiW(type, szNumber) || !lstrcmpiW(type, szUUID))
863     {
864         V_VT(v) = VT_BSTR;
865         V_BSTR(v) = bstr_from_xmlChar(str);
866
867         if(!V_BSTR(v))
868             return E_OUTOFMEMORY;
869     }
870     else if(!lstrcmpiW(type, szDateTime) || !lstrcmpiW(type, szDateTimeTZ) ||
871             !lstrcmpiW(type, szDate) || !lstrcmpiW(type, szTime) ||
872             !lstrcmpiW(type, szTimeTZ))
873     {
874         VARIANT src;
875         WCHAR *p, *e;
876         SYSTEMTIME st;
877         DOUBLE date = 0.0;
878
879         st.wYear = 1899;
880         st.wMonth = 12;
881         st.wDay = 30;
882         st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
883
884         V_VT(&src) = VT_BSTR;
885         V_BSTR(&src) = bstr_from_xmlChar(str);
886
887         if(!V_BSTR(&src))
888             return E_OUTOFMEMORY;
889
890         p = V_BSTR(&src);
891         e = p + SysStringLen(V_BSTR(&src));
892
893         if(p+4<e && *(p+4)=='-') /* parse date (yyyy-mm-dd) */
894         {
895             st.wYear = atoiW(p);
896             st.wMonth = atoiW(p+5);
897             st.wDay = atoiW(p+8);
898             p += 10;
899
900             if(*p == 'T') p++;
901         }
902
903         if(p+2<e && *(p+2)==':') /* parse time (hh:mm:ss.?) */
904         {
905             st.wHour = atoiW(p);
906             st.wMinute = atoiW(p+3);
907             st.wSecond = atoiW(p+6);
908             p += 8;
909
910             if(*p == '.')
911             {
912                 p++;
913                 while(isdigitW(*p)) p++;
914             }
915         }
916
917         SystemTimeToVariantTime(&st, &date);
918         V_VT(v) = VT_DATE;
919         V_DATE(v) = date;
920
921         if(*p == '+') /* parse timezone offset (+hh:mm) */
922             V_DATE(v) += (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
923         else if(*p == '-') /* parse timezone offset (-hh:mm) */
924             V_DATE(v) -= (DOUBLE)atoiW(p+1)/24 + (DOUBLE)atoiW(p+4)/1440;
925
926         VariantClear(&src);
927     }
928     else if(!lstrcmpiW(type, szBinHex))
929     {
930         SAFEARRAYBOUND sab;
931         int i, len;
932
933         len = xmlStrlen(str)/2;
934         sab.lLbound = 0;
935         sab.cElements = len;
936
937         V_VT(v) = (VT_ARRAY|VT_UI1);
938         V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
939
940         if(!V_ARRAY(v))
941             return E_OUTOFMEMORY;
942
943         for(i=0; i<len; i++)
944             ((BYTE*)V_ARRAY(v)->pvData)[i] = (hex_to_byte(str[2*i])<<4)
945                 + hex_to_byte(str[2*i+1]);
946     }
947     else if(!lstrcmpiW(type, szBinBase64))
948     {
949         SAFEARRAYBOUND sab;
950         int i, len;
951
952         len  = xmlStrlen(str);
953         if(str[len-2] == '=') i = 2;
954         else if(str[len-1] == '=') i = 1;
955         else i = 0;
956
957         sab.lLbound = 0;
958         sab.cElements = len/4*3-i;
959
960         V_VT(v) = (VT_ARRAY|VT_UI1);
961         V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab);
962
963         if(!V_ARRAY(v))
964             return E_OUTOFMEMORY;
965
966         for(i=0; i<len/4; i++)
967         {
968             ((BYTE*)V_ARRAY(v)->pvData)[3*i] = (base64_to_byte(str[4*i])<<2)
969                 + (base64_to_byte(str[4*i+1])>>4);
970             if(3*i+1 < sab.cElements)
971                 ((BYTE*)V_ARRAY(v)->pvData)[3*i+1] = (base64_to_byte(str[4*i+1])<<4)
972                     + (base64_to_byte(str[4*i+2])>>2);
973             if(3*i+2 < sab.cElements)
974                 ((BYTE*)V_ARRAY(v)->pvData)[3*i+2] = (base64_to_byte(str[4*i+2])<<6)
975                     + base64_to_byte(str[4*i+3]);
976         }
977     }
978     else
979     {
980         VARIANT src;
981         HRESULT hres;
982
983         if(!lstrcmpiW(type, szInt) || !lstrcmpiW(type, szI4))
984             V_VT(v) = VT_I4;
985         else if(!lstrcmpiW(type, szFixed))
986             V_VT(v) = VT_CY;
987         else if(!lstrcmpiW(type, szBoolean))
988             V_VT(v) = VT_BOOL;
989         else if(!lstrcmpiW(type, szI1))
990             V_VT(v) = VT_I1;
991         else if(!lstrcmpiW(type, szI2))
992             V_VT(v) = VT_I2;
993         else if(!lstrcmpiW(type, szIU1))
994             V_VT(v) = VT_UI1;
995         else if(!lstrcmpiW(type, szIU2))
996             V_VT(v) = VT_UI2;
997         else if(!lstrcmpiW(type, szIU4))
998             V_VT(v) = VT_UI4;
999         else if(!lstrcmpiW(type, szR4))
1000             V_VT(v) = VT_R4;
1001         else if(!lstrcmpiW(type, szR8) || !lstrcmpiW(type, szFloat))
1002             V_VT(v) = VT_R8;
1003         else
1004         {
1005             FIXME("Type handling not yet implemented\n");
1006             V_VT(v) = VT_BSTR;
1007         }
1008
1009         V_VT(&src) = VT_BSTR;
1010         V_BSTR(&src) = bstr_from_xmlChar(str);
1011
1012         if(!V_BSTR(&src))
1013             return E_OUTOFMEMORY;
1014
1015         hres = VariantChangeTypeEx(v, &src, MAKELCID(MAKELANGID(
1016                         LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT),0, V_VT(v));
1017         VariantClear(&src);
1018         return hres;
1019     }
1020
1021     return S_OK;
1022 }
1023
1024 static HRESULT WINAPI xmlnode_get_nodeTypedValue(
1025     IXMLDOMNode *iface,
1026     VARIANT* typedValue)
1027 {
1028     xmlnode *This = impl_from_IXMLDOMNode( iface );
1029     VARIANT type;
1030     xmlChar *content;
1031     HRESULT hres = S_FALSE;
1032
1033     TRACE("(%p)->(%p)\n", This, typedValue);
1034
1035     if(!typedValue)
1036         return E_INVALIDARG;
1037
1038     V_VT(typedValue) = VT_NULL;
1039
1040     if(This->node->type == XML_ELEMENT_NODE ||
1041             This->node->type == XML_TEXT_NODE ||
1042             This->node->type == XML_ENTITY_REF_NODE)
1043         hres = IXMLDOMNode_get_dataType(This->iface, &type);
1044
1045     if(hres != S_OK && This->node->type != XML_ELEMENT_NODE)
1046         return IXMLDOMNode_get_nodeValue(This->iface, typedValue);
1047
1048     content = xmlNodeGetContent(This->node);
1049     hres = VARIANT_from_xmlChar(content, typedValue,
1050             hres==S_OK ? V_BSTR(&type) : NULL);
1051     xmlFree(content);
1052     VariantClear(&type);
1053
1054     return hres;
1055 }
1056
1057 static HRESULT WINAPI xmlnode_put_nodeTypedValue(
1058     IXMLDOMNode *iface,
1059     VARIANT typedValue)
1060 {
1061     xmlnode *This = impl_from_IXMLDOMNode( iface );
1062     FIXME("%p\n", This);
1063     return E_NOTIMPL;
1064 }
1065
1066 static HRESULT WINAPI xmlnode_get_dataType(
1067     IXMLDOMNode *iface,
1068     VARIANT* dataTypeName)
1069 {
1070     xmlnode *This = impl_from_IXMLDOMNode( iface );
1071     xmlChar *pVal;
1072
1073     TRACE("(%p)->(%p)\n", This, dataTypeName);
1074
1075     if(!dataTypeName)
1076         return E_INVALIDARG;
1077
1078     /* Attribute, CDATA Section, Comment, Document, Document Fragment,
1079         Entity, Notation, PI, and Text Node are non-typed. */
1080     V_BSTR(dataTypeName) = NULL;
1081     V_VT(dataTypeName) = VT_NULL;
1082
1083     switch ( This->node->type )
1084     {
1085     case XML_ELEMENT_NODE:
1086         pVal = xmlGetNsProp(This->node, (const xmlChar*)"dt",
1087                             (const xmlChar*)"urn:schemas-microsoft-com:datatypes");
1088         if (pVal)
1089         {
1090             V_VT(dataTypeName) = VT_BSTR;
1091             V_BSTR(dataTypeName) = bstr_from_xmlChar( pVal );
1092             xmlFree(pVal);
1093         }
1094         break;
1095     case XML_ENTITY_REF_NODE:
1096         FIXME("XML_ENTITY_REF_NODE should return a valid value.\n");
1097         break;
1098     default:
1099         TRACE("Type %d returning NULL\n", This->node->type);
1100     }
1101
1102     /* non-typed nodes return S_FALSE */
1103     if(V_VT(dataTypeName) == VT_NULL)
1104     {
1105         return S_FALSE;
1106     }
1107
1108     return S_OK;
1109 }
1110
1111 static HRESULT WINAPI xmlnode_put_dataType(
1112     IXMLDOMNode *iface,
1113     BSTR dataTypeName)
1114 {
1115     xmlnode *This = impl_from_IXMLDOMNode( iface );
1116     HRESULT hr = E_FAIL;
1117
1118     TRACE("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
1119
1120     if(dataTypeName == NULL)
1121         return E_INVALIDARG;
1122
1123     /* An example of this is. The Text in the node needs to be a 0 or 1 for a boolean type.
1124        This applies to changing types (string->bool) or setting a new one
1125      */
1126     FIXME("Need to Validate the data before allowing a type to be set.\n");
1127
1128     /* Check all supported types. */
1129     if(lstrcmpiW(dataTypeName,szString) == 0  ||
1130        lstrcmpiW(dataTypeName,szNumber) == 0  ||
1131        lstrcmpiW(dataTypeName,szUUID) == 0    ||
1132        lstrcmpiW(dataTypeName,szInt) == 0     ||
1133        lstrcmpiW(dataTypeName,szI4) == 0      ||
1134        lstrcmpiW(dataTypeName,szFixed) == 0   ||
1135        lstrcmpiW(dataTypeName,szBoolean) == 0 ||
1136        lstrcmpiW(dataTypeName,szDateTime) == 0 ||
1137        lstrcmpiW(dataTypeName,szDateTimeTZ) == 0 ||
1138        lstrcmpiW(dataTypeName,szDate) == 0    ||
1139        lstrcmpiW(dataTypeName,szTime) == 0    ||
1140        lstrcmpiW(dataTypeName,szTimeTZ) == 0  ||
1141        lstrcmpiW(dataTypeName,szI1) == 0      ||
1142        lstrcmpiW(dataTypeName,szI2) == 0      ||
1143        lstrcmpiW(dataTypeName,szIU1) == 0     ||
1144        lstrcmpiW(dataTypeName,szIU2) == 0     ||
1145        lstrcmpiW(dataTypeName,szIU4) == 0     ||
1146        lstrcmpiW(dataTypeName,szR4) == 0      ||
1147        lstrcmpiW(dataTypeName,szR8) == 0      ||
1148        lstrcmpiW(dataTypeName,szFloat) == 0   ||
1149        lstrcmpiW(dataTypeName,szBinHex) == 0  ||
1150        lstrcmpiW(dataTypeName,szBinBase64) == 0)
1151     {
1152         xmlNsPtr pNS = NULL;
1153         xmlAttrPtr pAttr = NULL;
1154         xmlChar* str = xmlChar_from_wchar(dataTypeName);
1155
1156         pAttr = xmlHasNsProp(This->node, (const xmlChar*)"dt",
1157                             (const xmlChar*)"urn:schemas-microsoft-com:datatypes");
1158         if (pAttr)
1159         {
1160             pAttr = xmlSetNsProp(This->node, pAttr->ns, (const xmlChar*)"dt", str);
1161
1162             hr = S_OK;
1163         }
1164         else
1165         {
1166             pNS = xmlNewNs(This->node, (const xmlChar*)"urn:schemas-microsoft-com:datatypes", (const xmlChar*)"dt");
1167             if(pNS)
1168             {
1169                 pAttr = xmlNewNsProp(This->node, pNS, (const xmlChar*)"dt", str);
1170                 if(pAttr)
1171                 {
1172                     xmlAddChild(This->node, (xmlNodePtr)pAttr);
1173
1174                     hr = S_OK;
1175                 }
1176                 else
1177                     ERR("Failed to create Attribute\n");
1178             }
1179             else
1180                 ERR("Failed to Create Namepsace\n");
1181         }
1182         heap_free( str );
1183     }
1184
1185     return hr;
1186 }
1187
1188 static BSTR EnsureCorrectEOL(BSTR sInput)
1189 {
1190     int nNum = 0;
1191     BSTR sNew;
1192     int nLen;
1193     int i;
1194
1195     nLen = lstrlenW(sInput);
1196     /* Count line endings */
1197     for(i=0; i < nLen; i++)
1198     {
1199         if(sInput[i] == '\n')
1200             nNum++;
1201     }
1202
1203     TRACE("len=%d, num=%d\n", nLen, nNum);
1204
1205     /* Add linefeed as needed */
1206     if(nNum > 0)
1207     {
1208         int nPlace = 0;
1209         sNew = SysAllocStringLen(NULL, nLen + nNum+1);
1210         for(i=0; i < nLen; i++)
1211         {
1212             if(sInput[i] == '\n')
1213             {
1214                 sNew[i+nPlace] = '\r';
1215                 nPlace++;
1216             }
1217             sNew[i+nPlace] = sInput[i];
1218         }
1219
1220         SysFreeString(sInput);
1221     }
1222     else
1223     {
1224         sNew = sInput;
1225     }
1226
1227     TRACE("len %d\n", lstrlenW(sNew));
1228
1229     return sNew;
1230 }
1231
1232 /* Removes encoding information and last character (nullbyte) */
1233 static BSTR EnsureNoEncoding(BSTR sInput)
1234 {
1235     static const WCHAR wszEncoding[] = {'e','n','c','o','d','i','n','g','='};
1236     BSTR sNew;
1237     WCHAR *pBeg, *pEnd;
1238
1239     pBeg = sInput;
1240     while(*pBeg != '\n' && memcmp(pBeg, wszEncoding, sizeof(wszEncoding)))
1241         pBeg++;
1242
1243     if(*pBeg == '\n')
1244     {
1245         SysReAllocStringLen(&sInput, sInput, SysStringLen(sInput)-1);
1246         return sInput;
1247     }
1248     pBeg--;
1249
1250     pEnd = pBeg + sizeof(wszEncoding)/sizeof(WCHAR) + 2;
1251     while(*pEnd != '\"') pEnd++;
1252     pEnd++;
1253
1254     sNew = SysAllocStringLen(NULL,
1255             pBeg-sInput + SysStringLen(sInput)-(pEnd-sInput)-1);
1256     memcpy(sNew, sInput, (pBeg-sInput)*sizeof(WCHAR));
1257     memcpy(&sNew[pBeg-sInput], pEnd, (SysStringLen(sInput)-(pEnd-sInput)-1)*sizeof(WCHAR));
1258
1259     SysFreeString(sInput);
1260     return sNew;
1261 }
1262
1263 /*
1264  * We are trying to replicate the same behaviour as msxml by converting
1265  * line endings to \r\n and using indents as \t. The problem is that msxml
1266  * only formats nodes that have a line ending. Using libxml we cannot
1267  * reproduce behaviour exactly.
1268  *
1269  */
1270 static HRESULT WINAPI xmlnode_get_xml(
1271     IXMLDOMNode *iface,
1272     BSTR* xmlString)
1273 {
1274     xmlnode *This = impl_from_IXMLDOMNode( iface );
1275     xmlBufferPtr pXmlBuf;
1276     xmlNodePtr xmldecl;
1277     int nSize;
1278
1279     TRACE("(%p %d)->(%p)\n", This, This->node->type, xmlString);
1280
1281     if(!xmlString)
1282         return E_INVALIDARG;
1283
1284     *xmlString = NULL;
1285
1286     xmldecl = xmldoc_unlink_xmldecl( This->node->doc );
1287
1288     pXmlBuf = xmlBufferCreate();
1289     if(pXmlBuf)
1290     {
1291         nSize = xmlNodeDump(pXmlBuf, This->node->doc, This->node, 0, 1);
1292         if(nSize > 0)
1293         {
1294             const xmlChar *pContent;
1295             BSTR bstrContent;
1296
1297             /* Attribute Nodes return a space in front of their name */
1298             pContent = xmlBufferContent(pXmlBuf);
1299             if( ((const char*)pContent)[0] == ' ')
1300                 bstrContent = bstr_from_xmlChar(pContent+1);
1301             else
1302                 bstrContent = bstr_from_xmlChar(pContent);
1303
1304             switch(This->node->type)
1305             {
1306                 case XML_ELEMENT_NODE:
1307                     *xmlString = EnsureCorrectEOL(bstrContent);
1308                     break;
1309                 case XML_DOCUMENT_NODE:
1310                     *xmlString = EnsureCorrectEOL(bstrContent);
1311                     *xmlString = EnsureNoEncoding(*xmlString);
1312                     break;
1313                 default:
1314                     *xmlString = bstrContent;
1315             }
1316         }
1317
1318         xmlBufferFree(pXmlBuf);
1319     }
1320
1321     xmldoc_link_xmldecl( This->node->doc, xmldecl );
1322
1323     /* Always returns a string. */
1324     if(*xmlString == NULL)  *xmlString = SysAllocStringLen( NULL, 0 );
1325
1326     return S_OK;
1327 }
1328
1329 static HRESULT WINAPI xmlnode_transformNode(
1330     IXMLDOMNode *iface,
1331     IXMLDOMNode* styleSheet,
1332     BSTR* xmlString)
1333 {
1334 #ifdef SONAME_LIBXSLT
1335     xmlnode *This = impl_from_IXMLDOMNode( iface );
1336     xmlnode *pStyleSheet = NULL;
1337     xsltStylesheetPtr xsltSS = NULL;
1338     xmlDocPtr result = NULL;
1339
1340     TRACE("(%p)->(%p %p)\n", This, styleSheet, xmlString);
1341
1342     if (!libxslt_handle)
1343         return E_NOTIMPL;
1344     if(!styleSheet || !xmlString)
1345         return E_INVALIDARG;
1346
1347     *xmlString = NULL;
1348
1349     pStyleSheet = get_node_obj(styleSheet);
1350     if(!pStyleSheet) {
1351         FIXME("styleSheet is not our xmlnode implementation\n");
1352         return E_FAIL;
1353     }
1354
1355     xsltSS = pxsltParseStylesheetDoc( pStyleSheet->node->doc);
1356     if(xsltSS)
1357     {
1358         result = pxsltApplyStylesheet(xsltSS, This->node->doc, NULL);
1359         if(result)
1360         {
1361             const xmlChar *pContent;
1362
1363             if(result->type == XML_HTML_DOCUMENT_NODE)
1364             {
1365                 xmlOutputBufferPtr      pOutput = xmlAllocOutputBuffer(NULL);
1366                 if(pOutput)
1367                 {
1368                     htmlDocContentDumpOutput(pOutput, result->doc, NULL);
1369                     pContent = xmlBufferContent(pOutput->buffer);
1370                     *xmlString = bstr_from_xmlChar(pContent);
1371                     xmlOutputBufferClose(pOutput);
1372                 }
1373             }
1374             else
1375             {
1376                 xmlBufferPtr pXmlBuf;
1377                 int nSize;
1378
1379                 pXmlBuf = xmlBufferCreate();
1380                 if(pXmlBuf)
1381                 {
1382                     nSize = xmlNodeDump(pXmlBuf, NULL, (xmlNodePtr)result, 0, 0);
1383                     if(nSize > 0)
1384                     {
1385                         pContent = xmlBufferContent(pXmlBuf);
1386                         *xmlString = bstr_from_xmlChar(pContent);
1387                     }
1388                     xmlBufferFree(pXmlBuf);
1389                 }
1390             }
1391             xmlFreeDoc(result);
1392         }
1393         /* libxslt "helpfully" frees the XML document the stylesheet was
1394            generated from, too */
1395         xsltSS->doc = NULL;
1396         pxsltFreeStylesheet(xsltSS);
1397     }
1398
1399     if(*xmlString == NULL)
1400         *xmlString = SysAllocStringLen(NULL, 0);
1401
1402     return S_OK;
1403 #else
1404     FIXME("libxslt headers were not found at compile time\n");
1405     return E_NOTIMPL;
1406 #endif
1407 }
1408
1409 static HRESULT WINAPI xmlnode_selectNodes(
1410     IXMLDOMNode *iface,
1411     BSTR queryString,
1412     IXMLDOMNodeList** resultList)
1413 {
1414     xmlnode *This = impl_from_IXMLDOMNode( iface );
1415
1416     TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultList );
1417
1418     return queryresult_create( This->node, queryString, resultList );
1419 }
1420
1421 static HRESULT WINAPI xmlnode_selectSingleNode(
1422     IXMLDOMNode *iface,
1423     BSTR queryString,
1424     IXMLDOMNode** resultNode)
1425 {
1426     xmlnode *This = impl_from_IXMLDOMNode( iface );
1427     IXMLDOMNodeList *list;
1428     HRESULT r;
1429
1430     TRACE("(%p)->(%s %p)\n", This, debugstr_w(queryString), resultNode );
1431
1432     *resultNode = NULL;
1433     r = IXMLDOMNode_selectNodes(This->iface, queryString, &list);
1434     if(r == S_OK)
1435     {
1436         r = IXMLDOMNodeList_nextNode(list, resultNode);
1437         IXMLDOMNodeList_Release(list);
1438     }
1439     return r;
1440 }
1441
1442 static HRESULT WINAPI xmlnode_get_parsed(
1443     IXMLDOMNode *iface,
1444     VARIANT_BOOL* isParsed)
1445 {
1446     xmlnode *This = impl_from_IXMLDOMNode( iface );
1447     FIXME("(%p)->(%p) stub!\n", This, isParsed);
1448     *isParsed = VARIANT_TRUE;
1449     return S_OK;
1450 }
1451
1452 static HRESULT WINAPI xmlnode_get_namespaceURI(
1453     IXMLDOMNode *iface,
1454     BSTR* namespaceURI)
1455 {
1456     xmlnode *This = impl_from_IXMLDOMNode( iface );
1457     HRESULT hr = S_FALSE;
1458     xmlNsPtr *pNSList;
1459
1460     TRACE("(%p)->(%p)\n", This, namespaceURI );
1461
1462     if(!namespaceURI)
1463         return E_INVALIDARG;
1464
1465     *namespaceURI = NULL;
1466
1467     pNSList = xmlGetNsList(This->node->doc, This->node);
1468     if(pNSList)
1469     {
1470         *namespaceURI = bstr_from_xmlChar( pNSList[0]->href );
1471
1472         xmlFree( pNSList );
1473         hr = S_OK;
1474     }
1475
1476     return hr;
1477 }
1478
1479 static HRESULT WINAPI xmlnode_get_prefix(
1480     IXMLDOMNode *iface,
1481     BSTR* prefixString)
1482 {
1483     xmlnode *This = impl_from_IXMLDOMNode( iface );
1484     HRESULT hr = S_FALSE;
1485     xmlNsPtr *pNSList;
1486
1487     TRACE("(%p)->(%p)\n", This, prefixString );
1488
1489     if(!prefixString)
1490         return E_INVALIDARG;
1491
1492     *prefixString = NULL;
1493
1494     pNSList = xmlGetNsList(This->node->doc, This->node);
1495     if(pNSList)
1496     {
1497         *prefixString = bstr_from_xmlChar( pNSList[0]->prefix );
1498
1499         xmlFree(pNSList);
1500         hr = S_OK;
1501     }
1502
1503     return hr;
1504 }
1505
1506 static HRESULT WINAPI xmlnode_get_baseName(
1507     IXMLDOMNode *iface,
1508     BSTR* nameString)
1509 {
1510     xmlnode *This = impl_from_IXMLDOMNode( iface );
1511     BSTR str = NULL;
1512     HRESULT r = S_FALSE;
1513
1514     TRACE("(%p)->(%p)\n", This, nameString );
1515
1516     if ( !nameString )
1517         return E_INVALIDARG;
1518
1519     switch ( This->node->type )
1520     {
1521     case XML_ELEMENT_NODE:
1522     case XML_ATTRIBUTE_NODE:
1523     case XML_PI_NODE:
1524         str = bstr_from_xmlChar( This->node->name );
1525         r = S_OK;
1526         break;
1527     case XML_TEXT_NODE:
1528     case XML_COMMENT_NODE:
1529     case XML_DOCUMENT_NODE:
1530         break;
1531     default:
1532         ERR("Unhandled type %d\n", This->node->type );
1533         break;
1534     }
1535
1536     TRACE("returning %08x str = %s\n", r, debugstr_w( str ) );
1537
1538     *nameString = str;
1539     return r;
1540 }
1541
1542 static HRESULT WINAPI xmlnode_transformNodeToObject(
1543     IXMLDOMNode *iface,
1544     IXMLDOMNode* stylesheet,
1545     VARIANT outputObject)
1546 {
1547     xmlnode *This = impl_from_IXMLDOMNode( iface );
1548     FIXME("(%p)->(%p)\n", This, stylesheet);
1549     return E_NOTIMPL;
1550 }
1551
1552 static const struct IXMLDOMNodeVtbl xmlnode_vtbl =
1553 {
1554     xmlnode_QueryInterface,
1555     xmlnode_AddRef,
1556     xmlnode_Release,
1557     xmlnode_GetTypeInfoCount,
1558     xmlnode_GetTypeInfo,
1559     xmlnode_GetIDsOfNames,
1560     xmlnode_Invoke,
1561     xmlnode_get_nodeName,
1562     xmlnode_get_nodeValue,
1563     xmlnode_put_nodeValue,
1564     xmlnode_get_nodeType,
1565     xmlnode_get_parentNode,
1566     xmlnode_get_childNodes,
1567     xmlnode_get_firstChild,
1568     xmlnode_get_lastChild,
1569     xmlnode_get_previousSibling,
1570     xmlnode_get_nextSibling,
1571     xmlnode_get_attributes,
1572     xmlnode_insertBefore,
1573     xmlnode_replaceChild,
1574     xmlnode_removeChild,
1575     xmlnode_appendChild,
1576     xmlnode_hasChildNodes,
1577     xmlnode_get_ownerDocument,
1578     xmlnode_cloneNode,
1579     xmlnode_get_nodeTypeString,
1580     xmlnode_get_text,
1581     xmlnode_put_text,
1582     xmlnode_get_specified,
1583     xmlnode_get_definition,
1584     xmlnode_get_nodeTypedValue,
1585     xmlnode_put_nodeTypedValue,
1586     xmlnode_get_dataType,
1587     xmlnode_put_dataType,
1588     xmlnode_get_xml,
1589     xmlnode_transformNode,
1590     xmlnode_selectNodes,
1591     xmlnode_selectSingleNode,
1592     xmlnode_get_parsed,
1593     xmlnode_get_namespaceURI,
1594     xmlnode_get_prefix,
1595     xmlnode_get_baseName,
1596     xmlnode_transformNodeToObject,
1597 };
1598
1599 void destroy_xmlnode(xmlnode *This)
1600 {
1601     if(This->node)
1602         xmldoc_release(This->node->doc);
1603 }
1604
1605 void init_xmlnode(xmlnode *This, xmlNodePtr node, IXMLDOMNode *node_iface, dispex_static_data_t *dispex_data)
1606 {
1607     if(node)
1608         xmldoc_add_ref( node->doc );
1609
1610     This->lpVtbl = &xmlnode_vtbl;
1611     This->node = node;
1612     This->iface = node_iface;
1613
1614     if(dispex_data)
1615         init_dispex(&This->dispex, (IUnknown*)This->iface, dispex_data);
1616     else
1617         This->dispex.outer = NULL;
1618 }
1619
1620 typedef struct {
1621     xmlnode node;
1622     const IXMLDOMNodeVtbl *lpVtbl;
1623     LONG ref;
1624 } unknode;
1625
1626 static inline unknode *impl_from_unkIXMLDOMNode(IXMLDOMNode *iface)
1627 {
1628     return (unknode *)((char*)iface - FIELD_OFFSET(unknode, lpVtbl));
1629 }
1630
1631 static HRESULT WINAPI unknode_QueryInterface(
1632     IXMLDOMNode *iface,
1633     REFIID riid,
1634     void** ppvObject )
1635 {
1636     unknode *This = impl_from_unkIXMLDOMNode( iface );
1637
1638     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
1639
1640     if (IsEqualGUID(riid, &IID_IUnknown)) {
1641         *ppvObject = iface;
1642     }else if (IsEqualGUID( riid, &IID_IDispatch) ||
1643               IsEqualGUID( riid, &IID_IXMLDOMNode)) {
1644         *ppvObject = &This->lpVtbl;
1645     }else if(node_query_interface(&This->node, riid, ppvObject)) {
1646         return *ppvObject ? S_OK : E_NOINTERFACE;
1647     }else  {
1648         FIXME("interface %s not implemented\n", debugstr_guid(riid));
1649         *ppvObject = NULL;
1650         return E_NOINTERFACE;
1651     }
1652
1653     IUnknown_AddRef((IUnknown*)*ppvObject);
1654     return S_OK;
1655 }
1656
1657 static ULONG WINAPI unknode_AddRef(
1658     IXMLDOMNode *iface )
1659 {
1660     unknode *This = impl_from_unkIXMLDOMNode( iface );
1661
1662     return InterlockedIncrement(&This->ref);
1663 }
1664
1665 static ULONG WINAPI unknode_Release(
1666     IXMLDOMNode *iface )
1667 {
1668     unknode *This = impl_from_unkIXMLDOMNode( iface );
1669     LONG ref;
1670
1671     ref = InterlockedDecrement( &This->ref );
1672     if(!ref) {
1673         destroy_xmlnode(&This->node);
1674         heap_free(This);
1675     }
1676
1677     return ref;
1678 }
1679
1680 static HRESULT WINAPI unknode_GetTypeInfoCount(
1681     IXMLDOMNode *iface,
1682     UINT* pctinfo )
1683 {
1684     unknode *This = impl_from_unkIXMLDOMNode( iface );
1685
1686     TRACE("(%p)->(%p)\n", This, pctinfo);
1687
1688     *pctinfo = 1;
1689
1690     return S_OK;
1691 }
1692
1693 static HRESULT WINAPI unknode_GetTypeInfo(
1694     IXMLDOMNode *iface,
1695     UINT iTInfo,
1696     LCID lcid,
1697     ITypeInfo** ppTInfo )
1698 {
1699     unknode *This = impl_from_unkIXMLDOMNode( iface );
1700     HRESULT hr;
1701
1702     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1703
1704     hr = get_typeinfo(IXMLDOMNode_tid, ppTInfo);
1705
1706     return hr;
1707 }
1708
1709 static HRESULT WINAPI unknode_GetIDsOfNames(
1710     IXMLDOMNode *iface,
1711     REFIID riid,
1712     LPOLESTR* rgszNames,
1713     UINT cNames,
1714     LCID lcid,
1715     DISPID* rgDispId )
1716 {
1717     unknode *This = impl_from_unkIXMLDOMNode( iface );
1718
1719     ITypeInfo *typeinfo;
1720     HRESULT hr;
1721
1722     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1723           lcid, rgDispId);
1724
1725     if(!rgszNames || cNames == 0 || !rgDispId)
1726         return E_INVALIDARG;
1727
1728     hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1729     if(SUCCEEDED(hr))
1730     {
1731         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1732         ITypeInfo_Release(typeinfo);
1733     }
1734
1735     return hr;
1736 }
1737
1738 static HRESULT WINAPI unknode_Invoke(
1739     IXMLDOMNode *iface,
1740     DISPID dispIdMember,
1741     REFIID riid,
1742     LCID lcid,
1743     WORD wFlags,
1744     DISPPARAMS* pDispParams,
1745     VARIANT* pVarResult,
1746     EXCEPINFO* pExcepInfo,
1747     UINT* puArgErr )
1748 {
1749     unknode *This = impl_from_unkIXMLDOMNode( iface );
1750     ITypeInfo *typeinfo;
1751     HRESULT hr;
1752
1753     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1754           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1755
1756     hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo);
1757     if(SUCCEEDED(hr))
1758     {
1759         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
1760                 pVarResult, pExcepInfo, puArgErr);
1761         ITypeInfo_Release(typeinfo);
1762     }
1763
1764     return hr;
1765 }
1766
1767 static HRESULT WINAPI unknode_get_nodeName(
1768     IXMLDOMNode *iface,
1769     BSTR* p )
1770 {
1771     unknode *This = impl_from_unkIXMLDOMNode( iface );
1772
1773     FIXME("(%p)->(%p)\n", This, p);
1774
1775     return node_get_nodeName(&This->node, p);
1776 }
1777
1778 static HRESULT WINAPI unknode_get_nodeValue(
1779     IXMLDOMNode *iface,
1780     VARIANT* value)
1781 {
1782     unknode *This = impl_from_unkIXMLDOMNode( iface );
1783
1784     FIXME("(%p)->(%p)\n", This, value);
1785
1786     if(!value)
1787         return E_INVALIDARG;
1788
1789     V_VT(value) = VT_NULL;
1790     return S_FALSE;
1791 }
1792
1793 static HRESULT WINAPI unknode_put_nodeValue(
1794     IXMLDOMNode *iface,
1795     VARIANT value)
1796 {
1797     unknode *This = impl_from_unkIXMLDOMNode( iface );
1798     FIXME("(%p)->(v%d)\n", This, V_VT(&value));
1799     return E_FAIL;
1800 }
1801
1802 static HRESULT WINAPI unknode_get_nodeType(
1803     IXMLDOMNode *iface,
1804     DOMNodeType* domNodeType )
1805 {
1806     unknode *This = impl_from_unkIXMLDOMNode( iface );
1807
1808     FIXME("(%p)->(%p)\n", This, domNodeType);
1809
1810     *domNodeType = This->node.node->type;
1811     return S_OK;
1812 }
1813
1814 static HRESULT WINAPI unknode_get_parentNode(
1815     IXMLDOMNode *iface,
1816     IXMLDOMNode** parent )
1817 {
1818     unknode *This = impl_from_unkIXMLDOMNode( iface );
1819     FIXME("(%p)->(%p)\n", This, parent);
1820     if (!parent) return E_INVALIDARG;
1821     *parent = NULL;
1822     return S_FALSE;
1823 }
1824
1825 static HRESULT WINAPI unknode_get_childNodes(
1826     IXMLDOMNode *iface,
1827     IXMLDOMNodeList** outList)
1828 {
1829     unknode *This = impl_from_unkIXMLDOMNode( iface );
1830
1831     TRACE("(%p)->(%p)\n", This, outList);
1832
1833     return node_get_child_nodes(&This->node, outList);
1834 }
1835
1836 static HRESULT WINAPI unknode_get_firstChild(
1837     IXMLDOMNode *iface,
1838     IXMLDOMNode** domNode)
1839 {
1840     unknode *This = impl_from_unkIXMLDOMNode( iface );
1841     return IXMLDOMNode_get_firstChild( IXMLDOMNode_from_impl(&This->node), domNode );
1842 }
1843
1844 static HRESULT WINAPI unknode_get_lastChild(
1845     IXMLDOMNode *iface,
1846     IXMLDOMNode** domNode)
1847 {
1848     unknode *This = impl_from_unkIXMLDOMNode( iface );
1849     return IXMLDOMNode_get_lastChild( IXMLDOMNode_from_impl(&This->node), domNode );
1850 }
1851
1852 static HRESULT WINAPI unknode_get_previousSibling(
1853     IXMLDOMNode *iface,
1854     IXMLDOMNode** domNode)
1855 {
1856     unknode *This = impl_from_unkIXMLDOMNode( iface );
1857     return IXMLDOMNode_get_previousSibling( IXMLDOMNode_from_impl(&This->node), domNode );
1858 }
1859
1860 static HRESULT WINAPI unknode_get_nextSibling(
1861     IXMLDOMNode *iface,
1862     IXMLDOMNode** domNode)
1863 {
1864     unknode *This = impl_from_unkIXMLDOMNode( iface );
1865     return IXMLDOMNode_get_nextSibling( IXMLDOMNode_from_impl(&This->node), domNode );
1866 }
1867
1868 static HRESULT WINAPI unknode_get_attributes(
1869     IXMLDOMNode *iface,
1870     IXMLDOMNamedNodeMap** attributeMap)
1871 {
1872     unknode *This = impl_from_unkIXMLDOMNode( iface );
1873     return IXMLDOMNode_get_attributes( IXMLDOMNode_from_impl(&This->node), attributeMap );
1874 }
1875
1876 static HRESULT WINAPI unknode_insertBefore(
1877     IXMLDOMNode *iface,
1878     IXMLDOMNode* newNode, VARIANT var1,
1879     IXMLDOMNode** outOldNode)
1880 {
1881     unknode *This = impl_from_unkIXMLDOMNode( iface );
1882     return IXMLDOMNode_insertBefore( IXMLDOMNode_from_impl(&This->node), newNode, var1, outOldNode );
1883 }
1884
1885 static HRESULT WINAPI unknode_replaceChild(
1886     IXMLDOMNode *iface,
1887     IXMLDOMNode* newNode,
1888     IXMLDOMNode* oldNode,
1889     IXMLDOMNode** outOldNode)
1890 {
1891     unknode *This = impl_from_unkIXMLDOMNode( iface );
1892     return IXMLDOMNode_replaceChild( IXMLDOMNode_from_impl(&This->node), newNode, oldNode, outOldNode );
1893 }
1894
1895 static HRESULT WINAPI unknode_removeChild(
1896     IXMLDOMNode *iface,
1897     IXMLDOMNode* domNode, IXMLDOMNode** oldNode)
1898 {
1899     unknode *This = impl_from_unkIXMLDOMNode( iface );
1900     return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), domNode, oldNode );
1901 }
1902
1903 static HRESULT WINAPI unknode_appendChild(
1904     IXMLDOMNode *iface,
1905     IXMLDOMNode* newNode, IXMLDOMNode** outNewNode)
1906 {
1907     unknode *This = impl_from_unkIXMLDOMNode( iface );
1908     return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newNode, outNewNode );
1909 }
1910
1911 static HRESULT WINAPI unknode_hasChildNodes(
1912     IXMLDOMNode *iface,
1913     VARIANT_BOOL* pbool)
1914 {
1915     unknode *This = impl_from_unkIXMLDOMNode( iface );
1916     return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), pbool );
1917 }
1918
1919 static HRESULT WINAPI unknode_get_ownerDocument(
1920     IXMLDOMNode *iface,
1921     IXMLDOMDocument** domDocument)
1922 {
1923     unknode *This = impl_from_unkIXMLDOMNode( iface );
1924     return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), domDocument );
1925 }
1926
1927 static HRESULT WINAPI unknode_cloneNode(
1928     IXMLDOMNode *iface,
1929     VARIANT_BOOL pbool, IXMLDOMNode** outNode)
1930 {
1931     unknode *This = impl_from_unkIXMLDOMNode( iface );
1932     return IXMLDOMNode_cloneNode( IXMLDOMNode_from_impl(&This->node), pbool, outNode );
1933 }
1934
1935 static HRESULT WINAPI unknode_get_nodeTypeString(
1936     IXMLDOMNode *iface,
1937     BSTR* p)
1938 {
1939     unknode *This = impl_from_unkIXMLDOMNode( iface );
1940     return IXMLDOMNode_get_nodeTypeString( IXMLDOMNode_from_impl(&This->node), p );
1941 }
1942
1943 static HRESULT WINAPI unknode_get_text(
1944     IXMLDOMNode *iface,
1945     BSTR* p)
1946 {
1947     unknode *This = impl_from_unkIXMLDOMNode( iface );
1948     return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), p );
1949 }
1950
1951 static HRESULT WINAPI unknode_put_text(
1952     IXMLDOMNode *iface,
1953     BSTR p)
1954 {
1955     unknode *This = impl_from_unkIXMLDOMNode( iface );
1956     return IXMLDOMNode_put_text( IXMLDOMNode_from_impl(&This->node), p );
1957 }
1958
1959 static HRESULT WINAPI unknode_get_specified(
1960     IXMLDOMNode *iface,
1961     VARIANT_BOOL* pbool)
1962 {
1963     unknode *This = impl_from_unkIXMLDOMNode( iface );
1964     return IXMLDOMNode_get_specified( IXMLDOMNode_from_impl(&This->node), pbool );
1965 }
1966
1967 static HRESULT WINAPI unknode_get_definition(
1968     IXMLDOMNode *iface,
1969     IXMLDOMNode** domNode)
1970 {
1971     unknode *This = impl_from_unkIXMLDOMNode( iface );
1972     return IXMLDOMNode_get_definition( IXMLDOMNode_from_impl(&This->node), domNode );
1973 }
1974
1975 static HRESULT WINAPI unknode_get_nodeTypedValue(
1976     IXMLDOMNode *iface,
1977     VARIANT* var1)
1978 {
1979     unknode *This = impl_from_unkIXMLDOMNode( iface );
1980     return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), var1 );
1981 }
1982
1983 static HRESULT WINAPI unknode_put_nodeTypedValue(
1984     IXMLDOMNode *iface,
1985     VARIANT var1)
1986 {
1987     unknode *This = impl_from_unkIXMLDOMNode( iface );
1988     return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), var1 );
1989 }
1990
1991 static HRESULT WINAPI unknode_get_dataType(
1992     IXMLDOMNode *iface,
1993     VARIANT* var1)
1994 {
1995     unknode *This = impl_from_unkIXMLDOMNode( iface );
1996     return IXMLDOMNode_get_dataType( IXMLDOMNode_from_impl(&This->node), var1 );
1997 }
1998
1999 static HRESULT WINAPI unknode_put_dataType(
2000     IXMLDOMNode *iface,
2001     BSTR p)
2002 {
2003     unknode *This = impl_from_unkIXMLDOMNode( iface );
2004     return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), p );
2005 }
2006
2007 static HRESULT WINAPI unknode_get_xml(
2008     IXMLDOMNode *iface,
2009     BSTR* p)
2010 {
2011     unknode *This = impl_from_unkIXMLDOMNode( iface );
2012     return IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), p );
2013 }
2014
2015 static HRESULT WINAPI unknode_transformNode(
2016     IXMLDOMNode *iface,
2017     IXMLDOMNode* domNode, BSTR* p)
2018 {
2019     unknode *This = impl_from_unkIXMLDOMNode( iface );
2020     return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), domNode, p );
2021 }
2022
2023 static HRESULT WINAPI unknode_selectNodes(
2024     IXMLDOMNode *iface,
2025     BSTR p, IXMLDOMNodeList** outList)
2026 {
2027     unknode *This = impl_from_unkIXMLDOMNode( iface );
2028     return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), p, outList );
2029 }
2030
2031 static HRESULT WINAPI unknode_selectSingleNode(
2032     IXMLDOMNode *iface,
2033     BSTR p, IXMLDOMNode** outNode)
2034 {
2035     unknode *This = impl_from_unkIXMLDOMNode( iface );
2036     return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), p, outNode );
2037 }
2038
2039 static HRESULT WINAPI unknode_get_parsed(
2040     IXMLDOMNode *iface,
2041     VARIANT_BOOL* pbool)
2042 {
2043     unknode *This = impl_from_unkIXMLDOMNode( iface );
2044     return IXMLDOMNode_get_parsed( IXMLDOMNode_from_impl(&This->node), pbool );
2045 }
2046
2047 static HRESULT WINAPI unknode_get_namespaceURI(
2048     IXMLDOMNode *iface,
2049     BSTR* p)
2050 {
2051     unknode *This = impl_from_unkIXMLDOMNode( iface );
2052     return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), p );
2053 }
2054
2055 static HRESULT WINAPI unknode_get_prefix(
2056     IXMLDOMNode *iface,
2057     BSTR* p)
2058 {
2059     unknode *This = impl_from_unkIXMLDOMNode( iface );
2060     return IXMLDOMNode_get_prefix( IXMLDOMNode_from_impl(&This->node), p );
2061 }
2062
2063 static HRESULT WINAPI unknode_get_baseName(
2064     IXMLDOMNode *iface,
2065     BSTR* p)
2066 {
2067     unknode *This = impl_from_unkIXMLDOMNode( iface );
2068     return IXMLDOMNode_get_baseName( IXMLDOMNode_from_impl(&This->node), p );
2069 }
2070
2071 static HRESULT WINAPI unknode_transformNodeToObject(
2072     IXMLDOMNode *iface,
2073     IXMLDOMNode* domNode, VARIANT var1)
2074 {
2075     unknode *This = impl_from_unkIXMLDOMNode( iface );
2076     return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), domNode, var1 );
2077 }
2078
2079 static const struct IXMLDOMNodeVtbl unknode_vtbl =
2080 {
2081     unknode_QueryInterface,
2082     unknode_AddRef,
2083     unknode_Release,
2084     unknode_GetTypeInfoCount,
2085     unknode_GetTypeInfo,
2086     unknode_GetIDsOfNames,
2087     unknode_Invoke,
2088     unknode_get_nodeName,
2089     unknode_get_nodeValue,
2090     unknode_put_nodeValue,
2091     unknode_get_nodeType,
2092     unknode_get_parentNode,
2093     unknode_get_childNodes,
2094     unknode_get_firstChild,
2095     unknode_get_lastChild,
2096     unknode_get_previousSibling,
2097     unknode_get_nextSibling,
2098     unknode_get_attributes,
2099     unknode_insertBefore,
2100     unknode_replaceChild,
2101     unknode_removeChild,
2102     unknode_appendChild,
2103     unknode_hasChildNodes,
2104     unknode_get_ownerDocument,
2105     unknode_cloneNode,
2106     unknode_get_nodeTypeString,
2107     unknode_get_text,
2108     unknode_put_text,
2109     unknode_get_specified,
2110     unknode_get_definition,
2111     unknode_get_nodeTypedValue,
2112     unknode_put_nodeTypedValue,
2113     unknode_get_dataType,
2114     unknode_put_dataType,
2115     unknode_get_xml,
2116     unknode_transformNode,
2117     unknode_selectNodes,
2118     unknode_selectSingleNode,
2119     unknode_get_parsed,
2120     unknode_get_namespaceURI,
2121     unknode_get_prefix,
2122     unknode_get_baseName,
2123     unknode_transformNodeToObject
2124 };
2125
2126 IXMLDOMNode *create_node( xmlNodePtr node )
2127 {
2128     IUnknown *pUnk;
2129     IXMLDOMNode *ret;
2130     HRESULT hr;
2131
2132     if ( !node )
2133         return NULL;
2134
2135     TRACE("type %d\n", node->type);
2136     switch(node->type)
2137     {
2138     case XML_ELEMENT_NODE:
2139         pUnk = create_element( node );
2140         break;
2141     case XML_ATTRIBUTE_NODE:
2142         pUnk = create_attribute( node );
2143         break;
2144     case XML_TEXT_NODE:
2145         pUnk = create_text( node );
2146         break;
2147     case XML_CDATA_SECTION_NODE:
2148         pUnk = create_cdata( node );
2149         break;
2150     case XML_ENTITY_REF_NODE:
2151         pUnk = create_doc_entity_ref( node );
2152         break;
2153     case XML_PI_NODE:
2154         pUnk = create_pi( node );
2155         break;
2156     case XML_COMMENT_NODE:
2157         pUnk = create_comment( node );
2158         break;
2159     case XML_DOCUMENT_NODE:
2160         pUnk = create_domdoc( node );
2161         break;
2162     case XML_DOCUMENT_FRAG_NODE:
2163         pUnk = create_doc_fragment( node );
2164         break;
2165     default: {
2166         unknode *new_node;
2167
2168         FIXME("only creating basic node for type %d\n", node->type);
2169
2170         new_node = heap_alloc(sizeof(unknode));
2171         if(!new_node)
2172             return NULL;
2173
2174         new_node->lpVtbl = &unknode_vtbl;
2175         new_node->ref = 1;
2176         init_xmlnode(&new_node->node, node, (IXMLDOMNode*)&new_node->lpVtbl, NULL);
2177         pUnk = (IUnknown*)&new_node->lpVtbl;
2178     }
2179     }
2180
2181     hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
2182     IUnknown_Release(pUnk);
2183     if(FAILED(hr)) return NULL;
2184     return ret;
2185 }
2186 #endif