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