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