ws2_32/tests: Fix a race in sock.c:test_write_events().
[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 DOMNodeType get_node_type(VARIANT Type)
1114 {
1115     if(V_VT(&Type) == VT_I4)
1116         return V_I4(&Type);
1117
1118     FIXME("Unsupported variant type %x\n", V_VT(&Type));
1119     return 0;
1120 }
1121
1122 static HRESULT WINAPI domdoc_createNode(
1123     IXMLDOMDocument2 *iface,
1124     VARIANT Type,
1125     BSTR name,
1126     BSTR namespaceURI,
1127     IXMLDOMNode** node )
1128 {
1129     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1130     DOMNodeType node_type;
1131     xmlNodePtr xmlnode = NULL;
1132     xmlChar *xml_name;
1133
1134     TRACE("(%p)->(type,%s,%s,%p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1135
1136     node_type = get_node_type(Type);
1137     TRACE("node_type %d\n", node_type);
1138
1139     xml_name = xmlChar_from_wchar((WCHAR*)name);
1140
1141     switch(node_type)
1142     {
1143     case NODE_ELEMENT:
1144         xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
1145         *node = create_node(xmlnode);
1146         TRACE("created %p\n", xmlnode);
1147         break;
1148     case NODE_ATTRIBUTE:
1149         xmlnode = (xmlNode *)xmlNewProp(NULL, xml_name, NULL);
1150         if(xmlnode)
1151         {
1152             xmlnode->doc = get_doc( This );
1153
1154             *node = (IXMLDOMNode*)create_attribute(xmlnode);
1155         }
1156
1157         TRACE("created %p\n", xmlnode);
1158         break;
1159
1160     default:
1161         FIXME("unhandled node type %d\n", node_type);
1162         break;
1163     }
1164
1165     HeapFree(GetProcessHeap(), 0, xml_name);
1166
1167     if(xmlnode && *node)
1168         return S_OK;
1169
1170     return E_FAIL;
1171 }
1172
1173 static HRESULT WINAPI domdoc_nodeFromID(
1174     IXMLDOMDocument2 *iface,
1175     BSTR idString,
1176     IXMLDOMNode** node )
1177 {
1178     FIXME("\n");
1179     return E_NOTIMPL;
1180 }
1181
1182 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1183 {
1184     domdoc *This = obj;
1185     xmlDocPtr xmldoc;
1186
1187     xmldoc = doparse( ptr, len );
1188     if(xmldoc) {
1189         xmldoc->_private = 0;
1190         attach_xmlnode(This->node, (xmlNodePtr) xmldoc);
1191     }
1192
1193     return S_OK;
1194 }
1195
1196 static HRESULT doread( domdoc *This, LPWSTR filename )
1197 {
1198     bsc_t *bsc;
1199     HRESULT hr;
1200
1201     hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1202     if(FAILED(hr))
1203         return hr;
1204
1205     if(This->bsc)
1206         detach_bsc(This->bsc);
1207
1208     This->bsc = bsc;
1209     return S_OK;
1210 }
1211
1212 static HRESULT WINAPI domdoc_load(
1213     IXMLDOMDocument2 *iface,
1214     VARIANT xmlSource,
1215     VARIANT_BOOL* isSuccessful )
1216 {
1217     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1218     LPWSTR filename = NULL;
1219     HRESULT hr = S_FALSE;
1220     IXMLDOMDocument2 *pNewDoc = NULL;
1221     IStream *pStream = NULL;
1222     xmlDocPtr xmldoc;
1223
1224     TRACE("type %d\n", V_VT(&xmlSource) );
1225
1226     *isSuccessful = VARIANT_FALSE;
1227
1228     assert( This->node );
1229
1230     attach_xmlnode(This->node, NULL);
1231
1232     switch( V_VT(&xmlSource) )
1233     {
1234     case VT_BSTR:
1235         filename = V_BSTR(&xmlSource);
1236         break;
1237     case VT_UNKNOWN:
1238         hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument2, (void**)&pNewDoc);
1239         if(hr == S_OK)
1240         {
1241             if(pNewDoc)
1242             {
1243                 domdoc *newDoc = impl_from_IXMLDOMDocument2( pNewDoc );
1244                 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1245                 attach_xmlnode(This->node, (xmlNodePtr) xmldoc);
1246
1247                 *isSuccessful = VARIANT_TRUE;
1248
1249                 return S_OK;
1250             }
1251         }
1252         hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1253         if(hr == S_OK)
1254         {
1255             IPersistStream *pDocStream;
1256             hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1257             if(hr == S_OK)
1258             {
1259                 hr = xmldoc_IPersistStream_Load(pDocStream, pStream);
1260                 IStream_Release(pStream);
1261                 if(hr == S_OK)
1262                 {
1263                     *isSuccessful = VARIANT_TRUE;
1264
1265                     TRACE("Using ID_IStream to load Document\n");
1266                     return S_OK;
1267                 }
1268                 else
1269                 {
1270                     ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1271                 }
1272             }
1273             else
1274             {
1275                 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1276             }
1277         }
1278         else
1279         {
1280             /* ISequentialStream */
1281             FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1282         }
1283         break;
1284      default:
1285             FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1286      }
1287
1288     TRACE("filename (%s)\n", debugstr_w(filename));
1289
1290     if ( filename )
1291     {
1292         hr = doread( This, filename );
1293     
1294         if ( FAILED(hr) )
1295             This->error = E_FAIL;
1296         else
1297         {
1298             hr = This->error = S_OK;
1299             *isSuccessful = VARIANT_TRUE;
1300         }
1301     }
1302
1303     if(!filename || FAILED(hr)) {
1304         xmldoc = xmlNewDoc(NULL);
1305         xmldoc->_private = 0;
1306         attach_xmlnode(This->node, (xmlNodePtr) xmldoc);
1307         hr = S_FALSE;
1308     }
1309
1310     TRACE("ret (%d)\n", hr);
1311
1312     return hr;
1313 }
1314
1315
1316 static HRESULT WINAPI domdoc_get_readyState(
1317     IXMLDOMDocument2 *iface,
1318     long* value )
1319 {
1320     FIXME("\n");
1321     return E_NOTIMPL;
1322 }
1323
1324
1325 static HRESULT WINAPI domdoc_get_parseError(
1326     IXMLDOMDocument2 *iface,
1327     IXMLDOMParseError** errorObj )
1328 {
1329     BSTR error_string = NULL;
1330     static const WCHAR err[] = {'e','r','r','o','r',0};
1331     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1332
1333     FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
1334
1335     if(This->error)
1336         error_string = SysAllocString(err);
1337
1338     *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
1339     if(!*errorObj) return E_OUTOFMEMORY;
1340     return S_OK;
1341 }
1342
1343
1344 static HRESULT WINAPI domdoc_get_url(
1345     IXMLDOMDocument2 *iface,
1346     BSTR* urlString )
1347 {
1348     FIXME("\n");
1349     return E_NOTIMPL;
1350 }
1351
1352
1353 static HRESULT WINAPI domdoc_get_async(
1354     IXMLDOMDocument2 *iface,
1355     VARIANT_BOOL* isAsync )
1356 {
1357     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1358
1359     TRACE("%p <- %d\n", isAsync, This->async);
1360     *isAsync = This->async;
1361     return S_OK;
1362 }
1363
1364
1365 static HRESULT WINAPI domdoc_put_async(
1366     IXMLDOMDocument2 *iface,
1367     VARIANT_BOOL isAsync )
1368 {
1369     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1370
1371     TRACE("%d\n", isAsync);
1372     This->async = isAsync;
1373     return S_OK;
1374 }
1375
1376
1377 static HRESULT WINAPI domdoc_abort(
1378     IXMLDOMDocument2 *iface )
1379 {
1380     FIXME("\n");
1381     return E_NOTIMPL;
1382 }
1383
1384
1385 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
1386 {
1387     UINT len, blen = SysStringLen( bstr );
1388     LPSTR str;
1389
1390     len = WideCharToMultiByte( CP_UTF8, 0, bstr, blen, NULL, 0, NULL, NULL );
1391     str = HeapAlloc( GetProcessHeap(), 0, len );
1392     if ( !str )
1393         return FALSE;
1394     WideCharToMultiByte( CP_UTF8, 0, bstr, blen, str, len, NULL, NULL );
1395     *plen = len;
1396     *pstr = str;
1397     return TRUE;
1398 }
1399
1400 static HRESULT WINAPI domdoc_loadXML(
1401     IXMLDOMDocument2 *iface,
1402     BSTR bstrXML,
1403     VARIANT_BOOL* isSuccessful )
1404 {
1405     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1406     xmlDocPtr xmldoc = NULL;
1407     char *str;
1408     int len;
1409     HRESULT hr = S_FALSE;
1410
1411     TRACE("%p %s %p\n", This, debugstr_w( bstrXML ), isSuccessful );
1412
1413     assert ( This->node );
1414
1415     attach_xmlnode( This->node, NULL );
1416
1417     if ( isSuccessful )
1418     {
1419         *isSuccessful = VARIANT_FALSE;
1420
1421         if ( bstrXML  && bstr_to_utf8( bstrXML, &str, &len ) )
1422         {
1423             xmldoc = doparse( str, len );
1424             HeapFree( GetProcessHeap(), 0, str );
1425             if ( !xmldoc )
1426                 This->error = E_FAIL;
1427             else
1428             {
1429                 hr = This->error = S_OK;
1430                 *isSuccessful = VARIANT_TRUE;
1431             }
1432         }
1433     }
1434     if(!xmldoc)
1435         xmldoc = xmlNewDoc(NULL);
1436
1437     xmldoc->_private = 0;
1438     attach_xmlnode( This->node, (xmlNodePtr) xmldoc );
1439
1440     return hr;
1441 }
1442
1443
1444 static HRESULT WINAPI domdoc_save(
1445     IXMLDOMDocument2 *iface,
1446     VARIANT destination )
1447 {
1448     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1449     HANDLE handle;
1450     xmlChar *mem, *p;
1451     int size;
1452     HRESULT ret = S_OK;
1453     DWORD written;
1454
1455     TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
1456           V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
1457
1458     if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
1459     {
1460         FIXME("Unhandled vt %d\n", V_VT(&destination));
1461         return S_FALSE;
1462     }
1463
1464     if(V_VT(&destination) == VT_UNKNOWN)
1465     {
1466         IUnknown *pUnk = V_UNKNOWN(&destination);
1467         IXMLDOMDocument *pDocument;
1468
1469         ret = IXMLDOMDocument_QueryInterface(pUnk, &IID_IXMLDOMDocument2, (void**)&pDocument);
1470         if(ret == S_OK)
1471         {
1472             BSTR bXML;
1473             VARIANT_BOOL bSuccessful;
1474
1475             ret = IXMLDOMDocument_get_xml(iface, &bXML);
1476             if(ret == S_OK)
1477             {
1478                 ret = IXMLDOMDocument_loadXML(pDocument, bXML, &bSuccessful);
1479
1480                 SysFreeString(bXML);
1481             }
1482
1483             IXMLDOMDocument_Release(pDocument);
1484         }
1485
1486         TRACE("ret %d\n", ret);
1487
1488         return ret;
1489     }
1490
1491     handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
1492                           NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1493     if( handle == INVALID_HANDLE_VALUE )
1494     {
1495         WARN("failed to create file\n");
1496         return S_FALSE;
1497     }
1498
1499     xmlDocDumpMemory(get_doc(This), &mem, &size);
1500
1501     /*
1502      * libxml2 always adds XML declaration on top of the file and one for each processing instruction node in DOM tree.
1503      * MSXML adds XML declaration only for processing instruction nodes.
1504      * We skip the first XML declaration generated by libxml2 to get exactly what we need.
1505      */
1506     p = mem;
1507     if(size > 2 && p[0] == '<' && p[1] == '?') {
1508         while(p < mem+size && (p[0] != '?' || p[1] != '>'))
1509             p++;
1510         p += 2;
1511         while(p < mem+size && isspace(*p))
1512             p++;
1513         size -= p-mem;
1514     }
1515
1516     if(!WriteFile(handle, p, (DWORD)size, &written, NULL) || written != (DWORD)size)
1517     {
1518         WARN("write error\n");
1519         ret = S_FALSE;
1520     }
1521
1522     xmlFree(mem);
1523     CloseHandle(handle);
1524     return ret;
1525 }
1526
1527 static HRESULT WINAPI domdoc_get_validateOnParse(
1528     IXMLDOMDocument2 *iface,
1529     VARIANT_BOOL* isValidating )
1530 {
1531     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1532
1533     TRACE("%p <- %d\n", isValidating, This->validating);
1534     *isValidating = This->validating;
1535     return S_OK;
1536 }
1537
1538
1539 static HRESULT WINAPI domdoc_put_validateOnParse(
1540     IXMLDOMDocument2 *iface,
1541     VARIANT_BOOL isValidating )
1542 {
1543     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1544
1545     TRACE("%d\n", isValidating);
1546     This->validating = isValidating;
1547     return S_OK;
1548 }
1549
1550
1551 static HRESULT WINAPI domdoc_get_resolveExternals(
1552     IXMLDOMDocument2 *iface,
1553     VARIANT_BOOL* isResolving )
1554 {
1555     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1556
1557     TRACE("%p <- %d\n", isResolving, This->resolving);
1558     *isResolving = This->resolving;
1559     return S_OK;
1560 }
1561
1562
1563 static HRESULT WINAPI domdoc_put_resolveExternals(
1564     IXMLDOMDocument2 *iface,
1565     VARIANT_BOOL isResolving )
1566 {
1567     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1568
1569     TRACE("%d\n", isResolving);
1570     This->resolving = isResolving;
1571     return S_OK;
1572 }
1573
1574
1575 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
1576     IXMLDOMDocument2 *iface,
1577     VARIANT_BOOL* isPreserving )
1578 {
1579     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1580
1581     TRACE("%p <- %d\n", isPreserving, This->preserving);
1582     *isPreserving = This->preserving;
1583     return S_OK;
1584 }
1585
1586
1587 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
1588     IXMLDOMDocument2 *iface,
1589     VARIANT_BOOL isPreserving )
1590 {
1591     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1592
1593     TRACE("%d\n", isPreserving);
1594     This->preserving = isPreserving;
1595     return S_OK;
1596 }
1597
1598
1599 static HRESULT WINAPI domdoc_put_onReadyStateChange(
1600     IXMLDOMDocument2 *iface,
1601     VARIANT readyStateChangeSink )
1602 {
1603     FIXME("\n");
1604     return E_NOTIMPL;
1605 }
1606
1607
1608 static HRESULT WINAPI domdoc_put_onDataAvailable(
1609     IXMLDOMDocument2 *iface,
1610     VARIANT onDataAvailableSink )
1611 {
1612     FIXME("\n");
1613     return E_NOTIMPL;
1614 }
1615
1616 static HRESULT WINAPI domdoc_put_onTransformNode(
1617     IXMLDOMDocument2 *iface,
1618     VARIANT onTransformNodeSink )
1619 {
1620     FIXME("\n");
1621     return E_NOTIMPL;
1622 }
1623
1624 static HRESULT WINAPI domdoc_get_namespaces(
1625     IXMLDOMDocument2* iface,
1626     IXMLDOMSchemaCollection** schemaCollection )
1627 {
1628     FIXME("\n");
1629     return E_NOTIMPL;
1630 }
1631
1632 static HRESULT WINAPI domdoc_get_schemas(
1633     IXMLDOMDocument2* iface,
1634     VARIANT* var1 )
1635 {
1636     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1637     HRESULT hr = S_FALSE;
1638     IXMLDOMSchemaCollection *cur_schema = This->schema;
1639
1640     TRACE("(%p)->(%p)\n", This, var1);
1641
1642     VariantInit(var1); /* Test shows we don't call VariantClear here */
1643     V_VT(var1) = VT_NULL;
1644
1645     if(cur_schema)
1646     {
1647         hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
1648         if(SUCCEEDED(hr))
1649             V_VT(var1) = VT_DISPATCH;
1650     }
1651     return hr;
1652 }
1653
1654 static HRESULT WINAPI domdoc_putref_schemas(
1655     IXMLDOMDocument2* iface,
1656     VARIANT var1)
1657 {
1658     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1659     HRESULT hr = E_FAIL;
1660     IXMLDOMSchemaCollection *new_schema = NULL;
1661
1662     FIXME("(%p): semi-stub\n", This);
1663     switch(V_VT(&var1))
1664     {
1665     case VT_UNKNOWN:
1666         hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1667         break;
1668
1669     case VT_DISPATCH:
1670         hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1671         break;
1672
1673     case VT_NULL:
1674     case VT_EMPTY:
1675         hr = S_OK;
1676         break;
1677
1678     default:
1679         WARN("Can't get schema from vt %x\n", V_VT(&var1));
1680     }
1681
1682     if(SUCCEEDED(hr))
1683     {
1684         IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
1685         if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
1686     }
1687
1688     return hr;
1689 }
1690
1691 static HRESULT WINAPI domdoc_validate(
1692     IXMLDOMDocument2* iface,
1693     IXMLDOMParseError** err)
1694 {
1695     FIXME("\n");
1696     return E_NOTIMPL;
1697 }
1698
1699 static HRESULT WINAPI domdoc_setProperty(
1700     IXMLDOMDocument2* iface,
1701     BSTR p,
1702     VARIANT var)
1703 {
1704     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1705
1706     if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
1707     {
1708         VARIANT varStr;
1709         HRESULT hr;
1710         BSTR bstr;
1711
1712         V_VT(&varStr) = VT_EMPTY;
1713         if (V_VT(&var) != VT_BSTR)
1714         {
1715             if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
1716                 return hr;
1717             bstr = V_BSTR(&varStr);
1718         }
1719         else
1720             bstr = V_BSTR(&var);
1721
1722         hr = S_OK;
1723         if (lstrcmpiW(bstr, SZ_VALUE_XPATH) == 0)
1724             This->bUseXPath = TRUE;
1725         else if (lstrcmpiW(bstr, SZ_VALUE_XSLPATTERN) == 0)
1726             This->bUseXPath = FALSE;
1727         else
1728             hr = E_FAIL;
1729
1730         VariantClear(&varStr);
1731         return hr;
1732     }
1733
1734     FIXME("Unknown property %s\n", wine_dbgstr_w(p));
1735     return E_FAIL;
1736 }
1737
1738 static HRESULT WINAPI domdoc_getProperty(
1739     IXMLDOMDocument2* iface,
1740     BSTR p,
1741     VARIANT* var)
1742 {
1743     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1744
1745     if (var == NULL)
1746         return E_INVALIDARG;
1747     if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
1748     {
1749         V_VT(var) = VT_BSTR;
1750         if (This->bUseXPath)
1751             V_BSTR(var) = SysAllocString(SZ_VALUE_XPATH);
1752         else
1753             V_BSTR(var) = SysAllocString(SZ_VALUE_XSLPATTERN);
1754         return S_OK;
1755     }
1756
1757     FIXME("Unknown property %s\n", wine_dbgstr_w(p));
1758     return E_FAIL;
1759 }
1760
1761 static const struct IXMLDOMDocument2Vtbl domdoc_vtbl =
1762 {
1763     domdoc_QueryInterface,
1764     domdoc_AddRef,
1765     domdoc_Release,
1766     domdoc_GetTypeInfoCount,
1767     domdoc_GetTypeInfo,
1768     domdoc_GetIDsOfNames,
1769     domdoc_Invoke,
1770     domdoc_get_nodeName,
1771     domdoc_get_nodeValue,
1772     domdoc_put_nodeValue,
1773     domdoc_get_nodeType,
1774     domdoc_get_parentNode,
1775     domdoc_get_childNodes,
1776     domdoc_get_firstChild,
1777     domdoc_get_lastChild,
1778     domdoc_get_previousSibling,
1779     domdoc_get_nextSibling,
1780     domdoc_get_attributes,
1781     domdoc_insertBefore,
1782     domdoc_replaceChild,
1783     domdoc_removeChild,
1784     domdoc_appendChild,
1785     domdoc_hasChildNodes,
1786     domdoc_get_ownerDocument,
1787     domdoc_cloneNode,
1788     domdoc_get_nodeTypeString,
1789     domdoc_get_text,
1790     domdoc_put_text,
1791     domdoc_get_specified,
1792     domdoc_get_definition,
1793     domdoc_get_nodeTypedValue,
1794     domdoc_put_nodeTypedValue,
1795     domdoc_get_dataType,
1796     domdoc_put_dataType,
1797     domdoc_get_xml,
1798     domdoc_transformNode,
1799     domdoc_selectNodes,
1800     domdoc_selectSingleNode,
1801     domdoc_get_parsed,
1802     domdoc_get_namespaceURI,
1803     domdoc_get_prefix,
1804     domdoc_get_baseName,
1805     domdoc_transformNodeToObject,
1806     domdoc_get_doctype,
1807     domdoc_get_implementation,
1808     domdoc_get_documentElement,
1809     domdoc_put_documentElement,
1810     domdoc_createElement,
1811     domdoc_createDocumentFragment,
1812     domdoc_createTextNode,
1813     domdoc_createComment,
1814     domdoc_createCDATASection,
1815     domdoc_createProcessingInstruction,
1816     domdoc_createAttribute,
1817     domdoc_createEntityReference,
1818     domdoc_getElementsByTagName,
1819     domdoc_createNode,
1820     domdoc_nodeFromID,
1821     domdoc_load,
1822     domdoc_get_readyState,
1823     domdoc_get_parseError,
1824     domdoc_get_url,
1825     domdoc_get_async,
1826     domdoc_put_async,
1827     domdoc_abort,
1828     domdoc_loadXML,
1829     domdoc_save,
1830     domdoc_get_validateOnParse,
1831     domdoc_put_validateOnParse,
1832     domdoc_get_resolveExternals,
1833     domdoc_put_resolveExternals,
1834     domdoc_get_preserveWhiteSpace,
1835     domdoc_put_preserveWhiteSpace,
1836     domdoc_put_onReadyStateChange,
1837     domdoc_put_onDataAvailable,
1838     domdoc_put_onTransformNode,
1839     domdoc_get_namespaces,
1840     domdoc_get_schemas,
1841     domdoc_putref_schemas,
1842     domdoc_validate,
1843     domdoc_setProperty,
1844     domdoc_getProperty
1845 };
1846
1847 /* xmldoc implementation of IObjectWithSite */
1848 static HRESULT WINAPI
1849 xmldoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
1850 {
1851     domdoc *This = impl_from_IObjectWithSite(iface);
1852     return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppvObject );
1853 }
1854
1855 static ULONG WINAPI
1856 xmldoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
1857 {
1858     domdoc *This = impl_from_IObjectWithSite(iface);
1859     return IXMLDocument_AddRef((IXMLDocument *)This);
1860 }
1861
1862 static ULONG WINAPI
1863 xmldoc_ObjectWithSite_Release( IObjectWithSite* iface )
1864 {
1865     domdoc *This = impl_from_IObjectWithSite(iface);
1866     return IXMLDocument_Release((IXMLDocument *)This);
1867 }
1868
1869 static HRESULT WINAPI
1870 xmldoc_GetSite( IObjectWithSite *iface, REFIID iid, void ** ppvSite )
1871 {
1872     domdoc *This = impl_from_IObjectWithSite(iface);
1873
1874     TRACE("%p %s %p\n", This, debugstr_guid( iid ), ppvSite );
1875
1876     if ( !This->site )
1877         return E_FAIL;
1878
1879     return IUnknown_QueryInterface( This->site, iid, ppvSite );
1880 }
1881
1882 static HRESULT WINAPI
1883 xmldoc_SetSite( IObjectWithSite *iface, IUnknown *punk )
1884 {
1885     domdoc *This = impl_from_IObjectWithSite(iface);
1886
1887     TRACE("%p %p\n", iface, punk);
1888
1889     if(!punk)
1890     {
1891         if(This->site)
1892         {
1893             IUnknown_Release( This->site );
1894             This->site = NULL;
1895         }
1896
1897         return S_OK;
1898     }
1899
1900     if ( punk )
1901         IUnknown_AddRef( punk );
1902
1903     if(This->site)
1904         IUnknown_Release( This->site );
1905
1906     This->site = punk;
1907
1908     return S_OK;
1909 }
1910
1911 static const IObjectWithSiteVtbl domdocObjectSite =
1912 {
1913     xmldoc_ObjectWithSite_QueryInterface,
1914     xmldoc_ObjectWithSite_AddRef,
1915     xmldoc_ObjectWithSite_Release,
1916     xmldoc_SetSite,
1917     xmldoc_GetSite,
1918 };
1919
1920 static HRESULT WINAPI xmldoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
1921 {
1922     domdoc *This = impl_from_IObjectSafety(iface);
1923     return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppv );
1924 }
1925
1926 static ULONG WINAPI xmldoc_Safety_AddRef(IObjectSafety *iface)
1927 {
1928     domdoc *This = impl_from_IObjectSafety(iface);
1929     return IXMLDocument_AddRef((IXMLDocument *)This);
1930 }
1931
1932 static ULONG WINAPI xmldoc_Safety_Release(IObjectSafety *iface)
1933 {
1934     domdoc *This = impl_from_IObjectSafety(iface);
1935     return IXMLDocument_Release((IXMLDocument *)This);
1936 }
1937
1938 #define SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
1939
1940 static HRESULT WINAPI xmldoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
1941         DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
1942 {
1943     domdoc *This = impl_from_IObjectSafety(iface);
1944
1945     TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
1946
1947     if(!pdwSupportedOptions || !pdwEnabledOptions)
1948         return E_POINTER;
1949
1950     *pdwSupportedOptions = SUPPORTED_OPTIONS;
1951     *pdwEnabledOptions = This->safeopt;
1952
1953     return S_OK;
1954 }
1955
1956 static HRESULT WINAPI xmldoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
1957         DWORD dwOptionSetMask, DWORD dwEnabledOptions)
1958 {
1959     domdoc *This = impl_from_IObjectSafety(iface);
1960
1961     TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
1962
1963     if(dwOptionSetMask & ~SUPPORTED_OPTIONS)
1964         return E_FAIL;
1965
1966     This->safeopt = dwEnabledOptions & dwEnabledOptions;
1967     return S_OK;
1968 }
1969
1970 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
1971     xmldoc_Safety_QueryInterface,
1972     xmldoc_Safety_AddRef,
1973     xmldoc_Safety_Release,
1974     xmldoc_Safety_GetInterfaceSafetyOptions,
1975     xmldoc_Safety_SetInterfaceSafetyOptions
1976 };
1977
1978
1979 static const tid_t domdoc_iface_tids[] = {
1980     IXMLDOMNode_tid,
1981     IXMLDOMDocument_tid,
1982     IXMLDOMDocument2_tid,
1983     0
1984 };
1985 static dispex_static_data_t domdoc_dispex = {
1986     NULL,
1987     IXMLDOMDocument2_tid,
1988     NULL,
1989     domdoc_iface_tids
1990 };
1991
1992 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument2 **document)
1993 {
1994     domdoc *doc;
1995     HRESULT hr;
1996
1997     doc = HeapAlloc( GetProcessHeap(), 0, sizeof (*doc) );
1998     if( !doc )
1999         return E_OUTOFMEMORY;
2000
2001     doc->lpVtbl = &domdoc_vtbl;
2002     doc->lpvtblIPersistStream = &xmldoc_IPersistStream_VTable;
2003     doc->lpvtblIObjectWithSite = &domdocObjectSite;
2004     doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
2005     doc->ref = 1;
2006     doc->async = 0;
2007     doc->validating = 0;
2008     doc->resolving = 0;
2009     doc->preserving = 0;
2010     doc->bUseXPath = FALSE;
2011     doc->error = S_OK;
2012     doc->schema = NULL;
2013     doc->stream = NULL;
2014     doc->site = NULL;
2015     doc->safeopt = 0;
2016     doc->bsc = NULL;
2017
2018     doc->node_unk = create_basic_node( (xmlNodePtr)xmldoc, (IUnknown*)&doc->lpVtbl );
2019     if(!doc->node_unk)
2020     {
2021         HeapFree(GetProcessHeap(), 0, doc);
2022         return E_FAIL;
2023     }
2024
2025     hr = IUnknown_QueryInterface(doc->node_unk, &IID_IXMLDOMNode, (LPVOID*)&doc->node);
2026     if(FAILED(hr))
2027     {
2028         IUnknown_Release(doc->node_unk);
2029         HeapFree( GetProcessHeap(), 0, doc );
2030         return E_FAIL;
2031     }
2032
2033     init_dispex(&doc->dispex, (IUnknown*)&doc->lpVtbl, &domdoc_dispex);
2034
2035     /* The ref on doc->node is actually looped back into this object, so release it */
2036     IXMLDOMNode_Release(doc->node);
2037
2038     *document = (IXMLDOMDocument2*)&doc->lpVtbl;
2039
2040     TRACE("returning iface %p\n", *document);
2041     return S_OK;
2042 }
2043
2044 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2045 {
2046     xmlDocPtr xmldoc;
2047     HRESULT hr;
2048
2049     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
2050
2051     xmldoc = xmlNewDoc(NULL);
2052     if(!xmldoc)
2053         return E_OUTOFMEMORY;
2054
2055     xmldoc->_private = 0;
2056
2057     hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument2**)ppObj);
2058     if(FAILED(hr))
2059         xmlFreeDoc(xmldoc);
2060
2061     return hr;
2062 }
2063
2064 IUnknown* create_domdoc( xmlNodePtr document )
2065 {
2066     HRESULT hr;
2067     LPVOID pObj = NULL;
2068
2069     TRACE("(%p)\n", document);
2070
2071     hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument2**)&pObj);
2072     if (FAILED(hr))
2073         return NULL;
2074
2075     return (IUnknown*)pObj;
2076 }
2077
2078 #else
2079
2080 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2081 {
2082     MESSAGE("This program tried to use a DOMDocument object, but\n"
2083             "libxml2 support was not present at compile time.\n");
2084     return E_NOTIMPL;
2085 }
2086
2087 #endif