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