msi: Add tests for MsiEnumClients.
[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     FIXME("\n");
913     return E_NOTIMPL;
914 }
915
916
917 static HRESULT WINAPI domdoc_createCDATASection(
918     IXMLDOMDocument2 *iface,
919     BSTR data,
920     IXMLDOMCDATASection** cdata )
921 {
922     FIXME("\n");
923     return E_NOTIMPL;
924 }
925
926
927 static HRESULT WINAPI domdoc_createProcessingInstruction(
928     IXMLDOMDocument2 *iface,
929     BSTR target,
930     BSTR data,
931     IXMLDOMProcessingInstruction** pi )
932 {
933 #ifdef HAVE_XMLNEWDOCPI
934     xmlNodePtr xmlnode;
935     domdoc *This = impl_from_IXMLDOMDocument2( iface );
936     xmlChar *xml_target, *xml_content;
937
938     TRACE("%p->(%s %s %p)\n", iface, debugstr_w(target), debugstr_w(data), pi);
939
940     xml_target = xmlChar_from_wchar((WCHAR*)target);
941     xml_content = xmlChar_from_wchar((WCHAR*)data);
942
943     xmlnode = xmlNewDocPI(get_doc(This), xml_target, xml_content);
944     TRACE("created xmlptr %p\n", xmlnode);
945     *pi = (IXMLDOMProcessingInstruction*)create_pi(xmlnode);
946
947     HeapFree(GetProcessHeap(), 0, xml_content);
948     HeapFree(GetProcessHeap(), 0, xml_target);
949
950     return S_OK;
951 #else
952     FIXME("Libxml 2.6.15 or greater required.\n");
953     return E_NOTIMPL;
954 #endif
955 }
956
957
958 static HRESULT WINAPI domdoc_createAttribute(
959     IXMLDOMDocument2 *iface,
960     BSTR name,
961     IXMLDOMAttribute** attribute )
962 {
963     FIXME("\n");
964     return E_NOTIMPL;
965 }
966
967
968 static HRESULT WINAPI domdoc_createEntityReference(
969     IXMLDOMDocument2 *iface,
970     BSTR name,
971     IXMLDOMEntityReference** entityRef )
972 {
973     FIXME("\n");
974     return E_NOTIMPL;
975 }
976
977
978 static HRESULT WINAPI domdoc_getElementsByTagName(
979     IXMLDOMDocument2 *iface,
980     BSTR tagName,
981     IXMLDOMNodeList** resultList )
982 {
983     domdoc *This = impl_from_IXMLDOMDocument2( iface );
984     LPWSTR szPattern;
985     HRESULT hr;
986     TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
987
988     szPattern = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(2+lstrlenW(tagName)+1));
989     szPattern[0] = szPattern[1] = '/';
990     lstrcpyW(szPattern + 2, tagName);
991
992     hr = queryresult_create((xmlNodePtr)get_doc(This), szPattern, resultList);
993     HeapFree(GetProcessHeap(), 0, szPattern);
994
995     return hr;
996 }
997
998 static DOMNodeType get_node_type(VARIANT Type)
999 {
1000     if(V_VT(&Type) == VT_I4)
1001         return V_I4(&Type);
1002
1003     FIXME("Unsupported variant type %x\n", V_VT(&Type));
1004     return 0;
1005 }
1006
1007 static HRESULT WINAPI domdoc_createNode(
1008     IXMLDOMDocument2 *iface,
1009     VARIANT Type,
1010     BSTR name,
1011     BSTR namespaceURI,
1012     IXMLDOMNode** node )
1013 {
1014     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1015     DOMNodeType node_type;
1016     xmlNodePtr xmlnode = NULL;
1017     xmlChar *xml_name;
1018
1019     TRACE("(%p)->(type,%s,%s,%p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1020
1021     node_type = get_node_type(Type);
1022     TRACE("node_type %d\n", node_type);
1023
1024     xml_name = xmlChar_from_wchar((WCHAR*)name);
1025
1026     switch(node_type)
1027     {
1028     case NODE_ELEMENT:
1029         xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
1030         *node = create_node(xmlnode);
1031         TRACE("created %p\n", xmlnode);
1032         break;
1033
1034     default:
1035         FIXME("unhandled node type %d\n", node_type);
1036         break;
1037     }
1038
1039     HeapFree(GetProcessHeap(), 0, xml_name);
1040
1041     if(xmlnode && *node)
1042         return S_OK;
1043
1044     return E_FAIL;
1045 }
1046
1047 static HRESULT WINAPI domdoc_nodeFromID(
1048     IXMLDOMDocument2 *iface,
1049     BSTR idString,
1050     IXMLDOMNode** node )
1051 {
1052     FIXME("\n");
1053     return E_NOTIMPL;
1054 }
1055
1056 static xmlDocPtr doparse( char *ptr, int len )
1057 {
1058 #ifdef HAVE_XMLREADMEMORY
1059     /*
1060      * use xmlReadMemory if possible so we can suppress
1061      * writing errors to stderr
1062      */
1063     return xmlReadMemory( ptr, len, NULL, NULL,
1064                           XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS );
1065 #else
1066     return xmlParseMemory( ptr, len );
1067 #endif
1068 }
1069
1070 static xmlDocPtr doread( LPWSTR filename )
1071 {
1072     xmlDocPtr xmldoc = NULL;
1073     HRESULT hr;
1074     IBindCtx *pbc;
1075     IStream *stream, *memstream;
1076     WCHAR url[INTERNET_MAX_URL_LENGTH];
1077     BYTE buf[4096];
1078     DWORD read, written;
1079
1080     TRACE("%s\n", debugstr_w( filename ));
1081
1082     if(!PathIsURLW(filename))
1083     {
1084         WCHAR fullpath[MAX_PATH];
1085         DWORD needed = sizeof(url)/sizeof(WCHAR);
1086
1087         if(!PathSearchAndQualifyW(filename, fullpath, sizeof(fullpath)/sizeof(WCHAR)))
1088         {
1089             WARN("can't find path\n");
1090             return NULL;
1091         }
1092
1093         if(FAILED(UrlCreateFromPathW(fullpath, url, &needed, 0)))
1094         {
1095             ERR("can't create url from path\n");
1096             return NULL;
1097         }
1098         filename = url;
1099     }
1100
1101     hr = CreateBindCtx(0, &pbc);
1102     if(SUCCEEDED(hr))
1103     {
1104         hr = RegisterBindStatusCallback(pbc, (IBindStatusCallback*)&domdoc_bsc.lpVtbl, NULL, 0);
1105         if(SUCCEEDED(hr))
1106         {
1107             IMoniker *moniker;
1108             hr = CreateURLMoniker(NULL, filename, &moniker);
1109             if(SUCCEEDED(hr))
1110             {
1111                 hr = IMoniker_BindToStorage(moniker, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
1112                 IMoniker_Release(moniker);
1113             }
1114         }
1115         IBindCtx_Release(pbc);
1116     }
1117     if(FAILED(hr))
1118         return NULL;
1119
1120     hr = CreateStreamOnHGlobal(NULL, TRUE, &memstream);
1121     if(FAILED(hr))
1122     {
1123         IStream_Release(stream);
1124         return NULL;
1125     }
1126
1127     do
1128     {
1129         IStream_Read(stream, buf, sizeof(buf), &read);
1130         hr = IStream_Write(memstream, buf, read, &written);
1131     } while(SUCCEEDED(hr) && written != 0 && read != 0);
1132
1133     if(SUCCEEDED(hr))
1134     {
1135         HGLOBAL hglobal;
1136         hr = GetHGlobalFromStream(memstream, &hglobal);
1137         if(SUCCEEDED(hr))
1138         {
1139             DWORD len = GlobalSize(hglobal);
1140             char *ptr = GlobalLock(hglobal);
1141             if(len != 0)
1142                 xmldoc = doparse( ptr, len );
1143             GlobalUnlock(hglobal);
1144         }
1145     }
1146     IStream_Release(memstream);
1147     IStream_Release(stream);
1148     return xmldoc;
1149 }
1150
1151 static HRESULT WINAPI domdoc_load(
1152     IXMLDOMDocument2 *iface,
1153     VARIANT xmlSource,
1154     VARIANT_BOOL* isSuccessful )
1155 {
1156     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1157     LPWSTR filename = NULL;
1158     xmlDocPtr xmldoc = NULL;
1159     HRESULT hr = S_FALSE;
1160     IXMLDOMDocument2 *pNewDoc = NULL;
1161     IStream *pStream = NULL;
1162
1163     TRACE("type %d\n", V_VT(&xmlSource) );
1164
1165     *isSuccessful = VARIANT_FALSE;
1166
1167     assert( This->node );
1168
1169     attach_xmlnode(This->node, NULL);
1170
1171     switch( V_VT(&xmlSource) )
1172     {
1173     case VT_BSTR:
1174         filename = V_BSTR(&xmlSource);
1175         break;
1176     case VT_UNKNOWN:
1177         hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument2, (void**)&pNewDoc);
1178         if(hr == S_OK)
1179         {
1180             if(pNewDoc)
1181             {
1182                 domdoc *newDoc = impl_from_IXMLDOMDocument2( pNewDoc );
1183                 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1184                 attach_xmlnode(This->node, (xmlNodePtr) xmldoc);
1185
1186                 *isSuccessful = VARIANT_TRUE;
1187
1188                 return S_OK;
1189             }
1190         }
1191         hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1192         if(hr == S_OK)
1193         {
1194             IPersistStream *pDocStream;
1195             hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1196             if(hr == S_OK)
1197             {
1198                 hr = xmldoc_IPersistStream_Load(pDocStream, pStream);
1199                 IStream_Release(pStream);
1200                 if(hr == S_OK)
1201                 {
1202                     *isSuccessful = VARIANT_TRUE;
1203
1204                     TRACE("Using ID_IStream to load Document\n");
1205                     return S_OK;
1206                 }
1207                 else
1208                 {
1209                     ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1210                 }
1211             }
1212             else
1213             {
1214                 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1215             }
1216         }
1217         else
1218         {
1219             /* ISequentialStream */
1220             FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1221         }
1222         break;
1223      default:
1224             FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1225      }
1226
1227     TRACE("filename (%s)\n", debugstr_w(filename));
1228
1229     if ( filename )
1230     {
1231         xmldoc = doread( filename );
1232     
1233         if ( !xmldoc )
1234             This->error = E_FAIL;
1235         else
1236         {
1237             hr = This->error = S_OK;
1238             *isSuccessful = VARIANT_TRUE;
1239         }
1240     }
1241
1242     if(!xmldoc)
1243         xmldoc = xmlNewDoc(NULL);
1244
1245     xmldoc->_private = 0;
1246     attach_xmlnode(This->node, (xmlNodePtr) xmldoc);
1247
1248     TRACE("ret (%d)\n", hr);
1249
1250     return hr;
1251 }
1252
1253
1254 static HRESULT WINAPI domdoc_get_readyState(
1255     IXMLDOMDocument2 *iface,
1256     long* value )
1257 {
1258     FIXME("\n");
1259     return E_NOTIMPL;
1260 }
1261
1262
1263 static HRESULT WINAPI domdoc_get_parseError(
1264     IXMLDOMDocument2 *iface,
1265     IXMLDOMParseError** errorObj )
1266 {
1267     BSTR error_string = NULL;
1268     static const WCHAR err[] = {'e','r','r','o','r',0};
1269     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1270
1271     FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
1272
1273     if(This->error)
1274         error_string = SysAllocString(err);
1275
1276     *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
1277     if(!*errorObj) return E_OUTOFMEMORY;
1278     return S_OK;
1279 }
1280
1281
1282 static HRESULT WINAPI domdoc_get_url(
1283     IXMLDOMDocument2 *iface,
1284     BSTR* urlString )
1285 {
1286     FIXME("\n");
1287     return E_NOTIMPL;
1288 }
1289
1290
1291 static HRESULT WINAPI domdoc_get_async(
1292     IXMLDOMDocument2 *iface,
1293     VARIANT_BOOL* isAsync )
1294 {
1295     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1296
1297     TRACE("%p <- %d\n", isAsync, This->async);
1298     *isAsync = This->async;
1299     return S_OK;
1300 }
1301
1302
1303 static HRESULT WINAPI domdoc_put_async(
1304     IXMLDOMDocument2 *iface,
1305     VARIANT_BOOL isAsync )
1306 {
1307     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1308
1309     TRACE("%d\n", isAsync);
1310     This->async = isAsync;
1311     return S_OK;
1312 }
1313
1314
1315 static HRESULT WINAPI domdoc_abort(
1316     IXMLDOMDocument2 *iface )
1317 {
1318     FIXME("\n");
1319     return E_NOTIMPL;
1320 }
1321
1322
1323 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
1324 {
1325     UINT len, blen = SysStringLen( bstr );
1326     LPSTR str;
1327
1328     len = WideCharToMultiByte( CP_UTF8, 0, bstr, blen, NULL, 0, NULL, NULL );
1329     str = HeapAlloc( GetProcessHeap(), 0, len );
1330     if ( !str )
1331         return FALSE;
1332     WideCharToMultiByte( CP_UTF8, 0, bstr, blen, str, len, NULL, NULL );
1333     *plen = len;
1334     *pstr = str;
1335     return TRUE;
1336 }
1337
1338 static HRESULT WINAPI domdoc_loadXML(
1339     IXMLDOMDocument2 *iface,
1340     BSTR bstrXML,
1341     VARIANT_BOOL* isSuccessful )
1342 {
1343     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1344     xmlDocPtr xmldoc = NULL;
1345     char *str;
1346     int len;
1347     HRESULT hr = S_FALSE;
1348
1349     TRACE("%p %s %p\n", This, debugstr_w( bstrXML ), isSuccessful );
1350
1351     assert ( This->node );
1352
1353     attach_xmlnode( This->node, NULL );
1354
1355     if ( isSuccessful )
1356     {
1357         *isSuccessful = VARIANT_FALSE;
1358
1359         if ( bstrXML  && bstr_to_utf8( bstrXML, &str, &len ) )
1360         {
1361             xmldoc = doparse( str, len );
1362             HeapFree( GetProcessHeap(), 0, str );
1363             if ( !xmldoc )
1364                 This->error = E_FAIL;
1365             else
1366             {
1367                 hr = This->error = S_OK;
1368                 *isSuccessful = VARIANT_TRUE;
1369             }
1370         }
1371     }
1372     if(!xmldoc)
1373         xmldoc = xmlNewDoc(NULL);
1374
1375     xmldoc->_private = 0;
1376     attach_xmlnode( This->node, (xmlNodePtr) xmldoc );
1377
1378     return hr;
1379 }
1380
1381
1382 static HRESULT WINAPI domdoc_save(
1383     IXMLDOMDocument2 *iface,
1384     VARIANT destination )
1385 {
1386     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1387     HANDLE handle;
1388     xmlChar *mem;
1389     int size;
1390     HRESULT ret = S_OK;
1391     DWORD written;
1392
1393     TRACE("(%p)->(var(vt %x, %s))\n", This, V_VT(&destination),
1394           V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
1395
1396     if(V_VT(&destination) != VT_BSTR)
1397     {
1398         FIXME("Unhandled vt %x\n", V_VT(&destination));
1399         return S_FALSE;
1400     }
1401
1402     handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
1403                           NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1404     if( handle == INVALID_HANDLE_VALUE )
1405     {
1406         WARN("failed to create file\n");
1407         return S_FALSE;
1408     }
1409
1410     xmlDocDumpMemory(get_doc(This), &mem, &size);
1411     if(!WriteFile(handle, mem, (DWORD)size, &written, NULL) || written != (DWORD)size)
1412     {
1413         WARN("write error\n");
1414         ret = S_FALSE;
1415     }
1416
1417     xmlFree(mem);
1418     CloseHandle(handle);
1419     return ret;
1420 }
1421
1422 static HRESULT WINAPI domdoc_get_validateOnParse(
1423     IXMLDOMDocument2 *iface,
1424     VARIANT_BOOL* isValidating )
1425 {
1426     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1427
1428     TRACE("%p <- %d\n", isValidating, This->validating);
1429     *isValidating = This->validating;
1430     return S_OK;
1431 }
1432
1433
1434 static HRESULT WINAPI domdoc_put_validateOnParse(
1435     IXMLDOMDocument2 *iface,
1436     VARIANT_BOOL isValidating )
1437 {
1438     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1439
1440     TRACE("%d\n", isValidating);
1441     This->validating = isValidating;
1442     return S_OK;
1443 }
1444
1445
1446 static HRESULT WINAPI domdoc_get_resolveExternals(
1447     IXMLDOMDocument2 *iface,
1448     VARIANT_BOOL* isResolving )
1449 {
1450     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1451
1452     TRACE("%p <- %d\n", isResolving, This->resolving);
1453     *isResolving = This->resolving;
1454     return S_OK;
1455 }
1456
1457
1458 static HRESULT WINAPI domdoc_put_resolveExternals(
1459     IXMLDOMDocument2 *iface,
1460     VARIANT_BOOL isResolving )
1461 {
1462     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1463
1464     TRACE("%d\n", isResolving);
1465     This->resolving = isResolving;
1466     return S_OK;
1467 }
1468
1469
1470 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
1471     IXMLDOMDocument2 *iface,
1472     VARIANT_BOOL* isPreserving )
1473 {
1474     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1475
1476     TRACE("%p <- %d\n", isPreserving, This->preserving);
1477     *isPreserving = This->preserving;
1478     return S_OK;
1479 }
1480
1481
1482 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
1483     IXMLDOMDocument2 *iface,
1484     VARIANT_BOOL isPreserving )
1485 {
1486     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1487
1488     TRACE("%d\n", isPreserving);
1489     This->preserving = isPreserving;
1490     return S_OK;
1491 }
1492
1493
1494 static HRESULT WINAPI domdoc_put_onReadyStateChange(
1495     IXMLDOMDocument2 *iface,
1496     VARIANT readyStateChangeSink )
1497 {
1498     FIXME("\n");
1499     return E_NOTIMPL;
1500 }
1501
1502
1503 static HRESULT WINAPI domdoc_put_onDataAvailable(
1504     IXMLDOMDocument2 *iface,
1505     VARIANT onDataAvailableSink )
1506 {
1507     FIXME("\n");
1508     return E_NOTIMPL;
1509 }
1510
1511 static HRESULT WINAPI domdoc_put_onTransformNode(
1512     IXMLDOMDocument2 *iface,
1513     VARIANT onTransformNodeSink )
1514 {
1515     FIXME("\n");
1516     return E_NOTIMPL;
1517 }
1518
1519 static HRESULT WINAPI domdoc_get_namespaces(
1520     IXMLDOMDocument2* iface,
1521     IXMLDOMSchemaCollection** schemaCollection )
1522 {
1523     FIXME("\n");
1524     return E_NOTIMPL;
1525 }
1526
1527 static HRESULT WINAPI domdoc_get_schemas(
1528     IXMLDOMDocument2* iface,
1529     VARIANT* var1 )
1530 {
1531     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1532     HRESULT hr = S_FALSE;
1533     IXMLDOMSchemaCollection *cur_schema = This->schema;
1534
1535     TRACE("(%p)->(%p)\n", This, var1);
1536
1537     VariantInit(var1); /* Test shows we don't call VariantClear here */
1538     V_VT(var1) = VT_NULL;
1539
1540     if(cur_schema)
1541     {
1542         hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
1543         if(SUCCEEDED(hr))
1544             V_VT(var1) = VT_DISPATCH;
1545     }
1546     return hr;
1547 }
1548
1549 static HRESULT WINAPI domdoc_putref_schemas(
1550     IXMLDOMDocument2* iface,
1551     VARIANT var1)
1552 {
1553     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1554     HRESULT hr = E_FAIL;
1555     IXMLDOMSchemaCollection *new_schema = NULL;
1556
1557     FIXME("(%p): semi-stub\n", This);
1558     switch(V_VT(&var1))
1559     {
1560     case VT_UNKNOWN:
1561         hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1562         break;
1563
1564     case VT_DISPATCH:
1565         hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1566         break;
1567
1568     case VT_NULL:
1569     case VT_EMPTY:
1570         hr = S_OK;
1571         break;
1572
1573     default:
1574         WARN("Can't get schema from vt %x\n", V_VT(&var1));
1575     }
1576
1577     if(SUCCEEDED(hr))
1578     {
1579         IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
1580         if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
1581     }
1582
1583     return hr;
1584 }
1585
1586 static HRESULT WINAPI domdoc_validate(
1587     IXMLDOMDocument2* iface,
1588     IXMLDOMParseError** err)
1589 {
1590     FIXME("\n");
1591     return E_NOTIMPL;
1592 }
1593
1594 static HRESULT WINAPI domdoc_setProperty(
1595     IXMLDOMDocument2* iface,
1596     BSTR p,
1597     VARIANT var)
1598 {
1599     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1600
1601     if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
1602     {
1603         VARIANT varStr;
1604         HRESULT hr;
1605         BSTR bstr;
1606
1607         V_VT(&varStr) = VT_EMPTY;
1608         if (V_VT(&var) != VT_BSTR)
1609         {
1610             if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
1611                 return hr;
1612             bstr = V_BSTR(&varStr);
1613         }
1614         else
1615             bstr = V_BSTR(&var);
1616
1617         hr = S_OK;
1618         if (lstrcmpiW(bstr, SZ_VALUE_XPATH) == 0)
1619             This->bUseXPath = TRUE;
1620         else if (lstrcmpiW(bstr, SZ_VALUE_XSLPATTERN) == 0)
1621             This->bUseXPath = FALSE;
1622         else
1623             hr = E_FAIL;
1624
1625         VariantClear(&varStr);
1626         return hr;
1627     }
1628
1629     FIXME("Unknown property %s\n", wine_dbgstr_w(p));
1630     return E_FAIL;
1631 }
1632
1633 static HRESULT WINAPI domdoc_getProperty(
1634     IXMLDOMDocument2* iface,
1635     BSTR p,
1636     VARIANT* var)
1637 {
1638     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1639
1640     if (var == NULL)
1641         return E_INVALIDARG;
1642     if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
1643     {
1644         V_VT(var) = VT_BSTR;
1645         if (This->bUseXPath)
1646             V_BSTR(var) = SysAllocString(SZ_VALUE_XPATH);
1647         else
1648             V_BSTR(var) = SysAllocString(SZ_VALUE_XSLPATTERN);
1649         return S_OK;
1650     }
1651
1652     FIXME("Unknown property %s\n", wine_dbgstr_w(p));
1653     return E_FAIL;
1654 }
1655
1656 static const struct IXMLDOMDocument2Vtbl domdoc_vtbl =
1657 {
1658     domdoc_QueryInterface,
1659     domdoc_AddRef,
1660     domdoc_Release,
1661     domdoc_GetTypeInfoCount,
1662     domdoc_GetTypeInfo,
1663     domdoc_GetIDsOfNames,
1664     domdoc_Invoke,
1665     domdoc_get_nodeName,
1666     domdoc_get_nodeValue,
1667     domdoc_put_nodeValue,
1668     domdoc_get_nodeType,
1669     domdoc_get_parentNode,
1670     domdoc_get_childNodes,
1671     domdoc_get_firstChild,
1672     domdoc_get_lastChild,
1673     domdoc_get_previousSibling,
1674     domdoc_get_nextSibling,
1675     domdoc_get_attributes,
1676     domdoc_insertBefore,
1677     domdoc_replaceChild,
1678     domdoc_removeChild,
1679     domdoc_appendChild,
1680     domdoc_hasChildNodes,
1681     domdoc_get_ownerDocument,
1682     domdoc_cloneNode,
1683     domdoc_get_nodeTypeString,
1684     domdoc_get_text,
1685     domdoc_put_text,
1686     domdoc_get_specified,
1687     domdoc_get_definition,
1688     domdoc_get_nodeTypedValue,
1689     domdoc_put_nodeTypedValue,
1690     domdoc_get_dataType,
1691     domdoc_put_dataType,
1692     domdoc_get_xml,
1693     domdoc_transformNode,
1694     domdoc_selectNodes,
1695     domdoc_selectSingleNode,
1696     domdoc_get_parsed,
1697     domdoc_get_namespaceURI,
1698     domdoc_get_prefix,
1699     domdoc_get_baseName,
1700     domdoc_transformNodeToObject,
1701     domdoc_get_doctype,
1702     domdoc_get_implementation,
1703     domdoc_get_documentElement,
1704     domdoc_documentElement,
1705     domdoc_createElement,
1706     domdoc_createDocumentFragment,
1707     domdoc_createTextNode,
1708     domdoc_createComment,
1709     domdoc_createCDATASection,
1710     domdoc_createProcessingInstruction,
1711     domdoc_createAttribute,
1712     domdoc_createEntityReference,
1713     domdoc_getElementsByTagName,
1714     domdoc_createNode,
1715     domdoc_nodeFromID,
1716     domdoc_load,
1717     domdoc_get_readyState,
1718     domdoc_get_parseError,
1719     domdoc_get_url,
1720     domdoc_get_async,
1721     domdoc_put_async,
1722     domdoc_abort,
1723     domdoc_loadXML,
1724     domdoc_save,
1725     domdoc_get_validateOnParse,
1726     domdoc_put_validateOnParse,
1727     domdoc_get_resolveExternals,
1728     domdoc_put_resolveExternals,
1729     domdoc_get_preserveWhiteSpace,
1730     domdoc_put_preserveWhiteSpace,
1731     domdoc_put_onReadyStateChange,
1732     domdoc_put_onDataAvailable,
1733     domdoc_put_onTransformNode,
1734     domdoc_get_namespaces,
1735     domdoc_get_schemas,
1736     domdoc_putref_schemas,
1737     domdoc_validate,
1738     domdoc_setProperty,
1739     domdoc_getProperty
1740 };
1741
1742 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
1743 {
1744     domdoc *doc;
1745     HRESULT hr;
1746     xmlDocPtr xmldoc;
1747
1748     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
1749
1750     doc = HeapAlloc( GetProcessHeap(), 0, sizeof (*doc) );
1751     if( !doc )
1752         return E_OUTOFMEMORY;
1753
1754     doc->lpVtbl = &domdoc_vtbl;
1755     doc->lpvtblIPersistStream = &xmldoc_IPersistStream_VTable;
1756     doc->ref = 1;
1757     doc->async = 0;
1758     doc->validating = 0;
1759     doc->resolving = 0;
1760     doc->preserving = 0;
1761     doc->bUseXPath = FALSE;
1762     doc->error = S_OK;
1763     doc->schema = NULL;
1764     doc->stream = NULL;
1765
1766     xmldoc = xmlNewDoc(NULL);
1767     if(!xmldoc)
1768     {
1769         HeapFree(GetProcessHeap(), 0, doc);
1770         return E_OUTOFMEMORY;
1771     }
1772
1773     xmldoc->_private = 0;
1774
1775     doc->node_unk = create_basic_node( (xmlNodePtr)xmldoc, (IUnknown*)&doc->lpVtbl );
1776     if(!doc->node_unk)
1777     {
1778         xmlFreeDoc(xmldoc);
1779         HeapFree(GetProcessHeap(), 0, doc);
1780         return E_FAIL;
1781     }
1782
1783     hr = IUnknown_QueryInterface(doc->node_unk, &IID_IXMLDOMNode, (LPVOID*)&doc->node);
1784     if(FAILED(hr))
1785     {
1786         IUnknown_Release(doc->node_unk);
1787         HeapFree( GetProcessHeap(), 0, doc );
1788         return E_FAIL;
1789     }
1790     /* The ref on doc->node is actually looped back into this object, so release it */
1791     IXMLDOMNode_Release(doc->node);
1792
1793     *ppObj = &doc->lpVtbl;
1794
1795     TRACE("returning iface %p\n", *ppObj);
1796     return S_OK;
1797 }
1798
1799 #else
1800
1801 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
1802 {
1803     MESSAGE("This program tried to use a DOMDocument object, but\n"
1804             "libxml2 support was not present at compile time.\n");
1805     return E_NOTIMPL;
1806 }
1807
1808 #endif