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