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