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