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