dmloader: Declare some functions static.
[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 static 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("%d\n", ref);
178     return ref;
179 }
180
181 LONG xmldoc_release(xmlDocPtr doc)
182 {
183     LONG ref = InterlockedDecrement((LONG*)&doc->_private);
184     TRACE("%d\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     xmldoc = get_doc( This );
668
669     root = xmlDocGetRootElement( xmldoc );
670     if ( !root )
671         return S_FALSE;
672
673     element_node = create_node( root );
674     if(!element_node) return S_FALSE;
675
676     hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (LPVOID*)DOMElement);
677     IXMLDOMNode_Release(element_node);
678
679     return hr;
680 }
681
682
683 static HRESULT WINAPI domdoc_documentElement(
684     IXMLDOMDocument *iface,
685     IXMLDOMElement* DOMElement )
686 {
687     FIXME("\n");
688     return E_NOTIMPL;
689 }
690
691
692 static HRESULT WINAPI domdoc_createElement(
693     IXMLDOMDocument *iface,
694     BSTR tagname,
695     IXMLDOMElement** element )
696 {
697     xmlNodePtr xmlnode;
698     domdoc *This = impl_from_IXMLDOMDocument( iface );
699     xmlChar *xml_name;
700     IUnknown *elem_unk;
701     HRESULT hr;
702
703     TRACE("%p->(%s,%p)\n", iface, debugstr_w(tagname), element);
704
705     xml_name = xmlChar_from_wchar((WCHAR*)tagname);
706     xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
707
708     TRACE("created xmlptr %p\n", xmlnode);
709     elem_unk = create_element(xmlnode, NULL);
710     HeapFree(GetProcessHeap(), 0, xml_name);
711
712     hr = IUnknown_QueryInterface(elem_unk, &IID_IXMLDOMElement, (void **)element);
713     IUnknown_Release(elem_unk);
714     TRACE("returning %p\n", *element);
715     return hr;
716 }
717
718
719 static HRESULT WINAPI domdoc_createDocumentFragment(
720     IXMLDOMDocument *iface,
721     IXMLDOMDocumentFragment** docFrag )
722 {
723     FIXME("\n");
724     return E_NOTIMPL;
725 }
726
727
728 static HRESULT WINAPI domdoc_createTextNode(
729     IXMLDOMDocument *iface,
730     BSTR data,
731     IXMLDOMText** text )
732 {
733     FIXME("\n");
734     return E_NOTIMPL;
735 }
736
737
738 static HRESULT WINAPI domdoc_createComment(
739     IXMLDOMDocument *iface,
740     BSTR data,
741     IXMLDOMComment** comment )
742 {
743     FIXME("\n");
744     return E_NOTIMPL;
745 }
746
747
748 static HRESULT WINAPI domdoc_createCDATASection(
749     IXMLDOMDocument *iface,
750     BSTR data,
751     IXMLDOMCDATASection** cdata )
752 {
753     FIXME("\n");
754     return E_NOTIMPL;
755 }
756
757
758 static HRESULT WINAPI domdoc_createProcessingInstruction(
759     IXMLDOMDocument *iface,
760     BSTR target,
761     BSTR data,
762     IXMLDOMProcessingInstruction** pi )
763 {
764 #ifdef HAVE_XMLNEWDOCPI
765     xmlNodePtr xmlnode;
766     domdoc *This = impl_from_IXMLDOMDocument( iface );
767     xmlChar *xml_target, *xml_content;
768
769     TRACE("%p->(%s %s %p)\n", iface, debugstr_w(target), debugstr_w(data), pi);
770
771     xml_target = xmlChar_from_wchar((WCHAR*)target);
772     xml_content = xmlChar_from_wchar((WCHAR*)data);
773
774     xmlnode = xmlNewDocPI(get_doc(This), xml_target, xml_content);
775     TRACE("created xmlptr %p\n", xmlnode);
776     *pi = (IXMLDOMProcessingInstruction*)create_pi(xmlnode);
777
778     HeapFree(GetProcessHeap(), 0, xml_content);
779     HeapFree(GetProcessHeap(), 0, xml_target);
780
781     return S_OK;
782 #else
783     FIXME("Libxml 2.6.15 or greater required.\n");
784     return E_NOTIMPL;
785 #endif
786 }
787
788
789 static HRESULT WINAPI domdoc_createAttribute(
790     IXMLDOMDocument *iface,
791     BSTR name,
792     IXMLDOMAttribute** attribute )
793 {
794     FIXME("\n");
795     return E_NOTIMPL;
796 }
797
798
799 static HRESULT WINAPI domdoc_createEntityReference(
800     IXMLDOMDocument *iface,
801     BSTR name,
802     IXMLDOMEntityReference** entityRef )
803 {
804     FIXME("\n");
805     return E_NOTIMPL;
806 }
807
808
809 static HRESULT WINAPI domdoc_getElementsByTagName(
810     IXMLDOMDocument *iface,
811     BSTR tagName,
812     IXMLDOMNodeList** resultList )
813 {
814     domdoc *This = impl_from_IXMLDOMDocument( iface );
815     xmlChar *name;
816     TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
817
818     name = xmlChar_from_wchar((WCHAR*)tagName);
819     *resultList = create_filtered_nodelist((xmlNodePtr)get_doc(This), name, TRUE);
820     HeapFree(GetProcessHeap(), 0, name);
821
822     if(!*resultList) return S_FALSE;
823     return S_OK;
824 }
825
826 static DOMNodeType get_node_type(VARIANT Type)
827 {
828     if(V_VT(&Type) == VT_I4)
829         return V_I4(&Type);
830
831     FIXME("Unsupported variant type %x\n", V_VT(&Type));
832     return 0;
833 }
834
835 static HRESULT WINAPI domdoc_createNode(
836     IXMLDOMDocument *iface,
837     VARIANT Type,
838     BSTR name,
839     BSTR namespaceURI,
840     IXMLDOMNode** node )
841 {
842     domdoc *This = impl_from_IXMLDOMDocument( iface );
843     DOMNodeType node_type;
844     xmlNodePtr xmlnode = NULL;
845     xmlChar *xml_name;
846
847     TRACE("(%p)->(type,%s,%s,%p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
848
849     node_type = get_node_type(Type);
850     TRACE("node_type %d\n", node_type);
851
852     xml_name = xmlChar_from_wchar((WCHAR*)name);
853
854     switch(node_type)
855     {
856     case NODE_ELEMENT:
857         xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
858         *node = create_node(xmlnode);
859         TRACE("created %p\n", xmlnode);
860         break;
861
862     default:
863         FIXME("unhandled node type %d\n", node_type);
864         break;
865     }
866
867     HeapFree(GetProcessHeap(), 0, xml_name);
868
869     if(xmlnode && *node)
870         return S_OK;
871
872     return E_FAIL;
873 }
874
875 static HRESULT WINAPI domdoc_nodeFromID(
876     IXMLDOMDocument *iface,
877     BSTR idString,
878     IXMLDOMNode** node )
879 {
880     FIXME("\n");
881     return E_NOTIMPL;
882 }
883
884 static xmlDocPtr doparse( char *ptr, int len )
885 {
886 #ifdef HAVE_XMLREADMEMORY
887     /*
888      * use xmlReadMemory if possible so we can suppress
889      * writing errors to stderr
890      */
891     return xmlReadMemory( ptr, len, NULL, NULL,
892                           XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS );
893 #else
894     return xmlParseMemory( ptr, len );
895 #endif
896 }
897
898 static xmlDocPtr doread( LPWSTR filename )
899 {
900     xmlDocPtr xmldoc = NULL;
901     HRESULT hr;
902     IBindCtx *pbc;
903     IStream *stream, *memstream;
904     WCHAR url[INTERNET_MAX_URL_LENGTH];
905     BYTE buf[4096];
906     DWORD read, written;
907
908     TRACE("%s\n", debugstr_w( filename ));
909
910     if(!PathIsURLW(filename))
911     {
912         WCHAR fullpath[MAX_PATH];
913         DWORD needed = sizeof(url)/sizeof(WCHAR);
914
915         if(!PathSearchAndQualifyW(filename, fullpath, sizeof(fullpath)/sizeof(WCHAR)))
916         {
917             WARN("can't find path\n");
918             return NULL;
919         }
920
921         if(FAILED(UrlCreateFromPathW(fullpath, url, &needed, 0)))
922         {
923             ERR("can't create url from path\n");
924             return NULL;
925         }
926         filename = url;
927     }
928
929     hr = CreateBindCtx(0, &pbc);
930     if(SUCCEEDED(hr))
931     {
932         hr = RegisterBindStatusCallback(pbc, (IBindStatusCallback*)&domdoc_bsc.lpVtbl, NULL, 0);
933         if(SUCCEEDED(hr))
934         {
935             IMoniker *moniker;
936             hr = CreateURLMoniker(NULL, filename, &moniker);
937             if(SUCCEEDED(hr))
938             {
939                 hr = IMoniker_BindToStorage(moniker, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
940                 IMoniker_Release(moniker);
941             }
942         }
943         IBindCtx_Release(pbc);
944     }
945     if(FAILED(hr))
946         return NULL;
947
948     hr = CreateStreamOnHGlobal(NULL, TRUE, &memstream);
949     if(FAILED(hr))
950     {
951         IStream_Release(stream);
952         return NULL;
953     }
954
955     do
956     {
957         IStream_Read(stream, buf, sizeof(buf), &read);
958         hr = IStream_Write(memstream, buf, read, &written);
959     } while(SUCCEEDED(hr) && written != 0 && read != 0);
960
961     if(SUCCEEDED(hr))
962     {
963         HGLOBAL hglobal;
964         hr = GetHGlobalFromStream(memstream, &hglobal);
965         if(SUCCEEDED(hr))
966         {
967             DWORD len = GlobalSize(hglobal);
968             char *ptr = GlobalLock(hglobal);
969             if(len != 0)
970                 xmldoc = doparse( ptr, len );
971             GlobalUnlock(hglobal);
972         }
973     }
974     IStream_Release(memstream);
975     IStream_Release(stream);
976     return xmldoc;
977 }
978
979 static HRESULT WINAPI domdoc_load(
980     IXMLDOMDocument *iface,
981     VARIANT xmlSource,
982     VARIANT_BOOL* isSuccessful )
983 {
984     domdoc *This = impl_from_IXMLDOMDocument( iface );
985     LPWSTR filename = NULL;
986     xmlDocPtr xmldoc = NULL;
987     HRESULT hr = S_FALSE;
988
989     TRACE("type %d\n", V_VT(&xmlSource) );
990
991     *isSuccessful = VARIANT_FALSE;
992
993     assert( This->node );
994
995     attach_xmlnode(This->node, NULL);
996
997     switch( V_VT(&xmlSource) )
998     {
999     case VT_BSTR:
1000         filename = V_BSTR(&xmlSource);
1001     }
1002
1003     if ( filename )
1004     {
1005         xmldoc = doread( filename );
1006     
1007         if ( !xmldoc )
1008             This->error = E_FAIL;
1009         else
1010         {
1011             hr = This->error = S_OK;
1012             *isSuccessful = VARIANT_TRUE;
1013         }
1014     }
1015
1016     if(!xmldoc)
1017         xmldoc = xmlNewDoc(NULL);
1018
1019     xmldoc->_private = 0;
1020     attach_xmlnode(This->node, (xmlNodePtr) xmldoc);
1021
1022     return hr;
1023 }
1024
1025
1026 static HRESULT WINAPI domdoc_get_readyState(
1027     IXMLDOMDocument *iface,
1028     long* value )
1029 {
1030     FIXME("\n");
1031     return E_NOTIMPL;
1032 }
1033
1034
1035 static HRESULT WINAPI domdoc_get_parseError(
1036     IXMLDOMDocument *iface,
1037     IXMLDOMParseError** errorObj )
1038 {
1039     BSTR error_string = NULL;
1040     static const WCHAR err[] = {'e','r','r','o','r',0};
1041     domdoc *This = impl_from_IXMLDOMDocument( iface );
1042
1043     FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
1044
1045     if(This->error)
1046         error_string = SysAllocString(err);
1047
1048     *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
1049     if(!*errorObj) return E_OUTOFMEMORY;
1050     return S_OK;
1051 }
1052
1053
1054 static HRESULT WINAPI domdoc_get_url(
1055     IXMLDOMDocument *iface,
1056     BSTR* urlString )
1057 {
1058     FIXME("\n");
1059     return E_NOTIMPL;
1060 }
1061
1062
1063 static HRESULT WINAPI domdoc_get_async(
1064     IXMLDOMDocument *iface,
1065     VARIANT_BOOL* isAsync )
1066 {
1067     domdoc *This = impl_from_IXMLDOMDocument( iface );
1068
1069     TRACE("%p <- %d\n", isAsync, This->async);
1070     *isAsync = This->async;
1071     return S_OK;
1072 }
1073
1074
1075 static HRESULT WINAPI domdoc_put_async(
1076     IXMLDOMDocument *iface,
1077     VARIANT_BOOL isAsync )
1078 {
1079     domdoc *This = impl_from_IXMLDOMDocument( iface );
1080
1081     TRACE("%d\n", isAsync);
1082     This->async = isAsync;
1083     return S_OK;
1084 }
1085
1086
1087 static HRESULT WINAPI domdoc_abort(
1088     IXMLDOMDocument *iface )
1089 {
1090     FIXME("\n");
1091     return E_NOTIMPL;
1092 }
1093
1094
1095 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
1096 {
1097     UINT len, blen = SysStringLen( bstr );
1098     LPSTR str;
1099
1100     len = WideCharToMultiByte( CP_UTF8, 0, bstr, blen, NULL, 0, NULL, NULL );
1101     str = HeapAlloc( GetProcessHeap(), 0, len );
1102     if ( !str )
1103         return FALSE;
1104     WideCharToMultiByte( CP_UTF8, 0, bstr, blen, str, len, NULL, NULL );
1105     *plen = len;
1106     *pstr = str;
1107     return TRUE;
1108 }
1109
1110 static HRESULT WINAPI domdoc_loadXML(
1111     IXMLDOMDocument *iface,
1112     BSTR bstrXML,
1113     VARIANT_BOOL* isSuccessful )
1114 {
1115     domdoc *This = impl_from_IXMLDOMDocument( iface );
1116     xmlDocPtr xmldoc = NULL;
1117     char *str;
1118     int len;
1119     HRESULT hr = S_FALSE;
1120
1121     TRACE("%p %s %p\n", This, debugstr_w( bstrXML ), isSuccessful );
1122
1123     assert ( This->node );
1124
1125     attach_xmlnode( This->node, NULL );
1126
1127     if ( isSuccessful )
1128     {
1129         *isSuccessful = VARIANT_FALSE;
1130
1131         if ( bstrXML  && bstr_to_utf8( bstrXML, &str, &len ) )
1132         {
1133             xmldoc = doparse( str, len );
1134             HeapFree( GetProcessHeap(), 0, str );
1135             if ( !xmldoc )
1136                 This->error = E_FAIL;
1137             else
1138             {
1139                 hr = This->error = S_OK;
1140                 *isSuccessful = VARIANT_TRUE;
1141             }
1142         }
1143     }
1144     if(!xmldoc)
1145         xmldoc = xmlNewDoc(NULL);
1146
1147     xmldoc->_private = 0;
1148     attach_xmlnode( This->node, (xmlNodePtr) xmldoc );
1149
1150     return hr;
1151 }
1152
1153
1154 static HRESULT WINAPI domdoc_save(
1155     IXMLDOMDocument *iface,
1156     VARIANT destination )
1157 {
1158     domdoc *This = impl_from_IXMLDOMDocument( iface );
1159     HANDLE handle;
1160     xmlChar *mem;
1161     int size;
1162     HRESULT ret = S_OK;
1163     DWORD written;
1164
1165     TRACE("(%p)->(var(vt %x, %s))\n", This, V_VT(&destination),
1166           V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
1167
1168     if(V_VT(&destination) != VT_BSTR)
1169     {
1170         FIXME("Unhandled vt %x\n", V_VT(&destination));
1171         return S_FALSE;
1172     }
1173
1174     handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
1175                           NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1176     if( handle == INVALID_HANDLE_VALUE )
1177     {
1178         WARN("failed to create file\n");
1179         return S_FALSE;
1180     }
1181
1182     xmlDocDumpMemory(get_doc(This), &mem, &size);
1183     if(!WriteFile(handle, mem, (DWORD)size, &written, NULL) || written != (DWORD)size)
1184     {
1185         WARN("write error\n");
1186         ret = S_FALSE;
1187     }
1188
1189     xmlFree(mem);
1190     CloseHandle(handle);
1191     return ret;
1192 }
1193
1194 static HRESULT WINAPI domdoc_get_validateOnParse(
1195     IXMLDOMDocument *iface,
1196     VARIANT_BOOL* isValidating )
1197 {
1198     FIXME("\n");
1199     return E_NOTIMPL;
1200 }
1201
1202
1203 static HRESULT WINAPI domdoc_put_validateOnParse(
1204     IXMLDOMDocument *iface,
1205     VARIANT_BOOL isValidating )
1206 {
1207     FIXME("\n");
1208     return E_NOTIMPL;
1209 }
1210
1211
1212 static HRESULT WINAPI domdoc_get_resolveExternals(
1213     IXMLDOMDocument *iface,
1214     VARIANT_BOOL* isResolving )
1215 {
1216     FIXME("\n");
1217     return E_NOTIMPL;
1218 }
1219
1220
1221 static HRESULT WINAPI domdoc_put_resolveExternals(
1222     IXMLDOMDocument *iface,
1223     VARIANT_BOOL isValidating )
1224 {
1225     FIXME("\n");
1226     return E_NOTIMPL;
1227 }
1228
1229
1230 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
1231     IXMLDOMDocument *iface,
1232     VARIANT_BOOL* isPreserving )
1233 {
1234     FIXME("\n");
1235     return E_NOTIMPL;
1236 }
1237
1238
1239 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
1240     IXMLDOMDocument *iface,
1241     VARIANT_BOOL isPreserving )
1242 {
1243     FIXME("\n");
1244     return E_NOTIMPL;
1245 }
1246
1247
1248 static HRESULT WINAPI domdoc_put_onReadyStateChange(
1249     IXMLDOMDocument *iface,
1250     VARIANT readyStateChangeSink )
1251 {
1252     FIXME("\n");
1253     return E_NOTIMPL;
1254 }
1255
1256
1257 static HRESULT WINAPI domdoc_put_onDataAvailable(
1258     IXMLDOMDocument *iface,
1259     VARIANT onDataAvailableSink )
1260 {
1261     FIXME("\n");
1262     return E_NOTIMPL;
1263 }
1264
1265 static HRESULT WINAPI domdoc_put_onTransformNode(
1266     IXMLDOMDocument *iface,
1267     VARIANT onTransformNodeSink )
1268 {
1269     FIXME("\n");
1270     return E_NOTIMPL;
1271 }
1272
1273 static const struct IXMLDOMDocumentVtbl domdoc_vtbl =
1274 {
1275     domdoc_QueryInterface,
1276     domdoc_AddRef,
1277     domdoc_Release,
1278     domdoc_GetTypeInfoCount,
1279     domdoc_GetTypeInfo,
1280     domdoc_GetIDsOfNames,
1281     domdoc_Invoke,
1282     domdoc_get_nodeName,
1283     domdoc_get_nodeValue,
1284     domdoc_put_nodeValue,
1285     domdoc_get_nodeType,
1286     domdoc_get_parentNode,
1287     domdoc_get_childNodes,
1288     domdoc_get_firstChild,
1289     domdoc_get_lastChild,
1290     domdoc_get_previousSibling,
1291     domdoc_get_nextSibling,
1292     domdoc_get_attributes,
1293     domdoc_insertBefore,
1294     domdoc_replaceChild,
1295     domdoc_removeChild,
1296     domdoc_appendChild,
1297     domdoc_hasChildNodes,
1298     domdoc_get_ownerDocument,
1299     domdoc_cloneNode,
1300     domdoc_get_nodeTypeString,
1301     domdoc_get_text,
1302     domdoc_put_text,
1303     domdoc_get_specified,
1304     domdoc_get_definition,
1305     domdoc_get_nodeTypedValue,
1306     domdoc_put_nodeTypedValue,
1307     domdoc_get_dataType,
1308     domdoc_put_dataType,
1309     domdoc_get_xml,
1310     domdoc_transformNode,
1311     domdoc_selectNodes,
1312     domdoc_selectSingleNode,
1313     domdoc_get_parsed,
1314     domdoc_get_namespaceURI,
1315     domdoc_get_prefix,
1316     domdoc_get_baseName,
1317     domdoc_transformNodeToObject,
1318     domdoc_get_doctype,
1319     domdoc_get_implementation,
1320     domdoc_get_documentElement,
1321     domdoc_documentElement,
1322     domdoc_createElement,
1323     domdoc_createDocumentFragment,
1324     domdoc_createTextNode,
1325     domdoc_createComment,
1326     domdoc_createCDATASection,
1327     domdoc_createProcessingInstruction,
1328     domdoc_createAttribute,
1329     domdoc_createEntityReference,
1330     domdoc_getElementsByTagName,
1331     domdoc_createNode,
1332     domdoc_nodeFromID,
1333     domdoc_load,
1334     domdoc_get_readyState,
1335     domdoc_get_parseError,
1336     domdoc_get_url,
1337     domdoc_get_async,
1338     domdoc_put_async,
1339     domdoc_abort,
1340     domdoc_loadXML,
1341     domdoc_save,
1342     domdoc_get_validateOnParse,
1343     domdoc_put_validateOnParse,
1344     domdoc_get_resolveExternals,
1345     domdoc_put_resolveExternals,
1346     domdoc_get_preserveWhiteSpace,
1347     domdoc_put_preserveWhiteSpace,
1348     domdoc_put_onReadyStateChange,
1349     domdoc_put_onDataAvailable,
1350     domdoc_put_onTransformNode,
1351 };
1352
1353 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
1354 {
1355     domdoc *doc;
1356     HRESULT hr;
1357     xmlDocPtr xmldoc;
1358
1359     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
1360
1361     doc = HeapAlloc( GetProcessHeap(), 0, sizeof (*doc) );
1362     if( !doc )
1363         return E_OUTOFMEMORY;
1364
1365     doc->lpVtbl = &domdoc_vtbl;
1366     doc->ref = 1;
1367     doc->async = 0;
1368     doc->error = S_OK;
1369
1370     xmldoc = xmlNewDoc(NULL);
1371     if(!xmldoc)
1372     {
1373         HeapFree(GetProcessHeap(), 0, doc);
1374         return E_OUTOFMEMORY;
1375     }
1376
1377     xmldoc->_private = 0;
1378
1379     doc->node_unk = create_basic_node( (xmlNodePtr)xmldoc, (IUnknown*)&doc->lpVtbl );
1380     if(!doc->node_unk)
1381     {
1382         xmlFreeDoc(xmldoc);
1383         HeapFree(GetProcessHeap(), 0, doc);
1384         return E_FAIL;
1385     }
1386
1387     hr = IUnknown_QueryInterface(doc->node_unk, &IID_IXMLDOMNode, (LPVOID*)&doc->node);
1388     if(FAILED(hr))
1389     {
1390         IUnknown_Release(doc->node_unk);
1391         HeapFree( GetProcessHeap(), 0, doc );
1392         return E_FAIL;
1393     }
1394     /* The ref on doc->node is actually looped back into this object, so release it */
1395     IXMLDOMNode_Release(doc->node);
1396
1397     *ppObj = &doc->lpVtbl;
1398
1399     TRACE("returning iface %p\n", *ppObj);
1400     return S_OK;
1401 }
1402
1403 #else
1404
1405 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
1406 {
1407     MESSAGE("This program tried to use a DOMDocument object, but\n"
1408             "libxml2 support was not present at compile time.\n");
1409     return E_NOTIMPL;
1410 }
1411
1412 #endif