oleaut32/tests: Allow UuidCreate to return RPC_S_UUID_LOCAL_ONLY.
[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
1228     default:
1229         FIXME("unhandled node type %d\n", node_type);
1230         break;
1231     }
1232
1233     HeapFree(GetProcessHeap(), 0, xml_name);
1234
1235     if(xmlnode && *node)
1236         return S_OK;
1237
1238     return E_FAIL;
1239 }
1240
1241 static HRESULT WINAPI domdoc_nodeFromID(
1242     IXMLDOMDocument2 *iface,
1243     BSTR idString,
1244     IXMLDOMNode** node )
1245 {
1246     FIXME("\n");
1247     return E_NOTIMPL;
1248 }
1249
1250 static xmlDocPtr doparse( char *ptr, int len )
1251 {
1252 #ifdef HAVE_XMLREADMEMORY
1253     /*
1254      * use xmlReadMemory if possible so we can suppress
1255      * writing errors to stderr
1256      */
1257     return xmlReadMemory( ptr, len, NULL, NULL,
1258                           XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS );
1259 #else
1260     return xmlParseMemory( ptr, len );
1261 #endif
1262 }
1263
1264 static xmlDocPtr doread( LPWSTR filename )
1265 {
1266     xmlDocPtr xmldoc = NULL;
1267     HRESULT hr;
1268     IBindCtx *pbc;
1269     IStream *stream, *memstream;
1270     WCHAR url[INTERNET_MAX_URL_LENGTH];
1271     BYTE buf[4096];
1272     DWORD read, written;
1273
1274     TRACE("%s\n", debugstr_w( filename ));
1275
1276     if(!PathIsURLW(filename))
1277     {
1278         WCHAR fullpath[MAX_PATH];
1279         DWORD needed = sizeof(url)/sizeof(WCHAR);
1280
1281         if(!PathSearchAndQualifyW(filename, fullpath, sizeof(fullpath)/sizeof(WCHAR)))
1282         {
1283             WARN("can't find path\n");
1284             return NULL;
1285         }
1286
1287         if(FAILED(UrlCreateFromPathW(fullpath, url, &needed, 0)))
1288         {
1289             ERR("can't create url from path\n");
1290             return NULL;
1291         }
1292         filename = url;
1293     }
1294
1295     hr = CreateBindCtx(0, &pbc);
1296     if(SUCCEEDED(hr))
1297     {
1298         hr = RegisterBindStatusCallback(pbc, (IBindStatusCallback*)&domdoc_bsc.lpVtbl, NULL, 0);
1299         if(SUCCEEDED(hr))
1300         {
1301             IMoniker *moniker;
1302             hr = CreateURLMoniker(NULL, filename, &moniker);
1303             if(SUCCEEDED(hr))
1304             {
1305                 hr = IMoniker_BindToStorage(moniker, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
1306                 IMoniker_Release(moniker);
1307             }
1308         }
1309         IBindCtx_Release(pbc);
1310     }
1311     if(FAILED(hr))
1312         return NULL;
1313
1314     hr = CreateStreamOnHGlobal(NULL, TRUE, &memstream);
1315     if(FAILED(hr))
1316     {
1317         IStream_Release(stream);
1318         return NULL;
1319     }
1320
1321     do
1322     {
1323         IStream_Read(stream, buf, sizeof(buf), &read);
1324         hr = IStream_Write(memstream, buf, read, &written);
1325     } while(SUCCEEDED(hr) && written != 0 && read != 0);
1326
1327     if(SUCCEEDED(hr))
1328     {
1329         HGLOBAL hglobal;
1330         hr = GetHGlobalFromStream(memstream, &hglobal);
1331         if(SUCCEEDED(hr))
1332         {
1333             DWORD len = GlobalSize(hglobal);
1334             char *ptr = GlobalLock(hglobal);
1335             if(len != 0)
1336                 xmldoc = doparse( ptr, len );
1337             GlobalUnlock(hglobal);
1338         }
1339     }
1340     IStream_Release(memstream);
1341     IStream_Release(stream);
1342     return xmldoc;
1343 }
1344
1345 static HRESULT WINAPI domdoc_load(
1346     IXMLDOMDocument2 *iface,
1347     VARIANT xmlSource,
1348     VARIANT_BOOL* isSuccessful )
1349 {
1350     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1351     LPWSTR filename = NULL;
1352     xmlDocPtr xmldoc = NULL;
1353     HRESULT hr = S_FALSE;
1354     IXMLDOMDocument2 *pNewDoc = NULL;
1355     IStream *pStream = NULL;
1356
1357     TRACE("type %d\n", V_VT(&xmlSource) );
1358
1359     *isSuccessful = VARIANT_FALSE;
1360
1361     assert( This->node );
1362
1363     attach_xmlnode(This->node, NULL);
1364
1365     switch( V_VT(&xmlSource) )
1366     {
1367     case VT_BSTR:
1368         filename = V_BSTR(&xmlSource);
1369         break;
1370     case VT_UNKNOWN:
1371         hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument2, (void**)&pNewDoc);
1372         if(hr == S_OK)
1373         {
1374             if(pNewDoc)
1375             {
1376                 domdoc *newDoc = impl_from_IXMLDOMDocument2( pNewDoc );
1377                 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1378                 attach_xmlnode(This->node, (xmlNodePtr) xmldoc);
1379
1380                 *isSuccessful = VARIANT_TRUE;
1381
1382                 return S_OK;
1383             }
1384         }
1385         hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1386         if(hr == S_OK)
1387         {
1388             IPersistStream *pDocStream;
1389             hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1390             if(hr == S_OK)
1391             {
1392                 hr = xmldoc_IPersistStream_Load(pDocStream, pStream);
1393                 IStream_Release(pStream);
1394                 if(hr == S_OK)
1395                 {
1396                     *isSuccessful = VARIANT_TRUE;
1397
1398                     TRACE("Using ID_IStream to load Document\n");
1399                     return S_OK;
1400                 }
1401                 else
1402                 {
1403                     ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1404                 }
1405             }
1406             else
1407             {
1408                 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1409             }
1410         }
1411         else
1412         {
1413             /* ISequentialStream */
1414             FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1415         }
1416         break;
1417      default:
1418             FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1419      }
1420
1421     TRACE("filename (%s)\n", debugstr_w(filename));
1422
1423     if ( filename )
1424     {
1425         xmldoc = doread( filename );
1426     
1427         if ( !xmldoc )
1428             This->error = E_FAIL;
1429         else
1430         {
1431             hr = This->error = S_OK;
1432             *isSuccessful = VARIANT_TRUE;
1433         }
1434     }
1435
1436     if(!xmldoc)
1437         xmldoc = xmlNewDoc(NULL);
1438
1439     xmldoc->_private = 0;
1440     attach_xmlnode(This->node, (xmlNodePtr) xmldoc);
1441
1442     TRACE("ret (%d)\n", hr);
1443
1444     return hr;
1445 }
1446
1447
1448 static HRESULT WINAPI domdoc_get_readyState(
1449     IXMLDOMDocument2 *iface,
1450     long* value )
1451 {
1452     FIXME("\n");
1453     return E_NOTIMPL;
1454 }
1455
1456
1457 static HRESULT WINAPI domdoc_get_parseError(
1458     IXMLDOMDocument2 *iface,
1459     IXMLDOMParseError** errorObj )
1460 {
1461     BSTR error_string = NULL;
1462     static const WCHAR err[] = {'e','r','r','o','r',0};
1463     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1464
1465     FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
1466
1467     if(This->error)
1468         error_string = SysAllocString(err);
1469
1470     *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
1471     if(!*errorObj) return E_OUTOFMEMORY;
1472     return S_OK;
1473 }
1474
1475
1476 static HRESULT WINAPI domdoc_get_url(
1477     IXMLDOMDocument2 *iface,
1478     BSTR* urlString )
1479 {
1480     FIXME("\n");
1481     return E_NOTIMPL;
1482 }
1483
1484
1485 static HRESULT WINAPI domdoc_get_async(
1486     IXMLDOMDocument2 *iface,
1487     VARIANT_BOOL* isAsync )
1488 {
1489     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1490
1491     TRACE("%p <- %d\n", isAsync, This->async);
1492     *isAsync = This->async;
1493     return S_OK;
1494 }
1495
1496
1497 static HRESULT WINAPI domdoc_put_async(
1498     IXMLDOMDocument2 *iface,
1499     VARIANT_BOOL isAsync )
1500 {
1501     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1502
1503     TRACE("%d\n", isAsync);
1504     This->async = isAsync;
1505     return S_OK;
1506 }
1507
1508
1509 static HRESULT WINAPI domdoc_abort(
1510     IXMLDOMDocument2 *iface )
1511 {
1512     FIXME("\n");
1513     return E_NOTIMPL;
1514 }
1515
1516
1517 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
1518 {
1519     UINT len, blen = SysStringLen( bstr );
1520     LPSTR str;
1521
1522     len = WideCharToMultiByte( CP_UTF8, 0, bstr, blen, NULL, 0, NULL, NULL );
1523     str = HeapAlloc( GetProcessHeap(), 0, len );
1524     if ( !str )
1525         return FALSE;
1526     WideCharToMultiByte( CP_UTF8, 0, bstr, blen, str, len, NULL, NULL );
1527     *plen = len;
1528     *pstr = str;
1529     return TRUE;
1530 }
1531
1532 static HRESULT WINAPI domdoc_loadXML(
1533     IXMLDOMDocument2 *iface,
1534     BSTR bstrXML,
1535     VARIANT_BOOL* isSuccessful )
1536 {
1537     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1538     xmlDocPtr xmldoc = NULL;
1539     char *str;
1540     int len;
1541     HRESULT hr = S_FALSE;
1542
1543     TRACE("%p %s %p\n", This, debugstr_w( bstrXML ), isSuccessful );
1544
1545     assert ( This->node );
1546
1547     attach_xmlnode( This->node, NULL );
1548
1549     if ( isSuccessful )
1550     {
1551         *isSuccessful = VARIANT_FALSE;
1552
1553         if ( bstrXML  && bstr_to_utf8( bstrXML, &str, &len ) )
1554         {
1555             xmldoc = doparse( str, len );
1556             HeapFree( GetProcessHeap(), 0, str );
1557             if ( !xmldoc )
1558                 This->error = E_FAIL;
1559             else
1560             {
1561                 hr = This->error = S_OK;
1562                 *isSuccessful = VARIANT_TRUE;
1563             }
1564         }
1565     }
1566     if(!xmldoc)
1567         xmldoc = xmlNewDoc(NULL);
1568
1569     xmldoc->_private = 0;
1570     attach_xmlnode( This->node, (xmlNodePtr) xmldoc );
1571
1572     return hr;
1573 }
1574
1575
1576 static HRESULT WINAPI domdoc_save(
1577     IXMLDOMDocument2 *iface,
1578     VARIANT destination )
1579 {
1580     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1581     HANDLE handle;
1582     xmlChar *mem;
1583     int size;
1584     HRESULT ret = S_OK;
1585     DWORD written;
1586
1587     TRACE("(%p)->(var(vt %x, %s))\n", This, V_VT(&destination),
1588           V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
1589
1590     if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
1591     {
1592         FIXME("Unhandled vt %d\n", V_VT(&destination));
1593         return S_FALSE;
1594     }
1595
1596     if(V_VT(&destination) == VT_UNKNOWN)
1597     {
1598         IUnknown *pUnk = V_UNKNOWN(&destination);
1599         IXMLDOMDocument *pDocument;
1600
1601         ret = IXMLDOMDocument_QueryInterface(pUnk, &IID_IXMLDOMDocument2, (void**)&pDocument);
1602         if(ret == S_OK)
1603         {
1604             BSTR bXML;
1605             VARIANT_BOOL bSuccessful;
1606
1607             ret = IXMLDOMDocument_get_xml(iface, &bXML);
1608             if(ret == S_OK)
1609             {
1610                 ret = IXMLDOMDocument_loadXML(pDocument, bXML, &bSuccessful);
1611
1612                 SysFreeString(bXML);
1613             }
1614
1615             IXMLDOMDocument_Release(pDocument);
1616         }
1617
1618         return ret;
1619     }
1620
1621     handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
1622                           NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1623     if( handle == INVALID_HANDLE_VALUE )
1624     {
1625         WARN("failed to create file\n");
1626         return S_FALSE;
1627     }
1628
1629     xmlDocDumpMemory(get_doc(This), &mem, &size);
1630     if(!WriteFile(handle, mem, (DWORD)size, &written, NULL) || written != (DWORD)size)
1631     {
1632         WARN("write error\n");
1633         ret = S_FALSE;
1634     }
1635
1636     xmlFree(mem);
1637     CloseHandle(handle);
1638     return ret;
1639 }
1640
1641 static HRESULT WINAPI domdoc_get_validateOnParse(
1642     IXMLDOMDocument2 *iface,
1643     VARIANT_BOOL* isValidating )
1644 {
1645     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1646
1647     TRACE("%p <- %d\n", isValidating, This->validating);
1648     *isValidating = This->validating;
1649     return S_OK;
1650 }
1651
1652
1653 static HRESULT WINAPI domdoc_put_validateOnParse(
1654     IXMLDOMDocument2 *iface,
1655     VARIANT_BOOL isValidating )
1656 {
1657     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1658
1659     TRACE("%d\n", isValidating);
1660     This->validating = isValidating;
1661     return S_OK;
1662 }
1663
1664
1665 static HRESULT WINAPI domdoc_get_resolveExternals(
1666     IXMLDOMDocument2 *iface,
1667     VARIANT_BOOL* isResolving )
1668 {
1669     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1670
1671     TRACE("%p <- %d\n", isResolving, This->resolving);
1672     *isResolving = This->resolving;
1673     return S_OK;
1674 }
1675
1676
1677 static HRESULT WINAPI domdoc_put_resolveExternals(
1678     IXMLDOMDocument2 *iface,
1679     VARIANT_BOOL isResolving )
1680 {
1681     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1682
1683     TRACE("%d\n", isResolving);
1684     This->resolving = isResolving;
1685     return S_OK;
1686 }
1687
1688
1689 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
1690     IXMLDOMDocument2 *iface,
1691     VARIANT_BOOL* isPreserving )
1692 {
1693     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1694
1695     TRACE("%p <- %d\n", isPreserving, This->preserving);
1696     *isPreserving = This->preserving;
1697     return S_OK;
1698 }
1699
1700
1701 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
1702     IXMLDOMDocument2 *iface,
1703     VARIANT_BOOL isPreserving )
1704 {
1705     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1706
1707     TRACE("%d\n", isPreserving);
1708     This->preserving = isPreserving;
1709     return S_OK;
1710 }
1711
1712
1713 static HRESULT WINAPI domdoc_put_onReadyStateChange(
1714     IXMLDOMDocument2 *iface,
1715     VARIANT readyStateChangeSink )
1716 {
1717     FIXME("\n");
1718     return E_NOTIMPL;
1719 }
1720
1721
1722 static HRESULT WINAPI domdoc_put_onDataAvailable(
1723     IXMLDOMDocument2 *iface,
1724     VARIANT onDataAvailableSink )
1725 {
1726     FIXME("\n");
1727     return E_NOTIMPL;
1728 }
1729
1730 static HRESULT WINAPI domdoc_put_onTransformNode(
1731     IXMLDOMDocument2 *iface,
1732     VARIANT onTransformNodeSink )
1733 {
1734     FIXME("\n");
1735     return E_NOTIMPL;
1736 }
1737
1738 static HRESULT WINAPI domdoc_get_namespaces(
1739     IXMLDOMDocument2* iface,
1740     IXMLDOMSchemaCollection** schemaCollection )
1741 {
1742     FIXME("\n");
1743     return E_NOTIMPL;
1744 }
1745
1746 static HRESULT WINAPI domdoc_get_schemas(
1747     IXMLDOMDocument2* iface,
1748     VARIANT* var1 )
1749 {
1750     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1751     HRESULT hr = S_FALSE;
1752     IXMLDOMSchemaCollection *cur_schema = This->schema;
1753
1754     TRACE("(%p)->(%p)\n", This, var1);
1755
1756     VariantInit(var1); /* Test shows we don't call VariantClear here */
1757     V_VT(var1) = VT_NULL;
1758
1759     if(cur_schema)
1760     {
1761         hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
1762         if(SUCCEEDED(hr))
1763             V_VT(var1) = VT_DISPATCH;
1764     }
1765     return hr;
1766 }
1767
1768 static HRESULT WINAPI domdoc_putref_schemas(
1769     IXMLDOMDocument2* iface,
1770     VARIANT var1)
1771 {
1772     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1773     HRESULT hr = E_FAIL;
1774     IXMLDOMSchemaCollection *new_schema = NULL;
1775
1776     FIXME("(%p): semi-stub\n", This);
1777     switch(V_VT(&var1))
1778     {
1779     case VT_UNKNOWN:
1780         hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1781         break;
1782
1783     case VT_DISPATCH:
1784         hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1785         break;
1786
1787     case VT_NULL:
1788     case VT_EMPTY:
1789         hr = S_OK;
1790         break;
1791
1792     default:
1793         WARN("Can't get schema from vt %x\n", V_VT(&var1));
1794     }
1795
1796     if(SUCCEEDED(hr))
1797     {
1798         IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
1799         if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
1800     }
1801
1802     return hr;
1803 }
1804
1805 static HRESULT WINAPI domdoc_validate(
1806     IXMLDOMDocument2* iface,
1807     IXMLDOMParseError** err)
1808 {
1809     FIXME("\n");
1810     return E_NOTIMPL;
1811 }
1812
1813 static HRESULT WINAPI domdoc_setProperty(
1814     IXMLDOMDocument2* iface,
1815     BSTR p,
1816     VARIANT var)
1817 {
1818     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1819
1820     if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
1821     {
1822         VARIANT varStr;
1823         HRESULT hr;
1824         BSTR bstr;
1825
1826         V_VT(&varStr) = VT_EMPTY;
1827         if (V_VT(&var) != VT_BSTR)
1828         {
1829             if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
1830                 return hr;
1831             bstr = V_BSTR(&varStr);
1832         }
1833         else
1834             bstr = V_BSTR(&var);
1835
1836         hr = S_OK;
1837         if (lstrcmpiW(bstr, SZ_VALUE_XPATH) == 0)
1838             This->bUseXPath = TRUE;
1839         else if (lstrcmpiW(bstr, SZ_VALUE_XSLPATTERN) == 0)
1840             This->bUseXPath = FALSE;
1841         else
1842             hr = E_FAIL;
1843
1844         VariantClear(&varStr);
1845         return hr;
1846     }
1847
1848     FIXME("Unknown property %s\n", wine_dbgstr_w(p));
1849     return E_FAIL;
1850 }
1851
1852 static HRESULT WINAPI domdoc_getProperty(
1853     IXMLDOMDocument2* iface,
1854     BSTR p,
1855     VARIANT* var)
1856 {
1857     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1858
1859     if (var == NULL)
1860         return E_INVALIDARG;
1861     if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
1862     {
1863         V_VT(var) = VT_BSTR;
1864         if (This->bUseXPath)
1865             V_BSTR(var) = SysAllocString(SZ_VALUE_XPATH);
1866         else
1867             V_BSTR(var) = SysAllocString(SZ_VALUE_XSLPATTERN);
1868         return S_OK;
1869     }
1870
1871     FIXME("Unknown property %s\n", wine_dbgstr_w(p));
1872     return E_FAIL;
1873 }
1874
1875 static const struct IXMLDOMDocument2Vtbl domdoc_vtbl =
1876 {
1877     domdoc_QueryInterface,
1878     domdoc_AddRef,
1879     domdoc_Release,
1880     domdoc_GetTypeInfoCount,
1881     domdoc_GetTypeInfo,
1882     domdoc_GetIDsOfNames,
1883     domdoc_Invoke,
1884     domdoc_get_nodeName,
1885     domdoc_get_nodeValue,
1886     domdoc_put_nodeValue,
1887     domdoc_get_nodeType,
1888     domdoc_get_parentNode,
1889     domdoc_get_childNodes,
1890     domdoc_get_firstChild,
1891     domdoc_get_lastChild,
1892     domdoc_get_previousSibling,
1893     domdoc_get_nextSibling,
1894     domdoc_get_attributes,
1895     domdoc_insertBefore,
1896     domdoc_replaceChild,
1897     domdoc_removeChild,
1898     domdoc_appendChild,
1899     domdoc_hasChildNodes,
1900     domdoc_get_ownerDocument,
1901     domdoc_cloneNode,
1902     domdoc_get_nodeTypeString,
1903     domdoc_get_text,
1904     domdoc_put_text,
1905     domdoc_get_specified,
1906     domdoc_get_definition,
1907     domdoc_get_nodeTypedValue,
1908     domdoc_put_nodeTypedValue,
1909     domdoc_get_dataType,
1910     domdoc_put_dataType,
1911     domdoc_get_xml,
1912     domdoc_transformNode,
1913     domdoc_selectNodes,
1914     domdoc_selectSingleNode,
1915     domdoc_get_parsed,
1916     domdoc_get_namespaceURI,
1917     domdoc_get_prefix,
1918     domdoc_get_baseName,
1919     domdoc_transformNodeToObject,
1920     domdoc_get_doctype,
1921     domdoc_get_implementation,
1922     domdoc_get_documentElement,
1923     domdoc_documentElement,
1924     domdoc_createElement,
1925     domdoc_createDocumentFragment,
1926     domdoc_createTextNode,
1927     domdoc_createComment,
1928     domdoc_createCDATASection,
1929     domdoc_createProcessingInstruction,
1930     domdoc_createAttribute,
1931     domdoc_createEntityReference,
1932     domdoc_getElementsByTagName,
1933     domdoc_createNode,
1934     domdoc_nodeFromID,
1935     domdoc_load,
1936     domdoc_get_readyState,
1937     domdoc_get_parseError,
1938     domdoc_get_url,
1939     domdoc_get_async,
1940     domdoc_put_async,
1941     domdoc_abort,
1942     domdoc_loadXML,
1943     domdoc_save,
1944     domdoc_get_validateOnParse,
1945     domdoc_put_validateOnParse,
1946     domdoc_get_resolveExternals,
1947     domdoc_put_resolveExternals,
1948     domdoc_get_preserveWhiteSpace,
1949     domdoc_put_preserveWhiteSpace,
1950     domdoc_put_onReadyStateChange,
1951     domdoc_put_onDataAvailable,
1952     domdoc_put_onTransformNode,
1953     domdoc_get_namespaces,
1954     domdoc_get_schemas,
1955     domdoc_putref_schemas,
1956     domdoc_validate,
1957     domdoc_setProperty,
1958     domdoc_getProperty
1959 };
1960
1961 /* xmldoc implementation of IObjectWithSite */
1962 static HRESULT WINAPI
1963 xmldoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
1964 {
1965     domdoc *This = impl_from_IObjectWithSite(iface);
1966     return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppvObject );
1967 }
1968
1969 static ULONG WINAPI
1970 xmldoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
1971 {
1972     domdoc *This = impl_from_IObjectWithSite(iface);
1973     return IXMLDocument_AddRef((IXMLDocument *)This);
1974 }
1975
1976 static ULONG WINAPI
1977 xmldoc_ObjectWithSite_Release( IObjectWithSite* iface )
1978 {
1979     domdoc *This = impl_from_IObjectWithSite(iface);
1980     return IXMLDocument_Release((IXMLDocument *)This);
1981 }
1982
1983 static HRESULT WINAPI
1984 xmldoc_GetSite( IObjectWithSite *iface, REFIID iid, void ** ppvSite )
1985 {
1986     domdoc *This = impl_from_IObjectWithSite(iface);
1987
1988     TRACE("%p %s %p\n", This, debugstr_guid( iid ), ppvSite );
1989
1990     if ( !This->site )
1991         return E_FAIL;
1992
1993     return IUnknown_QueryInterface( This->site, iid, ppvSite );
1994 }
1995
1996 static HRESULT WINAPI
1997 xmldoc_SetSite( IObjectWithSite *iface, IUnknown *punk )
1998 {
1999     domdoc *This = impl_from_IObjectWithSite(iface);
2000
2001     TRACE("%p %p\n", iface, punk);
2002
2003     if(!punk)
2004     {
2005         if(This->site)
2006         {
2007             IUnknown_Release( This->site );
2008             This->site = NULL;
2009         }
2010
2011         return S_OK;
2012     }
2013
2014     if ( punk )
2015         IUnknown_AddRef( punk );
2016
2017     if(This->site)
2018         IUnknown_Release( This->site );
2019
2020     This->site = punk;
2021
2022     return S_OK;
2023 }
2024
2025 static const IObjectWithSiteVtbl domdocObjectSite =
2026 {
2027     xmldoc_ObjectWithSite_QueryInterface,
2028     xmldoc_ObjectWithSite_AddRef,
2029     xmldoc_ObjectWithSite_Release,
2030     xmldoc_SetSite,
2031     xmldoc_GetSite,
2032 };
2033
2034 static HRESULT WINAPI xmldoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
2035 {
2036     domdoc *This = impl_from_IObjectSafety(iface);
2037     return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppv );
2038 }
2039
2040 static ULONG WINAPI xmldoc_Safety_AddRef(IObjectSafety *iface)
2041 {
2042     domdoc *This = impl_from_IObjectSafety(iface);
2043     return IXMLDocument_AddRef((IXMLDocument *)This);
2044 }
2045
2046 static ULONG WINAPI xmldoc_Safety_Release(IObjectSafety *iface)
2047 {
2048     domdoc *This = impl_from_IObjectSafety(iface);
2049     return IXMLDocument_Release((IXMLDocument *)This);
2050 }
2051
2052 #define SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
2053
2054 static HRESULT WINAPI xmldoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2055         DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
2056 {
2057     domdoc *This = impl_from_IObjectSafety(iface);
2058
2059     TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
2060
2061     if(!pdwSupportedOptions || !pdwEnabledOptions)
2062         return E_POINTER;
2063
2064     *pdwSupportedOptions = SUPPORTED_OPTIONS;
2065     *pdwEnabledOptions = This->safeopt;
2066
2067     return S_OK;
2068 }
2069
2070 static HRESULT WINAPI xmldoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2071         DWORD dwOptionSetMask, DWORD dwEnabledOptions)
2072 {
2073     domdoc *This = impl_from_IObjectSafety(iface);
2074
2075     TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
2076
2077     if(dwOptionSetMask & ~SUPPORTED_OPTIONS)
2078         return E_FAIL;
2079
2080     This->safeopt = dwEnabledOptions & dwEnabledOptions;
2081     return S_OK;
2082 }
2083
2084 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
2085     xmldoc_Safety_QueryInterface,
2086     xmldoc_Safety_AddRef,
2087     xmldoc_Safety_Release,
2088     xmldoc_Safety_GetInterfaceSafetyOptions,
2089     xmldoc_Safety_SetInterfaceSafetyOptions
2090 };
2091
2092 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2093 {
2094     domdoc *doc;
2095     HRESULT hr;
2096     xmlDocPtr xmldoc;
2097
2098     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
2099
2100     doc = HeapAlloc( GetProcessHeap(), 0, sizeof (*doc) );
2101     if( !doc )
2102         return E_OUTOFMEMORY;
2103
2104     doc->lpVtbl = &domdoc_vtbl;
2105     doc->lpvtblIPersistStream = &xmldoc_IPersistStream_VTable;
2106     doc->lpvtblIObjectWithSite = &domdocObjectSite;
2107     doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
2108     doc->ref = 1;
2109     doc->async = 0;
2110     doc->validating = 0;
2111     doc->resolving = 0;
2112     doc->preserving = 0;
2113     doc->bUseXPath = FALSE;
2114     doc->error = S_OK;
2115     doc->schema = NULL;
2116     doc->stream = NULL;
2117     doc->site = NULL;
2118     doc->safeopt = 0;
2119
2120     xmldoc = xmlNewDoc(NULL);
2121     if(!xmldoc)
2122     {
2123         HeapFree(GetProcessHeap(), 0, doc);
2124         return E_OUTOFMEMORY;
2125     }
2126
2127     xmldoc->_private = 0;
2128
2129     doc->node_unk = create_basic_node( (xmlNodePtr)xmldoc, (IUnknown*)&doc->lpVtbl );
2130     if(!doc->node_unk)
2131     {
2132         xmlFreeDoc(xmldoc);
2133         HeapFree(GetProcessHeap(), 0, doc);
2134         return E_FAIL;
2135     }
2136
2137     hr = IUnknown_QueryInterface(doc->node_unk, &IID_IXMLDOMNode, (LPVOID*)&doc->node);
2138     if(FAILED(hr))
2139     {
2140         IUnknown_Release(doc->node_unk);
2141         HeapFree( GetProcessHeap(), 0, doc );
2142         return E_FAIL;
2143     }
2144     /* The ref on doc->node is actually looped back into this object, so release it */
2145     IXMLDOMNode_Release(doc->node);
2146
2147     *ppObj = &doc->lpVtbl;
2148
2149     TRACE("returning iface %p\n", *ppObj);
2150     return S_OK;
2151 }
2152
2153 #else
2154
2155 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2156 {
2157     MESSAGE("This program tried to use a DOMDocument object, but\n"
2158             "libxml2 support was not present at compile time.\n");
2159     return E_NOTIMPL;
2160 }
2161
2162 #endif