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