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