mscoree/tests: Remove spaces before '\n's in traces.
[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 = IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), &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_IXMLDOMDocument ) ||
522          IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
523          IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
524     {
525         *ppvObject = iface;
526     }
527     else if ( IsEqualGUID( riid, &IID_IXMLDOMNode ) )
528     {
529         *ppvObject = IXMLDOMNode_from_impl(&This->node);
530     }
531     else if (IsEqualGUID(&IID_IPersistStream, riid) ||
532              IsEqualGUID(&IID_IPersistStreamInit, riid))
533     {
534         *ppvObject = &(This->lpvtblIPersistStreamInit);
535     }
536     else if (IsEqualGUID(&IID_IObjectWithSite, riid))
537     {
538         *ppvObject = &(This->lpvtblIObjectWithSite);
539     }
540     else if (IsEqualGUID(&IID_IObjectSafety, riid))
541     {
542         *ppvObject = &(This->lpvtblIObjectSafety);
543     }
544     else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
545     {
546         *ppvObject = &This->lpvtblISupportErrorInfo;
547     }
548     else if(dispex_query_interface(&This->node.dispex, riid, ppvObject))
549     {
550         return *ppvObject ? S_OK : E_NOINTERFACE;
551     }
552     else if(IsEqualGUID(&IID_IRunnableObject, riid))
553     {
554         TRACE("IID_IRunnableObject not supported returning NULL\n");
555         return E_NOINTERFACE;
556     }
557     else
558     {
559         FIXME("interface %s not implemented\n", debugstr_guid(riid));
560         return E_NOINTERFACE;
561     }
562
563     IUnknown_AddRef((IUnknown*)*ppvObject);
564
565     return S_OK;
566 }
567
568
569 static ULONG WINAPI domdoc_AddRef(
570      IXMLDOMDocument3 *iface )
571 {
572     domdoc *This = impl_from_IXMLDOMDocument3( iface );
573     TRACE("%p\n", This );
574     return InterlockedIncrement( &This->ref );
575 }
576
577
578 static ULONG WINAPI domdoc_Release(
579      IXMLDOMDocument3 *iface )
580 {
581     domdoc *This = impl_from_IXMLDOMDocument3( iface );
582     LONG ref;
583
584     TRACE("%p\n", This );
585
586     ref = InterlockedDecrement( &This->ref );
587     if ( ref == 0 )
588     {
589         if(This->bsc)
590             detach_bsc(This->bsc);
591
592         if (This->site)
593             IUnknown_Release( This->site );
594         destroy_xmlnode(&This->node);
595         if(This->schema) IXMLDOMSchemaCollection_Release( This->schema );
596         if (This->stream) IStream_Release(This->stream);
597         HeapFree( GetProcessHeap(), 0, This );
598     }
599
600     return ref;
601 }
602
603 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
604 {
605     domdoc *This = impl_from_IXMLDOMDocument3( iface );
606
607     TRACE("(%p)->(%p)\n", This, pctinfo);
608
609     *pctinfo = 1;
610
611     return S_OK;
612 }
613
614 static HRESULT WINAPI domdoc_GetTypeInfo(
615     IXMLDOMDocument3 *iface,
616     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
617 {
618     domdoc *This = impl_from_IXMLDOMDocument3( iface );
619     HRESULT hr;
620
621     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
622
623     hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
624
625     return hr;
626 }
627
628 static HRESULT WINAPI domdoc_GetIDsOfNames(
629     IXMLDOMDocument3 *iface,
630     REFIID riid,
631     LPOLESTR* rgszNames,
632     UINT cNames,
633     LCID lcid,
634     DISPID* rgDispId)
635 {
636     domdoc *This = impl_from_IXMLDOMDocument3( iface );
637     ITypeInfo *typeinfo;
638     HRESULT hr;
639
640     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
641           lcid, rgDispId);
642
643     if(!rgszNames || cNames == 0 || !rgDispId)
644         return E_INVALIDARG;
645
646     hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
647     if(SUCCEEDED(hr))
648     {
649         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
650         ITypeInfo_Release(typeinfo);
651     }
652
653     return hr;
654 }
655
656
657 static HRESULT WINAPI domdoc_Invoke(
658     IXMLDOMDocument3 *iface,
659     DISPID dispIdMember,
660     REFIID riid,
661     LCID lcid,
662     WORD wFlags,
663     DISPPARAMS* pDispParams,
664     VARIANT* pVarResult,
665     EXCEPINFO* pExcepInfo,
666     UINT* puArgErr)
667 {
668     domdoc *This = impl_from_IXMLDOMDocument3( iface );
669     ITypeInfo *typeinfo;
670     HRESULT hr;
671
672     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
673           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
674
675     hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
676     if(SUCCEEDED(hr))
677     {
678         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
679                 pVarResult, pExcepInfo, puArgErr);
680         ITypeInfo_Release(typeinfo);
681     }
682
683     return hr;
684 }
685
686
687 static HRESULT WINAPI domdoc_get_nodeName(
688     IXMLDOMDocument3 *iface,
689     BSTR* name )
690 {
691     domdoc *This = impl_from_IXMLDOMDocument3( iface );
692     return IXMLDOMNode_get_nodeName( IXMLDOMNode_from_impl(&This->node), name );
693 }
694
695
696 static HRESULT WINAPI domdoc_get_nodeValue(
697     IXMLDOMDocument3 *iface,
698     VARIANT* value )
699 {
700     domdoc *This = impl_from_IXMLDOMDocument3( iface );
701     return IXMLDOMNode_get_nodeValue( IXMLDOMNode_from_impl(&This->node), value );
702 }
703
704
705 static HRESULT WINAPI domdoc_put_nodeValue(
706     IXMLDOMDocument3 *iface,
707     VARIANT value)
708 {
709     domdoc *This = impl_from_IXMLDOMDocument3( iface );
710     return IXMLDOMNode_put_nodeValue( IXMLDOMNode_from_impl(&This->node), value );
711 }
712
713
714 static HRESULT WINAPI domdoc_get_nodeType(
715     IXMLDOMDocument3 *iface,
716     DOMNodeType* type )
717 {
718     domdoc *This = impl_from_IXMLDOMDocument3( iface );
719     return IXMLDOMNode_get_nodeType( IXMLDOMNode_from_impl(&This->node), type );
720 }
721
722
723 static HRESULT WINAPI domdoc_get_parentNode(
724     IXMLDOMDocument3 *iface,
725     IXMLDOMNode** parent )
726 {
727     domdoc *This = impl_from_IXMLDOMDocument3( iface );
728     return IXMLDOMNode_get_parentNode( IXMLDOMNode_from_impl(&This->node), parent );
729 }
730
731
732 static HRESULT WINAPI domdoc_get_childNodes(
733     IXMLDOMDocument3 *iface,
734     IXMLDOMNodeList** childList )
735 {
736     domdoc *This = impl_from_IXMLDOMDocument3( iface );
737     return IXMLDOMNode_get_childNodes( IXMLDOMNode_from_impl(&This->node), childList );
738 }
739
740
741 static HRESULT WINAPI domdoc_get_firstChild(
742     IXMLDOMDocument3 *iface,
743     IXMLDOMNode** firstChild )
744 {
745     domdoc *This = impl_from_IXMLDOMDocument3( iface );
746     return IXMLDOMNode_get_firstChild( IXMLDOMNode_from_impl(&This->node), firstChild );
747 }
748
749
750 static HRESULT WINAPI domdoc_get_lastChild(
751     IXMLDOMDocument3 *iface,
752     IXMLDOMNode** lastChild )
753 {
754     domdoc *This = impl_from_IXMLDOMDocument3( iface );
755     return IXMLDOMNode_get_lastChild( IXMLDOMNode_from_impl(&This->node), lastChild );
756 }
757
758
759 static HRESULT WINAPI domdoc_get_previousSibling(
760     IXMLDOMDocument3 *iface,
761     IXMLDOMNode** previousSibling )
762 {
763     domdoc *This = impl_from_IXMLDOMDocument3( iface );
764     return IXMLDOMNode_get_previousSibling( IXMLDOMNode_from_impl(&This->node), previousSibling );
765 }
766
767
768 static HRESULT WINAPI domdoc_get_nextSibling(
769     IXMLDOMDocument3 *iface,
770     IXMLDOMNode** nextSibling )
771 {
772     domdoc *This = impl_from_IXMLDOMDocument3( iface );
773     return IXMLDOMNode_get_nextSibling( IXMLDOMNode_from_impl(&This->node), nextSibling );
774 }
775
776
777 static HRESULT WINAPI domdoc_get_attributes(
778     IXMLDOMDocument3 *iface,
779     IXMLDOMNamedNodeMap** attributeMap )
780 {
781     domdoc *This = impl_from_IXMLDOMDocument3( iface );
782     return IXMLDOMNode_get_attributes( IXMLDOMNode_from_impl(&This->node), attributeMap );
783 }
784
785
786 static HRESULT WINAPI domdoc_insertBefore(
787     IXMLDOMDocument3 *iface,
788     IXMLDOMNode* newChild,
789     VARIANT refChild,
790     IXMLDOMNode** outNewChild )
791 {
792     domdoc *This = impl_from_IXMLDOMDocument3( iface );
793     return IXMLDOMNode_insertBefore( IXMLDOMNode_from_impl(&This->node), newChild, refChild, outNewChild );
794 }
795
796
797 static HRESULT WINAPI domdoc_replaceChild(
798     IXMLDOMDocument3 *iface,
799     IXMLDOMNode* newChild,
800     IXMLDOMNode* oldChild,
801     IXMLDOMNode** outOldChild)
802 {
803     domdoc *This = impl_from_IXMLDOMDocument3( iface );
804     return IXMLDOMNode_replaceChild( IXMLDOMNode_from_impl(&This->node), newChild, oldChild, outOldChild );
805 }
806
807
808 static HRESULT WINAPI domdoc_removeChild(
809     IXMLDOMDocument3 *iface,
810     IXMLDOMNode* childNode,
811     IXMLDOMNode** oldChild)
812 {
813     domdoc *This = impl_from_IXMLDOMDocument3( iface );
814     return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), childNode, oldChild );
815 }
816
817
818 static HRESULT WINAPI domdoc_appendChild(
819     IXMLDOMDocument3 *iface,
820     IXMLDOMNode* newChild,
821     IXMLDOMNode** outNewChild)
822 {
823     domdoc *This = impl_from_IXMLDOMDocument3( iface );
824     return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newChild, outNewChild );
825 }
826
827
828 static HRESULT WINAPI domdoc_hasChildNodes(
829     IXMLDOMDocument3 *iface,
830     VARIANT_BOOL* hasChild)
831 {
832     domdoc *This = impl_from_IXMLDOMDocument3( iface );
833     return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), hasChild );
834 }
835
836
837 static HRESULT WINAPI domdoc_get_ownerDocument(
838     IXMLDOMDocument3 *iface,
839     IXMLDOMDocument** DOMDocument)
840 {
841     domdoc *This = impl_from_IXMLDOMDocument3( iface );
842     return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), DOMDocument );
843 }
844
845
846 static HRESULT WINAPI domdoc_cloneNode(
847     IXMLDOMDocument3 *iface,
848     VARIANT_BOOL deep,
849     IXMLDOMNode** cloneRoot)
850 {
851     domdoc *This = impl_from_IXMLDOMDocument3( iface );
852     return IXMLDOMNode_cloneNode( IXMLDOMNode_from_impl(&This->node), deep, cloneRoot );
853 }
854
855
856 static HRESULT WINAPI domdoc_get_nodeTypeString(
857     IXMLDOMDocument3 *iface,
858     BSTR* nodeType )
859 {
860     domdoc *This = impl_from_IXMLDOMDocument3( iface );
861     return IXMLDOMNode_get_nodeTypeString( IXMLDOMNode_from_impl(&This->node), nodeType );
862 }
863
864
865 static HRESULT WINAPI domdoc_get_text(
866     IXMLDOMDocument3 *iface,
867     BSTR* text )
868 {
869     domdoc *This = impl_from_IXMLDOMDocument3( iface );
870     return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), text );
871 }
872
873
874 static HRESULT WINAPI domdoc_put_text(
875     IXMLDOMDocument3 *iface,
876     BSTR text )
877 {
878     domdoc *This = impl_from_IXMLDOMDocument3( iface );
879     return IXMLDOMNode_put_text( IXMLDOMNode_from_impl(&This->node), text );
880 }
881
882
883 static HRESULT WINAPI domdoc_get_specified(
884     IXMLDOMDocument3 *iface,
885     VARIANT_BOOL* isSpecified )
886 {
887     domdoc *This = impl_from_IXMLDOMDocument3( iface );
888     return IXMLDOMNode_get_specified( IXMLDOMNode_from_impl(&This->node), isSpecified );
889 }
890
891
892 static HRESULT WINAPI domdoc_get_definition(
893     IXMLDOMDocument3 *iface,
894     IXMLDOMNode** definitionNode )
895 {
896     domdoc *This = impl_from_IXMLDOMDocument3( iface );
897     return IXMLDOMNode_get_definition( IXMLDOMNode_from_impl(&This->node), definitionNode );
898 }
899
900
901 static HRESULT WINAPI domdoc_get_nodeTypedValue(
902     IXMLDOMDocument3 *iface,
903     VARIANT* typedValue )
904 {
905     domdoc *This = impl_from_IXMLDOMDocument3( iface );
906     return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
907 }
908
909 static HRESULT WINAPI domdoc_put_nodeTypedValue(
910     IXMLDOMDocument3 *iface,
911     VARIANT typedValue )
912 {
913     domdoc *This = impl_from_IXMLDOMDocument3( iface );
914     return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
915 }
916
917
918 static HRESULT WINAPI domdoc_get_dataType(
919     IXMLDOMDocument3 *iface,
920     VARIANT* dataTypeName )
921 {
922     domdoc *This = impl_from_IXMLDOMDocument3( iface );
923     return IXMLDOMNode_get_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
924 }
925
926
927 static HRESULT WINAPI domdoc_put_dataType(
928     IXMLDOMDocument3 *iface,
929     BSTR dataTypeName )
930 {
931     domdoc *This = impl_from_IXMLDOMDocument3( iface );
932     return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
933 }
934
935
936 static HRESULT WINAPI domdoc_get_xml(
937     IXMLDOMDocument3 *iface,
938     BSTR* xmlString )
939 {
940     domdoc *This = impl_from_IXMLDOMDocument3( iface );
941     return IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), xmlString );
942 }
943
944
945 static HRESULT WINAPI domdoc_transformNode(
946     IXMLDOMDocument3 *iface,
947     IXMLDOMNode* styleSheet,
948     BSTR* xmlString )
949 {
950     domdoc *This = impl_from_IXMLDOMDocument3( iface );
951     return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), styleSheet, xmlString );
952 }
953
954
955 static HRESULT WINAPI domdoc_selectNodes(
956     IXMLDOMDocument3 *iface,
957     BSTR queryString,
958     IXMLDOMNodeList** resultList )
959 {
960     domdoc *This = impl_from_IXMLDOMDocument3( iface );
961     return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), queryString, resultList );
962 }
963
964
965 static HRESULT WINAPI domdoc_selectSingleNode(
966     IXMLDOMDocument3 *iface,
967     BSTR queryString,
968     IXMLDOMNode** resultNode )
969 {
970     domdoc *This = impl_from_IXMLDOMDocument3( iface );
971     return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), queryString, resultNode );
972 }
973
974
975 static HRESULT WINAPI domdoc_get_parsed(
976     IXMLDOMDocument3 *iface,
977     VARIANT_BOOL* isParsed )
978 {
979     domdoc *This = impl_from_IXMLDOMDocument3( iface );
980     return IXMLDOMNode_get_parsed( IXMLDOMNode_from_impl(&This->node), isParsed );
981 }
982
983
984 static HRESULT WINAPI domdoc_get_namespaceURI(
985     IXMLDOMDocument3 *iface,
986     BSTR* namespaceURI )
987 {
988     domdoc *This = impl_from_IXMLDOMDocument3( iface );
989     return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), namespaceURI );
990 }
991
992
993 static HRESULT WINAPI domdoc_get_prefix(
994     IXMLDOMDocument3 *iface,
995     BSTR* prefixString )
996 {
997     domdoc *This = impl_from_IXMLDOMDocument3( iface );
998     return IXMLDOMNode_get_prefix( IXMLDOMNode_from_impl(&This->node), prefixString );
999 }
1000
1001
1002 static HRESULT WINAPI domdoc_get_baseName(
1003     IXMLDOMDocument3 *iface,
1004     BSTR* nameString )
1005 {
1006     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1007     return IXMLDOMNode_get_baseName( IXMLDOMNode_from_impl(&This->node), nameString );
1008 }
1009
1010
1011 static HRESULT WINAPI domdoc_transformNodeToObject(
1012     IXMLDOMDocument3 *iface,
1013     IXMLDOMNode* stylesheet,
1014     VARIANT outputObject)
1015 {
1016     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1017     return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), stylesheet, outputObject );
1018 }
1019
1020
1021 static HRESULT WINAPI domdoc_get_doctype(
1022     IXMLDOMDocument3 *iface,
1023     IXMLDOMDocumentType** documentType )
1024 {
1025     domdoc *This = impl_from_IXMLDOMDocument3(iface);
1026     FIXME("(%p)\n", This);
1027     return E_NOTIMPL;
1028 }
1029
1030
1031 static HRESULT WINAPI domdoc_get_implementation(
1032     IXMLDOMDocument3 *iface,
1033     IXMLDOMImplementation** impl )
1034 {
1035     domdoc *This = impl_from_IXMLDOMDocument3(iface);
1036
1037     TRACE("(%p)->(%p)\n", This, impl);
1038
1039     if(!impl)
1040         return E_INVALIDARG;
1041
1042     *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1043
1044     return S_OK;
1045 }
1046
1047 static HRESULT WINAPI domdoc_get_documentElement(
1048     IXMLDOMDocument3 *iface,
1049     IXMLDOMElement** DOMElement )
1050 {
1051     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1052     xmlDocPtr xmldoc = NULL;
1053     xmlNodePtr root = NULL;
1054     IXMLDOMNode *element_node;
1055     HRESULT hr;
1056
1057     TRACE("(%p)->(%p)\n", This, DOMElement);
1058
1059     if(!DOMElement)
1060         return E_INVALIDARG;
1061
1062     *DOMElement = NULL;
1063
1064     xmldoc = get_doc( This );
1065
1066     root = xmlDocGetRootElement( xmldoc );
1067     if ( !root )
1068         return S_FALSE;
1069
1070     element_node = create_node( root );
1071     if(!element_node) return S_FALSE;
1072
1073     hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (LPVOID*)DOMElement);
1074     IXMLDOMNode_Release(element_node);
1075
1076     return hr;
1077 }
1078
1079
1080 static HRESULT WINAPI domdoc_put_documentElement(
1081     IXMLDOMDocument3 *iface,
1082     IXMLDOMElement* DOMElement )
1083 {
1084     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1085     IXMLDOMNode *elementNode;
1086     xmlNodePtr oldRoot;
1087     xmlnode *xmlNode;
1088     HRESULT hr;
1089
1090     TRACE("(%p)->(%p)\n", This, DOMElement);
1091
1092     hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1093     if(FAILED(hr))
1094         return hr;
1095
1096     xmlNode = impl_from_IXMLDOMNode( elementNode );
1097
1098     if(!xmlNode->node->parent)
1099         if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1100             WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1101
1102     oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1103     IXMLDOMNode_Release( elementNode );
1104
1105     if(oldRoot)
1106         xmldoc_add_orphan(oldRoot->doc, oldRoot);
1107
1108     return S_OK;
1109 }
1110
1111
1112 static HRESULT WINAPI domdoc_createElement(
1113     IXMLDOMDocument3 *iface,
1114     BSTR tagname,
1115     IXMLDOMElement** element )
1116 {
1117     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1118     IXMLDOMNode *node;
1119     VARIANT type;
1120     HRESULT hr;
1121
1122     TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1123
1124     if (!element || !tagname) return E_INVALIDARG;
1125
1126     V_VT(&type) = VT_I1;
1127     V_I1(&type) = NODE_ELEMENT;
1128
1129     hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1130     if (hr == S_OK)
1131     {
1132         IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1133         IXMLDOMNode_Release(node);
1134     }
1135
1136     return hr;
1137 }
1138
1139
1140 static HRESULT WINAPI domdoc_createDocumentFragment(
1141     IXMLDOMDocument3 *iface,
1142     IXMLDOMDocumentFragment** frag )
1143 {
1144     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1145     IXMLDOMNode *node;
1146     VARIANT type;
1147     HRESULT hr;
1148
1149     TRACE("(%p)->(%p)\n", This, frag);
1150
1151     if (!frag) return E_INVALIDARG;
1152
1153     *frag = NULL;
1154
1155     V_VT(&type) = VT_I1;
1156     V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1157
1158     hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1159     if (hr == S_OK)
1160     {
1161         IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1162         IXMLDOMNode_Release(node);
1163     }
1164
1165     return hr;
1166 }
1167
1168
1169 static HRESULT WINAPI domdoc_createTextNode(
1170     IXMLDOMDocument3 *iface,
1171     BSTR data,
1172     IXMLDOMText** text )
1173 {
1174     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1175     IXMLDOMNode *node;
1176     VARIANT type;
1177     HRESULT hr;
1178
1179     TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1180
1181     if (!text) return E_INVALIDARG;
1182
1183     *text = NULL;
1184
1185     V_VT(&type) = VT_I1;
1186     V_I1(&type) = NODE_TEXT;
1187
1188     hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1189     if (hr == S_OK)
1190     {
1191         IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1192         IXMLDOMNode_Release(node);
1193         hr = IXMLDOMText_put_data(*text, data);
1194     }
1195
1196     return hr;
1197 }
1198
1199
1200 static HRESULT WINAPI domdoc_createComment(
1201     IXMLDOMDocument3 *iface,
1202     BSTR data,
1203     IXMLDOMComment** comment )
1204 {
1205     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1206     VARIANT type;
1207     HRESULT hr;
1208     IXMLDOMNode *node;
1209
1210     TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1211
1212     if (!comment) return E_INVALIDARG;
1213
1214     *comment = NULL;
1215
1216     V_VT(&type) = VT_I1;
1217     V_I1(&type) = NODE_COMMENT;
1218
1219     hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1220     if (hr == S_OK)
1221     {
1222         IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1223         IXMLDOMNode_Release(node);
1224         hr = IXMLDOMComment_put_data(*comment, data);
1225     }
1226
1227     return hr;
1228 }
1229
1230
1231 static HRESULT WINAPI domdoc_createCDATASection(
1232     IXMLDOMDocument3 *iface,
1233     BSTR data,
1234     IXMLDOMCDATASection** cdata )
1235 {
1236     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1237     IXMLDOMNode *node;
1238     VARIANT type;
1239     HRESULT hr;
1240
1241     TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1242
1243     if (!cdata) return E_INVALIDARG;
1244
1245     *cdata = NULL;
1246
1247     V_VT(&type) = VT_I1;
1248     V_I1(&type) = NODE_CDATA_SECTION;
1249
1250     hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1251     if (hr == S_OK)
1252     {
1253         IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1254         IXMLDOMNode_Release(node);
1255         hr = IXMLDOMCDATASection_put_data(*cdata, data);
1256     }
1257
1258     return hr;
1259 }
1260
1261
1262 static HRESULT WINAPI domdoc_createProcessingInstruction(
1263     IXMLDOMDocument3 *iface,
1264     BSTR target,
1265     BSTR data,
1266     IXMLDOMProcessingInstruction** pi )
1267 {
1268     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1269     IXMLDOMNode *node;
1270     VARIANT type;
1271     HRESULT hr;
1272
1273     TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1274
1275     if (!pi) return E_INVALIDARG;
1276
1277     *pi = NULL;
1278
1279     V_VT(&type) = VT_I1;
1280     V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1281
1282     hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1283     if (hr == S_OK)
1284     {
1285         VARIANT v_data;
1286
1287         /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1288         V_VT(&v_data)   = VT_BSTR;
1289         V_BSTR(&v_data) = data;
1290
1291         hr = IXMLDOMNode_put_nodeValue( node, v_data );
1292
1293         IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1294         IXMLDOMNode_Release(node);
1295     }
1296
1297     return hr;
1298 }
1299
1300
1301 static HRESULT WINAPI domdoc_createAttribute(
1302     IXMLDOMDocument3 *iface,
1303     BSTR name,
1304     IXMLDOMAttribute** attribute )
1305 {
1306     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1307     IXMLDOMNode *node;
1308     VARIANT type;
1309     HRESULT hr;
1310
1311     TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1312
1313     if (!attribute || !name) return E_INVALIDARG;
1314
1315     V_VT(&type) = VT_I1;
1316     V_I1(&type) = NODE_ATTRIBUTE;
1317
1318     hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1319     if (hr == S_OK)
1320     {
1321         IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1322         IXMLDOMNode_Release(node);
1323     }
1324
1325     return hr;
1326 }
1327
1328
1329 static HRESULT WINAPI domdoc_createEntityReference(
1330     IXMLDOMDocument3 *iface,
1331     BSTR name,
1332     IXMLDOMEntityReference** entityref )
1333 {
1334     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1335     IXMLDOMNode *node;
1336     VARIANT type;
1337     HRESULT hr;
1338
1339     TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1340
1341     if (!entityref) return E_INVALIDARG;
1342
1343     *entityref = NULL;
1344
1345     V_VT(&type) = VT_I1;
1346     V_I1(&type) = NODE_ENTITY_REFERENCE;
1347
1348     hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1349     if (hr == S_OK)
1350     {
1351         IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1352         IXMLDOMNode_Release(node);
1353     }
1354
1355     return hr;
1356 }
1357
1358
1359 static HRESULT WINAPI domdoc_getElementsByTagName(
1360     IXMLDOMDocument3 *iface,
1361     BSTR tagName,
1362     IXMLDOMNodeList** resultList )
1363 {
1364     static const WCHAR xpathformat[] =
1365             { '/','/','*','[','l','o','c','a','l','-','n','a','m','e','(',')','=','\'','%','s','\'',']',0 };
1366     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1367     LPWSTR szPattern;
1368     HRESULT hr;
1369     TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagName), resultList);
1370
1371     if (tagName[0] == '*' && tagName[1] == 0)
1372     {
1373         szPattern = heap_alloc(sizeof(WCHAR)*4);
1374         szPattern[0] = szPattern[1] = '/';
1375         szPattern[2] = '*';
1376         szPattern[3] = 0;
1377     }
1378     else
1379     {
1380         szPattern = heap_alloc(sizeof(WCHAR)*(20+lstrlenW(tagName)+1));
1381         wsprintfW(szPattern, xpathformat, tagName);
1382     }
1383
1384     hr = queryresult_create((xmlNodePtr)get_doc(This), szPattern, resultList);
1385     heap_free(szPattern);
1386
1387     return hr;
1388 }
1389
1390 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1391 {
1392     VARIANT tmp;
1393     HRESULT hr;
1394
1395     VariantInit(&tmp);
1396     hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1397     if(FAILED(hr))
1398         return E_INVALIDARG;
1399
1400     *type = V_I4(&tmp);
1401
1402     return S_OK;
1403 }
1404
1405 static HRESULT WINAPI domdoc_createNode(
1406     IXMLDOMDocument3 *iface,
1407     VARIANT Type,
1408     BSTR name,
1409     BSTR namespaceURI,
1410     IXMLDOMNode** node )
1411 {
1412     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1413     DOMNodeType node_type;
1414     xmlNodePtr xmlnode;
1415     xmlChar *xml_name;
1416     HRESULT hr;
1417
1418     TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1419
1420     if(!node) return E_INVALIDARG;
1421
1422     if(namespaceURI && namespaceURI[0])
1423         FIXME("nodes with namespaces currently not supported.\n");
1424
1425     hr = get_node_type(Type, &node_type);
1426     if(FAILED(hr)) return hr;
1427
1428     TRACE("node_type %d\n", node_type);
1429
1430     /* exit earlier for types that need name */
1431     switch(node_type)
1432     {
1433     case NODE_ELEMENT:
1434     case NODE_ATTRIBUTE:
1435     case NODE_ENTITY_REFERENCE:
1436     case NODE_PROCESSING_INSTRUCTION:
1437         if (!name || *name == 0) return E_FAIL;
1438     default:
1439         break;
1440     }
1441
1442     xml_name = xmlChar_from_wchar(name);
1443
1444     switch(node_type)
1445     {
1446     case NODE_ELEMENT:
1447         xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
1448         break;
1449     case NODE_ATTRIBUTE:
1450         xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1451         break;
1452     case NODE_TEXT:
1453         xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1454         break;
1455     case NODE_CDATA_SECTION:
1456         xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1457         break;
1458     case NODE_ENTITY_REFERENCE:
1459         xmlnode = xmlNewReference(get_doc(This), xml_name);
1460         break;
1461     case NODE_PROCESSING_INSTRUCTION:
1462 #ifdef HAVE_XMLNEWDOCPI
1463         xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1464 #else
1465         FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1466         xmlnode = NULL;
1467 #endif
1468         break;
1469     case NODE_COMMENT:
1470         xmlnode = xmlNewDocComment(get_doc(This), NULL);
1471         break;
1472     case NODE_DOCUMENT_FRAGMENT:
1473         xmlnode = xmlNewDocFragment(get_doc(This));
1474         break;
1475     /* unsupported types */
1476     case NODE_DOCUMENT:
1477     case NODE_DOCUMENT_TYPE:
1478     case NODE_ENTITY:
1479     case NODE_NOTATION:
1480         heap_free(xml_name);
1481         return E_INVALIDARG;
1482     default:
1483         FIXME("unhandled node type %d\n", node_type);
1484         xmlnode = NULL;
1485         break;
1486     }
1487
1488     *node = create_node(xmlnode);
1489     heap_free(xml_name);
1490
1491     if(*node)
1492     {
1493         TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1494         xmldoc_add_orphan(xmlnode->doc, xmlnode);
1495         return S_OK;
1496     }
1497
1498     return E_FAIL;
1499 }
1500
1501 static HRESULT WINAPI domdoc_nodeFromID(
1502     IXMLDOMDocument3 *iface,
1503     BSTR idString,
1504     IXMLDOMNode** node )
1505 {
1506     domdoc *This = impl_from_IXMLDOMDocument3(iface);
1507     FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1508     return E_NOTIMPL;
1509 }
1510
1511 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1512 {
1513     domdoc *This = obj;
1514     xmlDocPtr xmldoc;
1515
1516     xmldoc = doparse( ptr, len, NULL );
1517     if(xmldoc) {
1518         xmldoc->_private = create_priv();
1519         return attach_xmldoc(&This->node, xmldoc);
1520     }
1521
1522     return S_OK;
1523 }
1524
1525 static HRESULT doread( domdoc *This, LPWSTR filename )
1526 {
1527     bsc_t *bsc;
1528     HRESULT hr;
1529
1530     hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1531     if(FAILED(hr))
1532         return hr;
1533
1534     if(This->bsc)
1535         detach_bsc(This->bsc);
1536
1537     This->bsc = bsc;
1538     return S_OK;
1539 }
1540
1541 static HRESULT WINAPI domdoc_load(
1542     IXMLDOMDocument3 *iface,
1543     VARIANT xmlSource,
1544     VARIANT_BOOL* isSuccessful )
1545 {
1546     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1547     LPWSTR filename = NULL;
1548     HRESULT hr = S_FALSE;
1549     IXMLDOMDocument3 *pNewDoc = NULL;
1550     IStream *pStream = NULL;
1551     xmlDocPtr xmldoc;
1552
1553     TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
1554
1555     *isSuccessful = VARIANT_FALSE;
1556
1557     assert( &This->node );
1558
1559     switch( V_VT(&xmlSource) )
1560     {
1561     case VT_BSTR:
1562         filename = V_BSTR(&xmlSource);
1563         break;
1564     case VT_UNKNOWN:
1565         hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
1566         if(hr == S_OK)
1567         {
1568             if(pNewDoc)
1569             {
1570                 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
1571                 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1572                 hr = attach_xmldoc(&This->node, xmldoc);
1573
1574                 if(SUCCEEDED(hr))
1575                     *isSuccessful = VARIANT_TRUE;
1576
1577                 return hr;
1578             }
1579         }
1580         hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1581         if(hr == S_OK)
1582         {
1583             IPersistStream *pDocStream;
1584             hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1585             if(hr == S_OK)
1586             {
1587                 hr = IPersistStream_Load(pDocStream, pStream);
1588                 IStream_Release(pStream);
1589                 if(hr == S_OK)
1590                 {
1591                     *isSuccessful = VARIANT_TRUE;
1592
1593                     TRACE("Using IStream to load Document\n");
1594                     return S_OK;
1595                 }
1596                 else
1597                 {
1598                     ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1599                 }
1600             }
1601             else
1602             {
1603                 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1604             }
1605         }
1606         else
1607         {
1608             /* ISequentialStream */
1609             FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1610         }
1611         break;
1612      default:
1613             FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1614      }
1615
1616     TRACE("filename (%s)\n", debugstr_w(filename));
1617
1618     if ( filename )
1619     {
1620         hr = doread( This, filename );
1621     
1622         if ( FAILED(hr) )
1623             This->error = E_FAIL;
1624         else
1625         {
1626             hr = This->error = S_OK;
1627             *isSuccessful = VARIANT_TRUE;
1628         }
1629     }
1630
1631     if(!filename || FAILED(hr)) {
1632         xmldoc = xmlNewDoc(NULL);
1633         xmldoc->_private = create_priv();
1634         hr = attach_xmldoc(&This->node, xmldoc);
1635         if(SUCCEEDED(hr))
1636             hr = S_FALSE;
1637     }
1638
1639     TRACE("ret (%d)\n", hr);
1640
1641     return hr;
1642 }
1643
1644
1645 static HRESULT WINAPI domdoc_get_readyState(
1646     IXMLDOMDocument3 *iface,
1647     LONG *value )
1648 {
1649     domdoc *This = impl_from_IXMLDOMDocument3(iface);
1650     FIXME("(%p)->(%p)\n", This, value);
1651     return E_NOTIMPL;
1652 }
1653
1654
1655 static HRESULT WINAPI domdoc_get_parseError(
1656     IXMLDOMDocument3 *iface,
1657     IXMLDOMParseError** errorObj )
1658 {
1659     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1660     static const WCHAR err[] = {'e','r','r','o','r',0};
1661     BSTR error_string = NULL;
1662
1663     FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
1664
1665     if(This->error)
1666         error_string = SysAllocString(err);
1667
1668     *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
1669     if(!*errorObj) return E_OUTOFMEMORY;
1670     return S_OK;
1671 }
1672
1673
1674 static HRESULT WINAPI domdoc_get_url(
1675     IXMLDOMDocument3 *iface,
1676     BSTR* urlString )
1677 {
1678     domdoc *This = impl_from_IXMLDOMDocument3(iface);
1679     FIXME("(%p)->(%p)\n", This, urlString);
1680     return E_NOTIMPL;
1681 }
1682
1683
1684 static HRESULT WINAPI domdoc_get_async(
1685     IXMLDOMDocument3 *iface,
1686     VARIANT_BOOL* isAsync )
1687 {
1688     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1689
1690     TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
1691     *isAsync = This->async;
1692     return S_OK;
1693 }
1694
1695
1696 static HRESULT WINAPI domdoc_put_async(
1697     IXMLDOMDocument3 *iface,
1698     VARIANT_BOOL isAsync )
1699 {
1700     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1701
1702     TRACE("(%p)->(%d)\n", This, isAsync);
1703     This->async = isAsync;
1704     return S_OK;
1705 }
1706
1707
1708 static HRESULT WINAPI domdoc_abort(
1709     IXMLDOMDocument3 *iface )
1710 {
1711     domdoc *This = impl_from_IXMLDOMDocument3(iface);
1712     FIXME("%p\n", This);
1713     return E_NOTIMPL;
1714 }
1715
1716
1717 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
1718 {
1719     UINT len;
1720     LPSTR str;
1721
1722     len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
1723     str = heap_alloc( len );
1724     if ( !str )
1725         return FALSE;
1726     WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
1727     *plen = len;
1728     *pstr = str;
1729     return TRUE;
1730 }
1731
1732 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
1733 static HRESULT WINAPI domdoc_loadXML(
1734     IXMLDOMDocument3 *iface,
1735     BSTR bstrXML,
1736     VARIANT_BOOL* isSuccessful )
1737 {
1738     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1739     xmlDocPtr xmldoc = NULL;
1740     HRESULT hr = S_FALSE, hr2;
1741     char *str;
1742     int len;
1743
1744     TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
1745
1746     assert ( &This->node );
1747
1748     if ( isSuccessful )
1749     {
1750         *isSuccessful = VARIANT_FALSE;
1751
1752         if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
1753         {
1754             xmldoc = doparse( str, len, "UTF-8" );
1755             heap_free( str );
1756             if ( !xmldoc )
1757                 This->error = E_FAIL;
1758             else
1759             {
1760                 hr = This->error = S_OK;
1761                 *isSuccessful = VARIANT_TRUE;
1762                 TRACE("parsed document %p\n", xmldoc);
1763             }
1764         }
1765     }
1766     if(!xmldoc)
1767         xmldoc = xmlNewDoc(NULL);
1768
1769     xmldoc->_private = create_priv();
1770     hr2 = attach_xmldoc( &This->node, xmldoc );
1771     if( FAILED(hr2) )
1772         hr = hr2;
1773
1774     return hr;
1775 }
1776
1777 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer,
1778                                              int len)
1779 {
1780     DWORD written = -1;
1781
1782     if(!WriteFile(ctx, buffer, len, &written, NULL))
1783     {
1784         WARN("write error\n");
1785         return -1;
1786     }
1787     else
1788         return written;
1789 }
1790
1791 static int XMLCALL domdoc_save_closecallback(void *ctx)
1792 {
1793     return CloseHandle(ctx) ? 0 : -1;
1794 }
1795
1796 static HRESULT WINAPI domdoc_save(
1797     IXMLDOMDocument3 *iface,
1798     VARIANT destination )
1799 {
1800     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1801     HANDLE handle;
1802     xmlSaveCtxtPtr ctx;
1803     xmlNodePtr xmldecl;
1804     HRESULT ret = S_OK;
1805
1806     TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
1807           V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
1808
1809     if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
1810     {
1811         FIXME("Unhandled vt %d\n", V_VT(&destination));
1812         return S_FALSE;
1813     }
1814
1815     if(V_VT(&destination) == VT_UNKNOWN)
1816     {
1817         IUnknown *pUnk = V_UNKNOWN(&destination);
1818         IXMLDOMDocument2 *pDocument;
1819
1820         ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&pDocument);
1821         if(ret == S_OK)
1822         {
1823             VARIANT_BOOL success;
1824             BSTR xml;
1825
1826             ret = IXMLDOMDocument3_get_xml(iface, &xml);
1827             if(ret == S_OK)
1828             {
1829                 ret = IXMLDOMDocument3_loadXML(pDocument, xml, &success);
1830                 SysFreeString(xml);
1831             }
1832
1833             IXMLDOMDocument3_Release(pDocument);
1834         }
1835
1836         TRACE("ret %d\n", ret);
1837
1838         return ret;
1839     }
1840
1841     handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
1842                           NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1843     if( handle == INVALID_HANDLE_VALUE )
1844     {
1845         WARN("failed to create file\n");
1846         return S_FALSE;
1847     }
1848
1849     /* disable top XML declaration */
1850     ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
1851                       handle, NULL, XML_SAVE_NO_DECL);
1852     if (!ctx)
1853     {
1854         CloseHandle(handle);
1855         return S_FALSE;
1856     }
1857
1858     xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
1859     if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
1860     xmldoc_link_xmldecl(get_doc(This), xmldecl);
1861
1862     /* will close file through close callback */
1863     xmlSaveClose(ctx);
1864
1865     return ret;
1866 }
1867
1868 static HRESULT WINAPI domdoc_get_validateOnParse(
1869     IXMLDOMDocument3 *iface,
1870     VARIANT_BOOL* isValidating )
1871 {
1872     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1873     TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
1874     *isValidating = This->validating;
1875     return S_OK;
1876 }
1877
1878
1879 static HRESULT WINAPI domdoc_put_validateOnParse(
1880     IXMLDOMDocument3 *iface,
1881     VARIANT_BOOL isValidating )
1882 {
1883     domdoc *This = impl_from_IXMLDOMDocument3( iface );
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     IXMLDOMDocument3 *iface,
1892     VARIANT_BOOL* isResolving )
1893 {
1894     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1895     TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
1896     *isResolving = This->resolving;
1897     return S_OK;
1898 }
1899
1900
1901 static HRESULT WINAPI domdoc_put_resolveExternals(
1902     IXMLDOMDocument3 *iface,
1903     VARIANT_BOOL isResolving )
1904 {
1905     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1906     TRACE("(%p)->(%d)\n", This, isResolving);
1907     This->resolving = isResolving;
1908     return S_OK;
1909 }
1910
1911
1912 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
1913     IXMLDOMDocument3 *iface,
1914     VARIANT_BOOL* isPreserving )
1915 {
1916     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1917     TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->preserving);
1918     *isPreserving = This->preserving;
1919     return S_OK;
1920 }
1921
1922
1923 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
1924     IXMLDOMDocument3 *iface,
1925     VARIANT_BOOL isPreserving )
1926 {
1927     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1928     TRACE("(%p)->(%d)\n", This, isPreserving);
1929     This->preserving = isPreserving;
1930     return S_OK;
1931 }
1932
1933
1934 static HRESULT WINAPI domdoc_put_onReadyStateChange(
1935     IXMLDOMDocument3 *iface,
1936     VARIANT readyStateChangeSink )
1937 {
1938     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1939     FIXME("%p\n", This);
1940     return E_NOTIMPL;
1941 }
1942
1943
1944 static HRESULT WINAPI domdoc_put_onDataAvailable(
1945     IXMLDOMDocument3 *iface,
1946     VARIANT onDataAvailableSink )
1947 {
1948     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1949     FIXME("%p\n", This);
1950     return E_NOTIMPL;
1951 }
1952
1953 static HRESULT WINAPI domdoc_put_onTransformNode(
1954     IXMLDOMDocument3 *iface,
1955     VARIANT onTransformNodeSink )
1956 {
1957     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1958     FIXME("%p\n", This);
1959     return E_NOTIMPL;
1960 }
1961
1962 static HRESULT WINAPI domdoc_get_namespaces(
1963     IXMLDOMDocument3* iface,
1964     IXMLDOMSchemaCollection** schemaCollection )
1965 {
1966     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1967     FIXME("(%p)->(%p)\n", This, schemaCollection);
1968     return E_NOTIMPL;
1969 }
1970
1971 static HRESULT WINAPI domdoc_get_schemas(
1972     IXMLDOMDocument3* iface,
1973     VARIANT* var1 )
1974 {
1975     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1976     HRESULT hr = S_FALSE;
1977     IXMLDOMSchemaCollection *cur_schema = This->schema;
1978
1979     TRACE("(%p)->(%p)\n", This, var1);
1980
1981     VariantInit(var1); /* Test shows we don't call VariantClear here */
1982     V_VT(var1) = VT_NULL;
1983
1984     if(cur_schema)
1985     {
1986         hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
1987         if(SUCCEEDED(hr))
1988             V_VT(var1) = VT_DISPATCH;
1989     }
1990     return hr;
1991 }
1992
1993 static HRESULT WINAPI domdoc_putref_schemas(
1994     IXMLDOMDocument3* iface,
1995     VARIANT var1)
1996 {
1997     domdoc *This = impl_from_IXMLDOMDocument3( iface );
1998     HRESULT hr = E_FAIL;
1999     IXMLDOMSchemaCollection *new_schema = NULL;
2000
2001     FIXME("(%p): semi-stub\n", This);
2002     switch(V_VT(&var1))
2003     {
2004     case VT_UNKNOWN:
2005         hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2006         break;
2007
2008     case VT_DISPATCH:
2009         hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2010         break;
2011
2012     case VT_NULL:
2013     case VT_EMPTY:
2014         hr = S_OK;
2015         break;
2016
2017     default:
2018         WARN("Can't get schema from vt %x\n", V_VT(&var1));
2019     }
2020
2021     if(SUCCEEDED(hr))
2022     {
2023         IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
2024         if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
2025     }
2026
2027     return hr;
2028 }
2029
2030 static HRESULT WINAPI domdoc_validate(
2031     IXMLDOMDocument3* iface,
2032     IXMLDOMParseError** err)
2033 {
2034     domdoc *This = impl_from_IXMLDOMDocument3( iface );
2035     FIXME("(%p)->(%p)\n", This, err);
2036     return E_NOTIMPL;
2037 }
2038
2039 static HRESULT WINAPI domdoc_setProperty(
2040     IXMLDOMDocument3* iface,
2041     BSTR p,
2042     VARIANT var)
2043 {
2044     domdoc *This = impl_from_IXMLDOMDocument3( iface );
2045
2046     TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2047
2048     if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2049     {
2050         VARIANT varStr;
2051         HRESULT hr;
2052         BSTR bstr;
2053
2054         V_VT(&varStr) = VT_EMPTY;
2055         if (V_VT(&var) != VT_BSTR)
2056         {
2057             if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2058                 return hr;
2059             bstr = V_BSTR(&varStr);
2060         }
2061         else
2062             bstr = V_BSTR(&var);
2063
2064         hr = S_OK;
2065         if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2066             This->bUseXPath = TRUE;
2067         else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2068             This->bUseXPath = FALSE;
2069         else
2070             hr = E_FAIL;
2071
2072         VariantClear(&varStr);
2073         return hr;
2074     }
2075     else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0)
2076     {
2077         /* Ignore */
2078         FIXME("Ignoring property ProhibitDTD, value %d\n", V_BOOL(&var));
2079         return S_OK;
2080     }
2081     else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2082     {
2083         if (V_VT(&var) == VT_BSTR)
2084             FIXME("Unsupported SelectionNamespaces: %s\n", wine_dbgstr_w(V_BSTR(&var)));
2085         return E_FAIL;
2086     }
2087
2088     FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2089     return E_FAIL;
2090 }
2091
2092 static HRESULT WINAPI domdoc_getProperty(
2093     IXMLDOMDocument3* iface,
2094     BSTR p,
2095     VARIANT* var)
2096 {
2097     domdoc *This = impl_from_IXMLDOMDocument3( iface );
2098
2099     TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2100
2101     if (var == NULL)
2102         return E_INVALIDARG;
2103
2104     if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2105     {
2106         V_VT(var) = VT_BSTR;
2107         if (This->bUseXPath)
2108             V_BSTR(var) = SysAllocString(PropValueXPathW);
2109         else
2110             V_BSTR(var) = SysAllocString(PropValueXSLPatternW);
2111         return S_OK;
2112     }
2113
2114     FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2115     return E_FAIL;
2116 }
2117
2118 static HRESULT WINAPI domdoc_validateNode(
2119     IXMLDOMDocument3* iface,
2120     IXMLDOMNode* node,
2121     IXMLDOMParseError** error)
2122 {
2123     domdoc *This = impl_from_IXMLDOMDocument3( iface );
2124     FIXME("(%p)->(%p %p): stub\n", This, node, error);
2125     return E_NOTIMPL;
2126 }
2127
2128 static HRESULT WINAPI domdoc_importNode(
2129     IXMLDOMDocument3* iface,
2130     IXMLDOMNode* node,
2131     VARIANT_BOOL deep,
2132     IXMLDOMNode** clone)
2133 {
2134     domdoc *This = impl_from_IXMLDOMDocument3( iface );
2135     FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
2136     return E_NOTIMPL;
2137 }
2138
2139 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
2140 {
2141     domdoc_QueryInterface,
2142     domdoc_AddRef,
2143     domdoc_Release,
2144     domdoc_GetTypeInfoCount,
2145     domdoc_GetTypeInfo,
2146     domdoc_GetIDsOfNames,
2147     domdoc_Invoke,
2148     domdoc_get_nodeName,
2149     domdoc_get_nodeValue,
2150     domdoc_put_nodeValue,
2151     domdoc_get_nodeType,
2152     domdoc_get_parentNode,
2153     domdoc_get_childNodes,
2154     domdoc_get_firstChild,
2155     domdoc_get_lastChild,
2156     domdoc_get_previousSibling,
2157     domdoc_get_nextSibling,
2158     domdoc_get_attributes,
2159     domdoc_insertBefore,
2160     domdoc_replaceChild,
2161     domdoc_removeChild,
2162     domdoc_appendChild,
2163     domdoc_hasChildNodes,
2164     domdoc_get_ownerDocument,
2165     domdoc_cloneNode,
2166     domdoc_get_nodeTypeString,
2167     domdoc_get_text,
2168     domdoc_put_text,
2169     domdoc_get_specified,
2170     domdoc_get_definition,
2171     domdoc_get_nodeTypedValue,
2172     domdoc_put_nodeTypedValue,
2173     domdoc_get_dataType,
2174     domdoc_put_dataType,
2175     domdoc_get_xml,
2176     domdoc_transformNode,
2177     domdoc_selectNodes,
2178     domdoc_selectSingleNode,
2179     domdoc_get_parsed,
2180     domdoc_get_namespaceURI,
2181     domdoc_get_prefix,
2182     domdoc_get_baseName,
2183     domdoc_transformNodeToObject,
2184     domdoc_get_doctype,
2185     domdoc_get_implementation,
2186     domdoc_get_documentElement,
2187     domdoc_put_documentElement,
2188     domdoc_createElement,
2189     domdoc_createDocumentFragment,
2190     domdoc_createTextNode,
2191     domdoc_createComment,
2192     domdoc_createCDATASection,
2193     domdoc_createProcessingInstruction,
2194     domdoc_createAttribute,
2195     domdoc_createEntityReference,
2196     domdoc_getElementsByTagName,
2197     domdoc_createNode,
2198     domdoc_nodeFromID,
2199     domdoc_load,
2200     domdoc_get_readyState,
2201     domdoc_get_parseError,
2202     domdoc_get_url,
2203     domdoc_get_async,
2204     domdoc_put_async,
2205     domdoc_abort,
2206     domdoc_loadXML,
2207     domdoc_save,
2208     domdoc_get_validateOnParse,
2209     domdoc_put_validateOnParse,
2210     domdoc_get_resolveExternals,
2211     domdoc_put_resolveExternals,
2212     domdoc_get_preserveWhiteSpace,
2213     domdoc_put_preserveWhiteSpace,
2214     domdoc_put_onReadyStateChange,
2215     domdoc_put_onDataAvailable,
2216     domdoc_put_onTransformNode,
2217     domdoc_get_namespaces,
2218     domdoc_get_schemas,
2219     domdoc_putref_schemas,
2220     domdoc_validate,
2221     domdoc_setProperty,
2222     domdoc_getProperty,
2223     domdoc_validateNode,
2224     domdoc_importNode
2225 };
2226
2227 /* xmldoc implementation of IObjectWithSite */
2228 static HRESULT WINAPI
2229 xmldoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
2230 {
2231     domdoc *This = impl_from_IObjectWithSite(iface);
2232     return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppvObject );
2233 }
2234
2235 static ULONG WINAPI
2236 xmldoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
2237 {
2238     domdoc *This = impl_from_IObjectWithSite(iface);
2239     return IXMLDocument_AddRef((IXMLDocument *)This);
2240 }
2241
2242 static ULONG WINAPI
2243 xmldoc_ObjectWithSite_Release( IObjectWithSite* iface )
2244 {
2245     domdoc *This = impl_from_IObjectWithSite(iface);
2246     return IXMLDocument_Release((IXMLDocument *)This);
2247 }
2248
2249 static HRESULT WINAPI
2250 xmldoc_GetSite( IObjectWithSite *iface, REFIID iid, void ** ppvSite )
2251 {
2252     domdoc *This = impl_from_IObjectWithSite(iface);
2253
2254     TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
2255
2256     if ( !This->site )
2257         return E_FAIL;
2258
2259     return IUnknown_QueryInterface( This->site, iid, ppvSite );
2260 }
2261
2262 static HRESULT WINAPI
2263 xmldoc_SetSite( IObjectWithSite *iface, IUnknown *punk )
2264 {
2265     domdoc *This = impl_from_IObjectWithSite(iface);
2266
2267     TRACE("(%p)->(%p)\n", iface, punk);
2268
2269     if(!punk)
2270     {
2271         if(This->site)
2272         {
2273             IUnknown_Release( This->site );
2274             This->site = NULL;
2275         }
2276
2277         return S_OK;
2278     }
2279
2280     IUnknown_AddRef( punk );
2281
2282     if(This->site)
2283         IUnknown_Release( This->site );
2284
2285     This->site = punk;
2286
2287     return S_OK;
2288 }
2289
2290 static const IObjectWithSiteVtbl domdocObjectSite =
2291 {
2292     xmldoc_ObjectWithSite_QueryInterface,
2293     xmldoc_ObjectWithSite_AddRef,
2294     xmldoc_ObjectWithSite_Release,
2295     xmldoc_SetSite,
2296     xmldoc_GetSite,
2297 };
2298
2299 static HRESULT WINAPI xmldoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
2300 {
2301     domdoc *This = impl_from_IObjectSafety(iface);
2302     return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppv );
2303 }
2304
2305 static ULONG WINAPI xmldoc_Safety_AddRef(IObjectSafety *iface)
2306 {
2307     domdoc *This = impl_from_IObjectSafety(iface);
2308     return IXMLDocument_AddRef((IXMLDocument *)This);
2309 }
2310
2311 static ULONG WINAPI xmldoc_Safety_Release(IObjectSafety *iface)
2312 {
2313     domdoc *This = impl_from_IObjectSafety(iface);
2314     return IXMLDocument_Release((IXMLDocument *)This);
2315 }
2316
2317 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
2318
2319 static HRESULT WINAPI xmldoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2320         DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
2321 {
2322     domdoc *This = impl_from_IObjectSafety(iface);
2323
2324     TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
2325
2326     if(!pdwSupportedOptions || !pdwEnabledOptions)
2327         return E_POINTER;
2328
2329     *pdwSupportedOptions = SAFETY_SUPPORTED_OPTIONS;
2330     *pdwEnabledOptions = This->safeopt;
2331
2332     return S_OK;
2333 }
2334
2335 static HRESULT WINAPI xmldoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2336         DWORD dwOptionSetMask, DWORD dwEnabledOptions)
2337 {
2338     domdoc *This = impl_from_IObjectSafety(iface);
2339     TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
2340
2341     if ((dwOptionSetMask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
2342         return E_FAIL;
2343
2344     This->safeopt = dwEnabledOptions & dwOptionSetMask & SAFETY_SUPPORTED_OPTIONS;
2345     return S_OK;
2346 }
2347
2348 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
2349     xmldoc_Safety_QueryInterface,
2350     xmldoc_Safety_AddRef,
2351     xmldoc_Safety_Release,
2352     xmldoc_Safety_GetInterfaceSafetyOptions,
2353     xmldoc_Safety_SetInterfaceSafetyOptions
2354 };
2355
2356
2357 static const tid_t domdoc_iface_tids[] = {
2358     IXMLDOMNode_tid,
2359     IXMLDOMDocument_tid,
2360     IXMLDOMDocument2_tid,
2361     0
2362 };
2363 static dispex_static_data_t domdoc_dispex = {
2364     NULL,
2365     IXMLDOMDocument2_tid,
2366     NULL,
2367     domdoc_iface_tids
2368 };
2369
2370 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
2371 {
2372     domdoc *doc;
2373
2374     doc = heap_alloc( sizeof (*doc) );
2375     if( !doc )
2376         return E_OUTOFMEMORY;
2377
2378     doc->lpVtbl = &domdoc_vtbl;
2379     doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
2380     doc->lpvtblIObjectWithSite = &domdocObjectSite;
2381     doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
2382     doc->lpvtblISupportErrorInfo = &support_error_vtbl;
2383     doc->ref = 1;
2384     doc->async = VARIANT_TRUE;
2385     doc->validating = 0;
2386     doc->resolving = 0;
2387     doc->preserving = 0;
2388     doc->bUseXPath = FALSE;
2389     doc->error = S_OK;
2390     doc->schema = NULL;
2391     doc->stream = NULL;
2392     doc->site = NULL;
2393     doc->safeopt = 0;
2394     doc->bsc = NULL;
2395
2396     init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IUnknown*)&doc->lpVtbl, &domdoc_dispex);
2397
2398     *document = (IXMLDOMDocument3*)&doc->lpVtbl;
2399
2400     TRACE("returning iface %p\n", *document);
2401     return S_OK;
2402 }
2403
2404 HRESULT DOMDocument_create(IUnknown *pUnkOuter, void **ppObj)
2405 {
2406     xmlDocPtr xmldoc;
2407     HRESULT hr;
2408
2409     TRACE("(%p, %p)\n", pUnkOuter, ppObj);
2410
2411     xmldoc = xmlNewDoc(NULL);
2412     if(!xmldoc)
2413         return E_OUTOFMEMORY;
2414
2415     xmldoc->_private = create_priv();
2416
2417     hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
2418     if(FAILED(hr))
2419         xmlFreeDoc(xmldoc);
2420
2421     return hr;
2422 }
2423
2424 IUnknown* create_domdoc( xmlNodePtr document )
2425 {
2426     void* pObj = NULL;
2427     HRESULT hr;
2428
2429     TRACE("(%p)\n", document);
2430
2431     hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
2432     if (FAILED(hr))
2433         return NULL;
2434
2435     return pObj;
2436 }
2437
2438 #else
2439
2440 HRESULT DOMDocument_create(IUnknown *pUnkOuter, void **ppObj)
2441 {
2442     MESSAGE("This program tried to use a DOMDocument object, but\n"
2443             "libxml2 support was not present at compile time.\n");
2444     return E_NOTIMPL;
2445 }
2446
2447 #endif