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