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