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