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