quartz: Do not assert() the existence of a media format of an input pin.
[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, blen = SysStringLen( bstr );
1654     LPSTR str;
1655
1656     len = WideCharToMultiByte( CP_UTF8, 0, bstr, blen, NULL, 0, NULL, NULL );
1657     str = heap_alloc( len );
1658     if ( !str )
1659         return FALSE;
1660     WideCharToMultiByte( CP_UTF8, 0, bstr, blen, str, len, NULL, NULL );
1661     *plen = len;
1662     *pstr = str;
1663     return TRUE;
1664 }
1665
1666 static HRESULT WINAPI domdoc_loadXML(
1667     IXMLDOMDocument2 *iface,
1668     BSTR bstrXML,
1669     VARIANT_BOOL* isSuccessful )
1670 {
1671     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1672     xmlDocPtr xmldoc = NULL;
1673     char *str;
1674     int len;
1675     HRESULT hr = S_FALSE, hr2;
1676
1677     TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
1678
1679     assert ( &This->node );
1680
1681     if ( isSuccessful )
1682     {
1683         *isSuccessful = VARIANT_FALSE;
1684
1685         if ( bstrXML  && bstr_to_utf8( bstrXML, &str, &len ) )
1686         {
1687             xmldoc = doparse( str, len );
1688             heap_free( str );
1689             if ( !xmldoc )
1690                 This->error = E_FAIL;
1691             else
1692             {
1693                 hr = This->error = S_OK;
1694                 *isSuccessful = VARIANT_TRUE;
1695             }
1696         }
1697     }
1698     if(!xmldoc)
1699         xmldoc = xmlNewDoc(NULL);
1700
1701     xmldoc->_private = create_priv();
1702     hr2 = attach_xmldoc( &This->node, xmldoc );
1703     if( FAILED(hr2) )
1704         hr = hr2;
1705
1706     return hr;
1707 }
1708
1709 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer,
1710                                              int len)
1711 {
1712     DWORD written = -1;
1713
1714     if(!WriteFile(ctx, buffer, len, &written, NULL))
1715     {
1716         WARN("write error\n");
1717         return -1;
1718     }
1719     else
1720         return written;
1721 }
1722
1723 static int XMLCALL domdoc_save_closecallback(void *ctx)
1724 {
1725     return CloseHandle(ctx) ? 0 : -1;
1726 }
1727
1728 static HRESULT WINAPI domdoc_save(
1729     IXMLDOMDocument2 *iface,
1730     VARIANT destination )
1731 {
1732     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1733     HANDLE handle;
1734     xmlSaveCtxtPtr ctx;
1735     HRESULT ret = S_OK;
1736
1737     TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
1738           V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
1739
1740     if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
1741     {
1742         FIXME("Unhandled vt %d\n", V_VT(&destination));
1743         return S_FALSE;
1744     }
1745
1746     if(V_VT(&destination) == VT_UNKNOWN)
1747     {
1748         IUnknown *pUnk = V_UNKNOWN(&destination);
1749         IXMLDOMDocument *pDocument;
1750
1751         ret = IXMLDOMDocument_QueryInterface(pUnk, &IID_IXMLDOMDocument2, (void**)&pDocument);
1752         if(ret == S_OK)
1753         {
1754             BSTR bXML;
1755             VARIANT_BOOL bSuccessful;
1756
1757             ret = IXMLDOMDocument_get_xml(iface, &bXML);
1758             if(ret == S_OK)
1759             {
1760                 ret = IXMLDOMDocument_loadXML(pDocument, bXML, &bSuccessful);
1761
1762                 SysFreeString(bXML);
1763             }
1764
1765             IXMLDOMDocument_Release(pDocument);
1766         }
1767
1768         TRACE("ret %d\n", ret);
1769
1770         return ret;
1771     }
1772
1773     handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
1774                           NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1775     if( handle == INVALID_HANDLE_VALUE )
1776     {
1777         WARN("failed to create file\n");
1778         return S_FALSE;
1779     }
1780
1781     /* disable top XML declaration */
1782     ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
1783                       handle, NULL, XML_SAVE_NO_DECL);
1784     if (!ctx)
1785     {
1786         CloseHandle(handle);
1787         return S_FALSE;
1788     }
1789
1790     if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
1791     /* will close file through close callback */
1792     xmlSaveClose(ctx);
1793
1794     return ret;
1795 }
1796
1797 static HRESULT WINAPI domdoc_get_validateOnParse(
1798     IXMLDOMDocument2 *iface,
1799     VARIANT_BOOL* isValidating )
1800 {
1801     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1802
1803     TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
1804     *isValidating = This->validating;
1805     return S_OK;
1806 }
1807
1808
1809 static HRESULT WINAPI domdoc_put_validateOnParse(
1810     IXMLDOMDocument2 *iface,
1811     VARIANT_BOOL isValidating )
1812 {
1813     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1814
1815     TRACE("(%p)->(%d)\n", This, isValidating);
1816     This->validating = isValidating;
1817     return S_OK;
1818 }
1819
1820
1821 static HRESULT WINAPI domdoc_get_resolveExternals(
1822     IXMLDOMDocument2 *iface,
1823     VARIANT_BOOL* isResolving )
1824 {
1825     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1826
1827     TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
1828     *isResolving = This->resolving;
1829     return S_OK;
1830 }
1831
1832
1833 static HRESULT WINAPI domdoc_put_resolveExternals(
1834     IXMLDOMDocument2 *iface,
1835     VARIANT_BOOL isResolving )
1836 {
1837     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1838
1839     TRACE("(%p)->(%d)\n", This, isResolving);
1840     This->resolving = isResolving;
1841     return S_OK;
1842 }
1843
1844
1845 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
1846     IXMLDOMDocument2 *iface,
1847     VARIANT_BOOL* isPreserving )
1848 {
1849     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1850
1851     TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->preserving);
1852     *isPreserving = This->preserving;
1853     return S_OK;
1854 }
1855
1856
1857 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
1858     IXMLDOMDocument2 *iface,
1859     VARIANT_BOOL isPreserving )
1860 {
1861     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1862
1863     TRACE("(%p)->(%d)\n", This, isPreserving);
1864     This->preserving = isPreserving;
1865     return S_OK;
1866 }
1867
1868
1869 static HRESULT WINAPI domdoc_put_onReadyStateChange(
1870     IXMLDOMDocument2 *iface,
1871     VARIANT readyStateChangeSink )
1872 {
1873     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1874     FIXME("%p\n", This);
1875     return E_NOTIMPL;
1876 }
1877
1878
1879 static HRESULT WINAPI domdoc_put_onDataAvailable(
1880     IXMLDOMDocument2 *iface,
1881     VARIANT onDataAvailableSink )
1882 {
1883     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1884     FIXME("%p\n", This);
1885     return E_NOTIMPL;
1886 }
1887
1888 static HRESULT WINAPI domdoc_put_onTransformNode(
1889     IXMLDOMDocument2 *iface,
1890     VARIANT onTransformNodeSink )
1891 {
1892     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1893     FIXME("%p\n", This);
1894     return E_NOTIMPL;
1895 }
1896
1897 static HRESULT WINAPI domdoc_get_namespaces(
1898     IXMLDOMDocument2* iface,
1899     IXMLDOMSchemaCollection** schemaCollection )
1900 {
1901     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1902     FIXME("(%p)->(%p)\n", This, schemaCollection);
1903     return E_NOTIMPL;
1904 }
1905
1906 static HRESULT WINAPI domdoc_get_schemas(
1907     IXMLDOMDocument2* iface,
1908     VARIANT* var1 )
1909 {
1910     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1911     HRESULT hr = S_FALSE;
1912     IXMLDOMSchemaCollection *cur_schema = This->schema;
1913
1914     TRACE("(%p)->(%p)\n", This, var1);
1915
1916     VariantInit(var1); /* Test shows we don't call VariantClear here */
1917     V_VT(var1) = VT_NULL;
1918
1919     if(cur_schema)
1920     {
1921         hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
1922         if(SUCCEEDED(hr))
1923             V_VT(var1) = VT_DISPATCH;
1924     }
1925     return hr;
1926 }
1927
1928 static HRESULT WINAPI domdoc_putref_schemas(
1929     IXMLDOMDocument2* iface,
1930     VARIANT var1)
1931 {
1932     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1933     HRESULT hr = E_FAIL;
1934     IXMLDOMSchemaCollection *new_schema = NULL;
1935
1936     FIXME("(%p): semi-stub\n", This);
1937     switch(V_VT(&var1))
1938     {
1939     case VT_UNKNOWN:
1940         hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1941         break;
1942
1943     case VT_DISPATCH:
1944         hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1945         break;
1946
1947     case VT_NULL:
1948     case VT_EMPTY:
1949         hr = S_OK;
1950         break;
1951
1952     default:
1953         WARN("Can't get schema from vt %x\n", V_VT(&var1));
1954     }
1955
1956     if(SUCCEEDED(hr))
1957     {
1958         IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
1959         if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
1960     }
1961
1962     return hr;
1963 }
1964
1965 static HRESULT WINAPI domdoc_validate(
1966     IXMLDOMDocument2* iface,
1967     IXMLDOMParseError** err)
1968 {
1969     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1970     FIXME("(%p)->(%p)\n", This, err);
1971     return E_NOTIMPL;
1972 }
1973
1974 static HRESULT WINAPI domdoc_setProperty(
1975     IXMLDOMDocument2* iface,
1976     BSTR p,
1977     VARIANT var)
1978 {
1979     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1980
1981     TRACE("(%p)->(%s)\n", This, debugstr_w(p));
1982
1983     if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
1984     {
1985         VARIANT varStr;
1986         HRESULT hr;
1987         BSTR bstr;
1988
1989         V_VT(&varStr) = VT_EMPTY;
1990         if (V_VT(&var) != VT_BSTR)
1991         {
1992             if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
1993                 return hr;
1994             bstr = V_BSTR(&varStr);
1995         }
1996         else
1997             bstr = V_BSTR(&var);
1998
1999         hr = S_OK;
2000         if (lstrcmpiW(bstr, SZ_VALUE_XPATH) == 0)
2001             This->bUseXPath = TRUE;
2002         else if (lstrcmpiW(bstr, SZ_VALUE_XSLPATTERN) == 0)
2003             This->bUseXPath = FALSE;
2004         else
2005             hr = E_FAIL;
2006
2007         VariantClear(&varStr);
2008         return hr;
2009     }
2010
2011     FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2012     return E_FAIL;
2013 }
2014
2015 static HRESULT WINAPI domdoc_getProperty(
2016     IXMLDOMDocument2* iface,
2017     BSTR p,
2018     VARIANT* var)
2019 {
2020     domdoc *This = impl_from_IXMLDOMDocument2( iface );
2021
2022     TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2023
2024     if (var == NULL)
2025         return E_INVALIDARG;
2026     if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
2027     {
2028         V_VT(var) = VT_BSTR;
2029         if (This->bUseXPath)
2030             V_BSTR(var) = SysAllocString(SZ_VALUE_XPATH);
2031         else
2032             V_BSTR(var) = SysAllocString(SZ_VALUE_XSLPATTERN);
2033         return S_OK;
2034     }
2035
2036     FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2037     return E_FAIL;
2038 }
2039
2040 static const struct IXMLDOMDocument2Vtbl domdoc_vtbl =
2041 {
2042     domdoc_QueryInterface,
2043     domdoc_AddRef,
2044     domdoc_Release,
2045     domdoc_GetTypeInfoCount,
2046     domdoc_GetTypeInfo,
2047     domdoc_GetIDsOfNames,
2048     domdoc_Invoke,
2049     domdoc_get_nodeName,
2050     domdoc_get_nodeValue,
2051     domdoc_put_nodeValue,
2052     domdoc_get_nodeType,
2053     domdoc_get_parentNode,
2054     domdoc_get_childNodes,
2055     domdoc_get_firstChild,
2056     domdoc_get_lastChild,
2057     domdoc_get_previousSibling,
2058     domdoc_get_nextSibling,
2059     domdoc_get_attributes,
2060     domdoc_insertBefore,
2061     domdoc_replaceChild,
2062     domdoc_removeChild,
2063     domdoc_appendChild,
2064     domdoc_hasChildNodes,
2065     domdoc_get_ownerDocument,
2066     domdoc_cloneNode,
2067     domdoc_get_nodeTypeString,
2068     domdoc_get_text,
2069     domdoc_put_text,
2070     domdoc_get_specified,
2071     domdoc_get_definition,
2072     domdoc_get_nodeTypedValue,
2073     domdoc_put_nodeTypedValue,
2074     domdoc_get_dataType,
2075     domdoc_put_dataType,
2076     domdoc_get_xml,
2077     domdoc_transformNode,
2078     domdoc_selectNodes,
2079     domdoc_selectSingleNode,
2080     domdoc_get_parsed,
2081     domdoc_get_namespaceURI,
2082     domdoc_get_prefix,
2083     domdoc_get_baseName,
2084     domdoc_transformNodeToObject,
2085     domdoc_get_doctype,
2086     domdoc_get_implementation,
2087     domdoc_get_documentElement,
2088     domdoc_put_documentElement,
2089     domdoc_createElement,
2090     domdoc_createDocumentFragment,
2091     domdoc_createTextNode,
2092     domdoc_createComment,
2093     domdoc_createCDATASection,
2094     domdoc_createProcessingInstruction,
2095     domdoc_createAttribute,
2096     domdoc_createEntityReference,
2097     domdoc_getElementsByTagName,
2098     domdoc_createNode,
2099     domdoc_nodeFromID,
2100     domdoc_load,
2101     domdoc_get_readyState,
2102     domdoc_get_parseError,
2103     domdoc_get_url,
2104     domdoc_get_async,
2105     domdoc_put_async,
2106     domdoc_abort,
2107     domdoc_loadXML,
2108     domdoc_save,
2109     domdoc_get_validateOnParse,
2110     domdoc_put_validateOnParse,
2111     domdoc_get_resolveExternals,
2112     domdoc_put_resolveExternals,
2113     domdoc_get_preserveWhiteSpace,
2114     domdoc_put_preserveWhiteSpace,
2115     domdoc_put_onReadyStateChange,
2116     domdoc_put_onDataAvailable,
2117     domdoc_put_onTransformNode,
2118     domdoc_get_namespaces,
2119     domdoc_get_schemas,
2120     domdoc_putref_schemas,
2121     domdoc_validate,
2122     domdoc_setProperty,
2123     domdoc_getProperty
2124 };
2125
2126 /* xmldoc implementation of IObjectWithSite */
2127 static HRESULT WINAPI
2128 xmldoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
2129 {
2130     domdoc *This = impl_from_IObjectWithSite(iface);
2131     return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppvObject );
2132 }
2133
2134 static ULONG WINAPI
2135 xmldoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
2136 {
2137     domdoc *This = impl_from_IObjectWithSite(iface);
2138     return IXMLDocument_AddRef((IXMLDocument *)This);
2139 }
2140
2141 static ULONG WINAPI
2142 xmldoc_ObjectWithSite_Release( IObjectWithSite* iface )
2143 {
2144     domdoc *This = impl_from_IObjectWithSite(iface);
2145     return IXMLDocument_Release((IXMLDocument *)This);
2146 }
2147
2148 static HRESULT WINAPI
2149 xmldoc_GetSite( IObjectWithSite *iface, REFIID iid, void ** ppvSite )
2150 {
2151     domdoc *This = impl_from_IObjectWithSite(iface);
2152
2153     TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
2154
2155     if ( !This->site )
2156         return E_FAIL;
2157
2158     return IUnknown_QueryInterface( This->site, iid, ppvSite );
2159 }
2160
2161 static HRESULT WINAPI
2162 xmldoc_SetSite( IObjectWithSite *iface, IUnknown *punk )
2163 {
2164     domdoc *This = impl_from_IObjectWithSite(iface);
2165
2166     TRACE("(%p)->(%p)\n", iface, punk);
2167
2168     if(!punk)
2169     {
2170         if(This->site)
2171         {
2172             IUnknown_Release( This->site );
2173             This->site = NULL;
2174         }
2175
2176         return S_OK;
2177     }
2178
2179     if ( punk )
2180         IUnknown_AddRef( punk );
2181
2182     if(This->site)
2183         IUnknown_Release( This->site );
2184
2185     This->site = punk;
2186
2187     return S_OK;
2188 }
2189
2190 static const IObjectWithSiteVtbl domdocObjectSite =
2191 {
2192     xmldoc_ObjectWithSite_QueryInterface,
2193     xmldoc_ObjectWithSite_AddRef,
2194     xmldoc_ObjectWithSite_Release,
2195     xmldoc_SetSite,
2196     xmldoc_GetSite,
2197 };
2198
2199 static HRESULT WINAPI xmldoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
2200 {
2201     domdoc *This = impl_from_IObjectSafety(iface);
2202     return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppv );
2203 }
2204
2205 static ULONG WINAPI xmldoc_Safety_AddRef(IObjectSafety *iface)
2206 {
2207     domdoc *This = impl_from_IObjectSafety(iface);
2208     return IXMLDocument_AddRef((IXMLDocument *)This);
2209 }
2210
2211 static ULONG WINAPI xmldoc_Safety_Release(IObjectSafety *iface)
2212 {
2213     domdoc *This = impl_from_IObjectSafety(iface);
2214     return IXMLDocument_Release((IXMLDocument *)This);
2215 }
2216
2217 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA)
2218
2219 static HRESULT WINAPI xmldoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2220         DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
2221 {
2222     domdoc *This = impl_from_IObjectSafety(iface);
2223
2224     TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
2225
2226     if(!pdwSupportedOptions || !pdwEnabledOptions)
2227         return E_POINTER;
2228
2229     *pdwSupportedOptions = SAFETY_SUPPORTED_OPTIONS;
2230     *pdwEnabledOptions = This->safeopt;
2231
2232     return S_OK;
2233 }
2234
2235 static HRESULT WINAPI xmldoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2236         DWORD dwOptionSetMask, DWORD dwEnabledOptions)
2237 {
2238     domdoc *This = impl_from_IObjectSafety(iface);
2239     TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
2240
2241     This->safeopt = dwEnabledOptions & dwOptionSetMask & SAFETY_SUPPORTED_OPTIONS;
2242     return S_OK;
2243 }
2244
2245 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
2246     xmldoc_Safety_QueryInterface,
2247     xmldoc_Safety_AddRef,
2248     xmldoc_Safety_Release,
2249     xmldoc_Safety_GetInterfaceSafetyOptions,
2250     xmldoc_Safety_SetInterfaceSafetyOptions
2251 };
2252
2253
2254 static const tid_t domdoc_iface_tids[] = {
2255     IXMLDOMNode_tid,
2256     IXMLDOMDocument_tid,
2257     IXMLDOMDocument2_tid,
2258     0
2259 };
2260 static dispex_static_data_t domdoc_dispex = {
2261     NULL,
2262     IXMLDOMDocument2_tid,
2263     NULL,
2264     domdoc_iface_tids
2265 };
2266
2267 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument2 **document)
2268 {
2269     domdoc *doc;
2270
2271     doc = heap_alloc( sizeof (*doc) );
2272     if( !doc )
2273         return E_OUTOFMEMORY;
2274
2275     doc->lpVtbl = &domdoc_vtbl;
2276     doc->lpvtblIPersistStream = &xmldoc_IPersistStream_VTable;
2277     doc->lpvtblIObjectWithSite = &domdocObjectSite;
2278     doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
2279     doc->lpvtblISupportErrorInfo = &support_error_vtbl;
2280     doc->ref = 1;
2281     doc->async = VARIANT_TRUE;
2282     doc->validating = 0;
2283     doc->resolving = 0;
2284     doc->preserving = 0;
2285     doc->bUseXPath = FALSE;
2286     doc->error = S_OK;
2287     doc->schema = NULL;
2288     doc->stream = NULL;
2289     doc->site = NULL;
2290     doc->safeopt = 0;
2291     doc->bsc = NULL;
2292
2293     init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IUnknown*)&doc->lpVtbl, &domdoc_dispex);
2294
2295     *document = (IXMLDOMDocument2*)&doc->lpVtbl;
2296
2297     TRACE("returning iface %p\n", *document);
2298     return S_OK;
2299 }
2300
2301 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2302 {
2303     xmlDocPtr xmldoc;
2304     HRESULT hr;
2305
2306     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
2307
2308     xmldoc = xmlNewDoc(NULL);
2309     if(!xmldoc)
2310         return E_OUTOFMEMORY;
2311
2312     xmldoc->_private = create_priv();
2313
2314     hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument2**)ppObj);
2315     if(FAILED(hr))
2316         xmlFreeDoc(xmldoc);
2317
2318     return hr;
2319 }
2320
2321 IUnknown* create_domdoc( xmlNodePtr document )
2322 {
2323     HRESULT hr;
2324     LPVOID pObj = NULL;
2325
2326     TRACE("(%p)\n", document);
2327
2328     hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument2**)&pObj);
2329     if (FAILED(hr))
2330         return NULL;
2331
2332     return pObj;
2333 }
2334
2335 #else
2336
2337 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2338 {
2339     MESSAGE("This program tried to use a DOMDocument object, but\n"
2340             "libxml2 support was not present at compile time.\n");
2341     return E_NOTIMPL;
2342 }
2343
2344 #endif