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