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