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 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};
51 static const WCHAR SZ_VALUE_XPATH[] = {'X','P','a','t','h',0};
52 static const WCHAR SZ_VALUE_XSLPATTERN[] = {'X','S','L','P','a','t','t','e','r','n',0};
54 typedef struct _domdoc
56 const struct IXMLDOMDocument2Vtbl *lpVtbl;
57 const struct IPersistStreamVtbl *lpvtblIPersistStream;
58 const struct IObjectWithSiteVtbl *lpvtblIObjectWithSite;
59 const struct IObjectSafetyVtbl *lpvtblIObjectSafety;
62 VARIANT_BOOL validating;
63 VARIANT_BOOL resolving;
64 VARIANT_BOOL preserving;
68 IXMLDOMSchemaCollection *schema;
86 In native windows, the whole lifetime management of XMLDOMNodes is
87 managed automatically using reference counts. Wine emulates that by
88 maintaining a reference count to the document that is increased for
89 each IXMLDOMNode pointer passed out for this document. If all these
90 pointers are gone, the document is unreachable and gets freed, that
91 is, all nodes in the tree of the document get freed.
93 You are able to create nodes that are associated to a document (in
94 fact, in msxml's XMLDOM model, all nodes are associated to a document),
95 but not in the tree of that document, for example using the createFoo
96 functions from IXMLDOMDocument. These nodes do not get cleaned up
97 by libxml, so we have to do it ourselves.
99 To catch these nodes, a list of "orphan nodes" is introduced.
100 It contains pointers to all roots of node trees that are
101 associated with the document without being part of the document
102 tree. All nodes with parent==NULL (except for the document root nodes)
103 should be in the orphan node list of their document. All orphan nodes
104 get freed together with the document itself.
107 typedef struct _xmldoc_priv {
112 typedef struct _orphan_entry {
117 static inline xmldoc_priv * priv_from_xmlDocPtr(xmlDocPtr doc)
119 return doc->_private;
122 static xmldoc_priv * create_priv(void)
125 priv = HeapAlloc( GetProcessHeap(), 0, sizeof (*priv) );
130 list_init( &priv->orphans );
136 static xmlDocPtr doparse( char *ptr, int len )
138 #ifdef HAVE_XMLREADMEMORY
140 * use xmlReadMemory if possible so we can suppress
141 * writing errors to stderr
143 return xmlReadMemory( ptr, len, NULL, NULL,
144 XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS );
146 return xmlParseMemory( ptr, len );
150 LONG xmldoc_add_ref(xmlDocPtr doc)
152 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
157 LONG xmldoc_release(xmlDocPtr doc)
159 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
160 LONG ref = InterlockedDecrement(&priv->refs);
164 orphan_entry *orphan, *orphan2;
165 TRACE("freeing docptr %p\n", doc);
167 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
169 xmlFreeNode( orphan->node );
170 HeapFree( GetProcessHeap(), 0, orphan );
172 HeapFree(GetProcessHeap(), 0, doc->_private);
180 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
182 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
185 entry = HeapAlloc( GetProcessHeap(), 0, sizeof (*entry) );
187 return E_OUTOFMEMORY;
190 list_add_head( &priv->orphans, &entry->entry );
194 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
196 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
197 orphan_entry *entry, *entry2;
199 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
201 if( entry->node == node )
203 list_remove( &entry->entry );
204 HeapFree( GetProcessHeap(), 0, entry );
212 static void attach_xmlnode( IXMLDOMNode *node, xmlNodePtr xml )
214 xmlnode *This = impl_from_IXMLDOMNode( node );
217 xmldoc_release(This->node->doc);
221 xmldoc_add_ref(This->node->doc);
226 static inline domdoc *impl_from_IXMLDOMDocument2( IXMLDOMDocument2 *iface )
228 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
231 static inline xmlDocPtr get_doc( domdoc *This )
233 return (xmlDocPtr) xmlNodePtr_from_domnode( This->node, XML_DOCUMENT_NODE );
236 static inline domdoc *impl_from_IPersistStream(IPersistStream *iface)
238 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStream));
241 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
243 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
246 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
248 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
252 /************************************************************************
253 * xmldoc implementation of IPersistStream.
255 static HRESULT WINAPI xmldoc_IPersistStream_QueryInterface(
256 IPersistStream *iface, REFIID riid, LPVOID *ppvObj)
258 domdoc *this = impl_from_IPersistStream(iface);
259 return IXMLDocument_QueryInterface((IXMLDocument *)this, riid, ppvObj);
262 static ULONG WINAPI xmldoc_IPersistStream_AddRef(
263 IPersistStream *iface)
265 domdoc *this = impl_from_IPersistStream(iface);
266 return IXMLDocument_AddRef((IXMLDocument *)this);
269 static ULONG WINAPI xmldoc_IPersistStream_Release(
270 IPersistStream *iface)
272 domdoc *this = impl_from_IPersistStream(iface);
273 return IXMLDocument_Release((IXMLDocument *)this);
276 static HRESULT WINAPI xmldoc_IPersistStream_GetClassID(
277 IPersistStream *iface, CLSID *classid)
279 TRACE("(%p,%p): stub!\n", iface, classid);
284 *classid = CLSID_DOMDocument2;
289 static HRESULT WINAPI xmldoc_IPersistStream_IsDirty(
290 IPersistStream *iface)
292 domdoc *This = impl_from_IPersistStream(iface);
294 FIXME("(%p->%p): stub!\n", iface, This);
299 static HRESULT WINAPI xmldoc_IPersistStream_Load(
300 IPersistStream *iface, LPSTREAM pStm)
302 domdoc *This = impl_from_IPersistStream(iface);
305 DWORD read, written, len;
308 xmlDocPtr xmldoc = NULL;
310 TRACE("(%p, %p)\n", iface, pStm);
315 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
321 IStream_Read(pStm, buf, sizeof(buf), &read);
322 hr = IStream_Write(This->stream, buf, read, &written);
323 } while(SUCCEEDED(hr) && written != 0 && read != 0);
327 ERR("Failed to copy stream\n");
331 hr = GetHGlobalFromStream(This->stream, &hglobal);
335 len = GlobalSize(hglobal);
336 ptr = GlobalLock(hglobal);
338 xmldoc = parse_xml(ptr, len);
339 GlobalUnlock(hglobal);
343 ERR("Failed to parse xml\n");
347 xmldoc->_private = create_priv();
348 attach_xmlnode( This->node, (xmlNodePtr)xmldoc );
353 static HRESULT WINAPI xmldoc_IPersistStream_Save(
354 IPersistStream *iface, LPSTREAM pStm, BOOL fClearDirty)
356 FIXME("(%p, %p, %d): stub!\n", iface, pStm, fClearDirty);
360 static HRESULT WINAPI xmldoc_IPersistStream_GetSizeMax(
361 IPersistStream *iface, ULARGE_INTEGER *pcbSize)
363 TRACE("(%p, %p): stub!\n", iface, pcbSize);
367 static const IPersistStreamVtbl xmldoc_IPersistStream_VTable =
369 xmldoc_IPersistStream_QueryInterface,
370 xmldoc_IPersistStream_AddRef,
371 xmldoc_IPersistStream_Release,
372 xmldoc_IPersistStream_GetClassID,
373 xmldoc_IPersistStream_IsDirty,
374 xmldoc_IPersistStream_Load,
375 xmldoc_IPersistStream_Save,
376 xmldoc_IPersistStream_GetSizeMax,
379 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument2 *iface, REFIID riid, void** ppvObject )
381 domdoc *This = impl_from_IXMLDOMDocument2( iface );
383 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
387 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
388 IsEqualGUID( riid, &IID_IDispatch ) ||
389 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
390 IsEqualGUID( riid, &IID_IXMLDOMDocument2 ) )
394 else if ( IsEqualGUID( riid, &IID_IXMLDOMNode ) )
396 return IUnknown_QueryInterface(This->node_unk, riid, ppvObject);
398 else if (IsEqualGUID(&IID_IPersistStream, riid))
400 *ppvObject = (IPersistStream*)&(This->lpvtblIPersistStream);
402 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
404 *ppvObject = (IObjectWithSite*)&(This->lpvtblIObjectWithSite);
406 else if(dispex_query_interface(&This->dispex, riid, ppvObject))
408 return *ppvObject ? S_OK : E_NOINTERFACE;
410 else if(IsEqualGUID(&IID_IRunnableObject, riid))
412 TRACE("IID_IRunnableObject not supported returning NULL\n");
413 return E_NOINTERFACE;
417 FIXME("interface %s not implemented\n", debugstr_guid(riid));
418 return E_NOINTERFACE;
421 IXMLDOMDocument_AddRef( iface );
427 static ULONG WINAPI domdoc_AddRef(
428 IXMLDOMDocument2 *iface )
430 domdoc *This = impl_from_IXMLDOMDocument2( iface );
431 TRACE("%p\n", This );
432 return InterlockedIncrement( &This->ref );
436 static ULONG WINAPI domdoc_Release(
437 IXMLDOMDocument2 *iface )
439 domdoc *This = impl_from_IXMLDOMDocument2( iface );
442 TRACE("%p\n", This );
444 ref = InterlockedDecrement( &This->ref );
448 detach_bsc(This->bsc);
451 IUnknown_Release( This->site );
452 IUnknown_Release( This->node_unk );
453 if(This->schema) IXMLDOMSchemaCollection_Release( This->schema );
454 if (This->stream) IStream_Release(This->stream);
455 HeapFree( GetProcessHeap(), 0, This );
461 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument2 *iface, UINT* pctinfo )
463 domdoc *This = impl_from_IXMLDOMDocument2( iface );
465 TRACE("(%p)->(%p)\n", This, pctinfo);
472 static HRESULT WINAPI domdoc_GetTypeInfo(
473 IXMLDOMDocument2 *iface,
474 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
476 domdoc *This = impl_from_IXMLDOMDocument2( iface );
479 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
481 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
486 static HRESULT WINAPI domdoc_GetIDsOfNames(
487 IXMLDOMDocument2 *iface,
494 domdoc *This = impl_from_IXMLDOMDocument2( iface );
498 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
501 if(!rgszNames || cNames == 0 || !rgDispId)
504 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
507 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
508 ITypeInfo_Release(typeinfo);
515 static HRESULT WINAPI domdoc_Invoke(
516 IXMLDOMDocument2 *iface,
521 DISPPARAMS* pDispParams,
523 EXCEPINFO* pExcepInfo,
526 domdoc *This = impl_from_IXMLDOMDocument2( iface );
530 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
531 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
533 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
536 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
537 pVarResult, pExcepInfo, puArgErr);
538 ITypeInfo_Release(typeinfo);
545 static HRESULT WINAPI domdoc_get_nodeName(
546 IXMLDOMDocument2 *iface,
549 domdoc *This = impl_from_IXMLDOMDocument2( iface );
550 return IXMLDOMNode_get_nodeName( This->node, name );
554 static HRESULT WINAPI domdoc_get_nodeValue(
555 IXMLDOMDocument2 *iface,
558 domdoc *This = impl_from_IXMLDOMDocument2( iface );
559 return IXMLDOMNode_get_nodeValue( This->node, value );
563 static HRESULT WINAPI domdoc_put_nodeValue(
564 IXMLDOMDocument2 *iface,
567 domdoc *This = impl_from_IXMLDOMDocument2( iface );
568 return IXMLDOMNode_put_nodeValue( This->node, value );
572 static HRESULT WINAPI domdoc_get_nodeType(
573 IXMLDOMDocument2 *iface,
576 domdoc *This = impl_from_IXMLDOMDocument2( iface );
577 return IXMLDOMNode_get_nodeType( This->node, type );
581 static HRESULT WINAPI domdoc_get_parentNode(
582 IXMLDOMDocument2 *iface,
583 IXMLDOMNode** parent )
585 domdoc *This = impl_from_IXMLDOMDocument2( iface );
586 return IXMLDOMNode_get_parentNode( This->node, parent );
590 static HRESULT WINAPI domdoc_get_childNodes(
591 IXMLDOMDocument2 *iface,
592 IXMLDOMNodeList** childList )
594 domdoc *This = impl_from_IXMLDOMDocument2( iface );
595 return IXMLDOMNode_get_childNodes( This->node, childList );
599 static HRESULT WINAPI domdoc_get_firstChild(
600 IXMLDOMDocument2 *iface,
601 IXMLDOMNode** firstChild )
603 domdoc *This = impl_from_IXMLDOMDocument2( iface );
604 return IXMLDOMNode_get_firstChild( This->node, firstChild );
608 static HRESULT WINAPI domdoc_get_lastChild(
609 IXMLDOMDocument2 *iface,
610 IXMLDOMNode** lastChild )
612 domdoc *This = impl_from_IXMLDOMDocument2( iface );
613 return IXMLDOMNode_get_lastChild( This->node, lastChild );
617 static HRESULT WINAPI domdoc_get_previousSibling(
618 IXMLDOMDocument2 *iface,
619 IXMLDOMNode** previousSibling )
621 domdoc *This = impl_from_IXMLDOMDocument2( iface );
622 return IXMLDOMNode_get_previousSibling( This->node, previousSibling );
626 static HRESULT WINAPI domdoc_get_nextSibling(
627 IXMLDOMDocument2 *iface,
628 IXMLDOMNode** nextSibling )
630 domdoc *This = impl_from_IXMLDOMDocument2( iface );
631 return IXMLDOMNode_get_nextSibling( This->node, nextSibling );
635 static HRESULT WINAPI domdoc_get_attributes(
636 IXMLDOMDocument2 *iface,
637 IXMLDOMNamedNodeMap** attributeMap )
639 domdoc *This = impl_from_IXMLDOMDocument2( iface );
640 return IXMLDOMNode_get_attributes( This->node, attributeMap );
644 static HRESULT WINAPI domdoc_insertBefore(
645 IXMLDOMDocument2 *iface,
646 IXMLDOMNode* newChild,
648 IXMLDOMNode** outNewChild )
650 domdoc *This = impl_from_IXMLDOMDocument2( iface );
651 return IXMLDOMNode_insertBefore( This->node, newChild, refChild, outNewChild );
655 static HRESULT WINAPI domdoc_replaceChild(
656 IXMLDOMDocument2 *iface,
657 IXMLDOMNode* newChild,
658 IXMLDOMNode* oldChild,
659 IXMLDOMNode** outOldChild)
661 domdoc *This = impl_from_IXMLDOMDocument2( iface );
662 return IXMLDOMNode_replaceChild( This->node, newChild, oldChild, outOldChild );
666 static HRESULT WINAPI domdoc_removeChild(
667 IXMLDOMDocument2 *iface,
668 IXMLDOMNode* childNode,
669 IXMLDOMNode** oldChild)
671 domdoc *This = impl_from_IXMLDOMDocument2( iface );
672 return IXMLDOMNode_removeChild( This->node, childNode, oldChild );
676 static HRESULT WINAPI domdoc_appendChild(
677 IXMLDOMDocument2 *iface,
678 IXMLDOMNode* newChild,
679 IXMLDOMNode** outNewChild)
681 domdoc *This = impl_from_IXMLDOMDocument2( iface );
682 return IXMLDOMNode_appendChild( This->node, newChild, outNewChild );
686 static HRESULT WINAPI domdoc_hasChildNodes(
687 IXMLDOMDocument2 *iface,
688 VARIANT_BOOL* hasChild)
690 domdoc *This = impl_from_IXMLDOMDocument2( iface );
691 return IXMLDOMNode_hasChildNodes( This->node, hasChild );
695 static HRESULT WINAPI domdoc_get_ownerDocument(
696 IXMLDOMDocument2 *iface,
697 IXMLDOMDocument** DOMDocument)
699 domdoc *This = impl_from_IXMLDOMDocument2( iface );
700 return IXMLDOMNode_get_ownerDocument( This->node, DOMDocument );
704 static HRESULT WINAPI domdoc_cloneNode(
705 IXMLDOMDocument2 *iface,
707 IXMLDOMNode** cloneRoot)
709 domdoc *This = impl_from_IXMLDOMDocument2( iface );
710 return IXMLDOMNode_cloneNode( This->node, deep, cloneRoot );
714 static HRESULT WINAPI domdoc_get_nodeTypeString(
715 IXMLDOMDocument2 *iface,
718 domdoc *This = impl_from_IXMLDOMDocument2( iface );
719 return IXMLDOMNode_get_nodeTypeString( This->node, nodeType );
723 static HRESULT WINAPI domdoc_get_text(
724 IXMLDOMDocument2 *iface,
727 domdoc *This = impl_from_IXMLDOMDocument2( iface );
728 return IXMLDOMNode_get_text( This->node, text );
732 static HRESULT WINAPI domdoc_put_text(
733 IXMLDOMDocument2 *iface,
736 domdoc *This = impl_from_IXMLDOMDocument2( iface );
737 return IXMLDOMNode_put_text( This->node, text );
741 static HRESULT WINAPI domdoc_get_specified(
742 IXMLDOMDocument2 *iface,
743 VARIANT_BOOL* isSpecified )
745 domdoc *This = impl_from_IXMLDOMDocument2( iface );
746 return IXMLDOMNode_get_specified( This->node, isSpecified );
750 static HRESULT WINAPI domdoc_get_definition(
751 IXMLDOMDocument2 *iface,
752 IXMLDOMNode** definitionNode )
754 domdoc *This = impl_from_IXMLDOMDocument2( iface );
755 return IXMLDOMNode_get_definition( This->node, definitionNode );
759 static HRESULT WINAPI domdoc_get_nodeTypedValue(
760 IXMLDOMDocument2 *iface,
761 VARIANT* typedValue )
763 domdoc *This = impl_from_IXMLDOMDocument2( iface );
764 return IXMLDOMNode_get_nodeTypedValue( This->node, typedValue );
767 static HRESULT WINAPI domdoc_put_nodeTypedValue(
768 IXMLDOMDocument2 *iface,
771 domdoc *This = impl_from_IXMLDOMDocument2( iface );
772 return IXMLDOMNode_put_nodeTypedValue( This->node, typedValue );
776 static HRESULT WINAPI domdoc_get_dataType(
777 IXMLDOMDocument2 *iface,
778 VARIANT* dataTypeName )
780 domdoc *This = impl_from_IXMLDOMDocument2( iface );
781 return IXMLDOMNode_get_dataType( This->node, dataTypeName );
785 static HRESULT WINAPI domdoc_put_dataType(
786 IXMLDOMDocument2 *iface,
789 domdoc *This = impl_from_IXMLDOMDocument2( iface );
790 return IXMLDOMNode_put_dataType( This->node, dataTypeName );
794 static HRESULT WINAPI domdoc_get_xml(
795 IXMLDOMDocument2 *iface,
798 domdoc *This = impl_from_IXMLDOMDocument2( iface );
799 return IXMLDOMNode_get_xml( This->node, xmlString );
803 static HRESULT WINAPI domdoc_transformNode(
804 IXMLDOMDocument2 *iface,
805 IXMLDOMNode* styleSheet,
808 domdoc *This = impl_from_IXMLDOMDocument2( iface );
809 return IXMLDOMNode_transformNode( This->node, styleSheet, xmlString );
813 static HRESULT WINAPI domdoc_selectNodes(
814 IXMLDOMDocument2 *iface,
816 IXMLDOMNodeList** resultList )
818 domdoc *This = impl_from_IXMLDOMDocument2( iface );
819 return IXMLDOMNode_selectNodes( This->node, queryString, resultList );
823 static HRESULT WINAPI domdoc_selectSingleNode(
824 IXMLDOMDocument2 *iface,
826 IXMLDOMNode** resultNode )
828 domdoc *This = impl_from_IXMLDOMDocument2( iface );
829 return IXMLDOMNode_selectSingleNode( This->node, queryString, resultNode );
833 static HRESULT WINAPI domdoc_get_parsed(
834 IXMLDOMDocument2 *iface,
835 VARIANT_BOOL* isParsed )
837 domdoc *This = impl_from_IXMLDOMDocument2( iface );
838 return IXMLDOMNode_get_parsed( This->node, isParsed );
842 static HRESULT WINAPI domdoc_get_namespaceURI(
843 IXMLDOMDocument2 *iface,
846 domdoc *This = impl_from_IXMLDOMDocument2( iface );
847 return IXMLDOMNode_get_namespaceURI( This->node, namespaceURI );
851 static HRESULT WINAPI domdoc_get_prefix(
852 IXMLDOMDocument2 *iface,
855 domdoc *This = impl_from_IXMLDOMDocument2( iface );
856 return IXMLDOMNode_get_prefix( This->node, prefixString );
860 static HRESULT WINAPI domdoc_get_baseName(
861 IXMLDOMDocument2 *iface,
864 domdoc *This = impl_from_IXMLDOMDocument2( iface );
865 return IXMLDOMNode_get_baseName( This->node, nameString );
869 static HRESULT WINAPI domdoc_transformNodeToObject(
870 IXMLDOMDocument2 *iface,
871 IXMLDOMNode* stylesheet,
872 VARIANT outputObject)
874 domdoc *This = impl_from_IXMLDOMDocument2( iface );
875 return IXMLDOMNode_transformNodeToObject( This->node, stylesheet, outputObject );
879 static HRESULT WINAPI domdoc_get_doctype(
880 IXMLDOMDocument2 *iface,
881 IXMLDOMDocumentType** documentType )
888 static HRESULT WINAPI domdoc_get_implementation(
889 IXMLDOMDocument2 *iface,
890 IXMLDOMImplementation** impl )
895 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
900 static HRESULT WINAPI domdoc_get_documentElement(
901 IXMLDOMDocument2 *iface,
902 IXMLDOMElement** DOMElement )
904 domdoc *This = impl_from_IXMLDOMDocument2( iface );
905 xmlDocPtr xmldoc = NULL;
906 xmlNodePtr root = NULL;
907 IXMLDOMNode *element_node;
910 TRACE("%p %p\n", This, This->node);
917 xmldoc = get_doc( This );
919 root = xmlDocGetRootElement( xmldoc );
923 element_node = create_node( root );
924 if(!element_node) return S_FALSE;
926 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (LPVOID*)DOMElement);
927 IXMLDOMNode_Release(element_node);
933 static HRESULT WINAPI domdoc_put_documentElement(
934 IXMLDOMDocument2 *iface,
935 IXMLDOMElement* DOMElement )
937 domdoc *This = impl_from_IXMLDOMDocument2( iface );
938 IXMLDOMNode *elementNode;
943 TRACE("(%p)->(%p)\n", This, DOMElement);
945 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
949 xmlNode = impl_from_IXMLDOMNode( elementNode );
951 if(!xmlNode->node->parent)
952 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
953 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
955 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
956 IXMLDOMNode_Release( elementNode );
959 xmldoc_add_orphan(oldRoot->doc, oldRoot);
965 static HRESULT WINAPI domdoc_createElement(
966 IXMLDOMDocument2 *iface,
968 IXMLDOMElement** element )
971 domdoc *This = impl_from_IXMLDOMDocument2( iface );
976 TRACE("%p->(%s,%p)\n", iface, debugstr_w(tagname), element);
978 xml_name = xmlChar_from_wchar((WCHAR*)tagname);
979 xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
980 xmldoc_add_orphan(xmlnode->doc, xmlnode);
982 TRACE("created xmlptr %p\n", xmlnode);
983 elem_unk = create_element(xmlnode, NULL);
984 HeapFree(GetProcessHeap(), 0, xml_name);
986 hr = IUnknown_QueryInterface(elem_unk, &IID_IXMLDOMElement, (void **)element);
987 IUnknown_Release(elem_unk);
988 TRACE("returning %p\n", *element);
993 static HRESULT WINAPI domdoc_createDocumentFragment(
994 IXMLDOMDocument2 *iface,
995 IXMLDOMDocumentFragment** docFrag )
997 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1000 TRACE("%p\n", iface);
1003 return E_INVALIDARG;
1007 xmlnode = xmlNewDocFragment(get_doc( This ) );
1012 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1013 *docFrag = (IXMLDOMDocumentFragment*)create_doc_fragment(xmlnode);
1019 static HRESULT WINAPI domdoc_createTextNode(
1020 IXMLDOMDocument2 *iface,
1022 IXMLDOMText** text )
1024 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1026 xmlChar *xml_content;
1028 TRACE("%p->(%s %p)\n", iface, debugstr_w(data), text);
1031 return E_INVALIDARG;
1035 xml_content = xmlChar_from_wchar((WCHAR*)data);
1036 xmlnode = xmlNewText(xml_content);
1037 HeapFree(GetProcessHeap(), 0, xml_content);
1042 xmlnode->doc = get_doc( This );
1043 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1045 *text = (IXMLDOMText*)create_text(xmlnode);
1051 static HRESULT WINAPI domdoc_createComment(
1052 IXMLDOMDocument2 *iface,
1054 IXMLDOMComment** comment )
1056 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1058 xmlChar *xml_content;
1060 TRACE("%p->(%s %p)\n", iface, debugstr_w(data), comment);
1063 return E_INVALIDARG;
1067 xml_content = xmlChar_from_wchar((WCHAR*)data);
1068 xmlnode = xmlNewComment(xml_content);
1069 HeapFree(GetProcessHeap(), 0, xml_content);
1074 xmlnode->doc = get_doc( This );
1075 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1077 *comment = (IXMLDOMComment*)create_comment(xmlnode);
1083 static HRESULT WINAPI domdoc_createCDATASection(
1084 IXMLDOMDocument2 *iface,
1086 IXMLDOMCDATASection** cdata )
1088 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1090 xmlChar *xml_content;
1092 TRACE("%p->(%s %p)\n", iface, debugstr_w(data), cdata);
1095 return E_INVALIDARG;
1099 xml_content = xmlChar_from_wchar((WCHAR*)data);
1100 xmlnode = xmlNewCDataBlock(get_doc( This ), xml_content, strlen( (char*)xml_content) );
1101 HeapFree(GetProcessHeap(), 0, xml_content);
1106 xmlnode->doc = get_doc( This );
1107 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1109 *cdata = (IXMLDOMCDATASection*)create_cdata(xmlnode);
1115 static HRESULT WINAPI domdoc_createProcessingInstruction(
1116 IXMLDOMDocument2 *iface,
1119 IXMLDOMProcessingInstruction** pi )
1121 #ifdef HAVE_XMLNEWDOCPI
1123 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1124 xmlChar *xml_target, *xml_content;
1126 TRACE("%p->(%s %s %p)\n", iface, debugstr_w(target), debugstr_w(data), pi);
1129 return E_INVALIDARG;
1131 if(!target || lstrlenW(target) == 0)
1134 xml_target = xmlChar_from_wchar((WCHAR*)target);
1135 xml_content = xmlChar_from_wchar((WCHAR*)data);
1137 xmlnode = xmlNewDocPI(get_doc(This), xml_target, xml_content);
1138 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1139 TRACE("created xmlptr %p\n", xmlnode);
1140 *pi = (IXMLDOMProcessingInstruction*)create_pi(xmlnode);
1142 HeapFree(GetProcessHeap(), 0, xml_content);
1143 HeapFree(GetProcessHeap(), 0, xml_target);
1147 FIXME("Libxml 2.6.15 or greater required.\n");
1153 static HRESULT WINAPI domdoc_createAttribute(
1154 IXMLDOMDocument2 *iface,
1156 IXMLDOMAttribute** attribute )
1158 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1162 TRACE("%p->(%s %p)\n", iface, debugstr_w(name), attribute);
1165 return E_INVALIDARG;
1169 xml_name = xmlChar_from_wchar((WCHAR*)name);
1170 xmlnode = (xmlNode *)xmlNewProp(NULL, xml_name, NULL);
1171 HeapFree(GetProcessHeap(), 0, xml_name);
1176 xmlnode->doc = get_doc( This );
1177 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1179 *attribute = (IXMLDOMAttribute*)create_attribute(xmlnode);
1185 static HRESULT WINAPI domdoc_createEntityReference(
1186 IXMLDOMDocument2 *iface,
1188 IXMLDOMEntityReference** entityRef )
1190 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1194 TRACE("%p\n", iface);
1197 return E_INVALIDARG;
1201 xml_name = xmlChar_from_wchar((WCHAR*)name);
1202 xmlnode = xmlNewReference(get_doc( This ), xml_name );
1203 HeapFree(GetProcessHeap(), 0, xml_name);
1208 xmlnode->doc = get_doc( This );
1209 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1211 *entityRef = (IXMLDOMEntityReference*)create_doc_entity_ref(xmlnode);
1217 static HRESULT WINAPI domdoc_getElementsByTagName(
1218 IXMLDOMDocument2 *iface,
1220 IXMLDOMNodeList** resultList )
1222 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1225 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1227 szPattern = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(2+lstrlenW(tagName)+1));
1228 szPattern[0] = szPattern[1] = '/';
1229 lstrcpyW(szPattern + 2, tagName);
1231 hr = queryresult_create((xmlNodePtr)get_doc(This), szPattern, resultList);
1232 HeapFree(GetProcessHeap(), 0, szPattern);
1237 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1243 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1245 return E_INVALIDARG;
1252 static HRESULT WINAPI domdoc_createNode(
1253 IXMLDOMDocument2 *iface,
1257 IXMLDOMNode** node )
1259 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1260 DOMNodeType node_type;
1261 xmlNodePtr xmlnode = NULL;
1265 TRACE("(%p)->(type,%s,%s,%p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1267 hr = get_node_type(Type, &node_type);
1271 TRACE("node_type %d\n", node_type);
1273 xml_name = xmlChar_from_wchar((WCHAR*)name);
1278 xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
1279 *node = create_node(xmlnode);
1280 TRACE("created %p\n", xmlnode);
1282 case NODE_ATTRIBUTE:
1283 xmlnode = (xmlNode *)xmlNewProp(NULL, xml_name, NULL);
1286 xmlnode->doc = get_doc( This );
1288 *node = (IXMLDOMNode*)create_attribute(xmlnode);
1291 TRACE("created %p\n", xmlnode);
1295 FIXME("unhandled node type %d\n", node_type);
1299 HeapFree(GetProcessHeap(), 0, xml_name);
1301 if(xmlnode && *node)
1303 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1310 static HRESULT WINAPI domdoc_nodeFromID(
1311 IXMLDOMDocument2 *iface,
1313 IXMLDOMNode** node )
1319 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1324 xmldoc = doparse( ptr, len );
1326 xmldoc->_private = create_priv();
1327 attach_xmlnode(This->node, (xmlNodePtr) xmldoc);
1333 static HRESULT doread( domdoc *This, LPWSTR filename )
1338 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1343 detach_bsc(This->bsc);
1349 static HRESULT WINAPI domdoc_load(
1350 IXMLDOMDocument2 *iface,
1352 VARIANT_BOOL* isSuccessful )
1354 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1355 LPWSTR filename = NULL;
1356 HRESULT hr = S_FALSE;
1357 IXMLDOMDocument2 *pNewDoc = NULL;
1358 IStream *pStream = NULL;
1361 TRACE("type %d\n", V_VT(&xmlSource) );
1363 *isSuccessful = VARIANT_FALSE;
1365 assert( This->node );
1367 attach_xmlnode(This->node, NULL);
1369 switch( V_VT(&xmlSource) )
1372 filename = V_BSTR(&xmlSource);
1375 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument2, (void**)&pNewDoc);
1380 domdoc *newDoc = impl_from_IXMLDOMDocument2( pNewDoc );
1381 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1382 attach_xmlnode(This->node, (xmlNodePtr) xmldoc);
1384 *isSuccessful = VARIANT_TRUE;
1389 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1392 IPersistStream *pDocStream;
1393 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1396 hr = xmldoc_IPersistStream_Load(pDocStream, pStream);
1397 IStream_Release(pStream);
1400 *isSuccessful = VARIANT_TRUE;
1402 TRACE("Using ID_IStream to load Document\n");
1407 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1412 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1417 /* ISequentialStream */
1418 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1422 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1425 TRACE("filename (%s)\n", debugstr_w(filename));
1429 hr = doread( This, filename );
1432 This->error = E_FAIL;
1435 hr = This->error = S_OK;
1436 *isSuccessful = VARIANT_TRUE;
1440 if(!filename || FAILED(hr)) {
1441 xmldoc = xmlNewDoc(NULL);
1442 xmldoc->_private = create_priv();
1443 attach_xmlnode(This->node, (xmlNodePtr) xmldoc);
1447 TRACE("ret (%d)\n", hr);
1453 static HRESULT WINAPI domdoc_get_readyState(
1454 IXMLDOMDocument2 *iface,
1462 static HRESULT WINAPI domdoc_get_parseError(
1463 IXMLDOMDocument2 *iface,
1464 IXMLDOMParseError** errorObj )
1466 BSTR error_string = NULL;
1467 static const WCHAR err[] = {'e','r','r','o','r',0};
1468 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1470 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
1473 error_string = SysAllocString(err);
1475 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
1476 if(!*errorObj) return E_OUTOFMEMORY;
1481 static HRESULT WINAPI domdoc_get_url(
1482 IXMLDOMDocument2 *iface,
1490 static HRESULT WINAPI domdoc_get_async(
1491 IXMLDOMDocument2 *iface,
1492 VARIANT_BOOL* isAsync )
1494 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1496 TRACE("%p <- %d\n", isAsync, This->async);
1497 *isAsync = This->async;
1502 static HRESULT WINAPI domdoc_put_async(
1503 IXMLDOMDocument2 *iface,
1504 VARIANT_BOOL isAsync )
1506 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1508 TRACE("%d\n", isAsync);
1509 This->async = isAsync;
1514 static HRESULT WINAPI domdoc_abort(
1515 IXMLDOMDocument2 *iface )
1522 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
1524 UINT len, blen = SysStringLen( bstr );
1527 len = WideCharToMultiByte( CP_UTF8, 0, bstr, blen, NULL, 0, NULL, NULL );
1528 str = HeapAlloc( GetProcessHeap(), 0, len );
1531 WideCharToMultiByte( CP_UTF8, 0, bstr, blen, str, len, NULL, NULL );
1537 static HRESULT WINAPI domdoc_loadXML(
1538 IXMLDOMDocument2 *iface,
1540 VARIANT_BOOL* isSuccessful )
1542 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1543 xmlDocPtr xmldoc = NULL;
1546 HRESULT hr = S_FALSE;
1548 TRACE("%p %s %p\n", This, debugstr_w( bstrXML ), isSuccessful );
1550 assert ( This->node );
1552 attach_xmlnode( This->node, NULL );
1556 *isSuccessful = VARIANT_FALSE;
1558 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
1560 xmldoc = doparse( str, len );
1561 HeapFree( GetProcessHeap(), 0, str );
1563 This->error = E_FAIL;
1566 hr = This->error = S_OK;
1567 *isSuccessful = VARIANT_TRUE;
1572 xmldoc = xmlNewDoc(NULL);
1574 xmldoc->_private = create_priv();
1575 attach_xmlnode( This->node, (xmlNodePtr) xmldoc );
1581 static HRESULT WINAPI domdoc_save(
1582 IXMLDOMDocument2 *iface,
1583 VARIANT destination )
1585 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1592 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
1593 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
1595 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
1597 FIXME("Unhandled vt %d\n", V_VT(&destination));
1601 if(V_VT(&destination) == VT_UNKNOWN)
1603 IUnknown *pUnk = V_UNKNOWN(&destination);
1604 IXMLDOMDocument *pDocument;
1606 ret = IXMLDOMDocument_QueryInterface(pUnk, &IID_IXMLDOMDocument2, (void**)&pDocument);
1610 VARIANT_BOOL bSuccessful;
1612 ret = IXMLDOMDocument_get_xml(iface, &bXML);
1615 ret = IXMLDOMDocument_loadXML(pDocument, bXML, &bSuccessful);
1617 SysFreeString(bXML);
1620 IXMLDOMDocument_Release(pDocument);
1623 TRACE("ret %d\n", ret);
1628 handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
1629 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1630 if( handle == INVALID_HANDLE_VALUE )
1632 WARN("failed to create file\n");
1636 xmlDocDumpMemory(get_doc(This), &mem, &size);
1639 * libxml2 always adds XML declaration on top of the file and one for each processing instruction node in DOM tree.
1640 * MSXML adds XML declaration only for processing instruction nodes.
1641 * We skip the first XML declaration generated by libxml2 to get exactly what we need.
1644 if(size > 2 && p[0] == '<' && p[1] == '?') {
1645 while(p < mem+size && (p[0] != '?' || p[1] != '>'))
1648 while(p < mem+size && isspace(*p))
1653 if(!WriteFile(handle, p, (DWORD)size, &written, NULL) || written != (DWORD)size)
1655 WARN("write error\n");
1660 CloseHandle(handle);
1664 static HRESULT WINAPI domdoc_get_validateOnParse(
1665 IXMLDOMDocument2 *iface,
1666 VARIANT_BOOL* isValidating )
1668 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1670 TRACE("%p <- %d\n", isValidating, This->validating);
1671 *isValidating = This->validating;
1676 static HRESULT WINAPI domdoc_put_validateOnParse(
1677 IXMLDOMDocument2 *iface,
1678 VARIANT_BOOL isValidating )
1680 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1682 TRACE("%d\n", isValidating);
1683 This->validating = isValidating;
1688 static HRESULT WINAPI domdoc_get_resolveExternals(
1689 IXMLDOMDocument2 *iface,
1690 VARIANT_BOOL* isResolving )
1692 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1694 TRACE("%p <- %d\n", isResolving, This->resolving);
1695 *isResolving = This->resolving;
1700 static HRESULT WINAPI domdoc_put_resolveExternals(
1701 IXMLDOMDocument2 *iface,
1702 VARIANT_BOOL isResolving )
1704 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1706 TRACE("%d\n", isResolving);
1707 This->resolving = isResolving;
1712 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
1713 IXMLDOMDocument2 *iface,
1714 VARIANT_BOOL* isPreserving )
1716 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1718 TRACE("%p <- %d\n", isPreserving, This->preserving);
1719 *isPreserving = This->preserving;
1724 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
1725 IXMLDOMDocument2 *iface,
1726 VARIANT_BOOL isPreserving )
1728 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1730 TRACE("%d\n", isPreserving);
1731 This->preserving = isPreserving;
1736 static HRESULT WINAPI domdoc_put_onReadyStateChange(
1737 IXMLDOMDocument2 *iface,
1738 VARIANT readyStateChangeSink )
1745 static HRESULT WINAPI domdoc_put_onDataAvailable(
1746 IXMLDOMDocument2 *iface,
1747 VARIANT onDataAvailableSink )
1753 static HRESULT WINAPI domdoc_put_onTransformNode(
1754 IXMLDOMDocument2 *iface,
1755 VARIANT onTransformNodeSink )
1761 static HRESULT WINAPI domdoc_get_namespaces(
1762 IXMLDOMDocument2* iface,
1763 IXMLDOMSchemaCollection** schemaCollection )
1769 static HRESULT WINAPI domdoc_get_schemas(
1770 IXMLDOMDocument2* iface,
1773 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1774 HRESULT hr = S_FALSE;
1775 IXMLDOMSchemaCollection *cur_schema = This->schema;
1777 TRACE("(%p)->(%p)\n", This, var1);
1779 VariantInit(var1); /* Test shows we don't call VariantClear here */
1780 V_VT(var1) = VT_NULL;
1784 hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
1786 V_VT(var1) = VT_DISPATCH;
1791 static HRESULT WINAPI domdoc_putref_schemas(
1792 IXMLDOMDocument2* iface,
1795 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1796 HRESULT hr = E_FAIL;
1797 IXMLDOMSchemaCollection *new_schema = NULL;
1799 FIXME("(%p): semi-stub\n", This);
1803 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1807 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1816 WARN("Can't get schema from vt %x\n", V_VT(&var1));
1821 IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
1822 if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
1828 static HRESULT WINAPI domdoc_validate(
1829 IXMLDOMDocument2* iface,
1830 IXMLDOMParseError** err)
1836 static HRESULT WINAPI domdoc_setProperty(
1837 IXMLDOMDocument2* iface,
1841 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1843 if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
1849 V_VT(&varStr) = VT_EMPTY;
1850 if (V_VT(&var) != VT_BSTR)
1852 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
1854 bstr = V_BSTR(&varStr);
1857 bstr = V_BSTR(&var);
1860 if (lstrcmpiW(bstr, SZ_VALUE_XPATH) == 0)
1861 This->bUseXPath = TRUE;
1862 else if (lstrcmpiW(bstr, SZ_VALUE_XSLPATTERN) == 0)
1863 This->bUseXPath = FALSE;
1867 VariantClear(&varStr);
1871 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
1875 static HRESULT WINAPI domdoc_getProperty(
1876 IXMLDOMDocument2* iface,
1880 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1883 return E_INVALIDARG;
1884 if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
1886 V_VT(var) = VT_BSTR;
1887 if (This->bUseXPath)
1888 V_BSTR(var) = SysAllocString(SZ_VALUE_XPATH);
1890 V_BSTR(var) = SysAllocString(SZ_VALUE_XSLPATTERN);
1894 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
1898 static const struct IXMLDOMDocument2Vtbl domdoc_vtbl =
1900 domdoc_QueryInterface,
1903 domdoc_GetTypeInfoCount,
1905 domdoc_GetIDsOfNames,
1907 domdoc_get_nodeName,
1908 domdoc_get_nodeValue,
1909 domdoc_put_nodeValue,
1910 domdoc_get_nodeType,
1911 domdoc_get_parentNode,
1912 domdoc_get_childNodes,
1913 domdoc_get_firstChild,
1914 domdoc_get_lastChild,
1915 domdoc_get_previousSibling,
1916 domdoc_get_nextSibling,
1917 domdoc_get_attributes,
1918 domdoc_insertBefore,
1919 domdoc_replaceChild,
1922 domdoc_hasChildNodes,
1923 domdoc_get_ownerDocument,
1925 domdoc_get_nodeTypeString,
1928 domdoc_get_specified,
1929 domdoc_get_definition,
1930 domdoc_get_nodeTypedValue,
1931 domdoc_put_nodeTypedValue,
1932 domdoc_get_dataType,
1933 domdoc_put_dataType,
1935 domdoc_transformNode,
1937 domdoc_selectSingleNode,
1939 domdoc_get_namespaceURI,
1941 domdoc_get_baseName,
1942 domdoc_transformNodeToObject,
1944 domdoc_get_implementation,
1945 domdoc_get_documentElement,
1946 domdoc_put_documentElement,
1947 domdoc_createElement,
1948 domdoc_createDocumentFragment,
1949 domdoc_createTextNode,
1950 domdoc_createComment,
1951 domdoc_createCDATASection,
1952 domdoc_createProcessingInstruction,
1953 domdoc_createAttribute,
1954 domdoc_createEntityReference,
1955 domdoc_getElementsByTagName,
1959 domdoc_get_readyState,
1960 domdoc_get_parseError,
1967 domdoc_get_validateOnParse,
1968 domdoc_put_validateOnParse,
1969 domdoc_get_resolveExternals,
1970 domdoc_put_resolveExternals,
1971 domdoc_get_preserveWhiteSpace,
1972 domdoc_put_preserveWhiteSpace,
1973 domdoc_put_onReadyStateChange,
1974 domdoc_put_onDataAvailable,
1975 domdoc_put_onTransformNode,
1976 domdoc_get_namespaces,
1978 domdoc_putref_schemas,
1984 /* xmldoc implementation of IObjectWithSite */
1985 static HRESULT WINAPI
1986 xmldoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
1988 domdoc *This = impl_from_IObjectWithSite(iface);
1989 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppvObject );
1993 xmldoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
1995 domdoc *This = impl_from_IObjectWithSite(iface);
1996 return IXMLDocument_AddRef((IXMLDocument *)This);
2000 xmldoc_ObjectWithSite_Release( IObjectWithSite* iface )
2002 domdoc *This = impl_from_IObjectWithSite(iface);
2003 return IXMLDocument_Release((IXMLDocument *)This);
2006 static HRESULT WINAPI
2007 xmldoc_GetSite( IObjectWithSite *iface, REFIID iid, void ** ppvSite )
2009 domdoc *This = impl_from_IObjectWithSite(iface);
2011 TRACE("%p %s %p\n", This, debugstr_guid( iid ), ppvSite );
2016 return IUnknown_QueryInterface( This->site, iid, ppvSite );
2019 static HRESULT WINAPI
2020 xmldoc_SetSite( IObjectWithSite *iface, IUnknown *punk )
2022 domdoc *This = impl_from_IObjectWithSite(iface);
2024 TRACE("%p %p\n", iface, punk);
2030 IUnknown_Release( This->site );
2038 IUnknown_AddRef( punk );
2041 IUnknown_Release( This->site );
2048 static const IObjectWithSiteVtbl domdocObjectSite =
2050 xmldoc_ObjectWithSite_QueryInterface,
2051 xmldoc_ObjectWithSite_AddRef,
2052 xmldoc_ObjectWithSite_Release,
2057 static HRESULT WINAPI xmldoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
2059 domdoc *This = impl_from_IObjectSafety(iface);
2060 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppv );
2063 static ULONG WINAPI xmldoc_Safety_AddRef(IObjectSafety *iface)
2065 domdoc *This = impl_from_IObjectSafety(iface);
2066 return IXMLDocument_AddRef((IXMLDocument *)This);
2069 static ULONG WINAPI xmldoc_Safety_Release(IObjectSafety *iface)
2071 domdoc *This = impl_from_IObjectSafety(iface);
2072 return IXMLDocument_Release((IXMLDocument *)This);
2075 #define SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
2077 static HRESULT WINAPI xmldoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2078 DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
2080 domdoc *This = impl_from_IObjectSafety(iface);
2082 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
2084 if(!pdwSupportedOptions || !pdwEnabledOptions)
2087 *pdwSupportedOptions = SUPPORTED_OPTIONS;
2088 *pdwEnabledOptions = This->safeopt;
2093 static HRESULT WINAPI xmldoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2094 DWORD dwOptionSetMask, DWORD dwEnabledOptions)
2096 domdoc *This = impl_from_IObjectSafety(iface);
2098 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
2100 if(dwOptionSetMask & ~SUPPORTED_OPTIONS)
2103 This->safeopt = dwEnabledOptions & dwEnabledOptions;
2107 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
2108 xmldoc_Safety_QueryInterface,
2109 xmldoc_Safety_AddRef,
2110 xmldoc_Safety_Release,
2111 xmldoc_Safety_GetInterfaceSafetyOptions,
2112 xmldoc_Safety_SetInterfaceSafetyOptions
2116 static const tid_t domdoc_iface_tids[] = {
2118 IXMLDOMDocument_tid,
2119 IXMLDOMDocument2_tid,
2122 static dispex_static_data_t domdoc_dispex = {
2124 IXMLDOMDocument2_tid,
2129 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument2 **document)
2134 doc = HeapAlloc( GetProcessHeap(), 0, sizeof (*doc) );
2136 return E_OUTOFMEMORY;
2138 doc->lpVtbl = &domdoc_vtbl;
2139 doc->lpvtblIPersistStream = &xmldoc_IPersistStream_VTable;
2140 doc->lpvtblIObjectWithSite = &domdocObjectSite;
2141 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
2144 doc->validating = 0;
2146 doc->preserving = 0;
2147 doc->bUseXPath = FALSE;
2155 doc->node_unk = create_basic_node( (xmlNodePtr)xmldoc, (IUnknown*)&doc->lpVtbl );
2158 HeapFree(GetProcessHeap(), 0, doc);
2162 hr = IUnknown_QueryInterface(doc->node_unk, &IID_IXMLDOMNode, (LPVOID*)&doc->node);
2165 IUnknown_Release(doc->node_unk);
2166 HeapFree( GetProcessHeap(), 0, doc );
2170 init_dispex(&doc->dispex, (IUnknown*)&doc->lpVtbl, &domdoc_dispex);
2172 /* The ref on doc->node is actually looped back into this object, so release it */
2173 IXMLDOMNode_Release(doc->node);
2175 *document = (IXMLDOMDocument2*)&doc->lpVtbl;
2177 TRACE("returning iface %p\n", *document);
2181 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2186 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
2188 xmldoc = xmlNewDoc(NULL);
2190 return E_OUTOFMEMORY;
2192 xmldoc->_private = create_priv();
2194 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument2**)ppObj);
2201 IUnknown* create_domdoc( xmlNodePtr document )
2206 TRACE("(%p)\n", document);
2208 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument2**)&pObj);
2212 return (IUnknown*)pObj;
2217 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2219 MESSAGE("This program tried to use a DOMDocument object, but\n"
2220 "libxml2 support was not present at compile time.\n");