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