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