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