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