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