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 PropertySelectionLanguageW[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
62 static const WCHAR PropertySelectionNamespacesW[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
63 static const WCHAR PropertyProhibitDTDW[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
64 static const WCHAR PropValueXPathW[] = {'X','P','a','t','h',0};
65 static const WCHAR PropValueXSLPatternW[] = {'X','S','L','P','a','t','t','e','r','n',0};
67 typedef struct _domdoc
70 const struct IXMLDOMDocument3Vtbl *lpVtbl;
71 const struct IPersistStreamInitVtbl *lpvtblIPersistStreamInit;
72 const struct IObjectWithSiteVtbl *lpvtblIObjectWithSite;
73 const struct IObjectSafetyVtbl *lpvtblIObjectSafety;
74 const struct ISupportErrorInfoVtbl *lpvtblISupportErrorInfo;
77 VARIANT_BOOL validating;
78 VARIANT_BOOL resolving;
79 VARIANT_BOOL preserving;
81 IXMLDOMSchemaCollection *schema;
96 In native windows, the whole lifetime management of XMLDOMNodes is
97 managed automatically using reference counts. Wine emulates that by
98 maintaining a reference count to the document that is increased for
99 each IXMLDOMNode pointer passed out for this document. If all these
100 pointers are gone, the document is unreachable and gets freed, that
101 is, all nodes in the tree of the document get freed.
103 You are able to create nodes that are associated to a document (in
104 fact, in msxml's XMLDOM model, all nodes are associated to a document),
105 but not in the tree of that document, for example using the createFoo
106 functions from IXMLDOMDocument. These nodes do not get cleaned up
107 by libxml, so we have to do it ourselves.
109 To catch these nodes, a list of "orphan nodes" is introduced.
110 It contains pointers to all roots of node trees that are
111 associated with the document without being part of the document
112 tree. All nodes with parent==NULL (except for the document root nodes)
113 should be in the orphan node list of their document. All orphan nodes
114 get freed together with the document itself.
117 typedef struct _xmldoc_priv {
122 typedef struct _orphan_entry {
127 static inline xmldoc_priv * priv_from_xmlDocPtr(xmlDocPtr doc)
129 return doc->_private;
132 static xmldoc_priv * create_priv(void)
135 priv = heap_alloc( sizeof (*priv) );
140 list_init( &priv->orphans );
146 /* links a "<?xml" node as a first child */
147 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
150 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
153 /* unlinks a first "<?xml" child if it was created */
154 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
160 if (doc->standalone != -1)
162 node = doc->children;
163 xmlUnlinkNode( node );
171 static xmlDocPtr doparse( char *ptr, int len, const char *encoding )
175 #ifdef HAVE_XMLREADMEMORY
177 * use xmlReadMemory if possible so we can suppress
178 * writing errors to stderr
180 doc = xmlReadMemory( ptr, len, NULL, encoding,
181 XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS );
183 doc = xmlParseMemory( ptr, len );
186 /* create first child as a <?xml...?> */
187 if (doc && doc->standalone != -1)
191 xmlChar *xmlbuff = (xmlChar*)buff;
193 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
195 /* version attribute can't be omitted */
196 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
197 xmlNodeAddContent( node, xmlbuff );
201 sprintf(buff, " encoding=\"%s\"", doc->encoding);
202 xmlNodeAddContent( node, xmlbuff );
205 if (doc->standalone != -2)
207 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
208 xmlNodeAddContent( node, xmlbuff );
211 xmldoc_link_xmldecl( doc, node );
217 LONG xmldoc_add_ref(xmlDocPtr doc)
219 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
220 TRACE("(%p)->(%d)\n", doc, ref);
224 LONG xmldoc_release(xmlDocPtr doc)
226 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
227 LONG ref = InterlockedDecrement(&priv->refs);
228 TRACE("(%p)->(%d)\n", doc, ref);
231 orphan_entry *orphan, *orphan2;
232 TRACE("freeing docptr %p\n", doc);
234 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
236 xmlFreeNode( orphan->node );
239 heap_free(doc->_private);
247 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
249 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
252 entry = heap_alloc( sizeof (*entry) );
254 return E_OUTOFMEMORY;
257 list_add_head( &priv->orphans, &entry->entry );
261 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
263 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
264 orphan_entry *entry, *entry2;
266 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
268 if( entry->node == node )
270 list_remove( &entry->entry );
279 static HRESULT attach_xmldoc( xmlnode *node, xmlDocPtr xml )
282 xmldoc_release(node->node->doc);
284 node->node = (xmlNodePtr) xml;
286 xmldoc_add_ref(node->node->doc);
291 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
293 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
296 static inline xmlDocPtr get_doc( domdoc *This )
298 return (xmlDocPtr)This->node.node;
301 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
303 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStreamInit));
306 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
308 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
311 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
313 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
316 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
318 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblISupportErrorInfo));
321 /************************************************************************
322 * domdoc implementation of IPersistStream.
324 static HRESULT WINAPI domdoc_IPersistStreamInit_QueryInterface(
325 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
327 domdoc *this = impl_from_IPersistStreamInit(iface);
328 return IXMLDOMDocument2_QueryInterface((IXMLDOMDocument2 *)this, riid, ppvObj);
331 static ULONG WINAPI domdoc_IPersistStreamInit_AddRef(
332 IPersistStreamInit *iface)
334 domdoc *this = impl_from_IPersistStreamInit(iface);
335 return IXMLDOMDocument2_AddRef((IXMLDOMDocument2 *)this);
338 static ULONG WINAPI domdoc_IPersistStreamInit_Release(
339 IPersistStreamInit *iface)
341 domdoc *this = impl_from_IPersistStreamInit(iface);
342 return IXMLDOMDocument2_Release((IXMLDOMDocument2 *)this);
345 static HRESULT WINAPI domdoc_IPersistStreamInit_GetClassID(
346 IPersistStreamInit *iface, CLSID *classid)
348 TRACE("(%p,%p): stub!\n", iface, classid);
353 *classid = CLSID_DOMDocument2;
358 static HRESULT WINAPI domdoc_IPersistStreamInit_IsDirty(
359 IPersistStreamInit *iface)
361 domdoc *This = impl_from_IPersistStreamInit(iface);
362 FIXME("(%p): stub!\n", This);
366 static HRESULT WINAPI domdoc_IPersistStreamInit_Load(
367 IPersistStreamInit *iface, LPSTREAM pStm)
369 domdoc *This = impl_from_IPersistStreamInit(iface);
372 DWORD read, written, len;
375 xmlDocPtr xmldoc = NULL;
377 TRACE("(%p)->(%p)\n", This, pStm);
382 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
388 IStream_Read(pStm, buf, sizeof(buf), &read);
389 hr = IStream_Write(This->stream, buf, read, &written);
390 } while(SUCCEEDED(hr) && written != 0 && read != 0);
394 ERR("Failed to copy stream\n");
398 hr = GetHGlobalFromStream(This->stream, &hglobal);
402 len = GlobalSize(hglobal);
403 ptr = GlobalLock(hglobal);
405 xmldoc = doparse(ptr, len, NULL);
406 GlobalUnlock(hglobal);
410 ERR("Failed to parse xml\n");
414 xmldoc->_private = create_priv();
416 return attach_xmldoc( &This->node, xmldoc );
419 static HRESULT WINAPI domdoc_IPersistStreamInit_Save(
420 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
422 domdoc *This = impl_from_IPersistStreamInit(iface);
426 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
428 hr = IXMLDOMDocument3_get_xml( (IXMLDOMDocument3*)&This->lpVtbl, &xmlString );
431 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
433 hr = IStream_Write( stream, xmlString, len, NULL );
434 SysFreeString(xmlString);
437 TRACE("ret 0x%08x\n", hr);
442 static HRESULT WINAPI domdoc_IPersistStreamInit_GetSizeMax(
443 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
445 domdoc *This = impl_from_IPersistStreamInit(iface);
446 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
450 static HRESULT WINAPI domdoc_IPersistStreamInit_InitNew(
451 IPersistStreamInit *iface)
453 domdoc *This = impl_from_IPersistStreamInit(iface);
454 TRACE("(%p)\n", This);
458 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
460 domdoc_IPersistStreamInit_QueryInterface,
461 domdoc_IPersistStreamInit_AddRef,
462 domdoc_IPersistStreamInit_Release,
463 domdoc_IPersistStreamInit_GetClassID,
464 domdoc_IPersistStreamInit_IsDirty,
465 domdoc_IPersistStreamInit_Load,
466 domdoc_IPersistStreamInit_Save,
467 domdoc_IPersistStreamInit_GetSizeMax,
468 domdoc_IPersistStreamInit_InitNew
471 /* ISupportErrorInfo interface */
472 static HRESULT WINAPI support_error_QueryInterface(
473 ISupportErrorInfo *iface,
474 REFIID riid, void** ppvObj )
476 domdoc *This = impl_from_ISupportErrorInfo(iface);
477 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3 *)This, riid, ppvObj);
480 static ULONG WINAPI support_error_AddRef(
481 ISupportErrorInfo *iface )
483 domdoc *This = impl_from_ISupportErrorInfo(iface);
484 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
487 static ULONG WINAPI support_error_Release(
488 ISupportErrorInfo *iface )
490 domdoc *This = impl_from_ISupportErrorInfo(iface);
491 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
494 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
495 ISupportErrorInfo *iface,
498 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
502 static const struct ISupportErrorInfoVtbl support_error_vtbl =
504 support_error_QueryInterface,
505 support_error_AddRef,
506 support_error_Release,
507 support_error_InterfaceSupportsErrorInfo
510 /* IXMLDOMDocument2 interface */
511 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
513 domdoc *This = impl_from_IXMLDOMDocument3( iface );
515 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
519 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
520 IsEqualGUID( riid, &IID_IDispatch ) ||
521 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
522 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
523 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
524 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
528 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
529 IsEqualGUID(&IID_IPersistStreamInit, riid))
531 *ppvObject = &(This->lpvtblIPersistStreamInit);
533 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
535 *ppvObject = &(This->lpvtblIObjectWithSite);
537 else if (IsEqualGUID(&IID_IObjectSafety, riid))
539 *ppvObject = &(This->lpvtblIObjectSafety);
541 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
543 *ppvObject = &This->lpvtblISupportErrorInfo;
545 else if(node_query_interface(&This->node, riid, ppvObject))
547 return *ppvObject ? S_OK : E_NOINTERFACE;
549 else if(IsEqualGUID(&IID_IRunnableObject, riid))
551 TRACE("IID_IRunnableObject not supported returning NULL\n");
552 return E_NOINTERFACE;
556 FIXME("interface %s not implemented\n", debugstr_guid(riid));
557 return E_NOINTERFACE;
560 IUnknown_AddRef((IUnknown*)*ppvObject);
566 static ULONG WINAPI domdoc_AddRef(
567 IXMLDOMDocument3 *iface )
569 domdoc *This = impl_from_IXMLDOMDocument3( iface );
570 TRACE("%p\n", This );
571 return InterlockedIncrement( &This->ref );
575 static ULONG WINAPI domdoc_Release(
576 IXMLDOMDocument3 *iface )
578 domdoc *This = impl_from_IXMLDOMDocument3( iface );
581 TRACE("%p\n", This );
583 ref = InterlockedDecrement( &This->ref );
587 detach_bsc(This->bsc);
590 IUnknown_Release( This->site );
591 destroy_xmlnode(&This->node);
592 if(This->schema) IXMLDOMSchemaCollection_Release( This->schema );
593 if (This->stream) IStream_Release(This->stream);
594 HeapFree( GetProcessHeap(), 0, This );
600 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
602 domdoc *This = impl_from_IXMLDOMDocument3( iface );
604 TRACE("(%p)->(%p)\n", This, pctinfo);
611 static HRESULT WINAPI domdoc_GetTypeInfo(
612 IXMLDOMDocument3 *iface,
613 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
615 domdoc *This = impl_from_IXMLDOMDocument3( iface );
618 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
620 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
625 static HRESULT WINAPI domdoc_GetIDsOfNames(
626 IXMLDOMDocument3 *iface,
633 domdoc *This = impl_from_IXMLDOMDocument3( iface );
637 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
640 if(!rgszNames || cNames == 0 || !rgDispId)
643 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
646 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
647 ITypeInfo_Release(typeinfo);
654 static HRESULT WINAPI domdoc_Invoke(
655 IXMLDOMDocument3 *iface,
660 DISPPARAMS* pDispParams,
662 EXCEPINFO* pExcepInfo,
665 domdoc *This = impl_from_IXMLDOMDocument3( iface );
669 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
670 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
672 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
675 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
676 pVarResult, pExcepInfo, puArgErr);
677 ITypeInfo_Release(typeinfo);
684 static HRESULT WINAPI domdoc_get_nodeName(
685 IXMLDOMDocument3 *iface,
688 domdoc *This = impl_from_IXMLDOMDocument3( iface );
690 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
692 TRACE("(%p)->(%p)\n", This, name);
694 return return_bstr(documentW, name);
698 static HRESULT WINAPI domdoc_get_nodeValue(
699 IXMLDOMDocument3 *iface,
702 domdoc *This = impl_from_IXMLDOMDocument3( iface );
704 TRACE("(%p)->(%p)\n", This, value);
709 V_VT(value) = VT_NULL;
710 V_BSTR(value) = NULL; /* tests show that we should do this */
715 static HRESULT WINAPI domdoc_put_nodeValue(
716 IXMLDOMDocument3 *iface,
719 domdoc *This = impl_from_IXMLDOMDocument3( iface );
720 FIXME("(%p)->(v%d)\n", This, V_VT(&value));
725 static HRESULT WINAPI domdoc_get_nodeType(
726 IXMLDOMDocument3 *iface,
729 domdoc *This = impl_from_IXMLDOMDocument3( iface );
731 TRACE("(%p)->(%p)\n", This, type);
733 *type = NODE_DOCUMENT;
738 static HRESULT WINAPI domdoc_get_parentNode(
739 IXMLDOMDocument3 *iface,
740 IXMLDOMNode** parent )
742 domdoc *This = impl_from_IXMLDOMDocument3( iface );
744 TRACE("(%p)->(%p)\n", This, parent);
746 return node_get_parent(&This->node, parent);
750 static HRESULT WINAPI domdoc_get_childNodes(
751 IXMLDOMDocument3 *iface,
752 IXMLDOMNodeList** childList )
754 domdoc *This = impl_from_IXMLDOMDocument3( iface );
756 TRACE("(%p)->(%p)\n", This, childList);
758 return node_get_child_nodes(&This->node, childList);
762 static HRESULT WINAPI domdoc_get_firstChild(
763 IXMLDOMDocument3 *iface,
764 IXMLDOMNode** firstChild )
766 domdoc *This = impl_from_IXMLDOMDocument3( iface );
768 TRACE("(%p)->(%p)\n", This, firstChild);
770 return node_get_first_child(&This->node, firstChild);
774 static HRESULT WINAPI domdoc_get_lastChild(
775 IXMLDOMDocument3 *iface,
776 IXMLDOMNode** lastChild )
778 domdoc *This = impl_from_IXMLDOMDocument3( iface );
780 TRACE("(%p)->(%p)\n", This, lastChild);
782 return node_get_first_child(&This->node, lastChild);
786 static HRESULT WINAPI domdoc_get_previousSibling(
787 IXMLDOMDocument3 *iface,
788 IXMLDOMNode** previousSibling )
790 domdoc *This = impl_from_IXMLDOMDocument3( iface );
791 return IXMLDOMNode_get_previousSibling( IXMLDOMNode_from_impl(&This->node), previousSibling );
795 static HRESULT WINAPI domdoc_get_nextSibling(
796 IXMLDOMDocument3 *iface,
797 IXMLDOMNode** nextSibling )
799 domdoc *This = impl_from_IXMLDOMDocument3( iface );
800 return IXMLDOMNode_get_nextSibling( IXMLDOMNode_from_impl(&This->node), nextSibling );
804 static HRESULT WINAPI domdoc_get_attributes(
805 IXMLDOMDocument3 *iface,
806 IXMLDOMNamedNodeMap** attributeMap )
808 domdoc *This = impl_from_IXMLDOMDocument3( iface );
809 return IXMLDOMNode_get_attributes( IXMLDOMNode_from_impl(&This->node), attributeMap );
813 static HRESULT WINAPI domdoc_insertBefore(
814 IXMLDOMDocument3 *iface,
815 IXMLDOMNode* newChild,
817 IXMLDOMNode** outNewChild )
819 domdoc *This = impl_from_IXMLDOMDocument3( iface );
820 return IXMLDOMNode_insertBefore( IXMLDOMNode_from_impl(&This->node), newChild, refChild, outNewChild );
824 static HRESULT WINAPI domdoc_replaceChild(
825 IXMLDOMDocument3 *iface,
826 IXMLDOMNode* newChild,
827 IXMLDOMNode* oldChild,
828 IXMLDOMNode** outOldChild)
830 domdoc *This = impl_from_IXMLDOMDocument3( iface );
831 return IXMLDOMNode_replaceChild( IXMLDOMNode_from_impl(&This->node), newChild, oldChild, outOldChild );
835 static HRESULT WINAPI domdoc_removeChild(
836 IXMLDOMDocument3 *iface,
837 IXMLDOMNode* childNode,
838 IXMLDOMNode** oldChild)
840 domdoc *This = impl_from_IXMLDOMDocument3( iface );
841 return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), childNode, oldChild );
845 static HRESULT WINAPI domdoc_appendChild(
846 IXMLDOMDocument3 *iface,
847 IXMLDOMNode* newChild,
848 IXMLDOMNode** outNewChild)
850 domdoc *This = impl_from_IXMLDOMDocument3( iface );
851 return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newChild, outNewChild );
855 static HRESULT WINAPI domdoc_hasChildNodes(
856 IXMLDOMDocument3 *iface,
857 VARIANT_BOOL* hasChild)
859 domdoc *This = impl_from_IXMLDOMDocument3( iface );
860 return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), hasChild );
864 static HRESULT WINAPI domdoc_get_ownerDocument(
865 IXMLDOMDocument3 *iface,
866 IXMLDOMDocument** DOMDocument)
868 domdoc *This = impl_from_IXMLDOMDocument3( iface );
869 return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), DOMDocument );
873 static HRESULT WINAPI domdoc_cloneNode(
874 IXMLDOMDocument3 *iface,
876 IXMLDOMNode** cloneRoot)
878 domdoc *This = impl_from_IXMLDOMDocument3( iface );
879 return IXMLDOMNode_cloneNode( IXMLDOMNode_from_impl(&This->node), deep, cloneRoot );
883 static HRESULT WINAPI domdoc_get_nodeTypeString(
884 IXMLDOMDocument3 *iface,
887 domdoc *This = impl_from_IXMLDOMDocument3( iface );
888 return IXMLDOMNode_get_nodeTypeString( IXMLDOMNode_from_impl(&This->node), nodeType );
892 static HRESULT WINAPI domdoc_get_text(
893 IXMLDOMDocument3 *iface,
896 domdoc *This = impl_from_IXMLDOMDocument3( iface );
897 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), text );
901 static HRESULT WINAPI domdoc_put_text(
902 IXMLDOMDocument3 *iface,
905 domdoc *This = impl_from_IXMLDOMDocument3( iface );
906 return IXMLDOMNode_put_text( IXMLDOMNode_from_impl(&This->node), text );
910 static HRESULT WINAPI domdoc_get_specified(
911 IXMLDOMDocument3 *iface,
912 VARIANT_BOOL* isSpecified )
914 domdoc *This = impl_from_IXMLDOMDocument3( iface );
915 return IXMLDOMNode_get_specified( IXMLDOMNode_from_impl(&This->node), isSpecified );
919 static HRESULT WINAPI domdoc_get_definition(
920 IXMLDOMDocument3 *iface,
921 IXMLDOMNode** definitionNode )
923 domdoc *This = impl_from_IXMLDOMDocument3( iface );
924 return IXMLDOMNode_get_definition( IXMLDOMNode_from_impl(&This->node), definitionNode );
928 static HRESULT WINAPI domdoc_get_nodeTypedValue(
929 IXMLDOMDocument3 *iface,
930 VARIANT* typedValue )
932 domdoc *This = impl_from_IXMLDOMDocument3( iface );
933 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
936 static HRESULT WINAPI domdoc_put_nodeTypedValue(
937 IXMLDOMDocument3 *iface,
940 domdoc *This = impl_from_IXMLDOMDocument3( iface );
941 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
945 static HRESULT WINAPI domdoc_get_dataType(
946 IXMLDOMDocument3 *iface,
947 VARIANT* dataTypeName )
949 domdoc *This = impl_from_IXMLDOMDocument3( iface );
950 return IXMLDOMNode_get_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
954 static HRESULT WINAPI domdoc_put_dataType(
955 IXMLDOMDocument3 *iface,
958 domdoc *This = impl_from_IXMLDOMDocument3( iface );
959 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
963 static HRESULT WINAPI domdoc_get_xml(
964 IXMLDOMDocument3 *iface,
967 domdoc *This = impl_from_IXMLDOMDocument3( iface );
968 return IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), xmlString );
972 static HRESULT WINAPI domdoc_transformNode(
973 IXMLDOMDocument3 *iface,
974 IXMLDOMNode* styleSheet,
977 domdoc *This = impl_from_IXMLDOMDocument3( iface );
978 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), styleSheet, xmlString );
982 static HRESULT WINAPI domdoc_selectNodes(
983 IXMLDOMDocument3 *iface,
985 IXMLDOMNodeList** resultList )
987 domdoc *This = impl_from_IXMLDOMDocument3( iface );
988 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), queryString, resultList );
992 static HRESULT WINAPI domdoc_selectSingleNode(
993 IXMLDOMDocument3 *iface,
995 IXMLDOMNode** resultNode )
997 domdoc *This = impl_from_IXMLDOMDocument3( iface );
998 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), queryString, resultNode );
1002 static HRESULT WINAPI domdoc_get_parsed(
1003 IXMLDOMDocument3 *iface,
1004 VARIANT_BOOL* isParsed )
1006 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1007 return IXMLDOMNode_get_parsed( IXMLDOMNode_from_impl(&This->node), isParsed );
1011 static HRESULT WINAPI domdoc_get_namespaceURI(
1012 IXMLDOMDocument3 *iface,
1013 BSTR* namespaceURI )
1015 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1016 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), namespaceURI );
1020 static HRESULT WINAPI domdoc_get_prefix(
1021 IXMLDOMDocument3 *iface,
1022 BSTR* prefixString )
1024 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1025 return IXMLDOMNode_get_prefix( IXMLDOMNode_from_impl(&This->node), prefixString );
1029 static HRESULT WINAPI domdoc_get_baseName(
1030 IXMLDOMDocument3 *iface,
1033 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1034 return IXMLDOMNode_get_baseName( IXMLDOMNode_from_impl(&This->node), nameString );
1038 static HRESULT WINAPI domdoc_transformNodeToObject(
1039 IXMLDOMDocument3 *iface,
1040 IXMLDOMNode* stylesheet,
1041 VARIANT outputObject)
1043 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1044 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), stylesheet, outputObject );
1048 static HRESULT WINAPI domdoc_get_doctype(
1049 IXMLDOMDocument3 *iface,
1050 IXMLDOMDocumentType** documentType )
1052 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1053 FIXME("(%p)\n", This);
1058 static HRESULT WINAPI domdoc_get_implementation(
1059 IXMLDOMDocument3 *iface,
1060 IXMLDOMImplementation** impl )
1062 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1064 TRACE("(%p)->(%p)\n", This, impl);
1067 return E_INVALIDARG;
1069 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1074 static HRESULT WINAPI domdoc_get_documentElement(
1075 IXMLDOMDocument3 *iface,
1076 IXMLDOMElement** DOMElement )
1078 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1079 IXMLDOMNode *element_node;
1083 TRACE("(%p)->(%p)\n", This, DOMElement);
1086 return E_INVALIDARG;
1090 root = xmlDocGetRootElement( get_doc(This) );
1094 element_node = create_node( root );
1095 if(!element_node) return S_FALSE;
1097 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1098 IXMLDOMNode_Release(element_node);
1104 static HRESULT WINAPI domdoc_put_documentElement(
1105 IXMLDOMDocument3 *iface,
1106 IXMLDOMElement* DOMElement )
1108 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1109 IXMLDOMNode *elementNode;
1114 TRACE("(%p)->(%p)\n", This, DOMElement);
1116 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1120 xmlNode = get_node_obj( elementNode );
1122 FIXME("elementNode is not our object\n");
1126 if(!xmlNode->node->parent)
1127 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1128 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1130 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1131 IXMLDOMNode_Release( elementNode );
1134 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1140 static HRESULT WINAPI domdoc_createElement(
1141 IXMLDOMDocument3 *iface,
1143 IXMLDOMElement** element )
1145 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1150 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1152 if (!element || !tagname) return E_INVALIDARG;
1154 V_VT(&type) = VT_I1;
1155 V_I1(&type) = NODE_ELEMENT;
1157 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1160 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1161 IXMLDOMNode_Release(node);
1168 static HRESULT WINAPI domdoc_createDocumentFragment(
1169 IXMLDOMDocument3 *iface,
1170 IXMLDOMDocumentFragment** frag )
1172 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1177 TRACE("(%p)->(%p)\n", This, frag);
1179 if (!frag) return E_INVALIDARG;
1183 V_VT(&type) = VT_I1;
1184 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1186 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1189 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1190 IXMLDOMNode_Release(node);
1197 static HRESULT WINAPI domdoc_createTextNode(
1198 IXMLDOMDocument3 *iface,
1200 IXMLDOMText** text )
1202 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1207 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1209 if (!text) return E_INVALIDARG;
1213 V_VT(&type) = VT_I1;
1214 V_I1(&type) = NODE_TEXT;
1216 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1219 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1220 IXMLDOMNode_Release(node);
1221 hr = IXMLDOMText_put_data(*text, data);
1228 static HRESULT WINAPI domdoc_createComment(
1229 IXMLDOMDocument3 *iface,
1231 IXMLDOMComment** comment )
1233 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1238 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1240 if (!comment) return E_INVALIDARG;
1244 V_VT(&type) = VT_I1;
1245 V_I1(&type) = NODE_COMMENT;
1247 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1250 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1251 IXMLDOMNode_Release(node);
1252 hr = IXMLDOMComment_put_data(*comment, data);
1259 static HRESULT WINAPI domdoc_createCDATASection(
1260 IXMLDOMDocument3 *iface,
1262 IXMLDOMCDATASection** cdata )
1264 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1269 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1271 if (!cdata) return E_INVALIDARG;
1275 V_VT(&type) = VT_I1;
1276 V_I1(&type) = NODE_CDATA_SECTION;
1278 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1281 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1282 IXMLDOMNode_Release(node);
1283 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1290 static HRESULT WINAPI domdoc_createProcessingInstruction(
1291 IXMLDOMDocument3 *iface,
1294 IXMLDOMProcessingInstruction** pi )
1296 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1301 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1303 if (!pi) return E_INVALIDARG;
1307 V_VT(&type) = VT_I1;
1308 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1310 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1316 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1317 node_obj = get_node_obj(node);
1318 V_VT(&v_data) = VT_BSTR;
1319 V_BSTR(&v_data) = data;
1321 hr = node_put_value(node_obj, &v_data);
1323 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1324 IXMLDOMNode_Release(node);
1331 static HRESULT WINAPI domdoc_createAttribute(
1332 IXMLDOMDocument3 *iface,
1334 IXMLDOMAttribute** attribute )
1336 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1341 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1343 if (!attribute || !name) return E_INVALIDARG;
1345 V_VT(&type) = VT_I1;
1346 V_I1(&type) = NODE_ATTRIBUTE;
1348 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1351 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1352 IXMLDOMNode_Release(node);
1359 static HRESULT WINAPI domdoc_createEntityReference(
1360 IXMLDOMDocument3 *iface,
1362 IXMLDOMEntityReference** entityref )
1364 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1369 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1371 if (!entityref) return E_INVALIDARG;
1375 V_VT(&type) = VT_I1;
1376 V_I1(&type) = NODE_ENTITY_REFERENCE;
1378 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1381 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1382 IXMLDOMNode_Release(node);
1389 static HRESULT WINAPI domdoc_getElementsByTagName(
1390 IXMLDOMDocument3 *iface,
1392 IXMLDOMNodeList** resultList )
1394 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1397 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagName), resultList);
1399 if (!tagName || !resultList) return E_INVALIDARG;
1401 if (tagName[0] == '*' && tagName[1] == 0)
1403 static const WCHAR formatallW[] = {'/','/','*',0};
1404 hr = queryresult_create((xmlNodePtr)get_doc(This), formatallW, resultList);
1408 static const WCHAR xpathformat[] =
1409 { '/','/','*','[','l','o','c','a','l','-','n','a','m','e','(',')','=','\'' };
1410 static const WCHAR closeW[] = { '\'',']',0 };
1416 length = lstrlenW(tagName);
1418 /* without two WCHARs from format specifier */
1419 ptr = pattern = heap_alloc(sizeof(xpathformat) + length*sizeof(WCHAR) + sizeof(closeW));
1421 memcpy(ptr, xpathformat, sizeof(xpathformat));
1422 ptr += sizeof(xpathformat)/sizeof(WCHAR);
1423 memcpy(ptr, tagName, length*sizeof(WCHAR));
1425 memcpy(ptr, closeW, sizeof(closeW));
1427 hr = queryresult_create((xmlNodePtr)get_doc(This), pattern, resultList);
1434 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1440 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1442 return E_INVALIDARG;
1449 static HRESULT WINAPI domdoc_createNode(
1450 IXMLDOMDocument3 *iface,
1454 IXMLDOMNode** node )
1456 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1457 DOMNodeType node_type;
1462 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1464 if(!node) return E_INVALIDARG;
1466 if(namespaceURI && namespaceURI[0])
1467 FIXME("nodes with namespaces currently not supported.\n");
1469 hr = get_node_type(Type, &node_type);
1470 if(FAILED(hr)) return hr;
1472 TRACE("node_type %d\n", node_type);
1474 /* exit earlier for types that need name */
1478 case NODE_ATTRIBUTE:
1479 case NODE_ENTITY_REFERENCE:
1480 case NODE_PROCESSING_INSTRUCTION:
1481 if (!name || *name == 0) return E_FAIL;
1486 xml_name = xmlChar_from_wchar(name);
1491 xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
1493 case NODE_ATTRIBUTE:
1494 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1497 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1499 case NODE_CDATA_SECTION:
1500 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1502 case NODE_ENTITY_REFERENCE:
1503 xmlnode = xmlNewReference(get_doc(This), xml_name);
1505 case NODE_PROCESSING_INSTRUCTION:
1506 #ifdef HAVE_XMLNEWDOCPI
1507 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1509 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1514 xmlnode = xmlNewDocComment(get_doc(This), NULL);
1516 case NODE_DOCUMENT_FRAGMENT:
1517 xmlnode = xmlNewDocFragment(get_doc(This));
1519 /* unsupported types */
1521 case NODE_DOCUMENT_TYPE:
1524 heap_free(xml_name);
1525 return E_INVALIDARG;
1527 FIXME("unhandled node type %d\n", node_type);
1532 *node = create_node(xmlnode);
1533 heap_free(xml_name);
1537 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1538 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1545 static HRESULT WINAPI domdoc_nodeFromID(
1546 IXMLDOMDocument3 *iface,
1548 IXMLDOMNode** node )
1550 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1551 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1555 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1560 xmldoc = doparse( ptr, len, NULL );
1562 xmldoc->_private = create_priv();
1563 return attach_xmldoc(&This->node, xmldoc);
1569 static HRESULT doread( domdoc *This, LPWSTR filename )
1574 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1579 detach_bsc(This->bsc);
1585 static HRESULT WINAPI domdoc_load(
1586 IXMLDOMDocument3 *iface,
1588 VARIANT_BOOL* isSuccessful )
1590 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1591 LPWSTR filename = NULL;
1592 HRESULT hr = S_FALSE;
1593 IXMLDOMDocument3 *pNewDoc = NULL;
1594 IStream *pStream = NULL;
1597 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
1599 *isSuccessful = VARIANT_FALSE;
1601 assert( &This->node );
1603 switch( V_VT(&xmlSource) )
1606 filename = V_BSTR(&xmlSource);
1609 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
1614 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
1615 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1616 hr = attach_xmldoc(&This->node, xmldoc);
1619 *isSuccessful = VARIANT_TRUE;
1624 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1627 IPersistStream *pDocStream;
1628 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1631 hr = IPersistStream_Load(pDocStream, pStream);
1632 IStream_Release(pStream);
1635 *isSuccessful = VARIANT_TRUE;
1637 TRACE("Using IStream to load Document\n");
1642 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1647 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1652 /* ISequentialStream */
1653 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1657 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1660 TRACE("filename (%s)\n", debugstr_w(filename));
1664 hr = doread( This, filename );
1667 This->error = E_FAIL;
1670 hr = This->error = S_OK;
1671 *isSuccessful = VARIANT_TRUE;
1675 if(!filename || FAILED(hr)) {
1676 xmldoc = xmlNewDoc(NULL);
1677 xmldoc->_private = create_priv();
1678 hr = attach_xmldoc(&This->node, xmldoc);
1683 TRACE("ret (%d)\n", hr);
1689 static HRESULT WINAPI domdoc_get_readyState(
1690 IXMLDOMDocument3 *iface,
1693 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1694 FIXME("(%p)->(%p)\n", This, value);
1699 static HRESULT WINAPI domdoc_get_parseError(
1700 IXMLDOMDocument3 *iface,
1701 IXMLDOMParseError** errorObj )
1703 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1704 static const WCHAR err[] = {'e','r','r','o','r',0};
1705 BSTR error_string = NULL;
1707 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
1710 error_string = SysAllocString(err);
1712 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
1713 if(!*errorObj) return E_OUTOFMEMORY;
1718 static HRESULT WINAPI domdoc_get_url(
1719 IXMLDOMDocument3 *iface,
1722 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1723 FIXME("(%p)->(%p)\n", This, urlString);
1728 static HRESULT WINAPI domdoc_get_async(
1729 IXMLDOMDocument3 *iface,
1730 VARIANT_BOOL* isAsync )
1732 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1734 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
1735 *isAsync = This->async;
1740 static HRESULT WINAPI domdoc_put_async(
1741 IXMLDOMDocument3 *iface,
1742 VARIANT_BOOL isAsync )
1744 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1746 TRACE("(%p)->(%d)\n", This, isAsync);
1747 This->async = isAsync;
1752 static HRESULT WINAPI domdoc_abort(
1753 IXMLDOMDocument3 *iface )
1755 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1756 FIXME("%p\n", This);
1761 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
1766 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
1767 str = heap_alloc( len );
1770 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
1776 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
1777 static HRESULT WINAPI domdoc_loadXML(
1778 IXMLDOMDocument3 *iface,
1780 VARIANT_BOOL* isSuccessful )
1782 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1783 xmlDocPtr xmldoc = NULL;
1784 HRESULT hr = S_FALSE, hr2;
1788 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
1790 assert ( &This->node );
1794 *isSuccessful = VARIANT_FALSE;
1796 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
1798 xmldoc = doparse( str, len, "UTF-8" );
1801 This->error = E_FAIL;
1804 hr = This->error = S_OK;
1805 *isSuccessful = VARIANT_TRUE;
1806 TRACE("parsed document %p\n", xmldoc);
1811 xmldoc = xmlNewDoc(NULL);
1813 xmldoc->_private = create_priv();
1814 hr2 = attach_xmldoc( &This->node, xmldoc );
1821 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer,
1826 if(!WriteFile(ctx, buffer, len, &written, NULL))
1828 WARN("write error\n");
1835 static int XMLCALL domdoc_save_closecallback(void *ctx)
1837 return CloseHandle(ctx) ? 0 : -1;
1840 static HRESULT WINAPI domdoc_save(
1841 IXMLDOMDocument3 *iface,
1842 VARIANT destination )
1844 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1850 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
1851 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
1853 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
1855 FIXME("Unhandled vt %d\n", V_VT(&destination));
1859 if(V_VT(&destination) == VT_UNKNOWN)
1861 IUnknown *pUnk = V_UNKNOWN(&destination);
1862 IXMLDOMDocument2 *pDocument;
1864 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&pDocument);
1867 VARIANT_BOOL success;
1870 ret = IXMLDOMDocument3_get_xml(iface, &xml);
1873 ret = IXMLDOMDocument3_loadXML(pDocument, xml, &success);
1877 IXMLDOMDocument3_Release(pDocument);
1880 TRACE("ret %d\n", ret);
1885 handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
1886 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1887 if( handle == INVALID_HANDLE_VALUE )
1889 WARN("failed to create file\n");
1893 /* disable top XML declaration */
1894 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
1895 handle, NULL, XML_SAVE_NO_DECL);
1898 CloseHandle(handle);
1902 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
1903 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
1904 xmldoc_link_xmldecl(get_doc(This), xmldecl);
1906 /* will close file through close callback */
1912 static HRESULT WINAPI domdoc_get_validateOnParse(
1913 IXMLDOMDocument3 *iface,
1914 VARIANT_BOOL* isValidating )
1916 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1917 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
1918 *isValidating = This->validating;
1923 static HRESULT WINAPI domdoc_put_validateOnParse(
1924 IXMLDOMDocument3 *iface,
1925 VARIANT_BOOL isValidating )
1927 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1928 TRACE("(%p)->(%d)\n", This, isValidating);
1929 This->validating = isValidating;
1934 static HRESULT WINAPI domdoc_get_resolveExternals(
1935 IXMLDOMDocument3 *iface,
1936 VARIANT_BOOL* isResolving )
1938 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1939 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
1940 *isResolving = This->resolving;
1945 static HRESULT WINAPI domdoc_put_resolveExternals(
1946 IXMLDOMDocument3 *iface,
1947 VARIANT_BOOL isResolving )
1949 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1950 TRACE("(%p)->(%d)\n", This, isResolving);
1951 This->resolving = isResolving;
1956 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
1957 IXMLDOMDocument3 *iface,
1958 VARIANT_BOOL* isPreserving )
1960 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1961 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->preserving);
1962 *isPreserving = This->preserving;
1967 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
1968 IXMLDOMDocument3 *iface,
1969 VARIANT_BOOL isPreserving )
1971 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1972 TRACE("(%p)->(%d)\n", This, isPreserving);
1973 This->preserving = isPreserving;
1978 static HRESULT WINAPI domdoc_put_onReadyStateChange(
1979 IXMLDOMDocument3 *iface,
1980 VARIANT readyStateChangeSink )
1982 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1983 FIXME("%p\n", This);
1988 static HRESULT WINAPI domdoc_put_onDataAvailable(
1989 IXMLDOMDocument3 *iface,
1990 VARIANT onDataAvailableSink )
1992 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1993 FIXME("%p\n", This);
1997 static HRESULT WINAPI domdoc_put_onTransformNode(
1998 IXMLDOMDocument3 *iface,
1999 VARIANT onTransformNodeSink )
2001 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2002 FIXME("%p\n", This);
2006 static HRESULT WINAPI domdoc_get_namespaces(
2007 IXMLDOMDocument3* iface,
2008 IXMLDOMSchemaCollection** schemaCollection )
2010 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2011 FIXME("(%p)->(%p)\n", This, schemaCollection);
2015 static HRESULT WINAPI domdoc_get_schemas(
2016 IXMLDOMDocument3* iface,
2019 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2020 HRESULT hr = S_FALSE;
2021 IXMLDOMSchemaCollection *cur_schema = This->schema;
2023 TRACE("(%p)->(%p)\n", This, var1);
2025 VariantInit(var1); /* Test shows we don't call VariantClear here */
2026 V_VT(var1) = VT_NULL;
2030 hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2032 V_VT(var1) = VT_DISPATCH;
2037 static HRESULT WINAPI domdoc_putref_schemas(
2038 IXMLDOMDocument3* iface,
2041 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2042 HRESULT hr = E_FAIL;
2043 IXMLDOMSchemaCollection *new_schema = NULL;
2045 FIXME("(%p): semi-stub\n", This);
2049 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2053 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2062 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2067 IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
2068 if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
2074 static HRESULT WINAPI domdoc_validate(
2075 IXMLDOMDocument3* iface,
2076 IXMLDOMParseError** err)
2078 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2079 FIXME("(%p)->(%p)\n", This, err);
2083 static HRESULT WINAPI domdoc_setProperty(
2084 IXMLDOMDocument3* iface,
2088 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2090 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2092 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2098 V_VT(&varStr) = VT_EMPTY;
2099 if (V_VT(&var) != VT_BSTR)
2101 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2103 bstr = V_BSTR(&varStr);
2106 bstr = V_BSTR(&var);
2109 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2110 This->bUseXPath = TRUE;
2111 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2112 This->bUseXPath = FALSE;
2116 VariantClear(&varStr);
2119 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0)
2122 FIXME("Ignoring property ProhibitDTD, value %d\n", V_BOOL(&var));
2125 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2127 if (V_VT(&var) == VT_BSTR)
2128 FIXME("Unsupported SelectionNamespaces: %s\n", wine_dbgstr_w(V_BSTR(&var)));
2132 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2136 static HRESULT WINAPI domdoc_getProperty(
2137 IXMLDOMDocument3* iface,
2141 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2143 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2146 return E_INVALIDARG;
2148 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2150 V_VT(var) = VT_BSTR;
2151 if (This->bUseXPath)
2152 V_BSTR(var) = SysAllocString(PropValueXPathW);
2154 V_BSTR(var) = SysAllocString(PropValueXSLPatternW);
2158 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2162 static HRESULT WINAPI domdoc_validateNode(
2163 IXMLDOMDocument3* iface,
2165 IXMLDOMParseError** error)
2167 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2168 FIXME("(%p)->(%p %p): stub\n", This, node, error);
2172 static HRESULT WINAPI domdoc_importNode(
2173 IXMLDOMDocument3* iface,
2176 IXMLDOMNode** clone)
2178 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2179 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
2183 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
2185 domdoc_QueryInterface,
2188 domdoc_GetTypeInfoCount,
2190 domdoc_GetIDsOfNames,
2192 domdoc_get_nodeName,
2193 domdoc_get_nodeValue,
2194 domdoc_put_nodeValue,
2195 domdoc_get_nodeType,
2196 domdoc_get_parentNode,
2197 domdoc_get_childNodes,
2198 domdoc_get_firstChild,
2199 domdoc_get_lastChild,
2200 domdoc_get_previousSibling,
2201 domdoc_get_nextSibling,
2202 domdoc_get_attributes,
2203 domdoc_insertBefore,
2204 domdoc_replaceChild,
2207 domdoc_hasChildNodes,
2208 domdoc_get_ownerDocument,
2210 domdoc_get_nodeTypeString,
2213 domdoc_get_specified,
2214 domdoc_get_definition,
2215 domdoc_get_nodeTypedValue,
2216 domdoc_put_nodeTypedValue,
2217 domdoc_get_dataType,
2218 domdoc_put_dataType,
2220 domdoc_transformNode,
2222 domdoc_selectSingleNode,
2224 domdoc_get_namespaceURI,
2226 domdoc_get_baseName,
2227 domdoc_transformNodeToObject,
2229 domdoc_get_implementation,
2230 domdoc_get_documentElement,
2231 domdoc_put_documentElement,
2232 domdoc_createElement,
2233 domdoc_createDocumentFragment,
2234 domdoc_createTextNode,
2235 domdoc_createComment,
2236 domdoc_createCDATASection,
2237 domdoc_createProcessingInstruction,
2238 domdoc_createAttribute,
2239 domdoc_createEntityReference,
2240 domdoc_getElementsByTagName,
2244 domdoc_get_readyState,
2245 domdoc_get_parseError,
2252 domdoc_get_validateOnParse,
2253 domdoc_put_validateOnParse,
2254 domdoc_get_resolveExternals,
2255 domdoc_put_resolveExternals,
2256 domdoc_get_preserveWhiteSpace,
2257 domdoc_put_preserveWhiteSpace,
2258 domdoc_put_onReadyStateChange,
2259 domdoc_put_onDataAvailable,
2260 domdoc_put_onTransformNode,
2261 domdoc_get_namespaces,
2263 domdoc_putref_schemas,
2267 domdoc_validateNode,
2271 /* xmldoc implementation of IObjectWithSite */
2272 static HRESULT WINAPI
2273 xmldoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
2275 domdoc *This = impl_from_IObjectWithSite(iface);
2276 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppvObject );
2280 xmldoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
2282 domdoc *This = impl_from_IObjectWithSite(iface);
2283 return IXMLDocument_AddRef((IXMLDocument *)This);
2287 xmldoc_ObjectWithSite_Release( IObjectWithSite* iface )
2289 domdoc *This = impl_from_IObjectWithSite(iface);
2290 return IXMLDocument_Release((IXMLDocument *)This);
2293 static HRESULT WINAPI
2294 xmldoc_GetSite( IObjectWithSite *iface, REFIID iid, void ** ppvSite )
2296 domdoc *This = impl_from_IObjectWithSite(iface);
2298 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
2303 return IUnknown_QueryInterface( This->site, iid, ppvSite );
2306 static HRESULT WINAPI
2307 xmldoc_SetSite( IObjectWithSite *iface, IUnknown *punk )
2309 domdoc *This = impl_from_IObjectWithSite(iface);
2311 TRACE("(%p)->(%p)\n", iface, punk);
2317 IUnknown_Release( This->site );
2324 IUnknown_AddRef( punk );
2327 IUnknown_Release( This->site );
2334 static const IObjectWithSiteVtbl domdocObjectSite =
2336 xmldoc_ObjectWithSite_QueryInterface,
2337 xmldoc_ObjectWithSite_AddRef,
2338 xmldoc_ObjectWithSite_Release,
2343 static HRESULT WINAPI xmldoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
2345 domdoc *This = impl_from_IObjectSafety(iface);
2346 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppv );
2349 static ULONG WINAPI xmldoc_Safety_AddRef(IObjectSafety *iface)
2351 domdoc *This = impl_from_IObjectSafety(iface);
2352 return IXMLDocument_AddRef((IXMLDocument *)This);
2355 static ULONG WINAPI xmldoc_Safety_Release(IObjectSafety *iface)
2357 domdoc *This = impl_from_IObjectSafety(iface);
2358 return IXMLDocument_Release((IXMLDocument *)This);
2361 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
2363 static HRESULT WINAPI xmldoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2364 DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
2366 domdoc *This = impl_from_IObjectSafety(iface);
2368 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
2370 if(!pdwSupportedOptions || !pdwEnabledOptions)
2373 *pdwSupportedOptions = SAFETY_SUPPORTED_OPTIONS;
2374 *pdwEnabledOptions = This->safeopt;
2379 static HRESULT WINAPI xmldoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2380 DWORD dwOptionSetMask, DWORD dwEnabledOptions)
2382 domdoc *This = impl_from_IObjectSafety(iface);
2383 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
2385 if ((dwOptionSetMask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
2388 This->safeopt = dwEnabledOptions & dwOptionSetMask & SAFETY_SUPPORTED_OPTIONS;
2392 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
2393 xmldoc_Safety_QueryInterface,
2394 xmldoc_Safety_AddRef,
2395 xmldoc_Safety_Release,
2396 xmldoc_Safety_GetInterfaceSafetyOptions,
2397 xmldoc_Safety_SetInterfaceSafetyOptions
2401 static const tid_t domdoc_iface_tids[] = {
2403 IXMLDOMDocument_tid,
2404 IXMLDOMDocument2_tid,
2407 static dispex_static_data_t domdoc_dispex = {
2409 IXMLDOMDocument2_tid,
2414 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
2418 doc = heap_alloc( sizeof (*doc) );
2420 return E_OUTOFMEMORY;
2422 doc->lpVtbl = &domdoc_vtbl;
2423 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
2424 doc->lpvtblIObjectWithSite = &domdocObjectSite;
2425 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
2426 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
2428 doc->async = VARIANT_TRUE;
2429 doc->validating = 0;
2431 doc->preserving = 0;
2432 doc->bUseXPath = FALSE;
2440 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->lpVtbl, &domdoc_dispex);
2442 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
2444 TRACE("returning iface %p\n", *document);
2448 HRESULT DOMDocument_create(IUnknown *pUnkOuter, void **ppObj)
2453 TRACE("(%p, %p)\n", pUnkOuter, ppObj);
2455 xmldoc = xmlNewDoc(NULL);
2457 return E_OUTOFMEMORY;
2459 xmldoc->_private = create_priv();
2461 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
2468 IUnknown* create_domdoc( xmlNodePtr document )
2473 TRACE("(%p)\n", document);
2475 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
2484 HRESULT DOMDocument_create(IUnknown *pUnkOuter, void **ppObj)
2486 MESSAGE("This program tried to use a DOMDocument object, but\n"
2487 "libxml2 support was not present at compile time.\n");