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