msxml3/tests: Fix leaks and wrong pointer use.
[wine] / dlls / msxml3 / domdoc.c
1 /*
2  *    DOM Document 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 #define COBJMACROS
22 #define NONAMELESSUNION
23
24 #include "config.h"
25
26 #include <stdarg.h>
27 #include <assert.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "winnls.h"
32 #include "ole2.h"
33 #include "msxml2.h"
34 #include "wininet.h"
35 #include "winreg.h"
36 #include "shlwapi.h"
37 #include "ocidl.h"
38 #include "objsafe.h"
39 #include "dispex.h"
40
41 #include "wine/debug.h"
42 #include "wine/list.h"
43
44 #include "msxml_private.h"
45
46 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
47
48 #ifdef HAVE_LIBXML2
49
50 #include <libxml/xmlsave.h>
51
52 /* not defined in older versions */
53 #define XML_SAVE_FORMAT     1
54 #define XML_SAVE_NO_DECL    2
55 #define XML_SAVE_NO_EMPTY   4
56 #define XML_SAVE_NO_XHTML   8
57 #define XML_SAVE_XHTML     16
58 #define XML_SAVE_AS_XML    32
59 #define XML_SAVE_AS_HTML   64
60
61 static const WCHAR SZ_PROPERTY_SELECTION_LANGUAGE[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
62 static const WCHAR SZ_VALUE_XPATH[] = {'X','P','a','t','h',0};
63 static const WCHAR SZ_VALUE_XSLPATTERN[] = {'X','S','L','P','a','t','t','e','r','n',0};
64
65 typedef struct _domdoc
66 {
67     xmlnode node;
68     const struct IXMLDOMDocument2Vtbl *lpVtbl;
69     const struct IPersistStreamVtbl   *lpvtblIPersistStream;
70     const struct IObjectWithSiteVtbl  *lpvtblIObjectWithSite;
71     const struct IObjectSafetyVtbl    *lpvtblIObjectSafety;
72     const struct ISupportErrorInfoVtbl *lpvtblISupportErrorInfo;
73     LONG ref;
74     VARIANT_BOOL async;
75     VARIANT_BOOL validating;
76     VARIANT_BOOL resolving;
77     VARIANT_BOOL preserving;
78     BOOL bUseXPath;
79     IXMLDOMSchemaCollection *schema;
80     bsc_t *bsc;
81     HRESULT error;
82
83     /* IPersistStream */
84     IStream *stream;
85
86     /* IObjectWithSite*/
87     IUnknown *site;
88
89     /* IObjectSafety */
90     DWORD safeopt;
91 } domdoc;
92
93 /*
94   In native windows, the whole lifetime management of XMLDOMNodes is
95   managed automatically using reference counts. Wine emulates that by
96   maintaining a reference count to the document that is increased for
97   each IXMLDOMNode pointer passed out for this document. If all these
98   pointers are gone, the document is unreachable and gets freed, that
99   is, all nodes in the tree of the document get freed.
100
101   You are able to create nodes that are associated to a document (in
102   fact, in msxml's XMLDOM model, all nodes are associated to a document),
103   but not in the tree of that document, for example using the createFoo
104   functions from IXMLDOMDocument. These nodes do not get cleaned up
105   by libxml, so we have to do it ourselves.
106
107   To catch these nodes, a list of "orphan nodes" is introduced.
108   It contains pointers to all roots of node trees that are
109   associated with the document without being part of the document
110   tree. All nodes with parent==NULL (except for the document root nodes)
111   should be in the orphan node list of their document. All orphan nodes
112   get freed together with the document itself.
113  */
114
115 typedef struct _xmldoc_priv {
116     LONG refs;
117     struct list orphans;
118 } xmldoc_priv;
119
120 typedef struct _orphan_entry {
121     struct list entry;
122     xmlNode * node;
123 } orphan_entry;
124
125 static inline xmldoc_priv * priv_from_xmlDocPtr(xmlDocPtr doc)
126 {
127     return doc->_private;
128 }
129
130 static xmldoc_priv * create_priv(void)
131 {
132     xmldoc_priv *priv;
133     priv = heap_alloc( sizeof (*priv) );
134
135     if(priv)
136     {
137         priv->refs = 0;
138         list_init( &priv->orphans );
139     }
140
141     return priv;
142 }
143
144 static xmlDocPtr doparse( char *ptr, int len )
145 {
146 #ifdef HAVE_XMLREADMEMORY
147     /*
148      * use xmlReadMemory if possible so we can suppress
149      * writing errors to stderr
150      */
151     return xmlReadMemory( ptr, len, NULL, NULL,
152                           XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS );
153 #else
154     return xmlParseMemory( ptr, len );
155 #endif
156 }
157
158 LONG xmldoc_add_ref(xmlDocPtr doc)
159 {
160     LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
161     TRACE("%d\n", ref);
162     return ref;
163 }
164
165 LONG xmldoc_release(xmlDocPtr doc)
166 {
167     xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
168     LONG ref = InterlockedDecrement(&priv->refs);
169     TRACE("%d\n", ref);
170     if(ref == 0)
171     {
172         orphan_entry *orphan, *orphan2;
173         TRACE("freeing docptr %p\n", doc);
174
175         LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
176         {
177             xmlFreeNode( orphan->node );
178             heap_free( orphan );
179         }
180         heap_free(doc->_private);
181
182         xmlFreeDoc(doc);
183     }
184
185     return ref;
186 }
187
188 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
189 {
190     xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
191     orphan_entry *entry;
192
193     entry = heap_alloc( sizeof (*entry) );
194     if(!entry)
195         return E_OUTOFMEMORY;
196
197     entry->node = node;
198     list_add_head( &priv->orphans, &entry->entry );
199     return S_OK;
200 }
201
202 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
203 {
204     xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
205     orphan_entry *entry, *entry2;
206
207     LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
208     {
209         if( entry->node == node )
210         {
211             list_remove( &entry->entry );
212             heap_free( entry );
213             return S_OK;
214         }
215     }
216
217     return S_FALSE;
218 }
219
220 static HRESULT attach_xmldoc( xmlnode *node, xmlDocPtr xml )
221 {
222     if(node->node)
223         xmldoc_release(node->node->doc);
224
225     node->node = (xmlNodePtr) xml;
226     if(node->node)
227         xmldoc_add_ref(node->node->doc);
228
229     return S_OK;
230 }
231
232 static inline domdoc *impl_from_IXMLDOMDocument2( IXMLDOMDocument2 *iface )
233 {
234     return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
235 }
236
237 static inline xmlDocPtr get_doc( domdoc *This )
238 {
239     return (xmlDocPtr)This->node.node;
240 }
241
242 static inline domdoc *impl_from_IPersistStream(IPersistStream *iface)
243 {
244     return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStream));
245 }
246
247 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
248 {
249     return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
250 }
251
252 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
253 {
254     return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
255 }
256
257 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
258 {
259     return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblISupportErrorInfo));
260 }
261
262 /************************************************************************
263  * xmldoc implementation of IPersistStream.
264  */
265 static HRESULT WINAPI xmldoc_IPersistStream_QueryInterface(
266     IPersistStream *iface, REFIID riid, LPVOID *ppvObj)
267 {
268     domdoc *this = impl_from_IPersistStream(iface);
269     return IXMLDocument_QueryInterface((IXMLDocument *)this, riid, ppvObj);
270 }
271
272 static ULONG WINAPI xmldoc_IPersistStream_AddRef(
273     IPersistStream *iface)
274 {
275     domdoc *this = impl_from_IPersistStream(iface);
276     return IXMLDocument_AddRef((IXMLDocument *)this);
277 }
278
279 static ULONG WINAPI xmldoc_IPersistStream_Release(
280     IPersistStream *iface)
281 {
282     domdoc *this = impl_from_IPersistStream(iface);
283     return IXMLDocument_Release((IXMLDocument *)this);
284 }
285
286 static HRESULT WINAPI xmldoc_IPersistStream_GetClassID(
287     IPersistStream *iface, CLSID *classid)
288 {
289     TRACE("(%p,%p): stub!\n", iface, classid);
290
291     if(!classid)
292         return E_POINTER;
293
294     *classid = CLSID_DOMDocument2;
295
296     return S_OK;
297 }
298
299 static HRESULT WINAPI xmldoc_IPersistStream_IsDirty(
300     IPersistStream *iface)
301 {
302     domdoc *This = impl_from_IPersistStream(iface);
303
304     FIXME("(%p): stub!\n", This);
305
306     return S_FALSE;
307 }
308
309 static HRESULT WINAPI xmldoc_IPersistStream_Load(
310     IPersistStream *iface, LPSTREAM pStm)
311 {
312     domdoc *This = impl_from_IPersistStream(iface);
313     HRESULT hr;
314     HGLOBAL hglobal;
315     DWORD read, written, len;
316     BYTE buf[4096];
317     char *ptr;
318     xmlDocPtr xmldoc = NULL;
319
320     TRACE("(%p)->(%p)\n", This, pStm);
321
322     if (!pStm)
323         return E_INVALIDARG;
324
325     hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
326     if (FAILED(hr))
327         return hr;
328
329     do
330     {
331         IStream_Read(pStm, buf, sizeof(buf), &read);
332         hr = IStream_Write(This->stream, buf, read, &written);
333     } while(SUCCEEDED(hr) && written != 0 && read != 0);
334
335     if (FAILED(hr))
336     {
337         ERR("Failed to copy stream\n");
338         return hr;
339     }
340
341     hr = GetHGlobalFromStream(This->stream, &hglobal);
342     if (FAILED(hr))
343         return hr;
344
345     len = GlobalSize(hglobal);
346     ptr = GlobalLock(hglobal);
347     if (len != 0)
348         xmldoc = parse_xml(ptr, len);
349     GlobalUnlock(hglobal);
350
351     if (!xmldoc)
352     {
353         ERR("Failed to parse xml\n");
354         return E_FAIL;
355     }
356
357     xmldoc->_private = create_priv();
358
359     return attach_xmldoc( &This->node, xmldoc );
360 }
361
362 static HRESULT WINAPI xmldoc_IPersistStream_Save(
363     IPersistStream *iface, LPSTREAM pStm, BOOL fClearDirty)
364 {
365     domdoc *This = impl_from_IPersistStream(iface);
366     HRESULT hr;
367     BSTR xmlString;
368
369     TRACE("(%p)->(%p %d)\n", This, pStm, fClearDirty);
370
371     hr = IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), &xmlString );
372     if(hr == S_OK)
373     {
374         DWORD count;
375         DWORD len = strlenW(xmlString) * sizeof(WCHAR);
376
377         hr = IStream_Write( pStm, xmlString, len, &count );
378
379         SysFreeString(xmlString);
380     }
381
382     TRACE("ret 0x%08x\n", hr);
383
384     return hr;
385 }
386
387 static HRESULT WINAPI xmldoc_IPersistStream_GetSizeMax(
388     IPersistStream *iface, ULARGE_INTEGER *pcbSize)
389 {
390     domdoc *This = impl_from_IPersistStream(iface);
391     TRACE("(%p)->(%p): stub!\n", This, pcbSize);
392     return E_NOTIMPL;
393 }
394
395 static const IPersistStreamVtbl xmldoc_IPersistStream_VTable =
396 {
397     xmldoc_IPersistStream_QueryInterface,
398     xmldoc_IPersistStream_AddRef,
399     xmldoc_IPersistStream_Release,
400     xmldoc_IPersistStream_GetClassID,
401     xmldoc_IPersistStream_IsDirty,
402     xmldoc_IPersistStream_Load,
403     xmldoc_IPersistStream_Save,
404     xmldoc_IPersistStream_GetSizeMax,
405 };
406
407 /* ISupportErrorInfo interface */
408 static HRESULT WINAPI support_error_QueryInterface(
409     ISupportErrorInfo *iface,
410     REFIID riid, void** ppvObj )
411 {
412     domdoc *This = impl_from_ISupportErrorInfo(iface);
413     return IXMLDocument_QueryInterface((IXMLDocument *)This, riid, ppvObj);
414 }
415
416 static ULONG WINAPI support_error_AddRef(
417     ISupportErrorInfo *iface )
418 {
419     domdoc *This = impl_from_ISupportErrorInfo(iface);
420     return IXMLDocument_AddRef((IXMLDocument *)This);
421 }
422
423 static ULONG WINAPI support_error_Release(
424     ISupportErrorInfo *iface )
425 {
426     domdoc *This = impl_from_ISupportErrorInfo(iface);
427     return IXMLDocument_Release((IXMLDocument *)This);
428 }
429
430 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
431     ISupportErrorInfo *iface,
432     REFIID riid )
433 {
434     FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
435     return S_FALSE;
436 }
437
438 static const struct ISupportErrorInfoVtbl support_error_vtbl =
439 {
440     support_error_QueryInterface,
441     support_error_AddRef,
442     support_error_Release,
443     support_error_InterfaceSupportsErrorInfo
444 };
445
446 /* IXMLDOMDocument2 interface */
447 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument2 *iface, REFIID riid, void** ppvObject )
448 {
449     domdoc *This = impl_from_IXMLDOMDocument2( iface );
450
451     TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
452
453     *ppvObject = NULL;
454
455     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
456          IsEqualGUID( riid, &IID_IDispatch ) ||
457          IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
458          IsEqualGUID( riid, &IID_IXMLDOMDocument2 ) )
459     {
460         *ppvObject = iface;
461     }
462     else if ( IsEqualGUID( riid, &IID_IXMLDOMNode ) )
463     {
464         *ppvObject = IXMLDOMNode_from_impl(&This->node);
465     }
466     else if (IsEqualGUID(&IID_IPersistStream, riid))
467     {
468         *ppvObject = &(This->lpvtblIPersistStream);
469     }
470     else if (IsEqualGUID(&IID_IObjectWithSite, riid))
471     {
472         *ppvObject = &(This->lpvtblIObjectWithSite);
473     }
474     else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
475     {
476         *ppvObject = &This->lpvtblISupportErrorInfo;
477     }
478     else if(dispex_query_interface(&This->node.dispex, riid, ppvObject))
479     {
480         return *ppvObject ? S_OK : E_NOINTERFACE;
481     }
482     else if(IsEqualGUID(&IID_IRunnableObject, riid))
483     {
484         TRACE("IID_IRunnableObject not supported returning NULL\n");
485         return E_NOINTERFACE;
486     }
487     else
488     {
489         FIXME("interface %s not implemented\n", debugstr_guid(riid));
490         return E_NOINTERFACE;
491     }
492
493     IUnknown_AddRef((IUnknown*)*ppvObject);
494
495     return S_OK;
496 }
497
498
499 static ULONG WINAPI domdoc_AddRef(
500      IXMLDOMDocument2 *iface )
501 {
502     domdoc *This = impl_from_IXMLDOMDocument2( iface );
503     TRACE("%p\n", This );
504     return InterlockedIncrement( &This->ref );
505 }
506
507
508 static ULONG WINAPI domdoc_Release(
509      IXMLDOMDocument2 *iface )
510 {
511     domdoc *This = impl_from_IXMLDOMDocument2( iface );
512     LONG ref;
513
514     TRACE("%p\n", This );
515
516     ref = InterlockedDecrement( &This->ref );
517     if ( ref == 0 )
518     {
519         if(This->bsc)
520             detach_bsc(This->bsc);
521
522         if (This->site)
523             IUnknown_Release( This->site );
524         destroy_xmlnode(&This->node);
525         if(This->schema) IXMLDOMSchemaCollection_Release( This->schema );
526         if (This->stream) IStream_Release(This->stream);
527         HeapFree( GetProcessHeap(), 0, This );
528     }
529
530     return ref;
531 }
532
533 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument2 *iface, UINT* pctinfo )
534 {
535     domdoc *This = impl_from_IXMLDOMDocument2( iface );
536
537     TRACE("(%p)->(%p)\n", This, pctinfo);
538
539     *pctinfo = 1;
540
541     return S_OK;
542 }
543
544 static HRESULT WINAPI domdoc_GetTypeInfo(
545     IXMLDOMDocument2 *iface,
546     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
547 {
548     domdoc *This = impl_from_IXMLDOMDocument2( iface );
549     HRESULT hr;
550
551     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
552
553     hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
554
555     return hr;
556 }
557
558 static HRESULT WINAPI domdoc_GetIDsOfNames(
559     IXMLDOMDocument2 *iface,
560     REFIID riid,
561     LPOLESTR* rgszNames,
562     UINT cNames,
563     LCID lcid,
564     DISPID* rgDispId)
565 {
566     domdoc *This = impl_from_IXMLDOMDocument2( iface );
567     ITypeInfo *typeinfo;
568     HRESULT hr;
569
570     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
571           lcid, rgDispId);
572
573     if(!rgszNames || cNames == 0 || !rgDispId)
574         return E_INVALIDARG;
575
576     hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
577     if(SUCCEEDED(hr))
578     {
579         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
580         ITypeInfo_Release(typeinfo);
581     }
582
583     return hr;
584 }
585
586
587 static HRESULT WINAPI domdoc_Invoke(
588     IXMLDOMDocument2 *iface,
589     DISPID dispIdMember,
590     REFIID riid,
591     LCID lcid,
592     WORD wFlags,
593     DISPPARAMS* pDispParams,
594     VARIANT* pVarResult,
595     EXCEPINFO* pExcepInfo,
596     UINT* puArgErr)
597 {
598     domdoc *This = impl_from_IXMLDOMDocument2( iface );
599     ITypeInfo *typeinfo;
600     HRESULT hr;
601
602     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
603           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
604
605     hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
606     if(SUCCEEDED(hr))
607     {
608         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
609                 pVarResult, pExcepInfo, puArgErr);
610         ITypeInfo_Release(typeinfo);
611     }
612
613     return hr;
614 }
615
616
617 static HRESULT WINAPI domdoc_get_nodeName(
618     IXMLDOMDocument2 *iface,
619     BSTR* name )
620 {
621     domdoc *This = impl_from_IXMLDOMDocument2( iface );
622     return IXMLDOMNode_get_nodeName( IXMLDOMNode_from_impl(&This->node), name );
623 }
624
625
626 static HRESULT WINAPI domdoc_get_nodeValue(
627     IXMLDOMDocument2 *iface,
628     VARIANT* value )
629 {
630     domdoc *This = impl_from_IXMLDOMDocument2( iface );
631     return IXMLDOMNode_get_nodeValue( IXMLDOMNode_from_impl(&This->node), value );
632 }
633
634
635 static HRESULT WINAPI domdoc_put_nodeValue(
636     IXMLDOMDocument2 *iface,
637     VARIANT value)
638 {
639     domdoc *This = impl_from_IXMLDOMDocument2( iface );
640     return IXMLDOMNode_put_nodeValue( IXMLDOMNode_from_impl(&This->node), value );
641 }
642
643
644 static HRESULT WINAPI domdoc_get_nodeType(
645     IXMLDOMDocument2 *iface,
646     DOMNodeType* type )
647 {
648     domdoc *This = impl_from_IXMLDOMDocument2( iface );
649     return IXMLDOMNode_get_nodeType( IXMLDOMNode_from_impl(&This->node), type );
650 }
651
652
653 static HRESULT WINAPI domdoc_get_parentNode(
654     IXMLDOMDocument2 *iface,
655     IXMLDOMNode** parent )
656 {
657     domdoc *This = impl_from_IXMLDOMDocument2( iface );
658     return IXMLDOMNode_get_parentNode( IXMLDOMNode_from_impl(&This->node), parent );
659 }
660
661
662 static HRESULT WINAPI domdoc_get_childNodes(
663     IXMLDOMDocument2 *iface,
664     IXMLDOMNodeList** childList )
665 {
666     domdoc *This = impl_from_IXMLDOMDocument2( iface );
667     return IXMLDOMNode_get_childNodes( IXMLDOMNode_from_impl(&This->node), childList );
668 }
669
670
671 static HRESULT WINAPI domdoc_get_firstChild(
672     IXMLDOMDocument2 *iface,
673     IXMLDOMNode** firstChild )
674 {
675     domdoc *This = impl_from_IXMLDOMDocument2( iface );
676     return IXMLDOMNode_get_firstChild( IXMLDOMNode_from_impl(&This->node), firstChild );
677 }
678
679
680 static HRESULT WINAPI domdoc_get_lastChild(
681     IXMLDOMDocument2 *iface,
682     IXMLDOMNode** lastChild )
683 {
684     domdoc *This = impl_from_IXMLDOMDocument2( iface );
685     return IXMLDOMNode_get_lastChild( IXMLDOMNode_from_impl(&This->node), lastChild );
686 }
687
688
689 static HRESULT WINAPI domdoc_get_previousSibling(
690     IXMLDOMDocument2 *iface,
691     IXMLDOMNode** previousSibling )
692 {
693     domdoc *This = impl_from_IXMLDOMDocument2( iface );
694     return IXMLDOMNode_get_previousSibling( IXMLDOMNode_from_impl(&This->node), previousSibling );
695 }
696
697
698 static HRESULT WINAPI domdoc_get_nextSibling(
699     IXMLDOMDocument2 *iface,
700     IXMLDOMNode** nextSibling )
701 {
702     domdoc *This = impl_from_IXMLDOMDocument2( iface );
703     return IXMLDOMNode_get_nextSibling( IXMLDOMNode_from_impl(&This->node), nextSibling );
704 }
705
706
707 static HRESULT WINAPI domdoc_get_attributes(
708     IXMLDOMDocument2 *iface,
709     IXMLDOMNamedNodeMap** attributeMap )
710 {
711     domdoc *This = impl_from_IXMLDOMDocument2( iface );
712     return IXMLDOMNode_get_attributes( IXMLDOMNode_from_impl(&This->node), attributeMap );
713 }
714
715
716 static HRESULT WINAPI domdoc_insertBefore(
717     IXMLDOMDocument2 *iface,
718     IXMLDOMNode* newChild,
719     VARIANT refChild,
720     IXMLDOMNode** outNewChild )
721 {
722     domdoc *This = impl_from_IXMLDOMDocument2( iface );
723     return IXMLDOMNode_insertBefore( IXMLDOMNode_from_impl(&This->node), newChild, refChild, outNewChild );
724 }
725
726
727 static HRESULT WINAPI domdoc_replaceChild(
728     IXMLDOMDocument2 *iface,
729     IXMLDOMNode* newChild,
730     IXMLDOMNode* oldChild,
731     IXMLDOMNode** outOldChild)
732 {
733     domdoc *This = impl_from_IXMLDOMDocument2( iface );
734     return IXMLDOMNode_replaceChild( IXMLDOMNode_from_impl(&This->node), newChild, oldChild, outOldChild );
735 }
736
737
738 static HRESULT WINAPI domdoc_removeChild(
739     IXMLDOMDocument2 *iface,
740     IXMLDOMNode* childNode,
741     IXMLDOMNode** oldChild)
742 {
743     domdoc *This = impl_from_IXMLDOMDocument2( iface );
744     return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), childNode, oldChild );
745 }
746
747
748 static HRESULT WINAPI domdoc_appendChild(
749     IXMLDOMDocument2 *iface,
750     IXMLDOMNode* newChild,
751     IXMLDOMNode** outNewChild)
752 {
753     domdoc *This = impl_from_IXMLDOMDocument2( iface );
754     return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newChild, outNewChild );
755 }
756
757
758 static HRESULT WINAPI domdoc_hasChildNodes(
759     IXMLDOMDocument2 *iface,
760     VARIANT_BOOL* hasChild)
761 {
762     domdoc *This = impl_from_IXMLDOMDocument2( iface );
763     return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), hasChild );
764 }
765
766
767 static HRESULT WINAPI domdoc_get_ownerDocument(
768     IXMLDOMDocument2 *iface,
769     IXMLDOMDocument** DOMDocument)
770 {
771     domdoc *This = impl_from_IXMLDOMDocument2( iface );
772     return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), DOMDocument );
773 }
774
775
776 static HRESULT WINAPI domdoc_cloneNode(
777     IXMLDOMDocument2 *iface,
778     VARIANT_BOOL deep,
779     IXMLDOMNode** cloneRoot)
780 {
781     domdoc *This = impl_from_IXMLDOMDocument2( iface );
782     return IXMLDOMNode_cloneNode( IXMLDOMNode_from_impl(&This->node), deep, cloneRoot );
783 }
784
785
786 static HRESULT WINAPI domdoc_get_nodeTypeString(
787     IXMLDOMDocument2 *iface,
788     BSTR* nodeType )
789 {
790     domdoc *This = impl_from_IXMLDOMDocument2( iface );
791     return IXMLDOMNode_get_nodeTypeString( IXMLDOMNode_from_impl(&This->node), nodeType );
792 }
793
794
795 static HRESULT WINAPI domdoc_get_text(
796     IXMLDOMDocument2 *iface,
797     BSTR* text )
798 {
799     domdoc *This = impl_from_IXMLDOMDocument2( iface );
800     return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), text );
801 }
802
803
804 static HRESULT WINAPI domdoc_put_text(
805     IXMLDOMDocument2 *iface,
806     BSTR text )
807 {
808     domdoc *This = impl_from_IXMLDOMDocument2( iface );
809     return IXMLDOMNode_put_text( IXMLDOMNode_from_impl(&This->node), text );
810 }
811
812
813 static HRESULT WINAPI domdoc_get_specified(
814     IXMLDOMDocument2 *iface,
815     VARIANT_BOOL* isSpecified )
816 {
817     domdoc *This = impl_from_IXMLDOMDocument2( iface );
818     return IXMLDOMNode_get_specified( IXMLDOMNode_from_impl(&This->node), isSpecified );
819 }
820
821
822 static HRESULT WINAPI domdoc_get_definition(
823     IXMLDOMDocument2 *iface,
824     IXMLDOMNode** definitionNode )
825 {
826     domdoc *This = impl_from_IXMLDOMDocument2( iface );
827     return IXMLDOMNode_get_definition( IXMLDOMNode_from_impl(&This->node), definitionNode );
828 }
829
830
831 static HRESULT WINAPI domdoc_get_nodeTypedValue(
832     IXMLDOMDocument2 *iface,
833     VARIANT* typedValue )
834 {
835     domdoc *This = impl_from_IXMLDOMDocument2( iface );
836     return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
837 }
838
839 static HRESULT WINAPI domdoc_put_nodeTypedValue(
840     IXMLDOMDocument2 *iface,
841     VARIANT typedValue )
842 {
843     domdoc *This = impl_from_IXMLDOMDocument2( iface );
844     return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
845 }
846
847
848 static HRESULT WINAPI domdoc_get_dataType(
849     IXMLDOMDocument2 *iface,
850     VARIANT* dataTypeName )
851 {
852     domdoc *This = impl_from_IXMLDOMDocument2( iface );
853     return IXMLDOMNode_get_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
854 }
855
856
857 static HRESULT WINAPI domdoc_put_dataType(
858     IXMLDOMDocument2 *iface,
859     BSTR dataTypeName )
860 {
861     domdoc *This = impl_from_IXMLDOMDocument2( iface );
862     return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
863 }
864
865
866 static HRESULT WINAPI domdoc_get_xml(
867     IXMLDOMDocument2 *iface,
868     BSTR* xmlString )
869 {
870     domdoc *This = impl_from_IXMLDOMDocument2( iface );
871     return IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), xmlString );
872 }
873
874
875 static HRESULT WINAPI domdoc_transformNode(
876     IXMLDOMDocument2 *iface,
877     IXMLDOMNode* styleSheet,
878     BSTR* xmlString )
879 {
880     domdoc *This = impl_from_IXMLDOMDocument2( iface );
881     return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), styleSheet, xmlString );
882 }
883
884
885 static HRESULT WINAPI domdoc_selectNodes(
886     IXMLDOMDocument2 *iface,
887     BSTR queryString,
888     IXMLDOMNodeList** resultList )
889 {
890     domdoc *This = impl_from_IXMLDOMDocument2( iface );
891     return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), queryString, resultList );
892 }
893
894
895 static HRESULT WINAPI domdoc_selectSingleNode(
896     IXMLDOMDocument2 *iface,
897     BSTR queryString,
898     IXMLDOMNode** resultNode )
899 {
900     domdoc *This = impl_from_IXMLDOMDocument2( iface );
901     return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), queryString, resultNode );
902 }
903
904
905 static HRESULT WINAPI domdoc_get_parsed(
906     IXMLDOMDocument2 *iface,
907     VARIANT_BOOL* isParsed )
908 {
909     domdoc *This = impl_from_IXMLDOMDocument2( iface );
910     return IXMLDOMNode_get_parsed( IXMLDOMNode_from_impl(&This->node), isParsed );
911 }
912
913
914 static HRESULT WINAPI domdoc_get_namespaceURI(
915     IXMLDOMDocument2 *iface,
916     BSTR* namespaceURI )
917 {
918     domdoc *This = impl_from_IXMLDOMDocument2( iface );
919     return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), namespaceURI );
920 }
921
922
923 static HRESULT WINAPI domdoc_get_prefix(
924     IXMLDOMDocument2 *iface,
925     BSTR* prefixString )
926 {
927     domdoc *This = impl_from_IXMLDOMDocument2( iface );
928     return IXMLDOMNode_get_prefix( IXMLDOMNode_from_impl(&This->node), prefixString );
929 }
930
931
932 static HRESULT WINAPI domdoc_get_baseName(
933     IXMLDOMDocument2 *iface,
934     BSTR* nameString )
935 {
936     domdoc *This = impl_from_IXMLDOMDocument2( iface );
937     return IXMLDOMNode_get_baseName( IXMLDOMNode_from_impl(&This->node), nameString );
938 }
939
940
941 static HRESULT WINAPI domdoc_transformNodeToObject(
942     IXMLDOMDocument2 *iface,
943     IXMLDOMNode* stylesheet,
944     VARIANT outputObject)
945 {
946     domdoc *This = impl_from_IXMLDOMDocument2( iface );
947     return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), stylesheet, outputObject );
948 }
949
950
951 static HRESULT WINAPI domdoc_get_doctype(
952     IXMLDOMDocument2 *iface,
953     IXMLDOMDocumentType** documentType )
954 {
955     domdoc *This = impl_from_IXMLDOMDocument2(iface);
956     FIXME("(%p)\n", This);
957     return E_NOTIMPL;
958 }
959
960
961 static HRESULT WINAPI domdoc_get_implementation(
962     IXMLDOMDocument2 *iface,
963     IXMLDOMImplementation** impl )
964 {
965     domdoc *This = impl_from_IXMLDOMDocument2(iface);
966
967     TRACE("(%p)->(%p)\n", This, impl);
968
969     if(!impl)
970         return E_INVALIDARG;
971
972     *impl = (IXMLDOMImplementation*)create_doc_Implementation();
973
974     return S_OK;
975 }
976
977 static HRESULT WINAPI domdoc_get_documentElement(
978     IXMLDOMDocument2 *iface,
979     IXMLDOMElement** DOMElement )
980 {
981     domdoc *This = impl_from_IXMLDOMDocument2( iface );
982     xmlDocPtr xmldoc = NULL;
983     xmlNodePtr root = NULL;
984     IXMLDOMNode *element_node;
985     HRESULT hr;
986
987     TRACE("(%p)->(%p)\n", This, DOMElement);
988
989     if(!DOMElement)
990         return E_INVALIDARG;
991
992     *DOMElement = NULL;
993
994     xmldoc = get_doc( This );
995
996     root = xmlDocGetRootElement( xmldoc );
997     if ( !root )
998         return S_FALSE;
999
1000     element_node = create_node( root );
1001     if(!element_node) return S_FALSE;
1002
1003     hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (LPVOID*)DOMElement);
1004     IXMLDOMNode_Release(element_node);
1005
1006     return hr;
1007 }
1008
1009
1010 static HRESULT WINAPI domdoc_put_documentElement(
1011     IXMLDOMDocument2 *iface,
1012     IXMLDOMElement* DOMElement )
1013 {
1014     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1015     IXMLDOMNode *elementNode;
1016     xmlNodePtr oldRoot;
1017     xmlnode *xmlNode;
1018     HRESULT hr;
1019
1020     TRACE("(%p)->(%p)\n", This, DOMElement);
1021
1022     hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1023     if(FAILED(hr))
1024         return hr;
1025
1026     xmlNode = impl_from_IXMLDOMNode( elementNode );
1027
1028     if(!xmlNode->node->parent)
1029         if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1030             WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1031
1032     oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1033     IXMLDOMNode_Release( elementNode );
1034
1035     if(oldRoot)
1036         xmldoc_add_orphan(oldRoot->doc, oldRoot);
1037
1038     return S_OK;
1039 }
1040
1041
1042 static HRESULT WINAPI domdoc_createElement(
1043     IXMLDOMDocument2 *iface,
1044     BSTR tagname,
1045     IXMLDOMElement** element )
1046 {
1047     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1048     IXMLDOMNode *node;
1049     VARIANT type;
1050     HRESULT hr;
1051
1052     TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1053
1054     if (!element || !tagname) return E_INVALIDARG;
1055
1056     V_VT(&type) = VT_I1;
1057     V_I1(&type) = NODE_ELEMENT;
1058
1059     hr = IXMLDOMDocument_createNode(iface, type, tagname, NULL, &node);
1060     if (hr == S_OK)
1061     {
1062         IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1063         IXMLDOMNode_Release(node);
1064     }
1065
1066     return hr;
1067 }
1068
1069
1070 static HRESULT WINAPI domdoc_createDocumentFragment(
1071     IXMLDOMDocument2 *iface,
1072     IXMLDOMDocumentFragment** frag )
1073 {
1074     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1075     IXMLDOMNode *node;
1076     VARIANT type;
1077     HRESULT hr;
1078
1079     TRACE("(%p)->(%p)\n", This, frag);
1080
1081     if (!frag) return E_INVALIDARG;
1082
1083     *frag = NULL;
1084
1085     V_VT(&type) = VT_I1;
1086     V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1087
1088     hr = IXMLDOMDocument_createNode(iface, type, NULL, NULL, &node);
1089     if (hr == S_OK)
1090     {
1091         IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1092         IXMLDOMNode_Release(node);
1093     }
1094
1095     return hr;
1096 }
1097
1098
1099 static HRESULT WINAPI domdoc_createTextNode(
1100     IXMLDOMDocument2 *iface,
1101     BSTR data,
1102     IXMLDOMText** text )
1103 {
1104     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1105     IXMLDOMNode *node;
1106     VARIANT type;
1107     HRESULT hr;
1108
1109     TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1110
1111     if (!text) return E_INVALIDARG;
1112
1113     *text = NULL;
1114
1115     V_VT(&type) = VT_I1;
1116     V_I1(&type) = NODE_TEXT;
1117
1118     hr = IXMLDOMDocument2_createNode(iface, type, NULL, NULL, &node);
1119     if (hr == S_OK)
1120     {
1121         IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1122         IXMLDOMNode_Release(node);
1123         hr = IXMLDOMText_put_data(*text, data);
1124     }
1125
1126     return hr;
1127 }
1128
1129
1130 static HRESULT WINAPI domdoc_createComment(
1131     IXMLDOMDocument2 *iface,
1132     BSTR data,
1133     IXMLDOMComment** comment )
1134 {
1135     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1136     VARIANT type;
1137     HRESULT hr;
1138     IXMLDOMNode *node;
1139
1140     TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1141
1142     if (!comment) return E_INVALIDARG;
1143
1144     *comment = NULL;
1145
1146     V_VT(&type) = VT_I1;
1147     V_I1(&type) = NODE_COMMENT;
1148
1149     hr = IXMLDOMDocument2_createNode(iface, type, NULL, NULL, &node);
1150     if (hr == S_OK)
1151     {
1152         IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1153         IXMLDOMNode_Release(node);
1154         hr = IXMLDOMComment_put_data(*comment, data);
1155     }
1156
1157     return hr;
1158 }
1159
1160
1161 static HRESULT WINAPI domdoc_createCDATASection(
1162     IXMLDOMDocument2 *iface,
1163     BSTR data,
1164     IXMLDOMCDATASection** cdata )
1165 {
1166     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1167     IXMLDOMNode *node;
1168     VARIANT type;
1169     HRESULT hr;
1170
1171     TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1172
1173     if (!cdata) return E_INVALIDARG;
1174
1175     *cdata = NULL;
1176
1177     V_VT(&type) = VT_I1;
1178     V_I1(&type) = NODE_CDATA_SECTION;
1179
1180     hr = IXMLDOMDocument2_createNode(iface, type, NULL, NULL, &node);
1181     if (hr == S_OK)
1182     {
1183         IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1184         IXMLDOMNode_Release(node);
1185         hr = IXMLDOMCDATASection_put_data(*cdata, data);
1186     }
1187
1188     return hr;
1189 }
1190
1191
1192 static HRESULT WINAPI domdoc_createProcessingInstruction(
1193     IXMLDOMDocument2 *iface,
1194     BSTR target,
1195     BSTR data,
1196     IXMLDOMProcessingInstruction** pi )
1197 {
1198     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1199     IXMLDOMNode *node;
1200     VARIANT type;
1201     HRESULT hr;
1202
1203     TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1204
1205     if (!pi) return E_INVALIDARG;
1206
1207     *pi = NULL;
1208
1209     V_VT(&type) = VT_I1;
1210     V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1211
1212     hr = IXMLDOMDocument2_createNode(iface, type, target, NULL, &node);
1213     if (hr == S_OK)
1214     {
1215         VARIANT v_data;
1216
1217         /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1218         V_VT(&v_data)   = VT_BSTR;
1219         V_BSTR(&v_data) = data;
1220
1221         hr = IXMLDOMNode_put_nodeValue( node, v_data );
1222
1223         IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1224         IXMLDOMNode_Release(node);
1225     }
1226
1227     return hr;
1228 }
1229
1230
1231 static HRESULT WINAPI domdoc_createAttribute(
1232     IXMLDOMDocument2 *iface,
1233     BSTR name,
1234     IXMLDOMAttribute** attribute )
1235 {
1236     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1237     IXMLDOMNode *node;
1238     VARIANT type;
1239     HRESULT hr;
1240
1241     TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1242
1243     if (!attribute || !name) return E_INVALIDARG;
1244
1245     V_VT(&type) = VT_I1;
1246     V_I1(&type) = NODE_ATTRIBUTE;
1247
1248     hr = IXMLDOMDocument_createNode(iface, type, name, NULL, &node);
1249     if (hr == S_OK)
1250     {
1251         IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1252         IXMLDOMNode_Release(node);
1253     }
1254
1255     return hr;
1256 }
1257
1258
1259 static HRESULT WINAPI domdoc_createEntityReference(
1260     IXMLDOMDocument2 *iface,
1261     BSTR name,
1262     IXMLDOMEntityReference** entityref )
1263 {
1264     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1265     IXMLDOMNode *node;
1266     VARIANT type;
1267     HRESULT hr;
1268
1269     TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1270
1271     if (!entityref) return E_INVALIDARG;
1272
1273     *entityref = NULL;
1274
1275     V_VT(&type) = VT_I1;
1276     V_I1(&type) = NODE_ENTITY_REFERENCE;
1277
1278     hr = IXMLDOMDocument2_createNode(iface, type, name, NULL, &node);
1279     if (hr == S_OK)
1280     {
1281         IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1282         IXMLDOMNode_Release(node);
1283     }
1284
1285     return hr;
1286 }
1287
1288
1289 static HRESULT WINAPI domdoc_getElementsByTagName(
1290     IXMLDOMDocument2 *iface,
1291     BSTR tagName,
1292     IXMLDOMNodeList** resultList )
1293 {
1294     static const WCHAR xpathformat[] =
1295             { '/','/','*','[','l','o','c','a','l','-','n','a','m','e','(',')','=','\'','%','s','\'',']',0 };
1296     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1297     LPWSTR szPattern;
1298     HRESULT hr;
1299     TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagName), resultList);
1300
1301     if (tagName[0] == '*' && tagName[1] == 0)
1302     {
1303         szPattern = heap_alloc(sizeof(WCHAR)*4);
1304         szPattern[0] = szPattern[1] = '/';
1305         szPattern[2] = '*';
1306         szPattern[3] = 0;
1307     }
1308     else
1309     {
1310         szPattern = heap_alloc(sizeof(WCHAR)*(20+lstrlenW(tagName)+1));
1311         wsprintfW(szPattern, xpathformat, tagName);
1312     }
1313
1314     hr = queryresult_create((xmlNodePtr)get_doc(This), szPattern, resultList);
1315     heap_free(szPattern);
1316
1317     return hr;
1318 }
1319
1320 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1321 {
1322     VARIANT tmp;
1323     HRESULT hr;
1324
1325     VariantInit(&tmp);
1326     hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1327     if(FAILED(hr))
1328         return E_INVALIDARG;
1329
1330     *type = V_I4(&tmp);
1331
1332     return S_OK;
1333 }
1334
1335 static HRESULT WINAPI domdoc_createNode(
1336     IXMLDOMDocument2 *iface,
1337     VARIANT Type,
1338     BSTR name,
1339     BSTR namespaceURI,
1340     IXMLDOMNode** node )
1341 {
1342     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1343     DOMNodeType node_type;
1344     xmlNodePtr xmlnode;
1345     xmlChar *xml_name;
1346     HRESULT hr;
1347
1348     TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1349
1350     if(!node) return E_INVALIDARG;
1351
1352     if(namespaceURI && namespaceURI[0])
1353         FIXME("nodes with namespaces currently not supported.\n");
1354
1355     hr = get_node_type(Type, &node_type);
1356     if(FAILED(hr)) return hr;
1357
1358     TRACE("node_type %d\n", node_type);
1359
1360     /* exit earlier for types that need name */
1361     switch(node_type)
1362     {
1363     case NODE_ELEMENT:
1364     case NODE_ATTRIBUTE:
1365     case NODE_ENTITY_REFERENCE:
1366     case NODE_PROCESSING_INSTRUCTION:
1367         if (!name || SysStringLen(name) == 0) return E_FAIL;
1368     default:
1369         break;
1370     }
1371
1372     xml_name = xmlChar_from_wchar(name);
1373
1374     switch(node_type)
1375     {
1376     case NODE_ELEMENT:
1377         xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
1378         break;
1379     case NODE_ATTRIBUTE:
1380         xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1381         break;
1382     case NODE_TEXT:
1383         xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1384         break;
1385     case NODE_CDATA_SECTION:
1386         xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1387         break;
1388     case NODE_ENTITY_REFERENCE:
1389         xmlnode = xmlNewReference(get_doc(This), xml_name);
1390         break;
1391     case NODE_PROCESSING_INSTRUCTION:
1392 #ifdef HAVE_XMLNEWDOCPI
1393         xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1394 #else
1395         FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1396         xmlnode = NULL;
1397 #endif
1398         break;
1399     case NODE_COMMENT:
1400         xmlnode = xmlNewDocComment(get_doc(This), NULL);
1401         break;
1402     case NODE_DOCUMENT_FRAGMENT:
1403         xmlnode = xmlNewDocFragment(get_doc(This));
1404         break;
1405     /* unsupported types */
1406     case NODE_DOCUMENT:
1407     case NODE_DOCUMENT_TYPE:
1408     case NODE_ENTITY:
1409     case NODE_NOTATION:
1410         heap_free(xml_name);
1411         return E_INVALIDARG;
1412     default:
1413         FIXME("unhandled node type %d\n", node_type);
1414         xmlnode = NULL;
1415         break;
1416     }
1417
1418     *node = create_node(xmlnode);
1419     heap_free(xml_name);
1420
1421     if(*node)
1422     {
1423         TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1424         xmldoc_add_orphan(xmlnode->doc, xmlnode);
1425         return S_OK;
1426     }
1427
1428     return E_FAIL;
1429 }
1430
1431 static HRESULT WINAPI domdoc_nodeFromID(
1432     IXMLDOMDocument2 *iface,
1433     BSTR idString,
1434     IXMLDOMNode** node )
1435 {
1436     domdoc *This = impl_from_IXMLDOMDocument2(iface);
1437     FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1438     return E_NOTIMPL;
1439 }
1440
1441 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1442 {
1443     domdoc *This = obj;
1444     xmlDocPtr xmldoc;
1445
1446     xmldoc = doparse( ptr, len );
1447     if(xmldoc) {
1448         xmldoc->_private = create_priv();
1449         return attach_xmldoc(&This->node, xmldoc);
1450     }
1451
1452     return S_OK;
1453 }
1454
1455 static HRESULT doread( domdoc *This, LPWSTR filename )
1456 {
1457     bsc_t *bsc;
1458     HRESULT hr;
1459
1460     hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1461     if(FAILED(hr))
1462         return hr;
1463
1464     if(This->bsc)
1465         detach_bsc(This->bsc);
1466
1467     This->bsc = bsc;
1468     return S_OK;
1469 }
1470
1471 static HRESULT WINAPI domdoc_load(
1472     IXMLDOMDocument2 *iface,
1473     VARIANT xmlSource,
1474     VARIANT_BOOL* isSuccessful )
1475 {
1476     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1477     LPWSTR filename = NULL;
1478     HRESULT hr = S_FALSE;
1479     IXMLDOMDocument2 *pNewDoc = NULL;
1480     IStream *pStream = NULL;
1481     xmlDocPtr xmldoc;
1482
1483     TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
1484
1485     *isSuccessful = VARIANT_FALSE;
1486
1487     assert( &This->node );
1488
1489     switch( V_VT(&xmlSource) )
1490     {
1491     case VT_BSTR:
1492         filename = V_BSTR(&xmlSource);
1493         break;
1494     case VT_UNKNOWN:
1495         hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument2, (void**)&pNewDoc);
1496         if(hr == S_OK)
1497         {
1498             if(pNewDoc)
1499             {
1500                 domdoc *newDoc = impl_from_IXMLDOMDocument2( pNewDoc );
1501                 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1502                 hr = attach_xmldoc(&This->node, xmldoc);
1503
1504                 if(SUCCEEDED(hr))
1505                     *isSuccessful = VARIANT_TRUE;
1506
1507                 return hr;
1508             }
1509         }
1510         hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1511         if(hr == S_OK)
1512         {
1513             IPersistStream *pDocStream;
1514             hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1515             if(hr == S_OK)
1516             {
1517                 hr = xmldoc_IPersistStream_Load(pDocStream, pStream);
1518                 IStream_Release(pStream);
1519                 if(hr == S_OK)
1520                 {
1521                     *isSuccessful = VARIANT_TRUE;
1522
1523                     TRACE("Using ID_IStream to load Document\n");
1524                     return S_OK;
1525                 }
1526                 else
1527                 {
1528                     ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1529                 }
1530             }
1531             else
1532             {
1533                 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1534             }
1535         }
1536         else
1537         {
1538             /* ISequentialStream */
1539             FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1540         }
1541         break;
1542      default:
1543             FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1544      }
1545
1546     TRACE("filename (%s)\n", debugstr_w(filename));
1547
1548     if ( filename )
1549     {
1550         hr = doread( This, filename );
1551     
1552         if ( FAILED(hr) )
1553             This->error = E_FAIL;
1554         else
1555         {
1556             hr = This->error = S_OK;
1557             *isSuccessful = VARIANT_TRUE;
1558         }
1559     }
1560
1561     if(!filename || FAILED(hr)) {
1562         xmldoc = xmlNewDoc(NULL);
1563         xmldoc->_private = create_priv();
1564         hr = attach_xmldoc(&This->node, xmldoc);
1565         if(SUCCEEDED(hr))
1566             hr = S_FALSE;
1567     }
1568
1569     TRACE("ret (%d)\n", hr);
1570
1571     return hr;
1572 }
1573
1574
1575 static HRESULT WINAPI domdoc_get_readyState(
1576     IXMLDOMDocument2 *iface,
1577     LONG *value )
1578 {
1579     domdoc *This = impl_from_IXMLDOMDocument2(iface);
1580     FIXME("(%p)->(%p)\n", This, value);
1581     return E_NOTIMPL;
1582 }
1583
1584
1585 static HRESULT WINAPI domdoc_get_parseError(
1586     IXMLDOMDocument2 *iface,
1587     IXMLDOMParseError** errorObj )
1588 {
1589     BSTR error_string = NULL;
1590     static const WCHAR err[] = {'e','r','r','o','r',0};
1591     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1592
1593     FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
1594
1595     if(This->error)
1596         error_string = SysAllocString(err);
1597
1598     *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
1599     if(!*errorObj) return E_OUTOFMEMORY;
1600     return S_OK;
1601 }
1602
1603
1604 static HRESULT WINAPI domdoc_get_url(
1605     IXMLDOMDocument2 *iface,
1606     BSTR* urlString )
1607 {
1608     domdoc *This = impl_from_IXMLDOMDocument2(iface);
1609     FIXME("(%p)->(%p)\n", This, urlString);
1610     return E_NOTIMPL;
1611 }
1612
1613
1614 static HRESULT WINAPI domdoc_get_async(
1615     IXMLDOMDocument2 *iface,
1616     VARIANT_BOOL* isAsync )
1617 {
1618     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1619
1620     TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
1621     *isAsync = This->async;
1622     return S_OK;
1623 }
1624
1625
1626 static HRESULT WINAPI domdoc_put_async(
1627     IXMLDOMDocument2 *iface,
1628     VARIANT_BOOL isAsync )
1629 {
1630     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1631
1632     TRACE("(%p)->(%d)\n", This, isAsync);
1633     This->async = isAsync;
1634     return S_OK;
1635 }
1636
1637
1638 static HRESULT WINAPI domdoc_abort(
1639     IXMLDOMDocument2 *iface )
1640 {
1641     domdoc *This = impl_from_IXMLDOMDocument2(iface);
1642     FIXME("%p\n", This);
1643     return E_NOTIMPL;
1644 }
1645
1646
1647 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
1648 {
1649     UINT len, blen = SysStringLen( bstr );
1650     LPSTR str;
1651
1652     len = WideCharToMultiByte( CP_UTF8, 0, bstr, blen, NULL, 0, NULL, NULL );
1653     str = heap_alloc( len );
1654     if ( !str )
1655         return FALSE;
1656     WideCharToMultiByte( CP_UTF8, 0, bstr, blen, str, len, NULL, NULL );
1657     *plen = len;
1658     *pstr = str;
1659     return TRUE;
1660 }
1661
1662 static HRESULT WINAPI domdoc_loadXML(
1663     IXMLDOMDocument2 *iface,
1664     BSTR bstrXML,
1665     VARIANT_BOOL* isSuccessful )
1666 {
1667     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1668     xmlDocPtr xmldoc = NULL;
1669     char *str;
1670     int len;
1671     HRESULT hr = S_FALSE, hr2;
1672
1673     TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
1674
1675     assert ( &This->node );
1676
1677     if ( isSuccessful )
1678     {
1679         *isSuccessful = VARIANT_FALSE;
1680
1681         if ( bstrXML  && bstr_to_utf8( bstrXML, &str, &len ) )
1682         {
1683             xmldoc = doparse( str, len );
1684             heap_free( str );
1685             if ( !xmldoc )
1686                 This->error = E_FAIL;
1687             else
1688             {
1689                 hr = This->error = S_OK;
1690                 *isSuccessful = VARIANT_TRUE;
1691             }
1692         }
1693     }
1694     if(!xmldoc)
1695         xmldoc = xmlNewDoc(NULL);
1696
1697     xmldoc->_private = create_priv();
1698     hr2 = attach_xmldoc( &This->node, xmldoc );
1699     if( FAILED(hr2) )
1700         hr = hr2;
1701
1702     return hr;
1703 }
1704
1705 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer,
1706                                              int len)
1707 {
1708     DWORD written = -1;
1709
1710     if(!WriteFile(ctx, buffer, len, &written, NULL))
1711     {
1712         WARN("write error\n");
1713         return -1;
1714     }
1715     else
1716         return written;
1717 }
1718
1719 static int XMLCALL domdoc_save_closecallback(void *ctx)
1720 {
1721     return CloseHandle(ctx) ? 0 : -1;
1722 }
1723
1724 static HRESULT WINAPI domdoc_save(
1725     IXMLDOMDocument2 *iface,
1726     VARIANT destination )
1727 {
1728     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1729     HANDLE handle;
1730     xmlSaveCtxtPtr ctx;
1731     HRESULT ret = S_OK;
1732
1733     TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
1734           V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
1735
1736     if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
1737     {
1738         FIXME("Unhandled vt %d\n", V_VT(&destination));
1739         return S_FALSE;
1740     }
1741
1742     if(V_VT(&destination) == VT_UNKNOWN)
1743     {
1744         IUnknown *pUnk = V_UNKNOWN(&destination);
1745         IXMLDOMDocument *pDocument;
1746
1747         ret = IXMLDOMDocument_QueryInterface(pUnk, &IID_IXMLDOMDocument2, (void**)&pDocument);
1748         if(ret == S_OK)
1749         {
1750             BSTR bXML;
1751             VARIANT_BOOL bSuccessful;
1752
1753             ret = IXMLDOMDocument_get_xml(iface, &bXML);
1754             if(ret == S_OK)
1755             {
1756                 ret = IXMLDOMDocument_loadXML(pDocument, bXML, &bSuccessful);
1757
1758                 SysFreeString(bXML);
1759             }
1760
1761             IXMLDOMDocument_Release(pDocument);
1762         }
1763
1764         TRACE("ret %d\n", ret);
1765
1766         return ret;
1767     }
1768
1769     handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
1770                           NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1771     if( handle == INVALID_HANDLE_VALUE )
1772     {
1773         WARN("failed to create file\n");
1774         return S_FALSE;
1775     }
1776
1777     /* disable top XML declaration */
1778     ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
1779                       handle, NULL, XML_SAVE_NO_DECL);
1780     if (!ctx)
1781     {
1782         CloseHandle(handle);
1783         return S_FALSE;
1784     }
1785
1786     if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
1787     /* will close file through close callback */
1788     xmlSaveClose(ctx);
1789
1790     return ret;
1791 }
1792
1793 static HRESULT WINAPI domdoc_get_validateOnParse(
1794     IXMLDOMDocument2 *iface,
1795     VARIANT_BOOL* isValidating )
1796 {
1797     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1798
1799     TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
1800     *isValidating = This->validating;
1801     return S_OK;
1802 }
1803
1804
1805 static HRESULT WINAPI domdoc_put_validateOnParse(
1806     IXMLDOMDocument2 *iface,
1807     VARIANT_BOOL isValidating )
1808 {
1809     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1810
1811     TRACE("(%p)->(%d)\n", This, isValidating);
1812     This->validating = isValidating;
1813     return S_OK;
1814 }
1815
1816
1817 static HRESULT WINAPI domdoc_get_resolveExternals(
1818     IXMLDOMDocument2 *iface,
1819     VARIANT_BOOL* isResolving )
1820 {
1821     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1822
1823     TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
1824     *isResolving = This->resolving;
1825     return S_OK;
1826 }
1827
1828
1829 static HRESULT WINAPI domdoc_put_resolveExternals(
1830     IXMLDOMDocument2 *iface,
1831     VARIANT_BOOL isResolving )
1832 {
1833     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1834
1835     TRACE("(%p)->(%d)\n", This, isResolving);
1836     This->resolving = isResolving;
1837     return S_OK;
1838 }
1839
1840
1841 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
1842     IXMLDOMDocument2 *iface,
1843     VARIANT_BOOL* isPreserving )
1844 {
1845     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1846
1847     TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->preserving);
1848     *isPreserving = This->preserving;
1849     return S_OK;
1850 }
1851
1852
1853 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
1854     IXMLDOMDocument2 *iface,
1855     VARIANT_BOOL isPreserving )
1856 {
1857     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1858
1859     TRACE("(%p)->(%d)\n", This, isPreserving);
1860     This->preserving = isPreserving;
1861     return S_OK;
1862 }
1863
1864
1865 static HRESULT WINAPI domdoc_put_onReadyStateChange(
1866     IXMLDOMDocument2 *iface,
1867     VARIANT readyStateChangeSink )
1868 {
1869     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1870     FIXME("%p\n", This);
1871     return E_NOTIMPL;
1872 }
1873
1874
1875 static HRESULT WINAPI domdoc_put_onDataAvailable(
1876     IXMLDOMDocument2 *iface,
1877     VARIANT onDataAvailableSink )
1878 {
1879     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1880     FIXME("%p\n", This);
1881     return E_NOTIMPL;
1882 }
1883
1884 static HRESULT WINAPI domdoc_put_onTransformNode(
1885     IXMLDOMDocument2 *iface,
1886     VARIANT onTransformNodeSink )
1887 {
1888     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1889     FIXME("%p\n", This);
1890     return E_NOTIMPL;
1891 }
1892
1893 static HRESULT WINAPI domdoc_get_namespaces(
1894     IXMLDOMDocument2* iface,
1895     IXMLDOMSchemaCollection** schemaCollection )
1896 {
1897     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1898     FIXME("(%p)->(%p)\n", This, schemaCollection);
1899     return E_NOTIMPL;
1900 }
1901
1902 static HRESULT WINAPI domdoc_get_schemas(
1903     IXMLDOMDocument2* iface,
1904     VARIANT* var1 )
1905 {
1906     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1907     HRESULT hr = S_FALSE;
1908     IXMLDOMSchemaCollection *cur_schema = This->schema;
1909
1910     TRACE("(%p)->(%p)\n", This, var1);
1911
1912     VariantInit(var1); /* Test shows we don't call VariantClear here */
1913     V_VT(var1) = VT_NULL;
1914
1915     if(cur_schema)
1916     {
1917         hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
1918         if(SUCCEEDED(hr))
1919             V_VT(var1) = VT_DISPATCH;
1920     }
1921     return hr;
1922 }
1923
1924 static HRESULT WINAPI domdoc_putref_schemas(
1925     IXMLDOMDocument2* iface,
1926     VARIANT var1)
1927 {
1928     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1929     HRESULT hr = E_FAIL;
1930     IXMLDOMSchemaCollection *new_schema = NULL;
1931
1932     FIXME("(%p): semi-stub\n", This);
1933     switch(V_VT(&var1))
1934     {
1935     case VT_UNKNOWN:
1936         hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1937         break;
1938
1939     case VT_DISPATCH:
1940         hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1941         break;
1942
1943     case VT_NULL:
1944     case VT_EMPTY:
1945         hr = S_OK;
1946         break;
1947
1948     default:
1949         WARN("Can't get schema from vt %x\n", V_VT(&var1));
1950     }
1951
1952     if(SUCCEEDED(hr))
1953     {
1954         IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
1955         if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
1956     }
1957
1958     return hr;
1959 }
1960
1961 static HRESULT WINAPI domdoc_validate(
1962     IXMLDOMDocument2* iface,
1963     IXMLDOMParseError** err)
1964 {
1965     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1966     FIXME("(%p)->(%p)\n", This, err);
1967     return E_NOTIMPL;
1968 }
1969
1970 static HRESULT WINAPI domdoc_setProperty(
1971     IXMLDOMDocument2* iface,
1972     BSTR p,
1973     VARIANT var)
1974 {
1975     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1976
1977     TRACE("(%p)->(%s)\n", This, debugstr_w(p));
1978
1979     if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
1980     {
1981         VARIANT varStr;
1982         HRESULT hr;
1983         BSTR bstr;
1984
1985         V_VT(&varStr) = VT_EMPTY;
1986         if (V_VT(&var) != VT_BSTR)
1987         {
1988             if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
1989                 return hr;
1990             bstr = V_BSTR(&varStr);
1991         }
1992         else
1993             bstr = V_BSTR(&var);
1994
1995         hr = S_OK;
1996         if (lstrcmpiW(bstr, SZ_VALUE_XPATH) == 0)
1997             This->bUseXPath = TRUE;
1998         else if (lstrcmpiW(bstr, SZ_VALUE_XSLPATTERN) == 0)
1999             This->bUseXPath = FALSE;
2000         else
2001             hr = E_FAIL;
2002
2003         VariantClear(&varStr);
2004         return hr;
2005     }
2006
2007     FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2008     return E_FAIL;
2009 }
2010
2011 static HRESULT WINAPI domdoc_getProperty(
2012     IXMLDOMDocument2* iface,
2013     BSTR p,
2014     VARIANT* var)
2015 {
2016     domdoc *This = impl_from_IXMLDOMDocument2( iface );
2017
2018     TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2019
2020     if (var == NULL)
2021         return E_INVALIDARG;
2022     if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
2023     {
2024         V_VT(var) = VT_BSTR;
2025         if (This->bUseXPath)
2026             V_BSTR(var) = SysAllocString(SZ_VALUE_XPATH);
2027         else
2028             V_BSTR(var) = SysAllocString(SZ_VALUE_XSLPATTERN);
2029         return S_OK;
2030     }
2031
2032     FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2033     return E_FAIL;
2034 }
2035
2036 static const struct IXMLDOMDocument2Vtbl domdoc_vtbl =
2037 {
2038     domdoc_QueryInterface,
2039     domdoc_AddRef,
2040     domdoc_Release,
2041     domdoc_GetTypeInfoCount,
2042     domdoc_GetTypeInfo,
2043     domdoc_GetIDsOfNames,
2044     domdoc_Invoke,
2045     domdoc_get_nodeName,
2046     domdoc_get_nodeValue,
2047     domdoc_put_nodeValue,
2048     domdoc_get_nodeType,
2049     domdoc_get_parentNode,
2050     domdoc_get_childNodes,
2051     domdoc_get_firstChild,
2052     domdoc_get_lastChild,
2053     domdoc_get_previousSibling,
2054     domdoc_get_nextSibling,
2055     domdoc_get_attributes,
2056     domdoc_insertBefore,
2057     domdoc_replaceChild,
2058     domdoc_removeChild,
2059     domdoc_appendChild,
2060     domdoc_hasChildNodes,
2061     domdoc_get_ownerDocument,
2062     domdoc_cloneNode,
2063     domdoc_get_nodeTypeString,
2064     domdoc_get_text,
2065     domdoc_put_text,
2066     domdoc_get_specified,
2067     domdoc_get_definition,
2068     domdoc_get_nodeTypedValue,
2069     domdoc_put_nodeTypedValue,
2070     domdoc_get_dataType,
2071     domdoc_put_dataType,
2072     domdoc_get_xml,
2073     domdoc_transformNode,
2074     domdoc_selectNodes,
2075     domdoc_selectSingleNode,
2076     domdoc_get_parsed,
2077     domdoc_get_namespaceURI,
2078     domdoc_get_prefix,
2079     domdoc_get_baseName,
2080     domdoc_transformNodeToObject,
2081     domdoc_get_doctype,
2082     domdoc_get_implementation,
2083     domdoc_get_documentElement,
2084     domdoc_put_documentElement,
2085     domdoc_createElement,
2086     domdoc_createDocumentFragment,
2087     domdoc_createTextNode,
2088     domdoc_createComment,
2089     domdoc_createCDATASection,
2090     domdoc_createProcessingInstruction,
2091     domdoc_createAttribute,
2092     domdoc_createEntityReference,
2093     domdoc_getElementsByTagName,
2094     domdoc_createNode,
2095     domdoc_nodeFromID,
2096     domdoc_load,
2097     domdoc_get_readyState,
2098     domdoc_get_parseError,
2099     domdoc_get_url,
2100     domdoc_get_async,
2101     domdoc_put_async,
2102     domdoc_abort,
2103     domdoc_loadXML,
2104     domdoc_save,
2105     domdoc_get_validateOnParse,
2106     domdoc_put_validateOnParse,
2107     domdoc_get_resolveExternals,
2108     domdoc_put_resolveExternals,
2109     domdoc_get_preserveWhiteSpace,
2110     domdoc_put_preserveWhiteSpace,
2111     domdoc_put_onReadyStateChange,
2112     domdoc_put_onDataAvailable,
2113     domdoc_put_onTransformNode,
2114     domdoc_get_namespaces,
2115     domdoc_get_schemas,
2116     domdoc_putref_schemas,
2117     domdoc_validate,
2118     domdoc_setProperty,
2119     domdoc_getProperty
2120 };
2121
2122 /* xmldoc implementation of IObjectWithSite */
2123 static HRESULT WINAPI
2124 xmldoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
2125 {
2126     domdoc *This = impl_from_IObjectWithSite(iface);
2127     return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppvObject );
2128 }
2129
2130 static ULONG WINAPI
2131 xmldoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
2132 {
2133     domdoc *This = impl_from_IObjectWithSite(iface);
2134     return IXMLDocument_AddRef((IXMLDocument *)This);
2135 }
2136
2137 static ULONG WINAPI
2138 xmldoc_ObjectWithSite_Release( IObjectWithSite* iface )
2139 {
2140     domdoc *This = impl_from_IObjectWithSite(iface);
2141     return IXMLDocument_Release((IXMLDocument *)This);
2142 }
2143
2144 static HRESULT WINAPI
2145 xmldoc_GetSite( IObjectWithSite *iface, REFIID iid, void ** ppvSite )
2146 {
2147     domdoc *This = impl_from_IObjectWithSite(iface);
2148
2149     TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
2150
2151     if ( !This->site )
2152         return E_FAIL;
2153
2154     return IUnknown_QueryInterface( This->site, iid, ppvSite );
2155 }
2156
2157 static HRESULT WINAPI
2158 xmldoc_SetSite( IObjectWithSite *iface, IUnknown *punk )
2159 {
2160     domdoc *This = impl_from_IObjectWithSite(iface);
2161
2162     TRACE("(%p)->(%p)\n", iface, punk);
2163
2164     if(!punk)
2165     {
2166         if(This->site)
2167         {
2168             IUnknown_Release( This->site );
2169             This->site = NULL;
2170         }
2171
2172         return S_OK;
2173     }
2174
2175     if ( punk )
2176         IUnknown_AddRef( punk );
2177
2178     if(This->site)
2179         IUnknown_Release( This->site );
2180
2181     This->site = punk;
2182
2183     return S_OK;
2184 }
2185
2186 static const IObjectWithSiteVtbl domdocObjectSite =
2187 {
2188     xmldoc_ObjectWithSite_QueryInterface,
2189     xmldoc_ObjectWithSite_AddRef,
2190     xmldoc_ObjectWithSite_Release,
2191     xmldoc_SetSite,
2192     xmldoc_GetSite,
2193 };
2194
2195 static HRESULT WINAPI xmldoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
2196 {
2197     domdoc *This = impl_from_IObjectSafety(iface);
2198     return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppv );
2199 }
2200
2201 static ULONG WINAPI xmldoc_Safety_AddRef(IObjectSafety *iface)
2202 {
2203     domdoc *This = impl_from_IObjectSafety(iface);
2204     return IXMLDocument_AddRef((IXMLDocument *)This);
2205 }
2206
2207 static ULONG WINAPI xmldoc_Safety_Release(IObjectSafety *iface)
2208 {
2209     domdoc *This = impl_from_IObjectSafety(iface);
2210     return IXMLDocument_Release((IXMLDocument *)This);
2211 }
2212
2213 #define SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
2214
2215 static HRESULT WINAPI xmldoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2216         DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
2217 {
2218     domdoc *This = impl_from_IObjectSafety(iface);
2219
2220     TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
2221
2222     if(!pdwSupportedOptions || !pdwEnabledOptions)
2223         return E_POINTER;
2224
2225     *pdwSupportedOptions = SUPPORTED_OPTIONS;
2226     *pdwEnabledOptions = This->safeopt;
2227
2228     return S_OK;
2229 }
2230
2231 static HRESULT WINAPI xmldoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2232         DWORD dwOptionSetMask, DWORD dwEnabledOptions)
2233 {
2234     domdoc *This = impl_from_IObjectSafety(iface);
2235
2236     TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
2237
2238     if(dwOptionSetMask & ~SUPPORTED_OPTIONS)
2239         return E_FAIL;
2240
2241     This->safeopt = dwEnabledOptions & dwEnabledOptions;
2242     return S_OK;
2243 }
2244
2245 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
2246     xmldoc_Safety_QueryInterface,
2247     xmldoc_Safety_AddRef,
2248     xmldoc_Safety_Release,
2249     xmldoc_Safety_GetInterfaceSafetyOptions,
2250     xmldoc_Safety_SetInterfaceSafetyOptions
2251 };
2252
2253
2254 static const tid_t domdoc_iface_tids[] = {
2255     IXMLDOMNode_tid,
2256     IXMLDOMDocument_tid,
2257     IXMLDOMDocument2_tid,
2258     0
2259 };
2260 static dispex_static_data_t domdoc_dispex = {
2261     NULL,
2262     IXMLDOMDocument2_tid,
2263     NULL,
2264     domdoc_iface_tids
2265 };
2266
2267 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument2 **document)
2268 {
2269     domdoc *doc;
2270
2271     doc = heap_alloc( sizeof (*doc) );
2272     if( !doc )
2273         return E_OUTOFMEMORY;
2274
2275     doc->lpVtbl = &domdoc_vtbl;
2276     doc->lpvtblIPersistStream = &xmldoc_IPersistStream_VTable;
2277     doc->lpvtblIObjectWithSite = &domdocObjectSite;
2278     doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
2279     doc->lpvtblISupportErrorInfo = &support_error_vtbl;
2280     doc->ref = 1;
2281     doc->async = VARIANT_TRUE;
2282     doc->validating = 0;
2283     doc->resolving = 0;
2284     doc->preserving = 0;
2285     doc->bUseXPath = FALSE;
2286     doc->error = S_OK;
2287     doc->schema = NULL;
2288     doc->stream = NULL;
2289     doc->site = NULL;
2290     doc->safeopt = 0;
2291     doc->bsc = NULL;
2292
2293     init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IUnknown*)&doc->lpVtbl, &domdoc_dispex);
2294
2295     *document = (IXMLDOMDocument2*)&doc->lpVtbl;
2296
2297     TRACE("returning iface %p\n", *document);
2298     return S_OK;
2299 }
2300
2301 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2302 {
2303     xmlDocPtr xmldoc;
2304     HRESULT hr;
2305
2306     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
2307
2308     xmldoc = xmlNewDoc(NULL);
2309     if(!xmldoc)
2310         return E_OUTOFMEMORY;
2311
2312     xmldoc->_private = create_priv();
2313
2314     hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument2**)ppObj);
2315     if(FAILED(hr))
2316         xmlFreeDoc(xmldoc);
2317
2318     return hr;
2319 }
2320
2321 IUnknown* create_domdoc( xmlNodePtr document )
2322 {
2323     HRESULT hr;
2324     LPVOID pObj = NULL;
2325
2326     TRACE("(%p)\n", document);
2327
2328     hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument2**)&pObj);
2329     if (FAILED(hr))
2330         return NULL;
2331
2332     return pObj;
2333 }
2334
2335 #else
2336
2337 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2338 {
2339     MESSAGE("This program tried to use a DOMDocument object, but\n"
2340             "libxml2 support was not present at compile time.\n");
2341     return E_NOTIMPL;
2342 }
2343
2344 #endif