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