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