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