2 * DOM Document implementation
4 * Copyright 2005 Mike McCormack
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.
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.
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
22 #define NONAMELESSUNION
41 #include "wine/debug.h"
42 #include "wine/list.h"
44 #include "msxml_private.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
50 #include <libxml/xmlsave.h>
52 /* not defined in older versions */
53 #define XML_SAVE_FORMAT 1
54 #define XML_SAVE_NO_DECL 2
55 #define XML_SAVE_NO_EMPTY 4
56 #define XML_SAVE_NO_XHTML 8
57 #define XML_SAVE_XHTML 16
58 #define XML_SAVE_AS_XML 32
59 #define XML_SAVE_AS_HTML 64
61 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};
62 static const WCHAR SZ_VALUE_XPATH[] = {'X','P','a','t','h',0};
63 static const WCHAR SZ_VALUE_XSLPATTERN[] = {'X','S','L','P','a','t','t','e','r','n',0};
65 typedef struct _domdoc
68 const struct IXMLDOMDocument2Vtbl *lpVtbl;
69 const struct IPersistStreamVtbl *lpvtblIPersistStream;
70 const struct IObjectWithSiteVtbl *lpvtblIObjectWithSite;
71 const struct IObjectSafetyVtbl *lpvtblIObjectSafety;
72 const struct ISupportErrorInfoVtbl *lpvtblISupportErrorInfo;
75 VARIANT_BOOL validating;
76 VARIANT_BOOL resolving;
77 VARIANT_BOOL preserving;
79 IXMLDOMSchemaCollection *schema;
94 In native windows, the whole lifetime management of XMLDOMNodes is
95 managed automatically using reference counts. Wine emulates that by
96 maintaining a reference count to the document that is increased for
97 each IXMLDOMNode pointer passed out for this document. If all these
98 pointers are gone, the document is unreachable and gets freed, that
99 is, all nodes in the tree of the document get freed.
101 You are able to create nodes that are associated to a document (in
102 fact, in msxml's XMLDOM model, all nodes are associated to a document),
103 but not in the tree of that document, for example using the createFoo
104 functions from IXMLDOMDocument. These nodes do not get cleaned up
105 by libxml, so we have to do it ourselves.
107 To catch these nodes, a list of "orphan nodes" is introduced.
108 It contains pointers to all roots of node trees that are
109 associated with the document without being part of the document
110 tree. All nodes with parent==NULL (except for the document root nodes)
111 should be in the orphan node list of their document. All orphan nodes
112 get freed together with the document itself.
115 typedef struct _xmldoc_priv {
120 typedef struct _orphan_entry {
125 static inline xmldoc_priv * priv_from_xmlDocPtr(xmlDocPtr doc)
127 return doc->_private;
130 static xmldoc_priv * create_priv(void)
133 priv = heap_alloc( sizeof (*priv) );
138 list_init( &priv->orphans );
144 static xmlDocPtr doparse( char *ptr, int len )
146 #ifdef HAVE_XMLREADMEMORY
148 * use xmlReadMemory if possible so we can suppress
149 * writing errors to stderr
151 return xmlReadMemory( ptr, len, NULL, NULL,
152 XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS );
154 return xmlParseMemory( ptr, len );
158 LONG xmldoc_add_ref(xmlDocPtr doc)
160 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
165 LONG xmldoc_release(xmlDocPtr doc)
167 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
168 LONG ref = InterlockedDecrement(&priv->refs);
172 orphan_entry *orphan, *orphan2;
173 TRACE("freeing docptr %p\n", doc);
175 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
177 xmlFreeNode( orphan->node );
180 heap_free(doc->_private);
188 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
190 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
193 entry = heap_alloc( sizeof (*entry) );
195 return E_OUTOFMEMORY;
198 list_add_head( &priv->orphans, &entry->entry );
202 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
204 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
205 orphan_entry *entry, *entry2;
207 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
209 if( entry->node == node )
211 list_remove( &entry->entry );
220 static HRESULT attach_xmldoc( xmlnode *node, xmlDocPtr xml )
223 xmldoc_release(node->node->doc);
225 node->node = (xmlNodePtr) xml;
227 xmldoc_add_ref(node->node->doc);
232 static inline domdoc *impl_from_IXMLDOMDocument2( IXMLDOMDocument2 *iface )
234 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
237 static inline xmlDocPtr get_doc( domdoc *This )
239 return (xmlDocPtr)This->node.node;
242 static inline domdoc *impl_from_IPersistStream(IPersistStream *iface)
244 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStream));
247 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
249 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
252 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
254 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
257 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
259 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblISupportErrorInfo));
262 /************************************************************************
263 * xmldoc implementation of IPersistStream.
265 static HRESULT WINAPI xmldoc_IPersistStream_QueryInterface(
266 IPersistStream *iface, REFIID riid, LPVOID *ppvObj)
268 domdoc *this = impl_from_IPersistStream(iface);
269 return IXMLDocument_QueryInterface((IXMLDocument *)this, riid, ppvObj);
272 static ULONG WINAPI xmldoc_IPersistStream_AddRef(
273 IPersistStream *iface)
275 domdoc *this = impl_from_IPersistStream(iface);
276 return IXMLDocument_AddRef((IXMLDocument *)this);
279 static ULONG WINAPI xmldoc_IPersistStream_Release(
280 IPersistStream *iface)
282 domdoc *this = impl_from_IPersistStream(iface);
283 return IXMLDocument_Release((IXMLDocument *)this);
286 static HRESULT WINAPI xmldoc_IPersistStream_GetClassID(
287 IPersistStream *iface, CLSID *classid)
289 TRACE("(%p,%p): stub!\n", iface, classid);
294 *classid = CLSID_DOMDocument2;
299 static HRESULT WINAPI xmldoc_IPersistStream_IsDirty(
300 IPersistStream *iface)
302 domdoc *This = impl_from_IPersistStream(iface);
304 FIXME("(%p): stub!\n", This);
309 static HRESULT WINAPI xmldoc_IPersistStream_Load(
310 IPersistStream *iface, LPSTREAM pStm)
312 domdoc *This = impl_from_IPersistStream(iface);
315 DWORD read, written, len;
318 xmlDocPtr xmldoc = NULL;
320 TRACE("(%p)->(%p)\n", This, pStm);
325 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
331 IStream_Read(pStm, buf, sizeof(buf), &read);
332 hr = IStream_Write(This->stream, buf, read, &written);
333 } while(SUCCEEDED(hr) && written != 0 && read != 0);
337 ERR("Failed to copy stream\n");
341 hr = GetHGlobalFromStream(This->stream, &hglobal);
345 len = GlobalSize(hglobal);
346 ptr = GlobalLock(hglobal);
348 xmldoc = parse_xml(ptr, len);
349 GlobalUnlock(hglobal);
353 ERR("Failed to parse xml\n");
357 xmldoc->_private = create_priv();
359 return attach_xmldoc( &This->node, xmldoc );
362 static HRESULT WINAPI xmldoc_IPersistStream_Save(
363 IPersistStream *iface, LPSTREAM pStm, BOOL fClearDirty)
365 domdoc *This = impl_from_IPersistStream(iface);
369 TRACE("(%p)->(%p %d)\n", This, pStm, fClearDirty);
371 hr = IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), &xmlString );
375 DWORD len = strlenW(xmlString) * sizeof(WCHAR);
377 hr = IStream_Write( pStm, xmlString, len, &count );
379 SysFreeString(xmlString);
382 TRACE("ret 0x%08x\n", hr);
387 static HRESULT WINAPI xmldoc_IPersistStream_GetSizeMax(
388 IPersistStream *iface, ULARGE_INTEGER *pcbSize)
390 domdoc *This = impl_from_IPersistStream(iface);
391 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
395 static const IPersistStreamVtbl xmldoc_IPersistStream_VTable =
397 xmldoc_IPersistStream_QueryInterface,
398 xmldoc_IPersistStream_AddRef,
399 xmldoc_IPersistStream_Release,
400 xmldoc_IPersistStream_GetClassID,
401 xmldoc_IPersistStream_IsDirty,
402 xmldoc_IPersistStream_Load,
403 xmldoc_IPersistStream_Save,
404 xmldoc_IPersistStream_GetSizeMax,
407 /* ISupportErrorInfo interface */
408 static HRESULT WINAPI support_error_QueryInterface(
409 ISupportErrorInfo *iface,
410 REFIID riid, void** ppvObj )
412 domdoc *This = impl_from_ISupportErrorInfo(iface);
413 return IXMLDocument_QueryInterface((IXMLDocument *)This, riid, ppvObj);
416 static ULONG WINAPI support_error_AddRef(
417 ISupportErrorInfo *iface )
419 domdoc *This = impl_from_ISupportErrorInfo(iface);
420 return IXMLDocument_AddRef((IXMLDocument *)This);
423 static ULONG WINAPI support_error_Release(
424 ISupportErrorInfo *iface )
426 domdoc *This = impl_from_ISupportErrorInfo(iface);
427 return IXMLDocument_Release((IXMLDocument *)This);
430 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
431 ISupportErrorInfo *iface,
434 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
438 static const struct ISupportErrorInfoVtbl support_error_vtbl =
440 support_error_QueryInterface,
441 support_error_AddRef,
442 support_error_Release,
443 support_error_InterfaceSupportsErrorInfo
446 /* IXMLDOMDocument2 interface */
447 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument2 *iface, REFIID riid, void** ppvObject )
449 domdoc *This = impl_from_IXMLDOMDocument2( iface );
451 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
455 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
456 IsEqualGUID( riid, &IID_IDispatch ) ||
457 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
458 IsEqualGUID( riid, &IID_IXMLDOMDocument2 ) )
462 else if ( IsEqualGUID( riid, &IID_IXMLDOMNode ) )
464 *ppvObject = IXMLDOMNode_from_impl(&This->node);
466 else if (IsEqualGUID(&IID_IPersistStream, riid))
468 *ppvObject = &(This->lpvtblIPersistStream);
470 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
472 *ppvObject = &(This->lpvtblIObjectWithSite);
474 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
476 *ppvObject = &This->lpvtblISupportErrorInfo;
478 else if(dispex_query_interface(&This->node.dispex, riid, ppvObject))
480 return *ppvObject ? S_OK : E_NOINTERFACE;
482 else if(IsEqualGUID(&IID_IRunnableObject, riid))
484 TRACE("IID_IRunnableObject not supported returning NULL\n");
485 return E_NOINTERFACE;
489 FIXME("interface %s not implemented\n", debugstr_guid(riid));
490 return E_NOINTERFACE;
493 IUnknown_AddRef((IUnknown*)*ppvObject);
499 static ULONG WINAPI domdoc_AddRef(
500 IXMLDOMDocument2 *iface )
502 domdoc *This = impl_from_IXMLDOMDocument2( iface );
503 TRACE("%p\n", This );
504 return InterlockedIncrement( &This->ref );
508 static ULONG WINAPI domdoc_Release(
509 IXMLDOMDocument2 *iface )
511 domdoc *This = impl_from_IXMLDOMDocument2( iface );
514 TRACE("%p\n", This );
516 ref = InterlockedDecrement( &This->ref );
520 detach_bsc(This->bsc);
523 IUnknown_Release( This->site );
524 destroy_xmlnode(&This->node);
525 if(This->schema) IXMLDOMSchemaCollection_Release( This->schema );
526 if (This->stream) IStream_Release(This->stream);
527 HeapFree( GetProcessHeap(), 0, This );
533 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument2 *iface, UINT* pctinfo )
535 domdoc *This = impl_from_IXMLDOMDocument2( iface );
537 TRACE("(%p)->(%p)\n", This, pctinfo);
544 static HRESULT WINAPI domdoc_GetTypeInfo(
545 IXMLDOMDocument2 *iface,
546 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
548 domdoc *This = impl_from_IXMLDOMDocument2( iface );
551 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
553 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
558 static HRESULT WINAPI domdoc_GetIDsOfNames(
559 IXMLDOMDocument2 *iface,
566 domdoc *This = impl_from_IXMLDOMDocument2( iface );
570 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
573 if(!rgszNames || cNames == 0 || !rgDispId)
576 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
579 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
580 ITypeInfo_Release(typeinfo);
587 static HRESULT WINAPI domdoc_Invoke(
588 IXMLDOMDocument2 *iface,
593 DISPPARAMS* pDispParams,
595 EXCEPINFO* pExcepInfo,
598 domdoc *This = impl_from_IXMLDOMDocument2( iface );
602 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
603 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
605 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
608 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
609 pVarResult, pExcepInfo, puArgErr);
610 ITypeInfo_Release(typeinfo);
617 static HRESULT WINAPI domdoc_get_nodeName(
618 IXMLDOMDocument2 *iface,
621 domdoc *This = impl_from_IXMLDOMDocument2( iface );
622 return IXMLDOMNode_get_nodeName( IXMLDOMNode_from_impl(&This->node), name );
626 static HRESULT WINAPI domdoc_get_nodeValue(
627 IXMLDOMDocument2 *iface,
630 domdoc *This = impl_from_IXMLDOMDocument2( iface );
631 return IXMLDOMNode_get_nodeValue( IXMLDOMNode_from_impl(&This->node), value );
635 static HRESULT WINAPI domdoc_put_nodeValue(
636 IXMLDOMDocument2 *iface,
639 domdoc *This = impl_from_IXMLDOMDocument2( iface );
640 return IXMLDOMNode_put_nodeValue( IXMLDOMNode_from_impl(&This->node), value );
644 static HRESULT WINAPI domdoc_get_nodeType(
645 IXMLDOMDocument2 *iface,
648 domdoc *This = impl_from_IXMLDOMDocument2( iface );
649 return IXMLDOMNode_get_nodeType( IXMLDOMNode_from_impl(&This->node), type );
653 static HRESULT WINAPI domdoc_get_parentNode(
654 IXMLDOMDocument2 *iface,
655 IXMLDOMNode** parent )
657 domdoc *This = impl_from_IXMLDOMDocument2( iface );
658 return IXMLDOMNode_get_parentNode( IXMLDOMNode_from_impl(&This->node), parent );
662 static HRESULT WINAPI domdoc_get_childNodes(
663 IXMLDOMDocument2 *iface,
664 IXMLDOMNodeList** childList )
666 domdoc *This = impl_from_IXMLDOMDocument2( iface );
667 return IXMLDOMNode_get_childNodes( IXMLDOMNode_from_impl(&This->node), childList );
671 static HRESULT WINAPI domdoc_get_firstChild(
672 IXMLDOMDocument2 *iface,
673 IXMLDOMNode** firstChild )
675 domdoc *This = impl_from_IXMLDOMDocument2( iface );
676 return IXMLDOMNode_get_firstChild( IXMLDOMNode_from_impl(&This->node), firstChild );
680 static HRESULT WINAPI domdoc_get_lastChild(
681 IXMLDOMDocument2 *iface,
682 IXMLDOMNode** lastChild )
684 domdoc *This = impl_from_IXMLDOMDocument2( iface );
685 return IXMLDOMNode_get_lastChild( IXMLDOMNode_from_impl(&This->node), lastChild );
689 static HRESULT WINAPI domdoc_get_previousSibling(
690 IXMLDOMDocument2 *iface,
691 IXMLDOMNode** previousSibling )
693 domdoc *This = impl_from_IXMLDOMDocument2( iface );
694 return IXMLDOMNode_get_previousSibling( IXMLDOMNode_from_impl(&This->node), previousSibling );
698 static HRESULT WINAPI domdoc_get_nextSibling(
699 IXMLDOMDocument2 *iface,
700 IXMLDOMNode** nextSibling )
702 domdoc *This = impl_from_IXMLDOMDocument2( iface );
703 return IXMLDOMNode_get_nextSibling( IXMLDOMNode_from_impl(&This->node), nextSibling );
707 static HRESULT WINAPI domdoc_get_attributes(
708 IXMLDOMDocument2 *iface,
709 IXMLDOMNamedNodeMap** attributeMap )
711 domdoc *This = impl_from_IXMLDOMDocument2( iface );
712 return IXMLDOMNode_get_attributes( IXMLDOMNode_from_impl(&This->node), attributeMap );
716 static HRESULT WINAPI domdoc_insertBefore(
717 IXMLDOMDocument2 *iface,
718 IXMLDOMNode* newChild,
720 IXMLDOMNode** outNewChild )
722 domdoc *This = impl_from_IXMLDOMDocument2( iface );
723 return IXMLDOMNode_insertBefore( IXMLDOMNode_from_impl(&This->node), newChild, refChild, outNewChild );
727 static HRESULT WINAPI domdoc_replaceChild(
728 IXMLDOMDocument2 *iface,
729 IXMLDOMNode* newChild,
730 IXMLDOMNode* oldChild,
731 IXMLDOMNode** outOldChild)
733 domdoc *This = impl_from_IXMLDOMDocument2( iface );
734 return IXMLDOMNode_replaceChild( IXMLDOMNode_from_impl(&This->node), newChild, oldChild, outOldChild );
738 static HRESULT WINAPI domdoc_removeChild(
739 IXMLDOMDocument2 *iface,
740 IXMLDOMNode* childNode,
741 IXMLDOMNode** oldChild)
743 domdoc *This = impl_from_IXMLDOMDocument2( iface );
744 return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), childNode, oldChild );
748 static HRESULT WINAPI domdoc_appendChild(
749 IXMLDOMDocument2 *iface,
750 IXMLDOMNode* newChild,
751 IXMLDOMNode** outNewChild)
753 domdoc *This = impl_from_IXMLDOMDocument2( iface );
754 return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newChild, outNewChild );
758 static HRESULT WINAPI domdoc_hasChildNodes(
759 IXMLDOMDocument2 *iface,
760 VARIANT_BOOL* hasChild)
762 domdoc *This = impl_from_IXMLDOMDocument2( iface );
763 return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), hasChild );
767 static HRESULT WINAPI domdoc_get_ownerDocument(
768 IXMLDOMDocument2 *iface,
769 IXMLDOMDocument** DOMDocument)
771 domdoc *This = impl_from_IXMLDOMDocument2( iface );
772 return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), DOMDocument );
776 static HRESULT WINAPI domdoc_cloneNode(
777 IXMLDOMDocument2 *iface,
779 IXMLDOMNode** cloneRoot)
781 domdoc *This = impl_from_IXMLDOMDocument2( iface );
782 return IXMLDOMNode_cloneNode( IXMLDOMNode_from_impl(&This->node), deep, cloneRoot );
786 static HRESULT WINAPI domdoc_get_nodeTypeString(
787 IXMLDOMDocument2 *iface,
790 domdoc *This = impl_from_IXMLDOMDocument2( iface );
791 return IXMLDOMNode_get_nodeTypeString( IXMLDOMNode_from_impl(&This->node), nodeType );
795 static HRESULT WINAPI domdoc_get_text(
796 IXMLDOMDocument2 *iface,
799 domdoc *This = impl_from_IXMLDOMDocument2( iface );
800 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), text );
804 static HRESULT WINAPI domdoc_put_text(
805 IXMLDOMDocument2 *iface,
808 domdoc *This = impl_from_IXMLDOMDocument2( iface );
809 return IXMLDOMNode_put_text( IXMLDOMNode_from_impl(&This->node), text );
813 static HRESULT WINAPI domdoc_get_specified(
814 IXMLDOMDocument2 *iface,
815 VARIANT_BOOL* isSpecified )
817 domdoc *This = impl_from_IXMLDOMDocument2( iface );
818 return IXMLDOMNode_get_specified( IXMLDOMNode_from_impl(&This->node), isSpecified );
822 static HRESULT WINAPI domdoc_get_definition(
823 IXMLDOMDocument2 *iface,
824 IXMLDOMNode** definitionNode )
826 domdoc *This = impl_from_IXMLDOMDocument2( iface );
827 return IXMLDOMNode_get_definition( IXMLDOMNode_from_impl(&This->node), definitionNode );
831 static HRESULT WINAPI domdoc_get_nodeTypedValue(
832 IXMLDOMDocument2 *iface,
833 VARIANT* typedValue )
835 domdoc *This = impl_from_IXMLDOMDocument2( iface );
836 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
839 static HRESULT WINAPI domdoc_put_nodeTypedValue(
840 IXMLDOMDocument2 *iface,
843 domdoc *This = impl_from_IXMLDOMDocument2( iface );
844 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
848 static HRESULT WINAPI domdoc_get_dataType(
849 IXMLDOMDocument2 *iface,
850 VARIANT* dataTypeName )
852 domdoc *This = impl_from_IXMLDOMDocument2( iface );
853 return IXMLDOMNode_get_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
857 static HRESULT WINAPI domdoc_put_dataType(
858 IXMLDOMDocument2 *iface,
861 domdoc *This = impl_from_IXMLDOMDocument2( iface );
862 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
866 static HRESULT WINAPI domdoc_get_xml(
867 IXMLDOMDocument2 *iface,
870 domdoc *This = impl_from_IXMLDOMDocument2( iface );
871 return IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), xmlString );
875 static HRESULT WINAPI domdoc_transformNode(
876 IXMLDOMDocument2 *iface,
877 IXMLDOMNode* styleSheet,
880 domdoc *This = impl_from_IXMLDOMDocument2( iface );
881 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), styleSheet, xmlString );
885 static HRESULT WINAPI domdoc_selectNodes(
886 IXMLDOMDocument2 *iface,
888 IXMLDOMNodeList** resultList )
890 domdoc *This = impl_from_IXMLDOMDocument2( iface );
891 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), queryString, resultList );
895 static HRESULT WINAPI domdoc_selectSingleNode(
896 IXMLDOMDocument2 *iface,
898 IXMLDOMNode** resultNode )
900 domdoc *This = impl_from_IXMLDOMDocument2( iface );
901 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), queryString, resultNode );
905 static HRESULT WINAPI domdoc_get_parsed(
906 IXMLDOMDocument2 *iface,
907 VARIANT_BOOL* isParsed )
909 domdoc *This = impl_from_IXMLDOMDocument2( iface );
910 return IXMLDOMNode_get_parsed( IXMLDOMNode_from_impl(&This->node), isParsed );
914 static HRESULT WINAPI domdoc_get_namespaceURI(
915 IXMLDOMDocument2 *iface,
918 domdoc *This = impl_from_IXMLDOMDocument2( iface );
919 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), namespaceURI );
923 static HRESULT WINAPI domdoc_get_prefix(
924 IXMLDOMDocument2 *iface,
927 domdoc *This = impl_from_IXMLDOMDocument2( iface );
928 return IXMLDOMNode_get_prefix( IXMLDOMNode_from_impl(&This->node), prefixString );
932 static HRESULT WINAPI domdoc_get_baseName(
933 IXMLDOMDocument2 *iface,
936 domdoc *This = impl_from_IXMLDOMDocument2( iface );
937 return IXMLDOMNode_get_baseName( IXMLDOMNode_from_impl(&This->node), nameString );
941 static HRESULT WINAPI domdoc_transformNodeToObject(
942 IXMLDOMDocument2 *iface,
943 IXMLDOMNode* stylesheet,
944 VARIANT outputObject)
946 domdoc *This = impl_from_IXMLDOMDocument2( iface );
947 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), stylesheet, outputObject );
951 static HRESULT WINAPI domdoc_get_doctype(
952 IXMLDOMDocument2 *iface,
953 IXMLDOMDocumentType** documentType )
955 domdoc *This = impl_from_IXMLDOMDocument2(iface);
956 FIXME("(%p)\n", This);
961 static HRESULT WINAPI domdoc_get_implementation(
962 IXMLDOMDocument2 *iface,
963 IXMLDOMImplementation** impl )
965 domdoc *This = impl_from_IXMLDOMDocument2(iface);
967 TRACE("(%p)->(%p)\n", This, impl);
972 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
977 static HRESULT WINAPI domdoc_get_documentElement(
978 IXMLDOMDocument2 *iface,
979 IXMLDOMElement** DOMElement )
981 domdoc *This = impl_from_IXMLDOMDocument2( iface );
982 xmlDocPtr xmldoc = NULL;
983 xmlNodePtr root = NULL;
984 IXMLDOMNode *element_node;
987 TRACE("(%p)->(%p)\n", This, DOMElement);
994 xmldoc = get_doc( This );
996 root = xmlDocGetRootElement( xmldoc );
1000 element_node = create_node( root );
1001 if(!element_node) return S_FALSE;
1003 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (LPVOID*)DOMElement);
1004 IXMLDOMNode_Release(element_node);
1010 static HRESULT WINAPI domdoc_put_documentElement(
1011 IXMLDOMDocument2 *iface,
1012 IXMLDOMElement* DOMElement )
1014 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1015 IXMLDOMNode *elementNode;
1020 TRACE("(%p)->(%p)\n", This, DOMElement);
1022 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1026 xmlNode = impl_from_IXMLDOMNode( elementNode );
1028 if(!xmlNode->node->parent)
1029 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1030 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1032 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1033 IXMLDOMNode_Release( elementNode );
1036 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1042 static HRESULT WINAPI domdoc_createElement(
1043 IXMLDOMDocument2 *iface,
1045 IXMLDOMElement** element )
1047 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1052 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1054 if (!element || !tagname) return E_INVALIDARG;
1056 V_VT(&type) = VT_I1;
1057 V_I1(&type) = NODE_ELEMENT;
1059 hr = IXMLDOMDocument_createNode(iface, type, tagname, NULL, &node);
1062 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1063 IXMLDOMNode_Release(node);
1070 static HRESULT WINAPI domdoc_createDocumentFragment(
1071 IXMLDOMDocument2 *iface,
1072 IXMLDOMDocumentFragment** frag )
1074 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1079 TRACE("(%p)->(%p)\n", This, frag);
1081 if (!frag) return E_INVALIDARG;
1085 V_VT(&type) = VT_I1;
1086 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1088 hr = IXMLDOMDocument_createNode(iface, type, NULL, NULL, &node);
1091 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1092 IXMLDOMNode_Release(node);
1099 static HRESULT WINAPI domdoc_createTextNode(
1100 IXMLDOMDocument2 *iface,
1102 IXMLDOMText** text )
1104 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1109 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1111 if (!text) return E_INVALIDARG;
1115 V_VT(&type) = VT_I1;
1116 V_I1(&type) = NODE_TEXT;
1118 hr = IXMLDOMDocument2_createNode(iface, type, NULL, NULL, &node);
1121 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1122 IXMLDOMNode_Release(node);
1123 hr = IXMLDOMText_put_data(*text, data);
1130 static HRESULT WINAPI domdoc_createComment(
1131 IXMLDOMDocument2 *iface,
1133 IXMLDOMComment** comment )
1135 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1140 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1142 if (!comment) return E_INVALIDARG;
1146 V_VT(&type) = VT_I1;
1147 V_I1(&type) = NODE_COMMENT;
1149 hr = IXMLDOMDocument2_createNode(iface, type, NULL, NULL, &node);
1152 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1153 IXMLDOMNode_Release(node);
1154 hr = IXMLDOMComment_put_data(*comment, data);
1161 static HRESULT WINAPI domdoc_createCDATASection(
1162 IXMLDOMDocument2 *iface,
1164 IXMLDOMCDATASection** cdata )
1166 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1171 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1173 if (!cdata) return E_INVALIDARG;
1177 V_VT(&type) = VT_I1;
1178 V_I1(&type) = NODE_CDATA_SECTION;
1180 hr = IXMLDOMDocument2_createNode(iface, type, NULL, NULL, &node);
1183 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1184 IXMLDOMNode_Release(node);
1185 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1192 static HRESULT WINAPI domdoc_createProcessingInstruction(
1193 IXMLDOMDocument2 *iface,
1196 IXMLDOMProcessingInstruction** pi )
1198 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1203 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1205 if (!pi) return E_INVALIDARG;
1209 V_VT(&type) = VT_I1;
1210 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1212 hr = IXMLDOMDocument2_createNode(iface, type, target, NULL, &node);
1217 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1218 V_VT(&v_data) = VT_BSTR;
1219 V_BSTR(&v_data) = data;
1221 hr = IXMLDOMNode_put_nodeValue( node, v_data );
1223 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1224 IXMLDOMNode_Release(node);
1231 static HRESULT WINAPI domdoc_createAttribute(
1232 IXMLDOMDocument2 *iface,
1234 IXMLDOMAttribute** attribute )
1236 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1241 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1243 if (!attribute || !name) return E_INVALIDARG;
1245 V_VT(&type) = VT_I1;
1246 V_I1(&type) = NODE_ATTRIBUTE;
1248 hr = IXMLDOMDocument_createNode(iface, type, name, NULL, &node);
1251 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1252 IXMLDOMNode_Release(node);
1259 static HRESULT WINAPI domdoc_createEntityReference(
1260 IXMLDOMDocument2 *iface,
1262 IXMLDOMEntityReference** entityref )
1264 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1269 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1271 if (!entityref) return E_INVALIDARG;
1275 V_VT(&type) = VT_I1;
1276 V_I1(&type) = NODE_ENTITY_REFERENCE;
1278 hr = IXMLDOMDocument2_createNode(iface, type, name, NULL, &node);
1281 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1282 IXMLDOMNode_Release(node);
1289 static HRESULT WINAPI domdoc_getElementsByTagName(
1290 IXMLDOMDocument2 *iface,
1292 IXMLDOMNodeList** resultList )
1294 static const WCHAR xpathformat[] =
1295 { '/','/','*','[','l','o','c','a','l','-','n','a','m','e','(',')','=','\'','%','s','\'',']',0 };
1296 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1299 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagName), resultList);
1301 if (tagName[0] == '*' && tagName[1] == 0)
1303 szPattern = heap_alloc(sizeof(WCHAR)*4);
1304 szPattern[0] = szPattern[1] = '/';
1310 szPattern = heap_alloc(sizeof(WCHAR)*(20+lstrlenW(tagName)+1));
1311 wsprintfW(szPattern, xpathformat, tagName);
1314 hr = queryresult_create((xmlNodePtr)get_doc(This), szPattern, resultList);
1315 heap_free(szPattern);
1320 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1326 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1328 return E_INVALIDARG;
1335 static HRESULT WINAPI domdoc_createNode(
1336 IXMLDOMDocument2 *iface,
1340 IXMLDOMNode** node )
1342 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1343 DOMNodeType node_type;
1348 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1350 if(!node) return E_INVALIDARG;
1352 if(namespaceURI && namespaceURI[0])
1353 FIXME("nodes with namespaces currently not supported.\n");
1355 hr = get_node_type(Type, &node_type);
1356 if(FAILED(hr)) return hr;
1358 TRACE("node_type %d\n", node_type);
1360 /* exit earlier for types that need name */
1364 case NODE_ATTRIBUTE:
1365 case NODE_ENTITY_REFERENCE:
1366 case NODE_PROCESSING_INSTRUCTION:
1367 if (!name || SysStringLen(name) == 0) return E_FAIL;
1372 xml_name = xmlChar_from_wchar(name);
1377 xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
1379 case NODE_ATTRIBUTE:
1380 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1383 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1385 case NODE_CDATA_SECTION:
1386 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1388 case NODE_ENTITY_REFERENCE:
1389 xmlnode = xmlNewReference(get_doc(This), xml_name);
1391 case NODE_PROCESSING_INSTRUCTION:
1392 #ifdef HAVE_XMLNEWDOCPI
1393 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1395 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1400 xmlnode = xmlNewDocComment(get_doc(This), NULL);
1402 case NODE_DOCUMENT_FRAGMENT:
1403 xmlnode = xmlNewDocFragment(get_doc(This));
1405 /* unsupported types */
1407 case NODE_DOCUMENT_TYPE:
1410 heap_free(xml_name);
1411 return E_INVALIDARG;
1413 FIXME("unhandled node type %d\n", node_type);
1418 *node = create_node(xmlnode);
1419 heap_free(xml_name);
1423 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1424 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1431 static HRESULT WINAPI domdoc_nodeFromID(
1432 IXMLDOMDocument2 *iface,
1434 IXMLDOMNode** node )
1436 domdoc *This = impl_from_IXMLDOMDocument2(iface);
1437 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1441 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1446 xmldoc = doparse( ptr, len );
1448 xmldoc->_private = create_priv();
1449 return attach_xmldoc(&This->node, xmldoc);
1455 static HRESULT doread( domdoc *This, LPWSTR filename )
1460 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1465 detach_bsc(This->bsc);
1471 static HRESULT WINAPI domdoc_load(
1472 IXMLDOMDocument2 *iface,
1474 VARIANT_BOOL* isSuccessful )
1476 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1477 LPWSTR filename = NULL;
1478 HRESULT hr = S_FALSE;
1479 IXMLDOMDocument2 *pNewDoc = NULL;
1480 IStream *pStream = NULL;
1483 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
1485 *isSuccessful = VARIANT_FALSE;
1487 assert( &This->node );
1489 switch( V_VT(&xmlSource) )
1492 filename = V_BSTR(&xmlSource);
1495 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument2, (void**)&pNewDoc);
1500 domdoc *newDoc = impl_from_IXMLDOMDocument2( pNewDoc );
1501 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1502 hr = attach_xmldoc(&This->node, xmldoc);
1505 *isSuccessful = VARIANT_TRUE;
1510 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1513 IPersistStream *pDocStream;
1514 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1517 hr = xmldoc_IPersistStream_Load(pDocStream, pStream);
1518 IStream_Release(pStream);
1521 *isSuccessful = VARIANT_TRUE;
1523 TRACE("Using ID_IStream to load Document\n");
1528 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1533 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1538 /* ISequentialStream */
1539 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1543 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1546 TRACE("filename (%s)\n", debugstr_w(filename));
1550 hr = doread( This, filename );
1553 This->error = E_FAIL;
1556 hr = This->error = S_OK;
1557 *isSuccessful = VARIANT_TRUE;
1561 if(!filename || FAILED(hr)) {
1562 xmldoc = xmlNewDoc(NULL);
1563 xmldoc->_private = create_priv();
1564 hr = attach_xmldoc(&This->node, xmldoc);
1569 TRACE("ret (%d)\n", hr);
1575 static HRESULT WINAPI domdoc_get_readyState(
1576 IXMLDOMDocument2 *iface,
1579 domdoc *This = impl_from_IXMLDOMDocument2(iface);
1580 FIXME("(%p)->(%p)\n", This, value);
1585 static HRESULT WINAPI domdoc_get_parseError(
1586 IXMLDOMDocument2 *iface,
1587 IXMLDOMParseError** errorObj )
1589 BSTR error_string = NULL;
1590 static const WCHAR err[] = {'e','r','r','o','r',0};
1591 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1593 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
1596 error_string = SysAllocString(err);
1598 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
1599 if(!*errorObj) return E_OUTOFMEMORY;
1604 static HRESULT WINAPI domdoc_get_url(
1605 IXMLDOMDocument2 *iface,
1608 domdoc *This = impl_from_IXMLDOMDocument2(iface);
1609 FIXME("(%p)->(%p)\n", This, urlString);
1614 static HRESULT WINAPI domdoc_get_async(
1615 IXMLDOMDocument2 *iface,
1616 VARIANT_BOOL* isAsync )
1618 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1620 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
1621 *isAsync = This->async;
1626 static HRESULT WINAPI domdoc_put_async(
1627 IXMLDOMDocument2 *iface,
1628 VARIANT_BOOL isAsync )
1630 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1632 TRACE("(%p)->(%d)\n", This, isAsync);
1633 This->async = isAsync;
1638 static HRESULT WINAPI domdoc_abort(
1639 IXMLDOMDocument2 *iface )
1641 domdoc *This = impl_from_IXMLDOMDocument2(iface);
1642 FIXME("%p\n", This);
1647 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
1649 UINT len, blen = SysStringLen( bstr );
1652 len = WideCharToMultiByte( CP_UTF8, 0, bstr, blen, NULL, 0, NULL, NULL );
1653 str = heap_alloc( len );
1656 WideCharToMultiByte( CP_UTF8, 0, bstr, blen, str, len, NULL, NULL );
1662 static HRESULT WINAPI domdoc_loadXML(
1663 IXMLDOMDocument2 *iface,
1665 VARIANT_BOOL* isSuccessful )
1667 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1668 xmlDocPtr xmldoc = NULL;
1671 HRESULT hr = S_FALSE, hr2;
1673 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
1675 assert ( &This->node );
1679 *isSuccessful = VARIANT_FALSE;
1681 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
1683 xmldoc = doparse( str, len );
1686 This->error = E_FAIL;
1689 hr = This->error = S_OK;
1690 *isSuccessful = VARIANT_TRUE;
1695 xmldoc = xmlNewDoc(NULL);
1697 xmldoc->_private = create_priv();
1698 hr2 = attach_xmldoc( &This->node, xmldoc );
1705 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer,
1710 if(!WriteFile(ctx, buffer, len, &written, NULL))
1712 WARN("write error\n");
1719 static int XMLCALL domdoc_save_closecallback(void *ctx)
1721 return CloseHandle(ctx) ? 0 : -1;
1724 static HRESULT WINAPI domdoc_save(
1725 IXMLDOMDocument2 *iface,
1726 VARIANT destination )
1728 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1733 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
1734 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
1736 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
1738 FIXME("Unhandled vt %d\n", V_VT(&destination));
1742 if(V_VT(&destination) == VT_UNKNOWN)
1744 IUnknown *pUnk = V_UNKNOWN(&destination);
1745 IXMLDOMDocument *pDocument;
1747 ret = IXMLDOMDocument_QueryInterface(pUnk, &IID_IXMLDOMDocument2, (void**)&pDocument);
1751 VARIANT_BOOL bSuccessful;
1753 ret = IXMLDOMDocument_get_xml(iface, &bXML);
1756 ret = IXMLDOMDocument_loadXML(pDocument, bXML, &bSuccessful);
1758 SysFreeString(bXML);
1761 IXMLDOMDocument_Release(pDocument);
1764 TRACE("ret %d\n", ret);
1769 handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
1770 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1771 if( handle == INVALID_HANDLE_VALUE )
1773 WARN("failed to create file\n");
1777 /* disable top XML declaration */
1778 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
1779 handle, NULL, XML_SAVE_NO_DECL);
1782 CloseHandle(handle);
1786 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
1787 /* will close file through close callback */
1793 static HRESULT WINAPI domdoc_get_validateOnParse(
1794 IXMLDOMDocument2 *iface,
1795 VARIANT_BOOL* isValidating )
1797 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1799 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
1800 *isValidating = This->validating;
1805 static HRESULT WINAPI domdoc_put_validateOnParse(
1806 IXMLDOMDocument2 *iface,
1807 VARIANT_BOOL isValidating )
1809 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1811 TRACE("(%p)->(%d)\n", This, isValidating);
1812 This->validating = isValidating;
1817 static HRESULT WINAPI domdoc_get_resolveExternals(
1818 IXMLDOMDocument2 *iface,
1819 VARIANT_BOOL* isResolving )
1821 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1823 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
1824 *isResolving = This->resolving;
1829 static HRESULT WINAPI domdoc_put_resolveExternals(
1830 IXMLDOMDocument2 *iface,
1831 VARIANT_BOOL isResolving )
1833 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1835 TRACE("(%p)->(%d)\n", This, isResolving);
1836 This->resolving = isResolving;
1841 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
1842 IXMLDOMDocument2 *iface,
1843 VARIANT_BOOL* isPreserving )
1845 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1847 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->preserving);
1848 *isPreserving = This->preserving;
1853 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
1854 IXMLDOMDocument2 *iface,
1855 VARIANT_BOOL isPreserving )
1857 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1859 TRACE("(%p)->(%d)\n", This, isPreserving);
1860 This->preserving = isPreserving;
1865 static HRESULT WINAPI domdoc_put_onReadyStateChange(
1866 IXMLDOMDocument2 *iface,
1867 VARIANT readyStateChangeSink )
1869 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1870 FIXME("%p\n", This);
1875 static HRESULT WINAPI domdoc_put_onDataAvailable(
1876 IXMLDOMDocument2 *iface,
1877 VARIANT onDataAvailableSink )
1879 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1880 FIXME("%p\n", This);
1884 static HRESULT WINAPI domdoc_put_onTransformNode(
1885 IXMLDOMDocument2 *iface,
1886 VARIANT onTransformNodeSink )
1888 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1889 FIXME("%p\n", This);
1893 static HRESULT WINAPI domdoc_get_namespaces(
1894 IXMLDOMDocument2* iface,
1895 IXMLDOMSchemaCollection** schemaCollection )
1897 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1898 FIXME("(%p)->(%p)\n", This, schemaCollection);
1902 static HRESULT WINAPI domdoc_get_schemas(
1903 IXMLDOMDocument2* iface,
1906 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1907 HRESULT hr = S_FALSE;
1908 IXMLDOMSchemaCollection *cur_schema = This->schema;
1910 TRACE("(%p)->(%p)\n", This, var1);
1912 VariantInit(var1); /* Test shows we don't call VariantClear here */
1913 V_VT(var1) = VT_NULL;
1917 hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
1919 V_VT(var1) = VT_DISPATCH;
1924 static HRESULT WINAPI domdoc_putref_schemas(
1925 IXMLDOMDocument2* iface,
1928 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1929 HRESULT hr = E_FAIL;
1930 IXMLDOMSchemaCollection *new_schema = NULL;
1932 FIXME("(%p): semi-stub\n", This);
1936 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1940 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1949 WARN("Can't get schema from vt %x\n", V_VT(&var1));
1954 IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
1955 if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
1961 static HRESULT WINAPI domdoc_validate(
1962 IXMLDOMDocument2* iface,
1963 IXMLDOMParseError** err)
1965 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1966 FIXME("(%p)->(%p)\n", This, err);
1970 static HRESULT WINAPI domdoc_setProperty(
1971 IXMLDOMDocument2* iface,
1975 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1977 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
1979 if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
1985 V_VT(&varStr) = VT_EMPTY;
1986 if (V_VT(&var) != VT_BSTR)
1988 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
1990 bstr = V_BSTR(&varStr);
1993 bstr = V_BSTR(&var);
1996 if (lstrcmpiW(bstr, SZ_VALUE_XPATH) == 0)
1997 This->bUseXPath = TRUE;
1998 else if (lstrcmpiW(bstr, SZ_VALUE_XSLPATTERN) == 0)
1999 This->bUseXPath = FALSE;
2003 VariantClear(&varStr);
2007 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2011 static HRESULT WINAPI domdoc_getProperty(
2012 IXMLDOMDocument2* iface,
2016 domdoc *This = impl_from_IXMLDOMDocument2( iface );
2018 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2021 return E_INVALIDARG;
2022 if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
2024 V_VT(var) = VT_BSTR;
2025 if (This->bUseXPath)
2026 V_BSTR(var) = SysAllocString(SZ_VALUE_XPATH);
2028 V_BSTR(var) = SysAllocString(SZ_VALUE_XSLPATTERN);
2032 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2036 static const struct IXMLDOMDocument2Vtbl domdoc_vtbl =
2038 domdoc_QueryInterface,
2041 domdoc_GetTypeInfoCount,
2043 domdoc_GetIDsOfNames,
2045 domdoc_get_nodeName,
2046 domdoc_get_nodeValue,
2047 domdoc_put_nodeValue,
2048 domdoc_get_nodeType,
2049 domdoc_get_parentNode,
2050 domdoc_get_childNodes,
2051 domdoc_get_firstChild,
2052 domdoc_get_lastChild,
2053 domdoc_get_previousSibling,
2054 domdoc_get_nextSibling,
2055 domdoc_get_attributes,
2056 domdoc_insertBefore,
2057 domdoc_replaceChild,
2060 domdoc_hasChildNodes,
2061 domdoc_get_ownerDocument,
2063 domdoc_get_nodeTypeString,
2066 domdoc_get_specified,
2067 domdoc_get_definition,
2068 domdoc_get_nodeTypedValue,
2069 domdoc_put_nodeTypedValue,
2070 domdoc_get_dataType,
2071 domdoc_put_dataType,
2073 domdoc_transformNode,
2075 domdoc_selectSingleNode,
2077 domdoc_get_namespaceURI,
2079 domdoc_get_baseName,
2080 domdoc_transformNodeToObject,
2082 domdoc_get_implementation,
2083 domdoc_get_documentElement,
2084 domdoc_put_documentElement,
2085 domdoc_createElement,
2086 domdoc_createDocumentFragment,
2087 domdoc_createTextNode,
2088 domdoc_createComment,
2089 domdoc_createCDATASection,
2090 domdoc_createProcessingInstruction,
2091 domdoc_createAttribute,
2092 domdoc_createEntityReference,
2093 domdoc_getElementsByTagName,
2097 domdoc_get_readyState,
2098 domdoc_get_parseError,
2105 domdoc_get_validateOnParse,
2106 domdoc_put_validateOnParse,
2107 domdoc_get_resolveExternals,
2108 domdoc_put_resolveExternals,
2109 domdoc_get_preserveWhiteSpace,
2110 domdoc_put_preserveWhiteSpace,
2111 domdoc_put_onReadyStateChange,
2112 domdoc_put_onDataAvailable,
2113 domdoc_put_onTransformNode,
2114 domdoc_get_namespaces,
2116 domdoc_putref_schemas,
2122 /* xmldoc implementation of IObjectWithSite */
2123 static HRESULT WINAPI
2124 xmldoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
2126 domdoc *This = impl_from_IObjectWithSite(iface);
2127 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppvObject );
2131 xmldoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
2133 domdoc *This = impl_from_IObjectWithSite(iface);
2134 return IXMLDocument_AddRef((IXMLDocument *)This);
2138 xmldoc_ObjectWithSite_Release( IObjectWithSite* iface )
2140 domdoc *This = impl_from_IObjectWithSite(iface);
2141 return IXMLDocument_Release((IXMLDocument *)This);
2144 static HRESULT WINAPI
2145 xmldoc_GetSite( IObjectWithSite *iface, REFIID iid, void ** ppvSite )
2147 domdoc *This = impl_from_IObjectWithSite(iface);
2149 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
2154 return IUnknown_QueryInterface( This->site, iid, ppvSite );
2157 static HRESULT WINAPI
2158 xmldoc_SetSite( IObjectWithSite *iface, IUnknown *punk )
2160 domdoc *This = impl_from_IObjectWithSite(iface);
2162 TRACE("(%p)->(%p)\n", iface, punk);
2168 IUnknown_Release( This->site );
2176 IUnknown_AddRef( punk );
2179 IUnknown_Release( This->site );
2186 static const IObjectWithSiteVtbl domdocObjectSite =
2188 xmldoc_ObjectWithSite_QueryInterface,
2189 xmldoc_ObjectWithSite_AddRef,
2190 xmldoc_ObjectWithSite_Release,
2195 static HRESULT WINAPI xmldoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
2197 domdoc *This = impl_from_IObjectSafety(iface);
2198 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppv );
2201 static ULONG WINAPI xmldoc_Safety_AddRef(IObjectSafety *iface)
2203 domdoc *This = impl_from_IObjectSafety(iface);
2204 return IXMLDocument_AddRef((IXMLDocument *)This);
2207 static ULONG WINAPI xmldoc_Safety_Release(IObjectSafety *iface)
2209 domdoc *This = impl_from_IObjectSafety(iface);
2210 return IXMLDocument_Release((IXMLDocument *)This);
2213 #define SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
2215 static HRESULT WINAPI xmldoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2216 DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
2218 domdoc *This = impl_from_IObjectSafety(iface);
2220 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
2222 if(!pdwSupportedOptions || !pdwEnabledOptions)
2225 *pdwSupportedOptions = SUPPORTED_OPTIONS;
2226 *pdwEnabledOptions = This->safeopt;
2231 static HRESULT WINAPI xmldoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2232 DWORD dwOptionSetMask, DWORD dwEnabledOptions)
2234 domdoc *This = impl_from_IObjectSafety(iface);
2236 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
2238 if(dwOptionSetMask & ~SUPPORTED_OPTIONS)
2241 This->safeopt = dwEnabledOptions & dwEnabledOptions;
2245 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
2246 xmldoc_Safety_QueryInterface,
2247 xmldoc_Safety_AddRef,
2248 xmldoc_Safety_Release,
2249 xmldoc_Safety_GetInterfaceSafetyOptions,
2250 xmldoc_Safety_SetInterfaceSafetyOptions
2254 static const tid_t domdoc_iface_tids[] = {
2256 IXMLDOMDocument_tid,
2257 IXMLDOMDocument2_tid,
2260 static dispex_static_data_t domdoc_dispex = {
2262 IXMLDOMDocument2_tid,
2267 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument2 **document)
2271 doc = heap_alloc( sizeof (*doc) );
2273 return E_OUTOFMEMORY;
2275 doc->lpVtbl = &domdoc_vtbl;
2276 doc->lpvtblIPersistStream = &xmldoc_IPersistStream_VTable;
2277 doc->lpvtblIObjectWithSite = &domdocObjectSite;
2278 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
2279 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
2281 doc->async = VARIANT_TRUE;
2282 doc->validating = 0;
2284 doc->preserving = 0;
2285 doc->bUseXPath = FALSE;
2293 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IUnknown*)&doc->lpVtbl, &domdoc_dispex);
2295 *document = (IXMLDOMDocument2*)&doc->lpVtbl;
2297 TRACE("returning iface %p\n", *document);
2301 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2306 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
2308 xmldoc = xmlNewDoc(NULL);
2310 return E_OUTOFMEMORY;
2312 xmldoc->_private = create_priv();
2314 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument2**)ppObj);
2321 IUnknown* create_domdoc( xmlNodePtr document )
2326 TRACE("(%p)\n", document);
2328 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument2**)&pObj);
2337 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2339 MESSAGE("This program tried to use a DOMDocument object, but\n"
2340 "libxml2 support was not present at compile time.\n");