mshtml: Added IHTMLStyleSheet::get_rules implementation.
[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     domdoc *This = impl_from_IXMLDOMDocument2( iface );
748     xmlNodePtr xmlnode;
749     xmlChar *xml_content;
750
751     TRACE("%p->(%s %p)\n", iface, debugstr_w(data), text);
752
753     if(!text)
754         return E_INVALIDARG;
755
756     *text = NULL;
757
758     xml_content = xmlChar_from_wchar((WCHAR*)data);
759     xmlnode = xmlNewText(xml_content);
760     HeapFree(GetProcessHeap(), 0, xml_content);
761
762     if(!xmlnode)
763         return E_FAIL;
764
765     xmlnode->doc = get_doc( This );
766
767     *text = (IXMLDOMText*)create_text(xmlnode);
768
769     return S_OK;
770 }
771
772
773 static HRESULT WINAPI domdoc_createComment(
774     IXMLDOMDocument2 *iface,
775     BSTR data,
776     IXMLDOMComment** comment )
777 {
778     FIXME("\n");
779     return E_NOTIMPL;
780 }
781
782
783 static HRESULT WINAPI domdoc_createCDATASection(
784     IXMLDOMDocument2 *iface,
785     BSTR data,
786     IXMLDOMCDATASection** cdata )
787 {
788     FIXME("\n");
789     return E_NOTIMPL;
790 }
791
792
793 static HRESULT WINAPI domdoc_createProcessingInstruction(
794     IXMLDOMDocument2 *iface,
795     BSTR target,
796     BSTR data,
797     IXMLDOMProcessingInstruction** pi )
798 {
799 #ifdef HAVE_XMLNEWDOCPI
800     xmlNodePtr xmlnode;
801     domdoc *This = impl_from_IXMLDOMDocument2( iface );
802     xmlChar *xml_target, *xml_content;
803
804     TRACE("%p->(%s %s %p)\n", iface, debugstr_w(target), debugstr_w(data), pi);
805
806     xml_target = xmlChar_from_wchar((WCHAR*)target);
807     xml_content = xmlChar_from_wchar((WCHAR*)data);
808
809     xmlnode = xmlNewDocPI(get_doc(This), xml_target, xml_content);
810     TRACE("created xmlptr %p\n", xmlnode);
811     *pi = (IXMLDOMProcessingInstruction*)create_pi(xmlnode);
812
813     HeapFree(GetProcessHeap(), 0, xml_content);
814     HeapFree(GetProcessHeap(), 0, xml_target);
815
816     return S_OK;
817 #else
818     FIXME("Libxml 2.6.15 or greater required.\n");
819     return E_NOTIMPL;
820 #endif
821 }
822
823
824 static HRESULT WINAPI domdoc_createAttribute(
825     IXMLDOMDocument2 *iface,
826     BSTR name,
827     IXMLDOMAttribute** attribute )
828 {
829     FIXME("\n");
830     return E_NOTIMPL;
831 }
832
833
834 static HRESULT WINAPI domdoc_createEntityReference(
835     IXMLDOMDocument2 *iface,
836     BSTR name,
837     IXMLDOMEntityReference** entityRef )
838 {
839     FIXME("\n");
840     return E_NOTIMPL;
841 }
842
843
844 static HRESULT WINAPI domdoc_getElementsByTagName(
845     IXMLDOMDocument2 *iface,
846     BSTR tagName,
847     IXMLDOMNodeList** resultList )
848 {
849     domdoc *This = impl_from_IXMLDOMDocument2( iface );
850     LPWSTR szPattern;
851     HRESULT hr;
852     TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
853
854     szPattern = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(2+lstrlenW(tagName)+1));
855     szPattern[0] = szPattern[1] = '/';
856     lstrcpyW(szPattern + 2, tagName);
857
858     hr = queryresult_create((xmlNodePtr)get_doc(This), szPattern, resultList);
859     HeapFree(GetProcessHeap(), 0, szPattern);
860
861     return hr;
862 }
863
864 static DOMNodeType get_node_type(VARIANT Type)
865 {
866     if(V_VT(&Type) == VT_I4)
867         return V_I4(&Type);
868
869     FIXME("Unsupported variant type %x\n", V_VT(&Type));
870     return 0;
871 }
872
873 static HRESULT WINAPI domdoc_createNode(
874     IXMLDOMDocument2 *iface,
875     VARIANT Type,
876     BSTR name,
877     BSTR namespaceURI,
878     IXMLDOMNode** node )
879 {
880     domdoc *This = impl_from_IXMLDOMDocument2( iface );
881     DOMNodeType node_type;
882     xmlNodePtr xmlnode = NULL;
883     xmlChar *xml_name;
884
885     TRACE("(%p)->(type,%s,%s,%p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
886
887     node_type = get_node_type(Type);
888     TRACE("node_type %d\n", node_type);
889
890     xml_name = xmlChar_from_wchar((WCHAR*)name);
891
892     switch(node_type)
893     {
894     case NODE_ELEMENT:
895         xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
896         *node = create_node(xmlnode);
897         TRACE("created %p\n", xmlnode);
898         break;
899
900     default:
901         FIXME("unhandled node type %d\n", node_type);
902         break;
903     }
904
905     HeapFree(GetProcessHeap(), 0, xml_name);
906
907     if(xmlnode && *node)
908         return S_OK;
909
910     return E_FAIL;
911 }
912
913 static HRESULT WINAPI domdoc_nodeFromID(
914     IXMLDOMDocument2 *iface,
915     BSTR idString,
916     IXMLDOMNode** node )
917 {
918     FIXME("\n");
919     return E_NOTIMPL;
920 }
921
922 static xmlDocPtr doparse( char *ptr, int len )
923 {
924 #ifdef HAVE_XMLREADMEMORY
925     /*
926      * use xmlReadMemory if possible so we can suppress
927      * writing errors to stderr
928      */
929     return xmlReadMemory( ptr, len, NULL, NULL,
930                           XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS );
931 #else
932     return xmlParseMemory( ptr, len );
933 #endif
934 }
935
936 static xmlDocPtr doread( LPWSTR filename )
937 {
938     xmlDocPtr xmldoc = NULL;
939     HRESULT hr;
940     IBindCtx *pbc;
941     IStream *stream, *memstream;
942     WCHAR url[INTERNET_MAX_URL_LENGTH];
943     BYTE buf[4096];
944     DWORD read, written;
945
946     TRACE("%s\n", debugstr_w( filename ));
947
948     if(!PathIsURLW(filename))
949     {
950         WCHAR fullpath[MAX_PATH];
951         DWORD needed = sizeof(url)/sizeof(WCHAR);
952
953         if(!PathSearchAndQualifyW(filename, fullpath, sizeof(fullpath)/sizeof(WCHAR)))
954         {
955             WARN("can't find path\n");
956             return NULL;
957         }
958
959         if(FAILED(UrlCreateFromPathW(fullpath, url, &needed, 0)))
960         {
961             ERR("can't create url from path\n");
962             return NULL;
963         }
964         filename = url;
965     }
966
967     hr = CreateBindCtx(0, &pbc);
968     if(SUCCEEDED(hr))
969     {
970         hr = RegisterBindStatusCallback(pbc, (IBindStatusCallback*)&domdoc_bsc.lpVtbl, NULL, 0);
971         if(SUCCEEDED(hr))
972         {
973             IMoniker *moniker;
974             hr = CreateURLMoniker(NULL, filename, &moniker);
975             if(SUCCEEDED(hr))
976             {
977                 hr = IMoniker_BindToStorage(moniker, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
978                 IMoniker_Release(moniker);
979             }
980         }
981         IBindCtx_Release(pbc);
982     }
983     if(FAILED(hr))
984         return NULL;
985
986     hr = CreateStreamOnHGlobal(NULL, TRUE, &memstream);
987     if(FAILED(hr))
988     {
989         IStream_Release(stream);
990         return NULL;
991     }
992
993     do
994     {
995         IStream_Read(stream, buf, sizeof(buf), &read);
996         hr = IStream_Write(memstream, buf, read, &written);
997     } while(SUCCEEDED(hr) && written != 0 && read != 0);
998
999     if(SUCCEEDED(hr))
1000     {
1001         HGLOBAL hglobal;
1002         hr = GetHGlobalFromStream(memstream, &hglobal);
1003         if(SUCCEEDED(hr))
1004         {
1005             DWORD len = GlobalSize(hglobal);
1006             char *ptr = GlobalLock(hglobal);
1007             if(len != 0)
1008                 xmldoc = doparse( ptr, len );
1009             GlobalUnlock(hglobal);
1010         }
1011     }
1012     IStream_Release(memstream);
1013     IStream_Release(stream);
1014     return xmldoc;
1015 }
1016
1017 static HRESULT WINAPI domdoc_load(
1018     IXMLDOMDocument2 *iface,
1019     VARIANT xmlSource,
1020     VARIANT_BOOL* isSuccessful )
1021 {
1022     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1023     LPWSTR filename = NULL;
1024     xmlDocPtr xmldoc = NULL;
1025     HRESULT hr = S_FALSE;
1026
1027     TRACE("type %d\n", V_VT(&xmlSource) );
1028
1029     *isSuccessful = VARIANT_FALSE;
1030
1031     assert( This->node );
1032
1033     attach_xmlnode(This->node, NULL);
1034
1035     switch( V_VT(&xmlSource) )
1036     {
1037     case VT_BSTR:
1038         filename = V_BSTR(&xmlSource);
1039     }
1040
1041     if ( filename )
1042     {
1043         xmldoc = doread( filename );
1044     
1045         if ( !xmldoc )
1046             This->error = E_FAIL;
1047         else
1048         {
1049             hr = This->error = S_OK;
1050             *isSuccessful = VARIANT_TRUE;
1051         }
1052     }
1053
1054     if(!xmldoc)
1055         xmldoc = xmlNewDoc(NULL);
1056
1057     xmldoc->_private = 0;
1058     attach_xmlnode(This->node, (xmlNodePtr) xmldoc);
1059
1060     return hr;
1061 }
1062
1063
1064 static HRESULT WINAPI domdoc_get_readyState(
1065     IXMLDOMDocument2 *iface,
1066     long* value )
1067 {
1068     FIXME("\n");
1069     return E_NOTIMPL;
1070 }
1071
1072
1073 static HRESULT WINAPI domdoc_get_parseError(
1074     IXMLDOMDocument2 *iface,
1075     IXMLDOMParseError** errorObj )
1076 {
1077     BSTR error_string = NULL;
1078     static const WCHAR err[] = {'e','r','r','o','r',0};
1079     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1080
1081     FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
1082
1083     if(This->error)
1084         error_string = SysAllocString(err);
1085
1086     *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
1087     if(!*errorObj) return E_OUTOFMEMORY;
1088     return S_OK;
1089 }
1090
1091
1092 static HRESULT WINAPI domdoc_get_url(
1093     IXMLDOMDocument2 *iface,
1094     BSTR* urlString )
1095 {
1096     FIXME("\n");
1097     return E_NOTIMPL;
1098 }
1099
1100
1101 static HRESULT WINAPI domdoc_get_async(
1102     IXMLDOMDocument2 *iface,
1103     VARIANT_BOOL* isAsync )
1104 {
1105     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1106
1107     TRACE("%p <- %d\n", isAsync, This->async);
1108     *isAsync = This->async;
1109     return S_OK;
1110 }
1111
1112
1113 static HRESULT WINAPI domdoc_put_async(
1114     IXMLDOMDocument2 *iface,
1115     VARIANT_BOOL isAsync )
1116 {
1117     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1118
1119     TRACE("%d\n", isAsync);
1120     This->async = isAsync;
1121     return S_OK;
1122 }
1123
1124
1125 static HRESULT WINAPI domdoc_abort(
1126     IXMLDOMDocument2 *iface )
1127 {
1128     FIXME("\n");
1129     return E_NOTIMPL;
1130 }
1131
1132
1133 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
1134 {
1135     UINT len, blen = SysStringLen( bstr );
1136     LPSTR str;
1137
1138     len = WideCharToMultiByte( CP_UTF8, 0, bstr, blen, NULL, 0, NULL, NULL );
1139     str = HeapAlloc( GetProcessHeap(), 0, len );
1140     if ( !str )
1141         return FALSE;
1142     WideCharToMultiByte( CP_UTF8, 0, bstr, blen, str, len, NULL, NULL );
1143     *plen = len;
1144     *pstr = str;
1145     return TRUE;
1146 }
1147
1148 static HRESULT WINAPI domdoc_loadXML(
1149     IXMLDOMDocument2 *iface,
1150     BSTR bstrXML,
1151     VARIANT_BOOL* isSuccessful )
1152 {
1153     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1154     xmlDocPtr xmldoc = NULL;
1155     char *str;
1156     int len;
1157     HRESULT hr = S_FALSE;
1158
1159     TRACE("%p %s %p\n", This, debugstr_w( bstrXML ), isSuccessful );
1160
1161     assert ( This->node );
1162
1163     attach_xmlnode( This->node, NULL );
1164
1165     if ( isSuccessful )
1166     {
1167         *isSuccessful = VARIANT_FALSE;
1168
1169         if ( bstrXML  && bstr_to_utf8( bstrXML, &str, &len ) )
1170         {
1171             xmldoc = doparse( str, len );
1172             HeapFree( GetProcessHeap(), 0, str );
1173             if ( !xmldoc )
1174                 This->error = E_FAIL;
1175             else
1176             {
1177                 hr = This->error = S_OK;
1178                 *isSuccessful = VARIANT_TRUE;
1179             }
1180         }
1181     }
1182     if(!xmldoc)
1183         xmldoc = xmlNewDoc(NULL);
1184
1185     xmldoc->_private = 0;
1186     attach_xmlnode( This->node, (xmlNodePtr) xmldoc );
1187
1188     return hr;
1189 }
1190
1191
1192 static HRESULT WINAPI domdoc_save(
1193     IXMLDOMDocument2 *iface,
1194     VARIANT destination )
1195 {
1196     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1197     HANDLE handle;
1198     xmlChar *mem;
1199     int size;
1200     HRESULT ret = S_OK;
1201     DWORD written;
1202
1203     TRACE("(%p)->(var(vt %x, %s))\n", This, V_VT(&destination),
1204           V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
1205
1206     if(V_VT(&destination) != VT_BSTR)
1207     {
1208         FIXME("Unhandled vt %x\n", V_VT(&destination));
1209         return S_FALSE;
1210     }
1211
1212     handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
1213                           NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1214     if( handle == INVALID_HANDLE_VALUE )
1215     {
1216         WARN("failed to create file\n");
1217         return S_FALSE;
1218     }
1219
1220     xmlDocDumpMemory(get_doc(This), &mem, &size);
1221     if(!WriteFile(handle, mem, (DWORD)size, &written, NULL) || written != (DWORD)size)
1222     {
1223         WARN("write error\n");
1224         ret = S_FALSE;
1225     }
1226
1227     xmlFree(mem);
1228     CloseHandle(handle);
1229     return ret;
1230 }
1231
1232 static HRESULT WINAPI domdoc_get_validateOnParse(
1233     IXMLDOMDocument2 *iface,
1234     VARIANT_BOOL* isValidating )
1235 {
1236     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1237
1238     TRACE("%p <- %d\n", isValidating, This->validating);
1239     *isValidating = This->validating;
1240     return S_OK;
1241 }
1242
1243
1244 static HRESULT WINAPI domdoc_put_validateOnParse(
1245     IXMLDOMDocument2 *iface,
1246     VARIANT_BOOL isValidating )
1247 {
1248     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1249
1250     TRACE("%d\n", isValidating);
1251     This->validating = isValidating;
1252     return S_OK;
1253 }
1254
1255
1256 static HRESULT WINAPI domdoc_get_resolveExternals(
1257     IXMLDOMDocument2 *iface,
1258     VARIANT_BOOL* isResolving )
1259 {
1260     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1261
1262     TRACE("%p <- %d\n", isResolving, This->resolving);
1263     *isResolving = This->resolving;
1264     return S_OK;
1265 }
1266
1267
1268 static HRESULT WINAPI domdoc_put_resolveExternals(
1269     IXMLDOMDocument2 *iface,
1270     VARIANT_BOOL isResolving )
1271 {
1272     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1273
1274     TRACE("%d\n", isResolving);
1275     This->resolving = isResolving;
1276     return S_OK;
1277 }
1278
1279
1280 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
1281     IXMLDOMDocument2 *iface,
1282     VARIANT_BOOL* isPreserving )
1283 {
1284     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1285
1286     TRACE("%p <- %d\n", isPreserving, This->preserving);
1287     *isPreserving = This->preserving;
1288     return S_OK;
1289 }
1290
1291
1292 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
1293     IXMLDOMDocument2 *iface,
1294     VARIANT_BOOL isPreserving )
1295 {
1296     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1297
1298     TRACE("%d\n", isPreserving);
1299     This->preserving = isPreserving;
1300     return S_OK;
1301 }
1302
1303
1304 static HRESULT WINAPI domdoc_put_onReadyStateChange(
1305     IXMLDOMDocument2 *iface,
1306     VARIANT readyStateChangeSink )
1307 {
1308     FIXME("\n");
1309     return E_NOTIMPL;
1310 }
1311
1312
1313 static HRESULT WINAPI domdoc_put_onDataAvailable(
1314     IXMLDOMDocument2 *iface,
1315     VARIANT onDataAvailableSink )
1316 {
1317     FIXME("\n");
1318     return E_NOTIMPL;
1319 }
1320
1321 static HRESULT WINAPI domdoc_put_onTransformNode(
1322     IXMLDOMDocument2 *iface,
1323     VARIANT onTransformNodeSink )
1324 {
1325     FIXME("\n");
1326     return E_NOTIMPL;
1327 }
1328
1329 static HRESULT WINAPI domdoc_get_namespaces(
1330     IXMLDOMDocument2* iface,
1331     IXMLDOMSchemaCollection** schemaCollection )
1332 {
1333     FIXME("\n");
1334     return E_NOTIMPL;
1335 }
1336
1337 static HRESULT WINAPI domdoc_get_schemas(
1338     IXMLDOMDocument2* iface,
1339     VARIANT* var1 )
1340 {
1341     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1342     HRESULT hr = S_FALSE;
1343     IXMLDOMSchemaCollection *cur_schema = This->schema;
1344
1345     TRACE("(%p)->(%p)\n", This, var1);
1346
1347     VariantInit(var1); /* Test shows we don't call VariantClear here */
1348     V_VT(var1) = VT_NULL;
1349
1350     if(cur_schema)
1351     {
1352         hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
1353         if(SUCCEEDED(hr))
1354             V_VT(var1) = VT_DISPATCH;
1355     }
1356     return hr;
1357 }
1358
1359 static HRESULT WINAPI domdoc_putref_schemas(
1360     IXMLDOMDocument2* iface,
1361     VARIANT var1)
1362 {
1363     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1364     HRESULT hr = E_FAIL;
1365     IXMLDOMSchemaCollection *new_schema = NULL;
1366
1367     FIXME("(%p): semi-stub\n", This);
1368     switch(V_VT(&var1))
1369     {
1370     case VT_UNKNOWN:
1371         hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1372         break;
1373
1374     case VT_DISPATCH:
1375         hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1376         break;
1377
1378     case VT_NULL:
1379     case VT_EMPTY:
1380         hr = S_OK;
1381         break;
1382
1383     default:
1384         WARN("Can't get schema from vt %x\n", V_VT(&var1));
1385     }
1386
1387     if(SUCCEEDED(hr))
1388     {
1389         IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
1390         if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
1391     }
1392
1393     return hr;
1394 }
1395
1396 static HRESULT WINAPI domdoc_validate(
1397     IXMLDOMDocument2* iface,
1398     IXMLDOMParseError** err)
1399 {
1400     FIXME("\n");
1401     return E_NOTIMPL;
1402 }
1403
1404 static HRESULT WINAPI domdoc_setProperty(
1405     IXMLDOMDocument2* iface,
1406     BSTR p,
1407     VARIANT var)
1408 {
1409     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1410
1411     if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
1412     {
1413         VARIANT varStr;
1414         HRESULT hr;
1415         BSTR bstr;
1416
1417         V_VT(&varStr) = VT_EMPTY;
1418         if (V_VT(&var) != VT_BSTR)
1419         {
1420             if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
1421                 return hr;
1422             bstr = V_BSTR(&varStr);
1423         }
1424         else
1425             bstr = V_BSTR(&var);
1426
1427         hr = S_OK;
1428         if (lstrcmpiW(bstr, SZ_VALUE_XPATH) == 0)
1429             This->bUseXPath = TRUE;
1430         else if (lstrcmpiW(bstr, SZ_VALUE_XSLPATTERN) == 0)
1431             This->bUseXPath = FALSE;
1432         else
1433             hr = E_FAIL;
1434
1435         VariantClear(&varStr);
1436         return hr;
1437     }
1438
1439     FIXME("Unknown property %s\n", wine_dbgstr_w(p));
1440     return E_FAIL;
1441 }
1442
1443 static HRESULT WINAPI domdoc_getProperty(
1444     IXMLDOMDocument2* iface,
1445     BSTR p,
1446     VARIANT* var)
1447 {
1448     domdoc *This = impl_from_IXMLDOMDocument2( iface );
1449
1450     if (var == NULL)
1451         return E_INVALIDARG;
1452     if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
1453     {
1454         V_VT(var) = VT_BSTR;
1455         if (This->bUseXPath)
1456             V_BSTR(var) = SysAllocString(SZ_VALUE_XPATH);
1457         else
1458             V_BSTR(var) = SysAllocString(SZ_VALUE_XSLPATTERN);
1459         return S_OK;
1460     }
1461
1462     FIXME("Unknown property %s\n", wine_dbgstr_w(p));
1463     return E_FAIL;
1464 }
1465
1466 static const struct IXMLDOMDocument2Vtbl domdoc_vtbl =
1467 {
1468     domdoc_QueryInterface,
1469     domdoc_AddRef,
1470     domdoc_Release,
1471     domdoc_GetTypeInfoCount,
1472     domdoc_GetTypeInfo,
1473     domdoc_GetIDsOfNames,
1474     domdoc_Invoke,
1475     domdoc_get_nodeName,
1476     domdoc_get_nodeValue,
1477     domdoc_put_nodeValue,
1478     domdoc_get_nodeType,
1479     domdoc_get_parentNode,
1480     domdoc_get_childNodes,
1481     domdoc_get_firstChild,
1482     domdoc_get_lastChild,
1483     domdoc_get_previousSibling,
1484     domdoc_get_nextSibling,
1485     domdoc_get_attributes,
1486     domdoc_insertBefore,
1487     domdoc_replaceChild,
1488     domdoc_removeChild,
1489     domdoc_appendChild,
1490     domdoc_hasChildNodes,
1491     domdoc_get_ownerDocument,
1492     domdoc_cloneNode,
1493     domdoc_get_nodeTypeString,
1494     domdoc_get_text,
1495     domdoc_put_text,
1496     domdoc_get_specified,
1497     domdoc_get_definition,
1498     domdoc_get_nodeTypedValue,
1499     domdoc_put_nodeTypedValue,
1500     domdoc_get_dataType,
1501     domdoc_put_dataType,
1502     domdoc_get_xml,
1503     domdoc_transformNode,
1504     domdoc_selectNodes,
1505     domdoc_selectSingleNode,
1506     domdoc_get_parsed,
1507     domdoc_get_namespaceURI,
1508     domdoc_get_prefix,
1509     domdoc_get_baseName,
1510     domdoc_transformNodeToObject,
1511     domdoc_get_doctype,
1512     domdoc_get_implementation,
1513     domdoc_get_documentElement,
1514     domdoc_documentElement,
1515     domdoc_createElement,
1516     domdoc_createDocumentFragment,
1517     domdoc_createTextNode,
1518     domdoc_createComment,
1519     domdoc_createCDATASection,
1520     domdoc_createProcessingInstruction,
1521     domdoc_createAttribute,
1522     domdoc_createEntityReference,
1523     domdoc_getElementsByTagName,
1524     domdoc_createNode,
1525     domdoc_nodeFromID,
1526     domdoc_load,
1527     domdoc_get_readyState,
1528     domdoc_get_parseError,
1529     domdoc_get_url,
1530     domdoc_get_async,
1531     domdoc_put_async,
1532     domdoc_abort,
1533     domdoc_loadXML,
1534     domdoc_save,
1535     domdoc_get_validateOnParse,
1536     domdoc_put_validateOnParse,
1537     domdoc_get_resolveExternals,
1538     domdoc_put_resolveExternals,
1539     domdoc_get_preserveWhiteSpace,
1540     domdoc_put_preserveWhiteSpace,
1541     domdoc_put_onReadyStateChange,
1542     domdoc_put_onDataAvailable,
1543     domdoc_put_onTransformNode,
1544     domdoc_get_namespaces,
1545     domdoc_get_schemas,
1546     domdoc_putref_schemas,
1547     domdoc_validate,
1548     domdoc_setProperty,
1549     domdoc_getProperty
1550 };
1551
1552 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
1553 {
1554     domdoc *doc;
1555     HRESULT hr;
1556     xmlDocPtr xmldoc;
1557
1558     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
1559
1560     doc = HeapAlloc( GetProcessHeap(), 0, sizeof (*doc) );
1561     if( !doc )
1562         return E_OUTOFMEMORY;
1563
1564     doc->lpVtbl = &domdoc_vtbl;
1565     doc->ref = 1;
1566     doc->async = 0;
1567     doc->validating = 0;
1568     doc->resolving = 0;
1569     doc->preserving = 0;
1570     doc->bUseXPath = FALSE;
1571     doc->error = S_OK;
1572     doc->schema = NULL;
1573
1574     xmldoc = xmlNewDoc(NULL);
1575     if(!xmldoc)
1576     {
1577         HeapFree(GetProcessHeap(), 0, doc);
1578         return E_OUTOFMEMORY;
1579     }
1580
1581     xmldoc->_private = 0;
1582
1583     doc->node_unk = create_basic_node( (xmlNodePtr)xmldoc, (IUnknown*)&doc->lpVtbl );
1584     if(!doc->node_unk)
1585     {
1586         xmlFreeDoc(xmldoc);
1587         HeapFree(GetProcessHeap(), 0, doc);
1588         return E_FAIL;
1589     }
1590
1591     hr = IUnknown_QueryInterface(doc->node_unk, &IID_IXMLDOMNode, (LPVOID*)&doc->node);
1592     if(FAILED(hr))
1593     {
1594         IUnknown_Release(doc->node_unk);
1595         HeapFree( GetProcessHeap(), 0, doc );
1596         return E_FAIL;
1597     }
1598     /* The ref on doc->node is actually looped back into this object, so release it */
1599     IXMLDOMNode_Release(doc->node);
1600
1601     *ppObj = &doc->lpVtbl;
1602
1603     TRACE("returning iface %p\n", *ppObj);
1604     return S_OK;
1605 }
1606
1607 #else
1608
1609 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
1610 {
1611     MESSAGE("This program tried to use a DOMDocument object, but\n"
1612             "libxml2 support was not present at compile time.\n");
1613     return E_NOTIMPL;
1614 }
1615
1616 #endif