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