msxml: Allow the element implementation to be aggregatable.
[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 typedef struct {
47     const struct IBindStatusCallbackVtbl *lpVtbl;
48 } bsc;
49
50 static HRESULT WINAPI bsc_QueryInterface(
51     IBindStatusCallback *iface,
52     REFIID riid,
53     LPVOID *ppobj )
54 {
55     if (IsEqualGUID(riid, &IID_IUnknown) ||
56         IsEqualGUID(riid, &IID_IBindStatusCallback))
57     {
58         IBindStatusCallback_AddRef( iface );
59         *ppobj = iface;
60         return S_OK;
61     }
62
63     FIXME("interface %s not implemented\n", debugstr_guid(riid));
64     return E_NOINTERFACE;
65 }
66
67 static ULONG WINAPI bsc_AddRef(
68     IBindStatusCallback *iface )
69 {
70     return 2;
71 }
72
73 static ULONG WINAPI bsc_Release(
74     IBindStatusCallback *iface )
75 {
76     return 1;
77 }
78
79 static HRESULT WINAPI bsc_OnStartBinding(
80         IBindStatusCallback* iface,
81         DWORD dwReserved,
82         IBinding* pib)
83 {
84     return S_OK;
85 }
86
87 static HRESULT WINAPI bsc_GetPriority(
88         IBindStatusCallback* iface,
89         LONG* pnPriority)
90 {
91     return S_OK;
92 }
93
94 static HRESULT WINAPI bsc_OnLowResource(
95         IBindStatusCallback* iface,
96         DWORD reserved)
97 {
98     return S_OK;
99 }
100
101 static HRESULT WINAPI bsc_OnProgress(
102         IBindStatusCallback* iface,
103         ULONG ulProgress,
104         ULONG ulProgressMax,
105         ULONG ulStatusCode,
106         LPCWSTR szStatusText)
107 {
108     return S_OK;
109 }
110
111 static HRESULT WINAPI bsc_OnStopBinding(
112         IBindStatusCallback* iface,
113         HRESULT hresult,
114         LPCWSTR szError)
115 {
116     return S_OK;
117 }
118
119 static HRESULT WINAPI bsc_GetBindInfo(
120         IBindStatusCallback* iface,
121         DWORD* grfBINDF,
122         BINDINFO* pbindinfo)
123 {
124     *grfBINDF = BINDF_RESYNCHRONIZE;
125     
126     return S_OK;
127 }
128
129 static HRESULT WINAPI bsc_OnDataAvailable(
130         IBindStatusCallback* iface,
131         DWORD grfBSCF,
132         DWORD dwSize,
133         FORMATETC* pformatetc,
134         STGMEDIUM* pstgmed)
135 {
136     return S_OK;
137 }
138
139 static HRESULT WINAPI bsc_OnObjectAvailable(
140         IBindStatusCallback* iface,
141         REFIID riid,
142         IUnknown* punk)
143 {
144     return S_OK;
145 }
146
147 const struct IBindStatusCallbackVtbl bsc_vtbl =
148 {
149     bsc_QueryInterface,
150     bsc_AddRef,
151     bsc_Release,
152     bsc_OnStartBinding,
153     bsc_GetPriority,
154     bsc_OnLowResource,
155     bsc_OnProgress,
156     bsc_OnStopBinding,
157     bsc_GetBindInfo,
158     bsc_OnDataAvailable,
159     bsc_OnObjectAvailable
160 };
161
162 static bsc domdoc_bsc = { &bsc_vtbl };
163
164 typedef struct _domdoc
165 {
166     const struct IXMLDOMDocumentVtbl *lpVtbl;
167     LONG ref;
168     VARIANT_BOOL async;
169     IUnknown *node_unk;
170     IXMLDOMNode *node;
171     HRESULT error;
172 } domdoc;
173
174 LONG xmldoc_add_ref(xmlDocPtr doc)
175 {
176     LONG ref = InterlockedIncrement((LONG*)&doc->_private);
177     TRACE("%ld\n", ref);
178     return ref;
179 }
180
181 LONG xmldoc_release(xmlDocPtr doc)
182 {
183     LONG ref = InterlockedDecrement((LONG*)&doc->_private);
184     TRACE("%ld\n", ref);
185     if(ref == 0)
186     {
187         TRACE("freeing docptr %p\n", doc);
188         xmlFreeDoc(doc);
189     }
190
191     return ref;
192 }
193
194 static inline domdoc *impl_from_IXMLDOMDocument( IXMLDOMDocument *iface )
195 {
196     return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
197 }
198
199 static inline xmlDocPtr get_doc( domdoc *This )
200 {
201     return (xmlDocPtr) xmlNodePtr_from_domnode( This->node, XML_DOCUMENT_NODE );
202 }
203
204 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument *iface, REFIID riid, void** ppvObject )
205 {
206     domdoc *This = impl_from_IXMLDOMDocument( iface );
207
208     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
209
210     if ( IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
211          IsEqualGUID( riid, &IID_IUnknown ) )
212     {
213         *ppvObject = iface;
214     }
215     else if ( IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
216               IsEqualGUID( riid, &IID_IDispatch ) )
217     {
218         return IUnknown_QueryInterface(This->node_unk, riid, ppvObject);
219     }
220     else
221     {
222         FIXME("interface %s not implemented\n", debugstr_guid(riid));
223         return E_NOINTERFACE;
224     }
225
226     IXMLDOMDocument_AddRef( iface );
227
228     return S_OK;
229 }
230
231
232 static ULONG WINAPI domdoc_AddRef(
233      IXMLDOMDocument *iface )
234 {
235     domdoc *This = impl_from_IXMLDOMDocument( iface );
236     TRACE("%p\n", This );
237     return InterlockedIncrement( &This->ref );
238 }
239
240
241 static ULONG WINAPI domdoc_Release(
242      IXMLDOMDocument *iface )
243 {
244     domdoc *This = impl_from_IXMLDOMDocument( iface );
245     LONG ref;
246
247     TRACE("%p\n", This );
248
249     ref = InterlockedDecrement( &This->ref );
250     if ( ref == 0 )
251     {
252         IUnknown_Release( This->node_unk );
253         HeapFree( GetProcessHeap(), 0, This );
254     }
255
256     return ref;
257 }
258
259 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument *iface, UINT* pctinfo )
260 {
261     FIXME("\n");
262     return E_NOTIMPL;
263 }
264
265 static HRESULT WINAPI domdoc_GetTypeInfo(
266     IXMLDOMDocument *iface,
267     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
268 {
269     FIXME("\n");
270     return E_NOTIMPL;
271 }
272
273 static HRESULT WINAPI domdoc_GetIDsOfNames(
274     IXMLDOMDocument *iface,
275     REFIID riid,
276     LPOLESTR* rgszNames,
277     UINT cNames,
278     LCID lcid,
279     DISPID* rgDispId)
280 {
281     FIXME("\n");
282     return E_NOTIMPL;
283 }
284
285
286 static HRESULT WINAPI domdoc_Invoke(
287     IXMLDOMDocument *iface,
288     DISPID dispIdMember,
289     REFIID riid,
290     LCID lcid,
291     WORD wFlags,
292     DISPPARAMS* pDispParams,
293     VARIANT* pVarResult,
294     EXCEPINFO* pExcepInfo,
295     UINT* puArgErr)
296 {
297     FIXME("\n");
298     return E_NOTIMPL;
299 }
300
301
302 static HRESULT WINAPI domdoc_get_nodeName(
303     IXMLDOMDocument *iface,
304     BSTR* name )
305 {
306     domdoc *This = impl_from_IXMLDOMDocument( iface );
307     return IXMLDOMNode_get_nodeName( This->node, name );
308 }
309
310
311 static HRESULT WINAPI domdoc_get_nodeValue(
312     IXMLDOMDocument *iface,
313     VARIANT* value )
314 {
315     domdoc *This = impl_from_IXMLDOMDocument( iface );
316     return IXMLDOMNode_get_nodeValue( This->node, value );
317 }
318
319
320 static HRESULT WINAPI domdoc_put_nodeValue(
321     IXMLDOMDocument *iface,
322     VARIANT value)
323 {
324     domdoc *This = impl_from_IXMLDOMDocument( iface );
325     return IXMLDOMNode_put_nodeValue( This->node, value );
326 }
327
328
329 static HRESULT WINAPI domdoc_get_nodeType(
330     IXMLDOMDocument *iface,
331     DOMNodeType* type )
332 {
333     domdoc *This = impl_from_IXMLDOMDocument( iface );
334     return IXMLDOMNode_get_nodeType( This->node, type );
335 }
336
337
338 static HRESULT WINAPI domdoc_get_parentNode(
339     IXMLDOMDocument *iface,
340     IXMLDOMNode** parent )
341 {
342     domdoc *This = impl_from_IXMLDOMDocument( iface );
343     return IXMLDOMNode_get_parentNode( This->node, parent );
344 }
345
346
347 static HRESULT WINAPI domdoc_get_childNodes(
348     IXMLDOMDocument *iface,
349     IXMLDOMNodeList** childList )
350 {
351     domdoc *This = impl_from_IXMLDOMDocument( iface );
352     return IXMLDOMNode_get_childNodes( This->node, childList );
353 }
354
355
356 static HRESULT WINAPI domdoc_get_firstChild(
357     IXMLDOMDocument *iface,
358     IXMLDOMNode** firstChild )
359 {
360     domdoc *This = impl_from_IXMLDOMDocument( iface );
361     return IXMLDOMNode_get_firstChild( This->node, firstChild );
362 }
363
364
365 static HRESULT WINAPI domdoc_get_lastChild(
366     IXMLDOMDocument *iface,
367     IXMLDOMNode** lastChild )
368 {
369     domdoc *This = impl_from_IXMLDOMDocument( iface );
370     return IXMLDOMNode_get_lastChild( This->node, lastChild );
371 }
372
373
374 static HRESULT WINAPI domdoc_get_previousSibling(
375     IXMLDOMDocument *iface,
376     IXMLDOMNode** previousSibling )
377 {
378     domdoc *This = impl_from_IXMLDOMDocument( iface );
379     return IXMLDOMNode_get_previousSibling( This->node, previousSibling );
380 }
381
382
383 static HRESULT WINAPI domdoc_get_nextSibling(
384     IXMLDOMDocument *iface,
385     IXMLDOMNode** nextSibling )
386 {
387     domdoc *This = impl_from_IXMLDOMDocument( iface );
388     return IXMLDOMNode_get_nextSibling( This->node, nextSibling );
389 }
390
391
392 static HRESULT WINAPI domdoc_get_attributes(
393     IXMLDOMDocument *iface,
394     IXMLDOMNamedNodeMap** attributeMap )
395 {
396     domdoc *This = impl_from_IXMLDOMDocument( iface );
397     return IXMLDOMNode_get_attributes( This->node, attributeMap );
398 }
399
400
401 static HRESULT WINAPI domdoc_insertBefore(
402     IXMLDOMDocument *iface,
403     IXMLDOMNode* newChild,
404     VARIANT refChild,
405     IXMLDOMNode** outNewChild )
406 {
407     domdoc *This = impl_from_IXMLDOMDocument( iface );
408     return IXMLDOMNode_insertBefore( This->node, newChild, refChild, outNewChild );
409 }
410
411
412 static HRESULT WINAPI domdoc_replaceChild(
413     IXMLDOMDocument *iface,
414     IXMLDOMNode* newChild,
415     IXMLDOMNode* oldChild,
416     IXMLDOMNode** outOldChild)
417 {
418     domdoc *This = impl_from_IXMLDOMDocument( iface );
419     return IXMLDOMNode_replaceChild( This->node, newChild, oldChild, outOldChild );
420 }
421
422
423 static HRESULT WINAPI domdoc_removeChild(
424     IXMLDOMDocument *iface,
425     IXMLDOMNode* childNode,
426     IXMLDOMNode** oldChild)
427 {
428     domdoc *This = impl_from_IXMLDOMDocument( iface );
429     return IXMLDOMNode_removeChild( This->node, childNode, oldChild );
430 }
431
432
433 static HRESULT WINAPI domdoc_appendChild(
434     IXMLDOMDocument *iface,
435     IXMLDOMNode* newChild,
436     IXMLDOMNode** outNewChild)
437 {
438     domdoc *This = impl_from_IXMLDOMDocument( iface );
439     return IXMLDOMNode_appendChild( This->node, newChild, outNewChild );
440 }
441
442
443 static HRESULT WINAPI domdoc_hasChildNodes(
444     IXMLDOMDocument *iface,
445     VARIANT_BOOL* hasChild)
446 {
447     domdoc *This = impl_from_IXMLDOMDocument( iface );
448     return IXMLDOMNode_hasChildNodes( This->node, hasChild );
449 }
450
451
452 static HRESULT WINAPI domdoc_get_ownerDocument(
453     IXMLDOMDocument *iface,
454     IXMLDOMDocument** DOMDocument)
455 {
456     domdoc *This = impl_from_IXMLDOMDocument( iface );
457     return IXMLDOMNode_get_ownerDocument( This->node, DOMDocument );
458 }
459
460
461 static HRESULT WINAPI domdoc_cloneNode(
462     IXMLDOMDocument *iface,
463     VARIANT_BOOL deep,
464     IXMLDOMNode** cloneRoot)
465 {
466     domdoc *This = impl_from_IXMLDOMDocument( iface );
467     return IXMLDOMNode_cloneNode( This->node, deep, cloneRoot );
468 }
469
470
471 static HRESULT WINAPI domdoc_get_nodeTypeString(
472     IXMLDOMDocument *iface,
473     BSTR* nodeType )
474 {
475     domdoc *This = impl_from_IXMLDOMDocument( iface );
476     return IXMLDOMNode_get_nodeTypeString( This->node, nodeType );
477 }
478
479
480 static HRESULT WINAPI domdoc_get_text(
481     IXMLDOMDocument *iface,
482     BSTR* text )
483 {
484     domdoc *This = impl_from_IXMLDOMDocument( iface );
485     return IXMLDOMNode_get_text( This->node, text );
486 }
487
488
489 static HRESULT WINAPI domdoc_put_text(
490     IXMLDOMDocument *iface,
491     BSTR text )
492 {
493     domdoc *This = impl_from_IXMLDOMDocument( iface );
494     return IXMLDOMNode_put_text( This->node, text );
495 }
496
497
498 static HRESULT WINAPI domdoc_get_specified(
499     IXMLDOMDocument *iface,
500     VARIANT_BOOL* isSpecified )
501 {
502     domdoc *This = impl_from_IXMLDOMDocument( iface );
503     return IXMLDOMNode_get_specified( This->node, isSpecified );
504 }
505
506
507 static HRESULT WINAPI domdoc_get_definition(
508     IXMLDOMDocument *iface,
509     IXMLDOMNode** definitionNode )
510 {
511     domdoc *This = impl_from_IXMLDOMDocument( iface );
512     return IXMLDOMNode_get_definition( This->node, definitionNode );
513 }
514
515
516 static HRESULT WINAPI domdoc_get_nodeTypedValue(
517     IXMLDOMDocument *iface,
518     VARIANT* typedValue )
519 {
520     domdoc *This = impl_from_IXMLDOMDocument( iface );
521     return IXMLDOMNode_get_nodeTypedValue( This->node, typedValue );
522 }
523
524 static HRESULT WINAPI domdoc_put_nodeTypedValue(
525     IXMLDOMDocument *iface,
526     VARIANT typedValue )
527 {
528     domdoc *This = impl_from_IXMLDOMDocument( iface );
529     return IXMLDOMNode_put_nodeTypedValue( This->node, typedValue );
530 }
531
532
533 static HRESULT WINAPI domdoc_get_dataType(
534     IXMLDOMDocument *iface,
535     VARIANT* dataTypeName )
536 {
537     domdoc *This = impl_from_IXMLDOMDocument( iface );
538     return IXMLDOMNode_get_dataType( This->node, dataTypeName );
539 }
540
541
542 static HRESULT WINAPI domdoc_put_dataType(
543     IXMLDOMDocument *iface,
544     BSTR dataTypeName )
545 {
546     domdoc *This = impl_from_IXMLDOMDocument( iface );
547     return IXMLDOMNode_put_dataType( This->node, dataTypeName );
548 }
549
550
551 static HRESULT WINAPI domdoc_get_xml(
552     IXMLDOMDocument *iface,
553     BSTR* xmlString )
554 {
555     domdoc *This = impl_from_IXMLDOMDocument( iface );
556     return IXMLDOMNode_get_xml( This->node, xmlString );
557 }
558
559
560 static HRESULT WINAPI domdoc_transformNode(
561     IXMLDOMDocument *iface,
562     IXMLDOMNode* styleSheet,
563     BSTR* xmlString )
564 {
565     domdoc *This = impl_from_IXMLDOMDocument( iface );
566     return IXMLDOMNode_transformNode( This->node, styleSheet, xmlString );
567 }
568
569
570 static HRESULT WINAPI domdoc_selectNodes(
571     IXMLDOMDocument *iface,
572     BSTR queryString,
573     IXMLDOMNodeList** resultList )
574 {
575     domdoc *This = impl_from_IXMLDOMDocument( iface );
576     return IXMLDOMNode_selectNodes( This->node, queryString, resultList );
577 }
578
579
580 static HRESULT WINAPI domdoc_selectSingleNode(
581     IXMLDOMDocument *iface,
582     BSTR queryString,
583     IXMLDOMNode** resultNode )
584 {
585     domdoc *This = impl_from_IXMLDOMDocument( iface );
586     return IXMLDOMNode_selectSingleNode( This->node, queryString, resultNode );
587 }
588
589
590 static HRESULT WINAPI domdoc_get_parsed(
591     IXMLDOMDocument *iface,
592     VARIANT_BOOL* isParsed )
593 {
594     domdoc *This = impl_from_IXMLDOMDocument( iface );
595     return IXMLDOMNode_get_parsed( This->node, isParsed );
596 }
597
598
599 static HRESULT WINAPI domdoc_get_namespaceURI(
600     IXMLDOMDocument *iface,
601     BSTR* namespaceURI )
602 {
603     domdoc *This = impl_from_IXMLDOMDocument( iface );
604     return IXMLDOMNode_get_namespaceURI( This->node, namespaceURI );
605 }
606
607
608 static HRESULT WINAPI domdoc_get_prefix(
609     IXMLDOMDocument *iface,
610     BSTR* prefixString )
611 {
612     domdoc *This = impl_from_IXMLDOMDocument( iface );
613     return IXMLDOMNode_get_prefix( This->node, prefixString );
614 }
615
616
617 static HRESULT WINAPI domdoc_get_baseName(
618     IXMLDOMDocument *iface,
619     BSTR* nameString )
620 {
621     domdoc *This = impl_from_IXMLDOMDocument( iface );
622     return IXMLDOMNode_get_baseName( This->node, nameString );
623 }
624
625
626 static HRESULT WINAPI domdoc_transformNodeToObject(
627     IXMLDOMDocument *iface,
628     IXMLDOMNode* stylesheet,
629     VARIANT outputObject)
630 {
631     domdoc *This = impl_from_IXMLDOMDocument( iface );
632     return IXMLDOMNode_transformNodeToObject( This->node, stylesheet, outputObject );
633 }
634
635
636 static HRESULT WINAPI domdoc_get_doctype(
637     IXMLDOMDocument *iface,
638     IXMLDOMDocumentType** documentType )
639 {
640     FIXME("\n");
641     return E_NOTIMPL;
642 }
643
644
645 static HRESULT WINAPI domdoc_get_implementation(
646     IXMLDOMDocument *iface,
647     IXMLDOMImplementation** impl )
648 {
649     FIXME("\n");
650     return E_NOTIMPL;
651 }
652
653 static HRESULT WINAPI domdoc_get_documentElement(
654     IXMLDOMDocument *iface,
655     IXMLDOMElement** DOMElement )
656 {
657     domdoc *This = impl_from_IXMLDOMDocument( iface );
658     xmlDocPtr xmldoc = NULL;
659     xmlNodePtr root = NULL;
660     IXMLDOMNode *element_node;
661     HRESULT hr;
662
663     TRACE("%p\n", This);
664
665     *DOMElement = NULL;
666
667     if ( !This->node )
668         return S_FALSE;
669
670     xmldoc = get_doc( This );
671     if ( !xmldoc )
672         return S_FALSE;
673
674     root = xmlDocGetRootElement( xmldoc );
675     if ( !root )
676         return S_FALSE;
677
678     element_node = create_node( root );
679     if(!element_node) return S_FALSE;
680
681     hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (LPVOID*)DOMElement);
682     IXMLDOMNode_Release(element_node);
683
684     return hr;
685 }
686
687
688 static HRESULT WINAPI domdoc_documentElement(
689     IXMLDOMDocument *iface,
690     IXMLDOMElement* DOMElement )
691 {
692     FIXME("\n");
693     return E_NOTIMPL;
694 }
695
696
697 static HRESULT WINAPI domdoc_createElement(
698     IXMLDOMDocument *iface,
699     BSTR tagname,
700     IXMLDOMElement** element )
701 {
702     FIXME("\n");
703     return E_NOTIMPL;
704 }
705
706
707 static HRESULT WINAPI domdoc_createDocumentFragment(
708     IXMLDOMDocument *iface,
709     IXMLDOMDocumentFragment** docFrag )
710 {
711     FIXME("\n");
712     return E_NOTIMPL;
713 }
714
715
716 static HRESULT WINAPI domdoc_createTextNode(
717     IXMLDOMDocument *iface,
718     BSTR data,
719     IXMLDOMText** text )
720 {
721     FIXME("\n");
722     return E_NOTIMPL;
723 }
724
725
726 static HRESULT WINAPI domdoc_createComment(
727     IXMLDOMDocument *iface,
728     BSTR data,
729     IXMLDOMComment** comment )
730 {
731     FIXME("\n");
732     return E_NOTIMPL;
733 }
734
735
736 static HRESULT WINAPI domdoc_createCDATASection(
737     IXMLDOMDocument *iface,
738     BSTR data,
739     IXMLDOMCDATASection** cdata )
740 {
741     FIXME("\n");
742     return E_NOTIMPL;
743 }
744
745
746 static HRESULT WINAPI domdoc_createProcessingInstruction(
747     IXMLDOMDocument *iface,
748     BSTR target,
749     BSTR data,
750     IXMLDOMProcessingInstruction** pi )
751 {
752     FIXME("\n");
753     return E_NOTIMPL;
754 }
755
756
757 static HRESULT WINAPI domdoc_createAttribute(
758     IXMLDOMDocument *iface,
759     BSTR name,
760     IXMLDOMAttribute** attribute )
761 {
762     FIXME("\n");
763     return E_NOTIMPL;
764 }
765
766
767 static HRESULT WINAPI domdoc_createEntityReference(
768     IXMLDOMDocument *iface,
769     BSTR name,
770     IXMLDOMEntityReference** entityRef )
771 {
772     FIXME("\n");
773     return E_NOTIMPL;
774 }
775
776
777 static HRESULT WINAPI domdoc_getElementsByTagName(
778     IXMLDOMDocument *iface,
779     BSTR tagName,
780     IXMLDOMNodeList** resultList )
781 {
782     domdoc *This = impl_from_IXMLDOMDocument( iface );
783     xmlChar *name;
784     TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
785
786     name = xmlChar_from_wchar((WCHAR*)tagName);
787     *resultList = create_filtered_nodelist((xmlNodePtr)get_doc(This), name, TRUE);
788     HeapFree(GetProcessHeap(), 0, name);
789
790     if(!*resultList) return S_FALSE;
791     return S_OK;
792 }
793
794 static DOMNodeType get_node_type(VARIANT Type)
795 {
796     if(V_VT(&Type) == VT_I4)
797         return V_I4(&Type);
798
799     FIXME("Unsupported variant type %x\n", V_VT(&Type));
800     return 0;
801 }
802
803 static HRESULT WINAPI domdoc_createNode(
804     IXMLDOMDocument *iface,
805     VARIANT Type,
806     BSTR name,
807     BSTR namespaceURI,
808     IXMLDOMNode** node )
809 {
810     domdoc *This = impl_from_IXMLDOMDocument( iface );
811     DOMNodeType node_type;
812     xmlNodePtr xmlnode = NULL;
813     xmlChar *xml_name;
814     xmlDocPtr xmldoc;
815
816     TRACE("(%p)->(type,%s,%s,%p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
817
818     node_type = get_node_type(Type);
819     TRACE("node_type %d\n", node_type);
820
821     xml_name = xmlChar_from_wchar((WCHAR*)name);
822
823     if(!get_doc(This))
824     {
825         xmldoc = xmlNewDoc(NULL);
826         xmldoc->_private = 0;
827         attach_xmlnode(This->node, (xmlNodePtr) xmldoc);
828     }
829
830     switch(node_type)
831     {
832     case NODE_ELEMENT:
833         xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
834         *node = create_node(xmlnode);
835         TRACE("created %p\n", xmlnode);
836         break;
837
838     default:
839         FIXME("unhandled node type %d\n", node_type);
840         break;
841     }
842
843     HeapFree(GetProcessHeap(), 0, xml_name);
844
845     if(xmlnode && *node)
846         return S_OK;
847
848     return E_FAIL;
849 }
850
851 static HRESULT WINAPI domdoc_nodeFromID(
852     IXMLDOMDocument *iface,
853     BSTR idString,
854     IXMLDOMNode** node )
855 {
856     FIXME("\n");
857     return E_NOTIMPL;
858 }
859
860 static xmlDocPtr doparse( char *ptr, int len )
861 {
862 #ifdef HAVE_XMLREADMEMORY
863     /*
864      * use xmlReadMemory if possible so we can suppress
865      * writing errors to stderr
866      */
867     return xmlReadMemory( ptr, len, NULL, NULL,
868                           XML_PARSE_NOERROR | XML_PARSE_NOWARNING );
869 #else
870     return xmlParseMemory( ptr, len );
871 #endif
872 }
873
874 static xmlDocPtr doread( LPWSTR filename )
875 {
876     xmlDocPtr xmldoc = NULL;
877     HRESULT hr;
878     IBindCtx *pbc;
879     IStream *stream, *memstream;
880     WCHAR url[INTERNET_MAX_URL_LENGTH];
881     BYTE buf[4096];
882     DWORD read, written;
883
884     TRACE("%s\n", debugstr_w( filename ));
885
886     if(!PathIsURLW(filename))
887     {
888         WCHAR fullpath[MAX_PATH];
889         DWORD needed = sizeof(url)/sizeof(WCHAR);
890
891         if(!PathSearchAndQualifyW(filename, fullpath, sizeof(fullpath)/sizeof(WCHAR)))
892         {
893             WARN("can't find path\n");
894             return NULL;
895         }
896
897         if(FAILED(UrlCreateFromPathW(fullpath, url, &needed, 0)))
898         {
899             ERR("can't create url from path\n");
900             return NULL;
901         }
902         filename = url;
903     }
904
905     hr = CreateBindCtx(0, &pbc);
906     if(SUCCEEDED(hr))
907     {
908         hr = RegisterBindStatusCallback(pbc, (IBindStatusCallback*)&domdoc_bsc.lpVtbl, NULL, 0);
909         if(SUCCEEDED(hr))
910         {
911             IMoniker *moniker;
912             hr = CreateURLMoniker(NULL, filename, &moniker);
913             if(SUCCEEDED(hr))
914             {
915                 hr = IMoniker_BindToStorage(moniker, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
916                 IMoniker_Release(moniker);
917             }
918         }
919         IBindCtx_Release(pbc);
920     }
921     if(FAILED(hr))
922         return NULL;
923
924     hr = CreateStreamOnHGlobal(NULL, TRUE, &memstream);
925     if(FAILED(hr))
926     {
927         IStream_Release(stream);
928         return NULL;
929     }
930
931     do
932     {
933         IStream_Read(stream, buf, sizeof(buf), &read);
934         hr = IStream_Write(memstream, buf, read, &written);
935     } while(SUCCEEDED(hr) && written != 0 && read != 0);
936
937     if(SUCCEEDED(hr))
938     {
939         HGLOBAL hglobal;
940         hr = GetHGlobalFromStream(memstream, &hglobal);
941         if(SUCCEEDED(hr))
942         {
943             DWORD len = GlobalSize(hglobal);
944             char *ptr = GlobalLock(hglobal);
945             if(len != 0)
946                 xmldoc = doparse( ptr, len );
947             GlobalUnlock(hglobal);
948         }
949     }
950     IStream_Release(memstream);
951     IStream_Release(stream);
952     return xmldoc;
953 }
954
955 static HRESULT WINAPI domdoc_load(
956     IXMLDOMDocument *iface,
957     VARIANT xmlSource,
958     VARIANT_BOOL* isSuccessful )
959 {
960     domdoc *This = impl_from_IXMLDOMDocument( iface );
961     LPWSTR filename = NULL;
962     xmlDocPtr xmldoc;
963
964     TRACE("type %d\n", V_VT(&xmlSource) );
965
966     *isSuccessful = VARIANT_FALSE;
967
968     assert( This->node );
969
970     attach_xmlnode(This->node, NULL);
971
972     switch( V_VT(&xmlSource) )
973     {
974     case VT_BSTR:
975         filename = V_BSTR(&xmlSource);
976     }
977
978     if ( !filename )
979         return S_FALSE;
980
981     xmldoc = doread( filename );
982     if ( !xmldoc )
983     {
984         This->error = E_FAIL;
985         return S_FALSE;
986     }
987
988     This->error = S_OK;
989     xmldoc->_private = 0;
990     attach_xmlnode(This->node, (xmlNodePtr) xmldoc);
991
992     *isSuccessful = VARIANT_TRUE;
993     return S_OK;
994 }
995
996
997 static HRESULT WINAPI domdoc_get_readyState(
998     IXMLDOMDocument *iface,
999     long* value )
1000 {
1001     FIXME("\n");
1002     return E_NOTIMPL;
1003 }
1004
1005
1006 static HRESULT WINAPI domdoc_get_parseError(
1007     IXMLDOMDocument *iface,
1008     IXMLDOMParseError** errorObj )
1009 {
1010     BSTR error_string = NULL;
1011     static const WCHAR err[] = {'e','r','r','o','r',0};
1012     domdoc *This = impl_from_IXMLDOMDocument( iface );
1013
1014     FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
1015
1016     if(This->error)
1017         error_string = SysAllocString(err);
1018
1019     *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
1020     if(!*errorObj) return E_OUTOFMEMORY;
1021     return S_OK;
1022 }
1023
1024
1025 static HRESULT WINAPI domdoc_get_url(
1026     IXMLDOMDocument *iface,
1027     BSTR* urlString )
1028 {
1029     FIXME("\n");
1030     return E_NOTIMPL;
1031 }
1032
1033
1034 static HRESULT WINAPI domdoc_get_async(
1035     IXMLDOMDocument *iface,
1036     VARIANT_BOOL* isAsync )
1037 {
1038     domdoc *This = impl_from_IXMLDOMDocument( iface );
1039
1040     TRACE("%p <- %d\n", isAsync, This->async);
1041     *isAsync = This->async;
1042     return S_OK;
1043 }
1044
1045
1046 static HRESULT WINAPI domdoc_put_async(
1047     IXMLDOMDocument *iface,
1048     VARIANT_BOOL isAsync )
1049 {
1050     domdoc *This = impl_from_IXMLDOMDocument( iface );
1051
1052     TRACE("%d\n", isAsync);
1053     This->async = isAsync;
1054     return S_OK;
1055 }
1056
1057
1058 static HRESULT WINAPI domdoc_abort(
1059     IXMLDOMDocument *iface )
1060 {
1061     FIXME("\n");
1062     return E_NOTIMPL;
1063 }
1064
1065
1066 BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
1067 {
1068     UINT len, blen = SysStringLen( bstr );
1069     LPSTR str;
1070
1071     len = WideCharToMultiByte( CP_UTF8, 0, bstr, blen, NULL, 0, NULL, NULL );
1072     str = HeapAlloc( GetProcessHeap(), 0, len );
1073     if ( !str )
1074         return FALSE;
1075     WideCharToMultiByte( CP_UTF8, 0, bstr, blen, str, len, NULL, NULL );
1076     *plen = len;
1077     *pstr = str;
1078     return TRUE;
1079 }
1080
1081 static HRESULT WINAPI domdoc_loadXML(
1082     IXMLDOMDocument *iface,
1083     BSTR bstrXML,
1084     VARIANT_BOOL* isSuccessful )
1085 {
1086     domdoc *This = impl_from_IXMLDOMDocument( iface );
1087     xmlDocPtr xmldoc;
1088     char *str;
1089     int len;
1090
1091     TRACE("%p %s %p\n", This, debugstr_w( bstrXML ), isSuccessful );
1092
1093     assert ( This->node );
1094
1095     attach_xmlnode( This->node, NULL );
1096
1097     if ( !isSuccessful )
1098         return S_FALSE;
1099
1100     *isSuccessful = VARIANT_FALSE;
1101
1102     if ( !bstrXML )
1103         return S_FALSE;
1104
1105     if ( !bstr_to_utf8( bstrXML, &str, &len ) )
1106         return S_FALSE;
1107
1108     xmldoc = doparse( str, len );
1109     HeapFree( GetProcessHeap(), 0, str );
1110     if ( !xmldoc )
1111     {
1112         This->error = E_FAIL;
1113         return S_FALSE;
1114     }
1115
1116     This->error = S_OK;
1117     xmldoc->_private = 0;
1118     attach_xmlnode( This->node, (xmlNodePtr) xmldoc );
1119
1120     *isSuccessful = VARIANT_TRUE;
1121     return S_OK;
1122 }
1123
1124
1125 static HRESULT WINAPI domdoc_save(
1126     IXMLDOMDocument *iface,
1127     VARIANT destination )
1128 {
1129     domdoc *This = impl_from_IXMLDOMDocument( iface );
1130     HANDLE handle;
1131     xmlChar *mem;
1132     int size;
1133     HRESULT ret = S_OK;
1134     DWORD written;
1135
1136     TRACE("(%p)->(var(vt %x, %s))\n", This, V_VT(&destination),
1137           V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
1138
1139     if(V_VT(&destination) != VT_BSTR)
1140     {
1141         FIXME("Unhandled vt %x\n", V_VT(&destination));
1142         return S_FALSE;
1143     }
1144
1145     handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
1146                           NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1147     if( handle == INVALID_HANDLE_VALUE )
1148     {
1149         WARN("failed to create file\n");
1150         return S_FALSE;
1151     }
1152
1153     xmlDocDumpMemory(get_doc(This), &mem, &size);
1154     if(!WriteFile(handle, mem, (DWORD)size, &written, NULL) || written != (DWORD)size)
1155     {
1156         WARN("write error\n");
1157         ret = S_FALSE;
1158     }
1159
1160     xmlFree(mem);
1161     CloseHandle(handle);
1162     return ret;
1163 }
1164
1165 static HRESULT WINAPI domdoc_get_validateOnParse(
1166     IXMLDOMDocument *iface,
1167     VARIANT_BOOL* isValidating )
1168 {
1169     FIXME("\n");
1170     return E_NOTIMPL;
1171 }
1172
1173
1174 static HRESULT WINAPI domdoc_put_validateOnParse(
1175     IXMLDOMDocument *iface,
1176     VARIANT_BOOL isValidating )
1177 {
1178     FIXME("\n");
1179     return E_NOTIMPL;
1180 }
1181
1182
1183 static HRESULT WINAPI domdoc_get_resolveExternals(
1184     IXMLDOMDocument *iface,
1185     VARIANT_BOOL* isResolving )
1186 {
1187     FIXME("\n");
1188     return E_NOTIMPL;
1189 }
1190
1191
1192 static HRESULT WINAPI domdoc_put_resolveExternals(
1193     IXMLDOMDocument *iface,
1194     VARIANT_BOOL isValidating )
1195 {
1196     FIXME("\n");
1197     return E_NOTIMPL;
1198 }
1199
1200
1201 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
1202     IXMLDOMDocument *iface,
1203     VARIANT_BOOL* isPreserving )
1204 {
1205     FIXME("\n");
1206     return E_NOTIMPL;
1207 }
1208
1209
1210 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
1211     IXMLDOMDocument *iface,
1212     VARIANT_BOOL isPreserving )
1213 {
1214     FIXME("\n");
1215     return E_NOTIMPL;
1216 }
1217
1218
1219 static HRESULT WINAPI domdoc_put_onReadyStateChange(
1220     IXMLDOMDocument *iface,
1221     VARIANT readyStateChangeSink )
1222 {
1223     FIXME("\n");
1224     return E_NOTIMPL;
1225 }
1226
1227
1228 static HRESULT WINAPI domdoc_put_onDataAvailable(
1229     IXMLDOMDocument *iface,
1230     VARIANT onDataAvailableSink )
1231 {
1232     FIXME("\n");
1233     return E_NOTIMPL;
1234 }
1235
1236 static HRESULT WINAPI domdoc_put_onTransformNode(
1237     IXMLDOMDocument *iface,
1238     VARIANT onTransformNodeSink )
1239 {
1240     FIXME("\n");
1241     return E_NOTIMPL;
1242 }
1243
1244 const struct IXMLDOMDocumentVtbl domdoc_vtbl =
1245 {
1246     domdoc_QueryInterface,
1247     domdoc_AddRef,
1248     domdoc_Release,
1249     domdoc_GetTypeInfoCount,
1250     domdoc_GetTypeInfo,
1251     domdoc_GetIDsOfNames,
1252     domdoc_Invoke,
1253     domdoc_get_nodeName,
1254     domdoc_get_nodeValue,
1255     domdoc_put_nodeValue,
1256     domdoc_get_nodeType,
1257     domdoc_get_parentNode,
1258     domdoc_get_childNodes,
1259     domdoc_get_firstChild,
1260     domdoc_get_lastChild,
1261     domdoc_get_previousSibling,
1262     domdoc_get_nextSibling,
1263     domdoc_get_attributes,
1264     domdoc_insertBefore,
1265     domdoc_replaceChild,
1266     domdoc_removeChild,
1267     domdoc_appendChild,
1268     domdoc_hasChildNodes,
1269     domdoc_get_ownerDocument,
1270     domdoc_cloneNode,
1271     domdoc_get_nodeTypeString,
1272     domdoc_get_text,
1273     domdoc_put_text,
1274     domdoc_get_specified,
1275     domdoc_get_definition,
1276     domdoc_get_nodeTypedValue,
1277     domdoc_put_nodeTypedValue,
1278     domdoc_get_dataType,
1279     domdoc_put_dataType,
1280     domdoc_get_xml,
1281     domdoc_transformNode,
1282     domdoc_selectNodes,
1283     domdoc_selectSingleNode,
1284     domdoc_get_parsed,
1285     domdoc_get_namespaceURI,
1286     domdoc_get_prefix,
1287     domdoc_get_baseName,
1288     domdoc_transformNodeToObject,
1289     domdoc_get_doctype,
1290     domdoc_get_implementation,
1291     domdoc_get_documentElement,
1292     domdoc_documentElement,
1293     domdoc_createElement,
1294     domdoc_createDocumentFragment,
1295     domdoc_createTextNode,
1296     domdoc_createComment,
1297     domdoc_createCDATASection,
1298     domdoc_createProcessingInstruction,
1299     domdoc_createAttribute,
1300     domdoc_createEntityReference,
1301     domdoc_getElementsByTagName,
1302     domdoc_createNode,
1303     domdoc_nodeFromID,
1304     domdoc_load,
1305     domdoc_get_readyState,
1306     domdoc_get_parseError,
1307     domdoc_get_url,
1308     domdoc_get_async,
1309     domdoc_put_async,
1310     domdoc_abort,
1311     domdoc_loadXML,
1312     domdoc_save,
1313     domdoc_get_validateOnParse,
1314     domdoc_put_validateOnParse,
1315     domdoc_get_resolveExternals,
1316     domdoc_put_resolveExternals,
1317     domdoc_get_preserveWhiteSpace,
1318     domdoc_put_preserveWhiteSpace,
1319     domdoc_put_onReadyStateChange,
1320     domdoc_put_onDataAvailable,
1321     domdoc_put_onTransformNode,
1322 };
1323
1324 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
1325 {
1326     domdoc *doc;
1327     HRESULT hr;
1328
1329     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
1330
1331     doc = HeapAlloc( GetProcessHeap(), 0, sizeof (*doc) );
1332     if( !doc )
1333         return E_OUTOFMEMORY;
1334
1335     doc->lpVtbl = &domdoc_vtbl;
1336     doc->ref = 1;
1337     doc->async = 0;
1338     doc->error = S_OK;
1339
1340     doc->node_unk = create_basic_node( NULL, (IUnknown*)&doc->lpVtbl );
1341     if(!doc->node_unk)
1342     {
1343         HeapFree(GetProcessHeap(), 0, doc);
1344         return E_FAIL;
1345     }
1346
1347     hr = IUnknown_QueryInterface(doc->node_unk, &IID_IXMLDOMNode, (LPVOID*)&doc->node);
1348     if(FAILED(hr))
1349     {
1350         IUnknown_Release(doc->node_unk);
1351         HeapFree( GetProcessHeap(), 0, doc );
1352         return E_FAIL;
1353     }
1354     /* The ref on doc->node is actually looped back into this object, so release it */
1355     IXMLDOMNode_Release(doc->node);
1356
1357     *ppObj = &doc->lpVtbl;
1358
1359     TRACE("returning iface %p\n", *ppObj);
1360     return S_OK;
1361 }
1362
1363 #else
1364
1365 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
1366 {
1367     MESSAGE("This program tried to use a DOMDocument object, but\n"
1368             "libxml2 support was not present at compile time.\n");
1369     return E_NOTIMPL;
1370 }
1371
1372 #endif