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