winspool.drv: Fix the character count passed into RegEnumKeyExW in get_local_monitors.
[wine] / dlls / msxml3 / node.c
1 /*
2  *    Node implementation
3  *
4  * Copyright 2005 Mike McCormack
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22
23 #define COBJMACROS
24
25 #include <stdarg.h>
26 #include <assert.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "winnls.h"
31 #include "ole2.h"
32 #include "msxml2.h"
33
34 #include "msxml_private.h"
35
36 #include "wine/debug.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
39
40 #ifdef HAVE_LIBXML2
41
42 static const WCHAR szBinBase64[]  = {'b','i','n','.','b','a','s','e','6','4',0};
43 static const WCHAR szString[]     = {'s','t','r','i','n','g',0};
44 static const WCHAR szNumber[]     = {'n','u','m','b','e','r',0};
45 static const WCHAR szInt[]        = {'I','n','t',0};
46 static const WCHAR szFixed[]      = {'F','i','x','e','d','.','1','4','.','4',0};
47 static const WCHAR szBoolean[]    = {'B','o','o','l','e','a','n',0};
48 static const WCHAR szDateTime[]   = {'d','a','t','e','T','i','m','e',0};
49 static const WCHAR szDateTimeTZ[] = {'d','a','t','e','T','i','m','e','.','t','z',0};
50 static const WCHAR szDate[]       = {'D','a','t','e',0};
51 static const WCHAR szTime[]       = {'T','i','m','e',0};
52 static const WCHAR szTimeTZ[]     = {'T','i','m','e','.','t','z',0};
53 static const WCHAR szI1[]         = {'i','1',0};
54 static const WCHAR szByte[]       = {'B','y','t','e',0};
55 static const WCHAR szI2[]         = {'i','2',0};
56 static const WCHAR szI4[]         = {'i','4',0};
57 static const WCHAR szIU1[]        = {'u','i','1',0};
58 static const WCHAR szIU2[]        = {'u','i','2',0};
59 static const WCHAR szIU4[]        = {'u','i','4',0};
60 static const WCHAR szR4[]         = {'r','4',0};
61 static const WCHAR szR8[]         = {'r','8',0};
62 static const WCHAR szFloat[]      = {'f','l','o','a','t',0};
63 static const WCHAR szUUID[]       = {'u','u','i','d',0};
64 static const WCHAR szBinHex[]     = {'b','i','n','.','h','e','x',0};
65
66 static inline xmlnode *impl_from_InternalUnknown( IUnknown *iface )
67 {
68     return (xmlnode *)((char*)iface - FIELD_OFFSET(xmlnode, lpInternalUnkVtbl));
69 }
70
71 xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type )
72 {
73     xmlnode *This;
74
75     if ( !iface )
76         return NULL;
77     This = impl_from_IXMLDOMNode( iface );
78     if ( !This->node )
79         return NULL;
80     if ( type && This->node->type != type )
81         return NULL;
82     return This->node;
83 }
84
85 void attach_xmlnode( IXMLDOMNode *node, xmlNodePtr xml )
86 {
87     xmlnode *This = impl_from_IXMLDOMNode( node );
88
89     if(This->node)
90         xmldoc_release(This->node->doc);
91
92     This->node = xml;
93     if(This->node)
94         xmldoc_add_ref(This->node->doc);
95
96     return;
97 }
98
99 static HRESULT WINAPI xmlnode_QueryInterface(
100     IXMLDOMNode *iface,
101     REFIID riid,
102     void** ppvObject )
103 {
104     xmlnode *This = impl_from_IXMLDOMNode( iface );
105     TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
106
107     return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObject);
108 }
109
110 static ULONG WINAPI xmlnode_AddRef(
111     IXMLDOMNode *iface )
112 {
113     xmlnode *This = impl_from_IXMLDOMNode( iface );
114     return IUnknown_AddRef(This->pUnkOuter);
115 }
116
117 static ULONG WINAPI xmlnode_Release(
118     IXMLDOMNode *iface )
119 {
120     xmlnode *This = impl_from_IXMLDOMNode( iface );
121     return IUnknown_Release(This->pUnkOuter);
122 }
123
124 static HRESULT WINAPI xmlnode_GetTypeInfoCount(
125     IXMLDOMNode *iface,
126     UINT* pctinfo )
127 {
128     FIXME("\n");
129     return E_NOTIMPL;
130 }
131
132 static HRESULT WINAPI xmlnode_GetTypeInfo(
133     IXMLDOMNode *iface,
134     UINT iTInfo,
135     LCID lcid,
136     ITypeInfo** ppTInfo )
137 {
138     FIXME("\n");
139     return E_NOTIMPL;
140 }
141
142 static HRESULT WINAPI xmlnode_GetIDsOfNames(
143     IXMLDOMNode *iface,
144     REFIID riid,
145     LPOLESTR* rgszNames,
146     UINT cNames,
147     LCID lcid,
148     DISPID* rgDispId )
149 {
150     FIXME("\n");
151     return E_NOTIMPL;
152 }
153
154 static HRESULT WINAPI xmlnode_Invoke(
155     IXMLDOMNode *iface,
156     DISPID dispIdMember,
157     REFIID riid,
158     LCID lcid,
159     WORD wFlags,
160     DISPPARAMS* pDispParams,
161     VARIANT* pVarResult,
162     EXCEPINFO* pExcepInfo,
163     UINT* puArgErr )
164 {
165     FIXME("\n");
166     return E_NOTIMPL;
167 }
168
169 static HRESULT WINAPI xmlnode_get_nodeName(
170     IXMLDOMNode *iface,
171     BSTR* name)
172 {
173     xmlnode *This = impl_from_IXMLDOMNode( iface );
174     const xmlChar *str;
175
176     TRACE("%p\n", This );
177
178     if (!name)
179         return E_INVALIDARG;
180
181     if ( !This->node )
182         return E_FAIL;
183
184     switch( This->node->type )
185     {
186     case XML_CDATA_SECTION_NODE:
187         str = (const xmlChar*) "#cdata-section";
188         break;
189     case XML_COMMENT_NODE:
190         str = (const xmlChar*) "#comment";
191         break;
192     case XML_DOCUMENT_FRAG_NODE:
193         str = (const xmlChar*) "#document-fragment";
194         break;
195     case XML_TEXT_NODE:
196          str = (const xmlChar*) "#text";
197          break;
198     case XML_DOCUMENT_NODE:
199          str = (const xmlChar*) "#document";
200             break;
201         case XML_ATTRIBUTE_NODE:
202         case XML_ELEMENT_NODE:
203         str = This->node->name;
204             break;
205     default:
206         FIXME("nodeName not mapped correctly (%d)\n", This->node->type);
207         str = This->node->name;
208         break;
209     }
210
211     *name = bstr_from_xmlChar( str );
212     if (!*name)
213         return S_FALSE;
214
215     return S_OK;
216 }
217
218 BSTR bstr_from_xmlChar( const xmlChar *buf )
219 {
220     DWORD len;
221     LPWSTR str;
222     BSTR bstr;
223
224     if ( !buf )
225         return NULL;
226
227     len = MultiByteToWideChar( CP_UTF8, 0, (LPCSTR) buf, -1, NULL, 0 );
228     str = (LPWSTR) HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
229     if ( !str )
230         return NULL;
231     MultiByteToWideChar( CP_UTF8, 0, (LPCSTR) buf, -1, str, len );
232     bstr = SysAllocString( str );
233     HeapFree( GetProcessHeap(), 0, str );
234     return bstr;
235 }
236
237 static HRESULT WINAPI xmlnode_get_nodeValue(
238     IXMLDOMNode *iface,
239     VARIANT* value)
240 {
241     xmlnode *This = impl_from_IXMLDOMNode( iface );
242     HRESULT r = S_FALSE;
243
244     TRACE("%p %p\n", This, value);
245
246     if(!value)
247         return E_INVALIDARG;
248
249     V_BSTR(value) = NULL;
250     V_VT(value) = VT_NULL;
251
252     switch ( This->node->type )
253     {
254     case XML_PI_NODE:
255     case XML_ATTRIBUTE_NODE:
256       {
257         xmlChar *content = xmlNodeGetContent(This->node);
258         V_VT(value) = VT_BSTR;
259         V_BSTR(value) = bstr_from_xmlChar( content );
260         xmlFree(content);
261         r = S_OK;
262         break;
263       }
264     case XML_TEXT_NODE:
265         V_VT(value) = VT_BSTR;
266         V_BSTR(value) = bstr_from_xmlChar( This->node->content );
267         r = S_OK;
268         break;
269     case XML_ELEMENT_NODE:
270     case XML_DOCUMENT_NODE:
271         /* these seem to return NULL */
272         break;
273
274     default:
275         FIXME("node %p type %d\n", This, This->node->type);
276     }
277  
278     TRACE("%p returned %s\n", This, debugstr_w( V_BSTR(value) ) );
279
280     return r;
281 }
282
283 static HRESULT WINAPI xmlnode_put_nodeValue(
284     IXMLDOMNode *iface,
285     VARIANT value)
286 {
287     FIXME("\n");
288     return E_NOTIMPL;
289 }
290
291 static HRESULT WINAPI xmlnode_get_nodeType(
292     IXMLDOMNode *iface,
293     DOMNodeType* type)
294 {
295     xmlnode *This = impl_from_IXMLDOMNode( iface );
296
297     TRACE("%p %p\n", This, type);
298
299     assert( NODE_ELEMENT == XML_ELEMENT_NODE );
300     assert( NODE_NOTATION == XML_NOTATION_NODE );
301
302     *type = This->node->type;
303
304     return S_OK;
305 }
306
307 static HRESULT get_node(
308     xmlnode *This,
309     const char *name,
310     xmlNodePtr node,
311     IXMLDOMNode **out )
312 {
313     TRACE("%p->%s %p\n", This, name, node );
314
315     if ( !out )
316         return E_INVALIDARG;
317     *out = create_node( node );
318     if (!*out)
319         return S_FALSE;
320     return S_OK;
321 }
322
323 static HRESULT WINAPI xmlnode_get_parentNode(
324     IXMLDOMNode *iface,
325     IXMLDOMNode** parent)
326 {
327     xmlnode *This = impl_from_IXMLDOMNode( iface );
328     return get_node( This, "parent", This->node->parent, parent );
329 }
330
331 static HRESULT WINAPI xmlnode_get_childNodes(
332     IXMLDOMNode *iface,
333     IXMLDOMNodeList** childList)
334 {
335     xmlnode *This = impl_from_IXMLDOMNode( iface );
336
337     TRACE("%p %p\n", This, childList );
338
339     if ( !childList )
340         return E_INVALIDARG;
341
342     *childList = create_children_nodelist(This->node);
343     if (*childList == NULL)
344         return E_OUTOFMEMORY;
345
346     return S_OK;
347 }
348
349 static HRESULT WINAPI xmlnode_get_firstChild(
350     IXMLDOMNode *iface,
351     IXMLDOMNode** firstChild)
352 {
353     xmlnode *This = impl_from_IXMLDOMNode( iface );
354     return get_node( This, "firstChild", This->node->children, firstChild );
355 }
356
357 static HRESULT WINAPI xmlnode_get_lastChild(
358     IXMLDOMNode *iface,
359     IXMLDOMNode** lastChild)
360 {
361     xmlnode *This = impl_from_IXMLDOMNode( iface );
362
363     TRACE("%p\n", This );
364
365     if (!lastChild)
366         return E_INVALIDARG;
367
368     switch( This->node->type )
369     {
370     /* CDATASection, Comment, PI and Text Nodes do not support lastChild */
371     case XML_TEXT_NODE:
372     case XML_CDATA_SECTION_NODE:
373     case XML_PI_NODE:
374     case XML_COMMENT_NODE:
375         *lastChild = NULL;
376         return S_FALSE;
377     default:
378         return get_node( This, "lastChild", This->node->last, lastChild );
379     }
380 }
381
382 static HRESULT WINAPI xmlnode_get_previousSibling(
383     IXMLDOMNode *iface,
384     IXMLDOMNode** previousSibling)
385 {
386     xmlnode *This = impl_from_IXMLDOMNode( iface );
387
388     TRACE("%p\n", This );
389
390     if (!previousSibling)
391         return E_INVALIDARG;
392
393     switch( This->node->type )
394     {
395     /* Attribute, Document and Document Fragment Nodes do not support previousSibling */
396     case XML_DOCUMENT_NODE:
397     case XML_DOCUMENT_FRAG_NODE:
398     case XML_ATTRIBUTE_NODE:
399         *previousSibling = NULL;
400         return S_FALSE;
401     default:
402         return get_node( This, "previous", This->node->prev, previousSibling );
403     }
404 }
405
406 static HRESULT WINAPI xmlnode_get_nextSibling(
407     IXMLDOMNode *iface,
408     IXMLDOMNode** nextSibling)
409 {
410     xmlnode *This = impl_from_IXMLDOMNode( iface );
411
412     TRACE("%p\n", This );
413
414     if (!nextSibling)
415         return E_INVALIDARG;
416
417     switch( This->node->type )
418     {
419     /* Attribute, Document and Document Fragment Nodes do not support nextSibling */
420     case XML_DOCUMENT_NODE:
421     case XML_DOCUMENT_FRAG_NODE:
422     case XML_ATTRIBUTE_NODE:
423         *nextSibling = NULL;
424         return S_FALSE;
425     default:
426         return get_node( This, "next", This->node->next, nextSibling );
427     }
428 }
429
430 static HRESULT WINAPI xmlnode_get_attributes(
431     IXMLDOMNode *iface,
432     IXMLDOMNamedNodeMap** attributeMap)
433 {
434     xmlnode *This = impl_from_IXMLDOMNode( iface );
435     TRACE("%p\n", This);
436
437     if (!attributeMap)
438         return E_INVALIDARG;
439
440     switch( This->node->type )
441     {
442     /* Attribute, CDataSection, Comment, Documents, Documents Fragments,
443        Entity and Text Nodes does not support get_attributes */
444     case XML_ATTRIBUTE_NODE:
445     case XML_CDATA_SECTION_NODE:
446     case XML_COMMENT_NODE:
447     case XML_DOCUMENT_NODE:
448     case XML_DOCUMENT_FRAG_NODE:
449     case XML_ENTITY_NODE:
450     case XML_ENTITY_REF_NODE:
451     case XML_TEXT_NODE:
452         *attributeMap = NULL;
453         return S_FALSE;
454     default:
455         *attributeMap = create_nodemap( iface );
456         return S_OK;
457     }
458 }
459
460 static HRESULT WINAPI xmlnode_insertBefore(
461     IXMLDOMNode *iface,
462     IXMLDOMNode* newChild,
463     VARIANT refChild,
464     IXMLDOMNode** outNewChild)
465 {
466     xmlnode *This = impl_from_IXMLDOMNode( iface );
467     xmlNodePtr before_node, new_child_node;
468     IXMLDOMNode *before = NULL, *new;
469     HRESULT hr;
470
471     TRACE("(%p)->(%p,var,%p)\n",This,newChild,outNewChild);
472
473     if (!newChild)
474         return E_INVALIDARG;
475
476     switch(V_VT(&refChild))
477     {
478     case VT_EMPTY:
479     case VT_NULL:
480         break;
481
482     case VT_UNKNOWN:
483         hr = IUnknown_QueryInterface(V_UNKNOWN(&refChild), &IID_IXMLDOMNode, (LPVOID)&before);
484         if(FAILED(hr)) return hr;
485         break;
486
487     case VT_DISPATCH:
488         hr = IDispatch_QueryInterface(V_DISPATCH(&refChild), &IID_IXMLDOMNode, (LPVOID)&before);
489         if(FAILED(hr)) return hr;
490         break;
491
492     default:
493         FIXME("refChild var type %x\n", V_VT(&refChild));
494         return E_FAIL;
495     }
496
497     IXMLDOMNode_QueryInterface(newChild, &IID_IXMLDOMNode, (LPVOID)&new);
498     new_child_node = impl_from_IXMLDOMNode(new)->node;
499     TRACE("new_child_node %p This->node %p\n", new_child_node, This->node);
500
501     if(before)
502     {
503         before_node = impl_from_IXMLDOMNode(before)->node;
504         xmlAddPrevSibling(before_node, new_child_node);
505         IXMLDOMNode_Release(before);
506     }
507     else
508     {
509         xmlAddChild(This->node, new_child_node);
510     }
511
512     IXMLDOMNode_Release(new);
513     IXMLDOMNode_AddRef(newChild);
514     if(outNewChild)
515         *outNewChild = newChild;
516
517     TRACE("ret S_OK\n");
518     return S_OK;
519 }
520
521 static HRESULT WINAPI xmlnode_replaceChild(
522     IXMLDOMNode *iface,
523     IXMLDOMNode* newChild,
524     IXMLDOMNode* oldChild,
525     IXMLDOMNode** outOldChild)
526 {
527     FIXME("\n");
528     return E_NOTIMPL;
529 }
530
531 static HRESULT WINAPI xmlnode_removeChild(
532     IXMLDOMNode *iface,
533     IXMLDOMNode* childNode,
534     IXMLDOMNode** oldChild)
535 {
536     xmlnode *This = impl_from_IXMLDOMNode( iface );
537     xmlNode *ancestor, *child_node_ptr;
538     HRESULT hr;
539     IXMLDOMNode *child;
540
541     TRACE("%p->(%p, %p)\n", This, childNode, oldChild);
542
543     *oldChild = NULL;
544
545     if(!childNode) return E_INVALIDARG;
546
547     hr = IXMLDOMNode_QueryInterface(childNode, &IID_IXMLDOMNode, (LPVOID)&child);
548     if(FAILED(hr))
549         return hr;
550
551     child_node_ptr = ancestor = impl_from_IXMLDOMNode(child)->node;
552     while(ancestor->parent)
553     {
554         if(ancestor->parent == This->node)
555             break;
556         ancestor = ancestor->parent;
557     }
558     if(!ancestor->parent)
559     {
560         WARN("childNode %p is not a child of %p\n", childNode, iface);
561         IXMLDOMNode_Release(child);
562         return E_INVALIDARG;
563     }
564
565     xmlUnlinkNode(child_node_ptr);
566
567     IXMLDOMNode_Release(child);
568     IXMLDOMNode_AddRef(childNode);
569     *oldChild = childNode;
570     return S_OK;
571 }
572
573 static HRESULT WINAPI xmlnode_appendChild(
574     IXMLDOMNode *iface,
575     IXMLDOMNode* newChild,
576     IXMLDOMNode** outNewChild)
577 {
578     xmlnode *This = impl_from_IXMLDOMNode( iface );
579     IXMLDOMNode *pAttr = NULL;
580     VARIANT var;
581
582     TRACE("(%p)->(%p,%p)\n", This, newChild, outNewChild);
583
584     /* Cannot Append an Attribute node. */
585     IUnknown_QueryInterface(newChild, &IID_IXMLDOMNode, (LPVOID*)&pAttr);
586     if(pAttr)
587     {
588         xmlnode *ThisNew = impl_from_IXMLDOMNode( pAttr );
589
590         if(ThisNew->node->type == XML_ATTRIBUTE_NODE)
591         {
592             if(outNewChild) *outNewChild = NULL;
593
594             IUnknown_Release(pAttr);
595
596             return E_FAIL;
597         }
598
599         IUnknown_Release(pAttr);
600     }
601
602     VariantInit(&var);
603     return IXMLDOMNode_insertBefore(iface, newChild, var, outNewChild);
604 }
605
606 static HRESULT WINAPI xmlnode_hasChildNodes(
607     IXMLDOMNode *iface,
608     VARIANT_BOOL* hasChild)
609 {
610     xmlnode *This = impl_from_IXMLDOMNode( iface );
611
612     TRACE("%p\n", This);
613
614     if (!hasChild)
615         return E_INVALIDARG;
616     if (!This->node->children)
617     {
618         *hasChild = VARIANT_FALSE;
619         return S_FALSE;
620     }
621
622     *hasChild = VARIANT_TRUE;
623     return S_OK;
624 }
625
626 static HRESULT WINAPI xmlnode_get_ownerDocument(
627     IXMLDOMNode *iface,
628     IXMLDOMDocument** DOMDocument)
629 {
630     FIXME("\n");
631     return E_NOTIMPL;
632 }
633
634 static HRESULT WINAPI xmlnode_cloneNode(
635     IXMLDOMNode *iface,
636     VARIANT_BOOL deep,
637     IXMLDOMNode** cloneRoot)
638 {
639     xmlnode *This = impl_from_IXMLDOMNode( iface );
640     xmlNodePtr pClone = NULL;
641     IXMLDOMNode *pNode = NULL;
642
643     TRACE("%p (%d)\n", This, deep);
644
645     if(!cloneRoot)
646         return E_INVALIDARG;
647
648     pClone = xmlCopyNode(This->node, deep ? 1 : 2);
649     if(pClone)
650     {
651         pClone->doc = This->node->doc;
652
653         pNode = create_node(pClone);
654         if(!pNode)
655         {
656             ERR("Copy failed\n");
657             return E_FAIL;
658         }
659
660         *cloneRoot = pNode;
661     }
662     else
663     {
664         ERR("Copy failed\n");
665         return E_FAIL;
666     }
667
668     return S_OK;
669 }
670
671 static HRESULT WINAPI xmlnode_get_nodeTypeString(
672     IXMLDOMNode *iface,
673     BSTR* xmlnodeType)
674 {
675     xmlnode *This = impl_from_IXMLDOMNode( iface );
676     const xmlChar *str;
677
678     TRACE("%p\n", This );
679
680     if (!xmlnodeType)
681         return E_INVALIDARG;
682
683     if ( !This->node )
684         return E_FAIL;
685
686     switch( This->node->type )
687     {
688     case XML_ATTRIBUTE_NODE:
689         str = (const xmlChar*) "attribute";
690         break;
691     case XML_CDATA_SECTION_NODE:
692         str = (const xmlChar*) "cdatasection";
693         break;
694     case XML_COMMENT_NODE:
695         str = (const xmlChar*) "comment";
696         break;
697     case XML_DOCUMENT_NODE:
698         str = (const xmlChar*) "document";
699         break;
700     case XML_DOCUMENT_FRAG_NODE:
701         str = (const xmlChar*) "documentfragment";
702         break;
703     case XML_ELEMENT_NODE:
704         str = (const xmlChar*) "element";
705         break;
706     case XML_ENTITY_NODE:
707         str = (const xmlChar*) "entity";
708         break;
709     case XML_ENTITY_REF_NODE:
710         str = (const xmlChar*) "entityreference";
711         break;
712     case XML_NOTATION_NODE:
713         str = (const xmlChar*) "notation";
714         break;
715     case XML_PI_NODE:
716         str = (const xmlChar*) "processinginstruction";
717         break;
718     case XML_TEXT_NODE:
719         str = (const xmlChar*) "text";
720         break;
721     default:
722         FIXME("nodeName not mapped correctly (%d)\n", This->node->type);
723         str = This->node->name;
724         break;
725     }
726
727     *xmlnodeType = bstr_from_xmlChar( str );
728     if (!*xmlnodeType)
729         return S_FALSE;
730
731     return S_OK;
732 }
733
734 static HRESULT WINAPI xmlnode_get_text(
735     IXMLDOMNode *iface,
736     BSTR* text)
737 {
738     xmlnode *This = impl_from_IXMLDOMNode( iface );
739     BSTR str = NULL;
740
741     TRACE("%p\n", This);
742
743     if ( !text )
744         return E_INVALIDARG;
745
746     switch(This->node->type)
747     {
748     case XML_ELEMENT_NODE:
749     case XML_ATTRIBUTE_NODE:
750     {
751         xmlNodePtr child = This->node->children;
752         if ( child && child->type == XML_TEXT_NODE )
753             str = bstr_from_xmlChar( child->content );
754         break;
755     }
756
757     case XML_TEXT_NODE:
758     case XML_CDATA_SECTION_NODE:
759     case XML_PI_NODE:
760     case XML_COMMENT_NODE:
761         str = bstr_from_xmlChar( This->node->content );
762         break;
763
764     default:
765         FIXME("Unhandled node type %d\n", This->node->type);
766     }
767
768     /* Always return a string. */
769     if (!str) str = SysAllocStringLen( NULL, 0 );
770
771     TRACE("%p %s\n", This, debugstr_w(str) );
772     *text = str;
773  
774     return S_OK;
775 }
776
777 static HRESULT WINAPI xmlnode_put_text(
778     IXMLDOMNode *iface,
779     BSTR text)
780 {
781     xmlnode *This = impl_from_IXMLDOMNode( iface );
782     xmlChar *str = NULL;
783
784     TRACE("%p\n", This);
785
786     switch(This->node->type)
787     {
788     case XML_DOCUMENT_NODE:
789         return E_FAIL;
790     default:
791         break;
792     }
793
794     str = xmlChar_from_wchar((WCHAR*)text);
795
796     /* Escape the string. */
797     str = xmlEncodeEntitiesReentrant(This->node->doc, str);
798     str = xmlEncodeSpecialChars(This->node->doc, str);
799
800     xmlNodeSetContent(This->node, str);
801     xmlFree(str);
802
803     return S_OK;
804 }
805
806 static HRESULT WINAPI xmlnode_get_specified(
807     IXMLDOMNode *iface,
808     VARIANT_BOOL* isSpecified)
809 {
810     FIXME("\n");
811     return E_NOTIMPL;
812 }
813
814 static HRESULT WINAPI xmlnode_get_definition(
815     IXMLDOMNode *iface,
816     IXMLDOMNode** definitionNode)
817 {
818     FIXME("\n");
819     return E_NOTIMPL;
820 }
821
822 static HRESULT WINAPI xmlnode_get_nodeTypedValue(
823     IXMLDOMNode *iface,
824     VARIANT* typedValue)
825 {
826     FIXME("ignoring data type\n");
827     return xmlnode_get_nodeValue(iface, typedValue);
828 }
829
830 static HRESULT WINAPI xmlnode_put_nodeTypedValue(
831     IXMLDOMNode *iface,
832     VARIANT typedValue)
833 {
834     FIXME("\n");
835     return E_NOTIMPL;
836 }
837
838 static HRESULT WINAPI xmlnode_get_dataType(
839     IXMLDOMNode *iface,
840     VARIANT* dataTypeName)
841 {
842     xmlnode *This = impl_from_IXMLDOMNode( iface );
843     xmlChar *pVal;
844
845     TRACE("iface %p\n", iface);
846
847     if(!dataTypeName)
848         return E_INVALIDARG;
849
850     /* Attribute, CDATA Section, Comment, Document, Document Fragment,
851         Entity, Notation, PI, and Text Node are non-typed. */
852     V_BSTR(dataTypeName) = NULL;
853     V_VT(dataTypeName) = VT_NULL;
854
855     switch ( This->node->type )
856     {
857     case XML_ELEMENT_NODE:
858         pVal = xmlGetNsProp(This->node, (xmlChar*)"dt",
859                             (xmlChar*)"urn:schemas-microsoft-com:datatypes");
860         if (pVal)
861         {
862             V_VT(dataTypeName) = VT_BSTR;
863             V_BSTR(dataTypeName) = bstr_from_xmlChar( pVal );
864             xmlFree(pVal);
865         }
866         break;
867     case XML_ENTITY_REF_NODE:
868         FIXME("XML_ENTITY_REF_NODE should return a valid value.\n");
869         break;
870     default:
871         TRACE("Type %d returning NULL\n", This->node->type);
872     }
873
874     /* non-typed nodes return S_FALSE */
875     if(V_VT(dataTypeName) == VT_NULL)
876     {
877         return S_FALSE;
878     }
879
880     return S_OK;
881 }
882
883 static HRESULT WINAPI xmlnode_put_dataType(
884     IXMLDOMNode *iface,
885     BSTR dataTypeName)
886 {
887     xmlnode *This = impl_from_IXMLDOMNode( iface );
888     HRESULT hr = E_FAIL;
889
890     TRACE("iface %p\n", iface);
891
892     if(dataTypeName == NULL)
893         return E_INVALIDARG;
894
895     /* An example of this is. The Text in the node needs to be a 0 or 1 for a boolean type.
896        This applies to changing types (string->bool) or setting a new one
897      */
898     FIXME("Need to Validate the data before allowing a type to be set.\n");
899
900     /* Check all supported types. */
901     if(lstrcmpiW(dataTypeName,szString) == 0  ||
902        lstrcmpiW(dataTypeName,szNumber) == 0  ||
903        lstrcmpiW(dataTypeName,szUUID) == 0    ||
904        lstrcmpiW(dataTypeName,szInt) == 0     ||
905        lstrcmpiW(dataTypeName,szI4) == 0      ||
906        lstrcmpiW(dataTypeName,szFixed) == 0   ||
907        lstrcmpiW(dataTypeName,szBoolean) == 0 ||
908        lstrcmpiW(dataTypeName,szDateTime) == 0 ||
909        lstrcmpiW(dataTypeName,szDateTimeTZ) == 0 ||
910        lstrcmpiW(dataTypeName,szDate) == 0    ||
911        lstrcmpiW(dataTypeName,szTime) == 0    ||
912        lstrcmpiW(dataTypeName,szTimeTZ) == 0  ||
913        lstrcmpiW(dataTypeName,szI1) == 0      ||
914        lstrcmpiW(dataTypeName,szByte) == 0    ||
915        lstrcmpiW(dataTypeName,szI2) == 0      ||
916        lstrcmpiW(dataTypeName,szIU1) == 0     ||
917        lstrcmpiW(dataTypeName,szIU2) == 0     ||
918        lstrcmpiW(dataTypeName,szIU4) == 0     ||
919        lstrcmpiW(dataTypeName,szR4) == 0      ||
920        lstrcmpiW(dataTypeName,szR8) == 0      ||
921        lstrcmpiW(dataTypeName,szFloat) == 0   ||
922        lstrcmpiW(dataTypeName,szBinHex) == 0  ||
923        lstrcmpiW(dataTypeName,szBinBase64) == 0)
924     {
925         xmlNsPtr pNS = NULL;
926         xmlAttrPtr pAttr = NULL;
927         xmlChar* str = xmlChar_from_wchar((WCHAR*)dataTypeName);
928
929         pAttr = xmlHasNsProp(This->node, (xmlChar*)"dt",
930                             (xmlChar*)"urn:schemas-microsoft-com:datatypes");
931         if (pAttr)
932         {
933             pAttr = xmlSetNsProp(This->node, pAttr->ns, (xmlChar*)"dt", str);
934
935             hr = S_OK;
936         }
937         else
938         {
939             pNS = xmlNewNs(This->node, (xmlChar*)"urn:schemas-microsoft-com:datatypes", (xmlChar*)"dt");
940             if(pNS)
941             {
942                 pAttr = xmlNewNsProp(This->node, pNS, (xmlChar*)"dt", str);
943                 if(pAttr)
944                 {
945                     xmlAddChild(This->node, (xmlNodePtr)pAttr);
946
947                     hr = S_OK;
948                 }
949                 else
950                     ERR("Failed to create Attribute\n");
951             }
952             else
953                 ERR("Failed to Create Namepsace\n");
954         }
955     }
956
957     return hr;
958 }
959
960 static HRESULT WINAPI xmlnode_get_xml(
961     IXMLDOMNode *iface,
962     BSTR* xmlString)
963 {
964     xmlnode *This = impl_from_IXMLDOMNode( iface );
965     xmlBufferPtr pXmlBuf;
966     int nSize;
967
968     TRACE("iface %p\n", iface);
969
970     if(!xmlString)
971         return E_INVALIDARG;
972
973     *xmlString = NULL;
974
975     pXmlBuf = xmlBufferCreate();
976     if(pXmlBuf)
977     {
978         nSize = xmlNodeDump(pXmlBuf, This->node->doc, This->node, 0, 0);
979         if(nSize > 0)
980         {
981             const xmlChar *pContent;
982
983             /* Attribute Nodes return a space infront of their name */
984             pContent = xmlBufferContent(pXmlBuf);
985             if( ((char*)pContent)[0] == ' ')
986                 *xmlString = bstr_from_xmlChar(pContent+1);
987             else
988                 *xmlString = bstr_from_xmlChar(pContent);
989
990
991             xmlBufferFree(pXmlBuf);
992         }
993     }
994
995     /* Always returns a string. */
996     if(*xmlString == NULL)  *xmlString = SysAllocStringLen( NULL, 0 );
997
998     return S_OK;
999 }
1000
1001 static HRESULT WINAPI xmlnode_transformNode(
1002     IXMLDOMNode *iface,
1003     IXMLDOMNode* styleSheet,
1004     BSTR* xmlString)
1005 {
1006     FIXME("\n");
1007     return E_NOTIMPL;
1008 }
1009
1010 static HRESULT WINAPI xmlnode_selectNodes(
1011     IXMLDOMNode *iface,
1012     BSTR queryString,
1013     IXMLDOMNodeList** resultList)
1014 {
1015     xmlnode *This = impl_from_IXMLDOMNode( iface );
1016
1017     TRACE("%p %s %p\n", This, debugstr_w(queryString), resultList );
1018
1019     return queryresult_create( This->node, queryString, resultList );
1020 }
1021
1022 static HRESULT WINAPI xmlnode_selectSingleNode(
1023     IXMLDOMNode *iface,
1024     BSTR queryString,
1025     IXMLDOMNode** resultNode)
1026 {
1027     xmlnode *This = impl_from_IXMLDOMNode( iface );
1028     IXMLDOMNodeList *list;
1029     HRESULT r;
1030
1031     TRACE("%p %s %p\n", This, debugstr_w(queryString), resultNode );
1032
1033     *resultNode = NULL;
1034     r = IXMLDOMNode_selectNodes(iface, queryString, &list);
1035     if(r == S_OK)
1036     {
1037         r = IXMLDOMNodeList_nextNode(list, resultNode);
1038         IXMLDOMNodeList_Release(list);
1039     }
1040     return r;
1041 }
1042
1043 static HRESULT WINAPI xmlnode_get_parsed(
1044     IXMLDOMNode *iface,
1045     VARIANT_BOOL* isParsed)
1046 {
1047     FIXME("\n");
1048     return E_NOTIMPL;
1049 }
1050
1051 static HRESULT WINAPI xmlnode_get_namespaceURI(
1052     IXMLDOMNode *iface,
1053     BSTR* namespaceURI)
1054 {
1055     FIXME("\n");
1056     return E_NOTIMPL;
1057 }
1058
1059 static HRESULT WINAPI xmlnode_get_prefix(
1060     IXMLDOMNode *iface,
1061     BSTR* prefixString)
1062 {
1063     FIXME("\n");
1064     return E_NOTIMPL;
1065 }
1066
1067 static HRESULT WINAPI xmlnode_get_baseName(
1068     IXMLDOMNode *iface,
1069     BSTR* nameString)
1070 {
1071     xmlnode *This = impl_from_IXMLDOMNode( iface );
1072     BSTR str = NULL;
1073     HRESULT r = S_FALSE;
1074
1075     TRACE("%p %p\n", This, nameString );
1076
1077     if ( !nameString )
1078         return E_INVALIDARG;
1079
1080     switch ( This->node->type )
1081     {
1082     case XML_ELEMENT_NODE:
1083     case XML_ATTRIBUTE_NODE:
1084         str = bstr_from_xmlChar( This->node->name );
1085         r = S_OK;
1086         break;
1087     case XML_TEXT_NODE:
1088         break;
1089     default:
1090         ERR("Unhandled type %d\n", This->node->type );
1091         break;
1092     }
1093
1094     TRACE("returning %08x str = %s\n", r, debugstr_w( str ) );
1095
1096     *nameString = str;
1097     return r;
1098 }
1099
1100 static HRESULT WINAPI xmlnode_transformNodeToObject(
1101     IXMLDOMNode *iface,
1102     IXMLDOMNode* stylesheet,
1103     VARIANT outputObject)
1104 {
1105     FIXME("\n");
1106     return E_NOTIMPL;
1107 }
1108
1109 static const struct IXMLDOMNodeVtbl xmlnode_vtbl =
1110 {
1111     xmlnode_QueryInterface,
1112     xmlnode_AddRef,
1113     xmlnode_Release,
1114     xmlnode_GetTypeInfoCount,
1115     xmlnode_GetTypeInfo,
1116     xmlnode_GetIDsOfNames,
1117     xmlnode_Invoke,
1118     xmlnode_get_nodeName,
1119     xmlnode_get_nodeValue,
1120     xmlnode_put_nodeValue,
1121     xmlnode_get_nodeType,
1122     xmlnode_get_parentNode,
1123     xmlnode_get_childNodes,
1124     xmlnode_get_firstChild,
1125     xmlnode_get_lastChild,
1126     xmlnode_get_previousSibling,
1127     xmlnode_get_nextSibling,
1128     xmlnode_get_attributes,
1129     xmlnode_insertBefore,
1130     xmlnode_replaceChild,
1131     xmlnode_removeChild,
1132     xmlnode_appendChild,
1133     xmlnode_hasChildNodes,
1134     xmlnode_get_ownerDocument,
1135     xmlnode_cloneNode,
1136     xmlnode_get_nodeTypeString,
1137     xmlnode_get_text,
1138     xmlnode_put_text,
1139     xmlnode_get_specified,
1140     xmlnode_get_definition,
1141     xmlnode_get_nodeTypedValue,
1142     xmlnode_put_nodeTypedValue,
1143     xmlnode_get_dataType,
1144     xmlnode_put_dataType,
1145     xmlnode_get_xml,
1146     xmlnode_transformNode,
1147     xmlnode_selectNodes,
1148     xmlnode_selectSingleNode,
1149     xmlnode_get_parsed,
1150     xmlnode_get_namespaceURI,
1151     xmlnode_get_prefix,
1152     xmlnode_get_baseName,
1153     xmlnode_transformNodeToObject,
1154 };
1155
1156 static HRESULT WINAPI Internal_QueryInterface(
1157     IUnknown *iface,
1158     REFIID riid,
1159     void** ppvObject )
1160 {
1161     xmlnode *This = impl_from_InternalUnknown( iface );
1162
1163     TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
1164
1165
1166     if ( IsEqualGUID( riid, &IID_IUnknown ))
1167         *ppvObject = iface;
1168     else if ( IsEqualGUID( riid, &IID_IDispatch ) ||
1169               IsEqualGUID( riid, &IID_IXMLDOMNode ) )
1170         *ppvObject = &This->lpVtbl;
1171     else
1172     {
1173         FIXME("interface %s not implemented\n", debugstr_guid(riid));
1174         *ppvObject = NULL;
1175         return E_NOINTERFACE;
1176     }
1177
1178     IUnknown_AddRef( (IUnknown*)*ppvObject );
1179
1180     return S_OK;
1181 }
1182
1183 static ULONG WINAPI Internal_AddRef(
1184                  IUnknown *iface )
1185 {
1186     xmlnode *This = impl_from_InternalUnknown( iface );
1187     return InterlockedIncrement( &This->ref );
1188 }
1189
1190 static ULONG WINAPI Internal_Release(
1191     IUnknown *iface )
1192 {
1193     xmlnode *This = impl_from_InternalUnknown( iface );
1194     ULONG ref;
1195
1196     ref = InterlockedDecrement( &This->ref );
1197     if ( ref == 0 )
1198     {
1199         if( This->node )
1200             xmldoc_release( This->node->doc );
1201         HeapFree( GetProcessHeap(), 0, This );
1202     }
1203
1204     return ref;
1205 }
1206
1207 static const struct IUnknownVtbl internal_unk_vtbl =
1208 {
1209     Internal_QueryInterface,
1210     Internal_AddRef,
1211     Internal_Release
1212 };
1213
1214 IUnknown *create_basic_node( xmlNodePtr node, IUnknown *pUnkOuter )
1215 {
1216     xmlnode *This;
1217
1218     This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
1219     if ( !This )
1220         return NULL;
1221
1222     if(node)
1223         xmldoc_add_ref( node->doc );
1224
1225     This->lpVtbl = &xmlnode_vtbl;
1226     This->lpInternalUnkVtbl = &internal_unk_vtbl;
1227
1228     if(pUnkOuter)
1229         This->pUnkOuter = pUnkOuter; /* Don't take a ref on outer Unknown */
1230     else
1231         This->pUnkOuter = (IUnknown *)&This->lpInternalUnkVtbl;
1232
1233     This->ref = 1;
1234     This->node = node;
1235
1236     return (IUnknown*)&This->lpInternalUnkVtbl;
1237 }
1238
1239 IXMLDOMNode *create_node( xmlNodePtr node )
1240 {
1241     IUnknown *pUnk;
1242     IXMLDOMNode *ret;
1243     HRESULT hr;
1244
1245     if ( !node )
1246         return NULL;
1247
1248     TRACE("type %d\n", node->type);
1249     switch(node->type)
1250     {
1251     case XML_ELEMENT_NODE:
1252         pUnk = create_element( node, NULL );
1253         break;
1254     case XML_ATTRIBUTE_NODE:
1255         pUnk = create_attribute( node );
1256         break;
1257     case XML_TEXT_NODE:
1258         pUnk = create_text( node );
1259         break;
1260     case XML_COMMENT_NODE:
1261         pUnk = create_comment( node );
1262         break;
1263     case XML_DOCUMENT_NODE:
1264         ERR("shouldn't be here!\n");
1265         return NULL;
1266     default:
1267         FIXME("only creating basic node for type %d\n", node->type);
1268         pUnk = create_basic_node( node, NULL );
1269     }
1270
1271     hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
1272     IUnknown_Release(pUnk);
1273     if(FAILED(hr)) return NULL;
1274     return ret;
1275 }
1276 #endif