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 return IXMLDOMNode_put_nodeValue( IXMLDOMNode_from_impl(&This->node), value );
724 static HRESULT WINAPI domdoc_get_nodeType(
725 IXMLDOMDocument3 *iface,
728 domdoc *This = impl_from_IXMLDOMDocument3( iface );
729 return IXMLDOMNode_get_nodeType( IXMLDOMNode_from_impl(&This->node), type );
733 static HRESULT WINAPI domdoc_get_parentNode(
734 IXMLDOMDocument3 *iface,
735 IXMLDOMNode** parent )
737 domdoc *This = impl_from_IXMLDOMDocument3( iface );
738 return IXMLDOMNode_get_parentNode( IXMLDOMNode_from_impl(&This->node), parent );
742 static HRESULT WINAPI domdoc_get_childNodes(
743 IXMLDOMDocument3 *iface,
744 IXMLDOMNodeList** childList )
746 domdoc *This = impl_from_IXMLDOMDocument3( iface );
747 return IXMLDOMNode_get_childNodes( IXMLDOMNode_from_impl(&This->node), childList );
751 static HRESULT WINAPI domdoc_get_firstChild(
752 IXMLDOMDocument3 *iface,
753 IXMLDOMNode** firstChild )
755 domdoc *This = impl_from_IXMLDOMDocument3( iface );
756 return IXMLDOMNode_get_firstChild( IXMLDOMNode_from_impl(&This->node), firstChild );
760 static HRESULT WINAPI domdoc_get_lastChild(
761 IXMLDOMDocument3 *iface,
762 IXMLDOMNode** lastChild )
764 domdoc *This = impl_from_IXMLDOMDocument3( iface );
765 return IXMLDOMNode_get_lastChild( IXMLDOMNode_from_impl(&This->node), lastChild );
769 static HRESULT WINAPI domdoc_get_previousSibling(
770 IXMLDOMDocument3 *iface,
771 IXMLDOMNode** previousSibling )
773 domdoc *This = impl_from_IXMLDOMDocument3( iface );
774 return IXMLDOMNode_get_previousSibling( IXMLDOMNode_from_impl(&This->node), previousSibling );
778 static HRESULT WINAPI domdoc_get_nextSibling(
779 IXMLDOMDocument3 *iface,
780 IXMLDOMNode** nextSibling )
782 domdoc *This = impl_from_IXMLDOMDocument3( iface );
783 return IXMLDOMNode_get_nextSibling( IXMLDOMNode_from_impl(&This->node), nextSibling );
787 static HRESULT WINAPI domdoc_get_attributes(
788 IXMLDOMDocument3 *iface,
789 IXMLDOMNamedNodeMap** attributeMap )
791 domdoc *This = impl_from_IXMLDOMDocument3( iface );
792 return IXMLDOMNode_get_attributes( IXMLDOMNode_from_impl(&This->node), attributeMap );
796 static HRESULT WINAPI domdoc_insertBefore(
797 IXMLDOMDocument3 *iface,
798 IXMLDOMNode* newChild,
800 IXMLDOMNode** outNewChild )
802 domdoc *This = impl_from_IXMLDOMDocument3( iface );
803 return IXMLDOMNode_insertBefore( IXMLDOMNode_from_impl(&This->node), newChild, refChild, outNewChild );
807 static HRESULT WINAPI domdoc_replaceChild(
808 IXMLDOMDocument3 *iface,
809 IXMLDOMNode* newChild,
810 IXMLDOMNode* oldChild,
811 IXMLDOMNode** outOldChild)
813 domdoc *This = impl_from_IXMLDOMDocument3( iface );
814 return IXMLDOMNode_replaceChild( IXMLDOMNode_from_impl(&This->node), newChild, oldChild, outOldChild );
818 static HRESULT WINAPI domdoc_removeChild(
819 IXMLDOMDocument3 *iface,
820 IXMLDOMNode* childNode,
821 IXMLDOMNode** oldChild)
823 domdoc *This = impl_from_IXMLDOMDocument3( iface );
824 return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), childNode, oldChild );
828 static HRESULT WINAPI domdoc_appendChild(
829 IXMLDOMDocument3 *iface,
830 IXMLDOMNode* newChild,
831 IXMLDOMNode** outNewChild)
833 domdoc *This = impl_from_IXMLDOMDocument3( iface );
834 return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newChild, outNewChild );
838 static HRESULT WINAPI domdoc_hasChildNodes(
839 IXMLDOMDocument3 *iface,
840 VARIANT_BOOL* hasChild)
842 domdoc *This = impl_from_IXMLDOMDocument3( iface );
843 return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), hasChild );
847 static HRESULT WINAPI domdoc_get_ownerDocument(
848 IXMLDOMDocument3 *iface,
849 IXMLDOMDocument** DOMDocument)
851 domdoc *This = impl_from_IXMLDOMDocument3( iface );
852 return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), DOMDocument );
856 static HRESULT WINAPI domdoc_cloneNode(
857 IXMLDOMDocument3 *iface,
859 IXMLDOMNode** cloneRoot)
861 domdoc *This = impl_from_IXMLDOMDocument3( iface );
862 return IXMLDOMNode_cloneNode( IXMLDOMNode_from_impl(&This->node), deep, cloneRoot );
866 static HRESULT WINAPI domdoc_get_nodeTypeString(
867 IXMLDOMDocument3 *iface,
870 domdoc *This = impl_from_IXMLDOMDocument3( iface );
871 return IXMLDOMNode_get_nodeTypeString( IXMLDOMNode_from_impl(&This->node), nodeType );
875 static HRESULT WINAPI domdoc_get_text(
876 IXMLDOMDocument3 *iface,
879 domdoc *This = impl_from_IXMLDOMDocument3( iface );
880 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), text );
884 static HRESULT WINAPI domdoc_put_text(
885 IXMLDOMDocument3 *iface,
888 domdoc *This = impl_from_IXMLDOMDocument3( iface );
889 return IXMLDOMNode_put_text( IXMLDOMNode_from_impl(&This->node), text );
893 static HRESULT WINAPI domdoc_get_specified(
894 IXMLDOMDocument3 *iface,
895 VARIANT_BOOL* isSpecified )
897 domdoc *This = impl_from_IXMLDOMDocument3( iface );
898 return IXMLDOMNode_get_specified( IXMLDOMNode_from_impl(&This->node), isSpecified );
902 static HRESULT WINAPI domdoc_get_definition(
903 IXMLDOMDocument3 *iface,
904 IXMLDOMNode** definitionNode )
906 domdoc *This = impl_from_IXMLDOMDocument3( iface );
907 return IXMLDOMNode_get_definition( IXMLDOMNode_from_impl(&This->node), definitionNode );
911 static HRESULT WINAPI domdoc_get_nodeTypedValue(
912 IXMLDOMDocument3 *iface,
913 VARIANT* typedValue )
915 domdoc *This = impl_from_IXMLDOMDocument3( iface );
916 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
919 static HRESULT WINAPI domdoc_put_nodeTypedValue(
920 IXMLDOMDocument3 *iface,
923 domdoc *This = impl_from_IXMLDOMDocument3( iface );
924 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
928 static HRESULT WINAPI domdoc_get_dataType(
929 IXMLDOMDocument3 *iface,
930 VARIANT* dataTypeName )
932 domdoc *This = impl_from_IXMLDOMDocument3( iface );
933 return IXMLDOMNode_get_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
937 static HRESULT WINAPI domdoc_put_dataType(
938 IXMLDOMDocument3 *iface,
941 domdoc *This = impl_from_IXMLDOMDocument3( iface );
942 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
946 static HRESULT WINAPI domdoc_get_xml(
947 IXMLDOMDocument3 *iface,
950 domdoc *This = impl_from_IXMLDOMDocument3( iface );
951 return IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), xmlString );
955 static HRESULT WINAPI domdoc_transformNode(
956 IXMLDOMDocument3 *iface,
957 IXMLDOMNode* styleSheet,
960 domdoc *This = impl_from_IXMLDOMDocument3( iface );
961 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), styleSheet, xmlString );
965 static HRESULT WINAPI domdoc_selectNodes(
966 IXMLDOMDocument3 *iface,
968 IXMLDOMNodeList** resultList )
970 domdoc *This = impl_from_IXMLDOMDocument3( iface );
971 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), queryString, resultList );
975 static HRESULT WINAPI domdoc_selectSingleNode(
976 IXMLDOMDocument3 *iface,
978 IXMLDOMNode** resultNode )
980 domdoc *This = impl_from_IXMLDOMDocument3( iface );
981 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), queryString, resultNode );
985 static HRESULT WINAPI domdoc_get_parsed(
986 IXMLDOMDocument3 *iface,
987 VARIANT_BOOL* isParsed )
989 domdoc *This = impl_from_IXMLDOMDocument3( iface );
990 return IXMLDOMNode_get_parsed( IXMLDOMNode_from_impl(&This->node), isParsed );
994 static HRESULT WINAPI domdoc_get_namespaceURI(
995 IXMLDOMDocument3 *iface,
998 domdoc *This = impl_from_IXMLDOMDocument3( iface );
999 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), namespaceURI );
1003 static HRESULT WINAPI domdoc_get_prefix(
1004 IXMLDOMDocument3 *iface,
1005 BSTR* prefixString )
1007 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1008 return IXMLDOMNode_get_prefix( IXMLDOMNode_from_impl(&This->node), prefixString );
1012 static HRESULT WINAPI domdoc_get_baseName(
1013 IXMLDOMDocument3 *iface,
1016 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1017 return IXMLDOMNode_get_baseName( IXMLDOMNode_from_impl(&This->node), nameString );
1021 static HRESULT WINAPI domdoc_transformNodeToObject(
1022 IXMLDOMDocument3 *iface,
1023 IXMLDOMNode* stylesheet,
1024 VARIANT outputObject)
1026 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1027 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), stylesheet, outputObject );
1031 static HRESULT WINAPI domdoc_get_doctype(
1032 IXMLDOMDocument3 *iface,
1033 IXMLDOMDocumentType** documentType )
1035 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1036 FIXME("(%p)\n", This);
1041 static HRESULT WINAPI domdoc_get_implementation(
1042 IXMLDOMDocument3 *iface,
1043 IXMLDOMImplementation** impl )
1045 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1047 TRACE("(%p)->(%p)\n", This, impl);
1050 return E_INVALIDARG;
1052 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1057 static HRESULT WINAPI domdoc_get_documentElement(
1058 IXMLDOMDocument3 *iface,
1059 IXMLDOMElement** DOMElement )
1061 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1062 IXMLDOMNode *element_node;
1066 TRACE("(%p)->(%p)\n", This, DOMElement);
1069 return E_INVALIDARG;
1073 root = xmlDocGetRootElement( get_doc(This) );
1077 element_node = create_node( root );
1078 if(!element_node) return S_FALSE;
1080 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1081 IXMLDOMNode_Release(element_node);
1087 static HRESULT WINAPI domdoc_put_documentElement(
1088 IXMLDOMDocument3 *iface,
1089 IXMLDOMElement* DOMElement )
1091 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1092 IXMLDOMNode *elementNode;
1097 TRACE("(%p)->(%p)\n", This, DOMElement);
1099 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1103 xmlNode = get_node_obj( elementNode );
1105 FIXME("elementNode is not our object\n");
1109 if(!xmlNode->node->parent)
1110 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1111 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1113 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1114 IXMLDOMNode_Release( elementNode );
1117 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1123 static HRESULT WINAPI domdoc_createElement(
1124 IXMLDOMDocument3 *iface,
1126 IXMLDOMElement** element )
1128 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1133 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1135 if (!element || !tagname) return E_INVALIDARG;
1137 V_VT(&type) = VT_I1;
1138 V_I1(&type) = NODE_ELEMENT;
1140 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1143 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1144 IXMLDOMNode_Release(node);
1151 static HRESULT WINAPI domdoc_createDocumentFragment(
1152 IXMLDOMDocument3 *iface,
1153 IXMLDOMDocumentFragment** frag )
1155 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1160 TRACE("(%p)->(%p)\n", This, frag);
1162 if (!frag) return E_INVALIDARG;
1166 V_VT(&type) = VT_I1;
1167 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1169 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1172 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1173 IXMLDOMNode_Release(node);
1180 static HRESULT WINAPI domdoc_createTextNode(
1181 IXMLDOMDocument3 *iface,
1183 IXMLDOMText** text )
1185 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1190 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1192 if (!text) return E_INVALIDARG;
1196 V_VT(&type) = VT_I1;
1197 V_I1(&type) = NODE_TEXT;
1199 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1202 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1203 IXMLDOMNode_Release(node);
1204 hr = IXMLDOMText_put_data(*text, data);
1211 static HRESULT WINAPI domdoc_createComment(
1212 IXMLDOMDocument3 *iface,
1214 IXMLDOMComment** comment )
1216 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1221 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1223 if (!comment) return E_INVALIDARG;
1227 V_VT(&type) = VT_I1;
1228 V_I1(&type) = NODE_COMMENT;
1230 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1233 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1234 IXMLDOMNode_Release(node);
1235 hr = IXMLDOMComment_put_data(*comment, data);
1242 static HRESULT WINAPI domdoc_createCDATASection(
1243 IXMLDOMDocument3 *iface,
1245 IXMLDOMCDATASection** cdata )
1247 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1252 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1254 if (!cdata) return E_INVALIDARG;
1258 V_VT(&type) = VT_I1;
1259 V_I1(&type) = NODE_CDATA_SECTION;
1261 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1264 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1265 IXMLDOMNode_Release(node);
1266 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1273 static HRESULT WINAPI domdoc_createProcessingInstruction(
1274 IXMLDOMDocument3 *iface,
1277 IXMLDOMProcessingInstruction** pi )
1279 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1284 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1286 if (!pi) return E_INVALIDARG;
1290 V_VT(&type) = VT_I1;
1291 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1293 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1299 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1300 node_obj = get_node_obj(node);
1301 V_VT(&v_data) = VT_BSTR;
1302 V_BSTR(&v_data) = data;
1304 hr = IXMLDOMNode_put_nodeValue( IXMLDOMNode_from_impl(node_obj), v_data );
1306 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1307 IXMLDOMNode_Release(node);
1314 static HRESULT WINAPI domdoc_createAttribute(
1315 IXMLDOMDocument3 *iface,
1317 IXMLDOMAttribute** attribute )
1319 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1324 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1326 if (!attribute || !name) return E_INVALIDARG;
1328 V_VT(&type) = VT_I1;
1329 V_I1(&type) = NODE_ATTRIBUTE;
1331 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1334 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1335 IXMLDOMNode_Release(node);
1342 static HRESULT WINAPI domdoc_createEntityReference(
1343 IXMLDOMDocument3 *iface,
1345 IXMLDOMEntityReference** entityref )
1347 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1352 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1354 if (!entityref) return E_INVALIDARG;
1358 V_VT(&type) = VT_I1;
1359 V_I1(&type) = NODE_ENTITY_REFERENCE;
1361 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1364 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1365 IXMLDOMNode_Release(node);
1372 static HRESULT WINAPI domdoc_getElementsByTagName(
1373 IXMLDOMDocument3 *iface,
1375 IXMLDOMNodeList** resultList )
1377 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1380 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagName), resultList);
1382 if (!tagName || !resultList) return E_INVALIDARG;
1384 if (tagName[0] == '*' && tagName[1] == 0)
1386 static const WCHAR formatallW[] = {'/','/','*',0};
1387 hr = queryresult_create((xmlNodePtr)get_doc(This), formatallW, resultList);
1391 static const WCHAR xpathformat[] =
1392 { '/','/','*','[','l','o','c','a','l','-','n','a','m','e','(',')','=','\'' };
1393 static const WCHAR closeW[] = { '\'',']',0 };
1399 length = lstrlenW(tagName);
1401 /* without two WCHARs from format specifier */
1402 ptr = pattern = heap_alloc(sizeof(xpathformat) + length*sizeof(WCHAR) + sizeof(closeW));
1404 memcpy(ptr, xpathformat, sizeof(xpathformat));
1405 ptr += sizeof(xpathformat)/sizeof(WCHAR);
1406 memcpy(ptr, tagName, length*sizeof(WCHAR));
1408 memcpy(ptr, closeW, sizeof(closeW));
1410 hr = queryresult_create((xmlNodePtr)get_doc(This), pattern, resultList);
1417 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1423 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1425 return E_INVALIDARG;
1432 static HRESULT WINAPI domdoc_createNode(
1433 IXMLDOMDocument3 *iface,
1437 IXMLDOMNode** node )
1439 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1440 DOMNodeType node_type;
1445 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1447 if(!node) return E_INVALIDARG;
1449 if(namespaceURI && namespaceURI[0])
1450 FIXME("nodes with namespaces currently not supported.\n");
1452 hr = get_node_type(Type, &node_type);
1453 if(FAILED(hr)) return hr;
1455 TRACE("node_type %d\n", node_type);
1457 /* exit earlier for types that need name */
1461 case NODE_ATTRIBUTE:
1462 case NODE_ENTITY_REFERENCE:
1463 case NODE_PROCESSING_INSTRUCTION:
1464 if (!name || *name == 0) return E_FAIL;
1469 xml_name = xmlChar_from_wchar(name);
1474 xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
1476 case NODE_ATTRIBUTE:
1477 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1480 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1482 case NODE_CDATA_SECTION:
1483 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1485 case NODE_ENTITY_REFERENCE:
1486 xmlnode = xmlNewReference(get_doc(This), xml_name);
1488 case NODE_PROCESSING_INSTRUCTION:
1489 #ifdef HAVE_XMLNEWDOCPI
1490 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1492 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1497 xmlnode = xmlNewDocComment(get_doc(This), NULL);
1499 case NODE_DOCUMENT_FRAGMENT:
1500 xmlnode = xmlNewDocFragment(get_doc(This));
1502 /* unsupported types */
1504 case NODE_DOCUMENT_TYPE:
1507 heap_free(xml_name);
1508 return E_INVALIDARG;
1510 FIXME("unhandled node type %d\n", node_type);
1515 *node = create_node(xmlnode);
1516 heap_free(xml_name);
1520 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1521 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1528 static HRESULT WINAPI domdoc_nodeFromID(
1529 IXMLDOMDocument3 *iface,
1531 IXMLDOMNode** node )
1533 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1534 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1538 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1543 xmldoc = doparse( ptr, len, NULL );
1545 xmldoc->_private = create_priv();
1546 return attach_xmldoc(&This->node, xmldoc);
1552 static HRESULT doread( domdoc *This, LPWSTR filename )
1557 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1562 detach_bsc(This->bsc);
1568 static HRESULT WINAPI domdoc_load(
1569 IXMLDOMDocument3 *iface,
1571 VARIANT_BOOL* isSuccessful )
1573 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1574 LPWSTR filename = NULL;
1575 HRESULT hr = S_FALSE;
1576 IXMLDOMDocument3 *pNewDoc = NULL;
1577 IStream *pStream = NULL;
1580 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
1582 *isSuccessful = VARIANT_FALSE;
1584 assert( &This->node );
1586 switch( V_VT(&xmlSource) )
1589 filename = V_BSTR(&xmlSource);
1592 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
1597 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
1598 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1599 hr = attach_xmldoc(&This->node, xmldoc);
1602 *isSuccessful = VARIANT_TRUE;
1607 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1610 IPersistStream *pDocStream;
1611 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1614 hr = IPersistStream_Load(pDocStream, pStream);
1615 IStream_Release(pStream);
1618 *isSuccessful = VARIANT_TRUE;
1620 TRACE("Using IStream to load Document\n");
1625 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1630 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1635 /* ISequentialStream */
1636 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1640 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1643 TRACE("filename (%s)\n", debugstr_w(filename));
1647 hr = doread( This, filename );
1650 This->error = E_FAIL;
1653 hr = This->error = S_OK;
1654 *isSuccessful = VARIANT_TRUE;
1658 if(!filename || FAILED(hr)) {
1659 xmldoc = xmlNewDoc(NULL);
1660 xmldoc->_private = create_priv();
1661 hr = attach_xmldoc(&This->node, xmldoc);
1666 TRACE("ret (%d)\n", hr);
1672 static HRESULT WINAPI domdoc_get_readyState(
1673 IXMLDOMDocument3 *iface,
1676 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1677 FIXME("(%p)->(%p)\n", This, value);
1682 static HRESULT WINAPI domdoc_get_parseError(
1683 IXMLDOMDocument3 *iface,
1684 IXMLDOMParseError** errorObj )
1686 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1687 static const WCHAR err[] = {'e','r','r','o','r',0};
1688 BSTR error_string = NULL;
1690 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
1693 error_string = SysAllocString(err);
1695 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
1696 if(!*errorObj) return E_OUTOFMEMORY;
1701 static HRESULT WINAPI domdoc_get_url(
1702 IXMLDOMDocument3 *iface,
1705 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1706 FIXME("(%p)->(%p)\n", This, urlString);
1711 static HRESULT WINAPI domdoc_get_async(
1712 IXMLDOMDocument3 *iface,
1713 VARIANT_BOOL* isAsync )
1715 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1717 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
1718 *isAsync = This->async;
1723 static HRESULT WINAPI domdoc_put_async(
1724 IXMLDOMDocument3 *iface,
1725 VARIANT_BOOL isAsync )
1727 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1729 TRACE("(%p)->(%d)\n", This, isAsync);
1730 This->async = isAsync;
1735 static HRESULT WINAPI domdoc_abort(
1736 IXMLDOMDocument3 *iface )
1738 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1739 FIXME("%p\n", This);
1744 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
1749 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
1750 str = heap_alloc( len );
1753 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
1759 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
1760 static HRESULT WINAPI domdoc_loadXML(
1761 IXMLDOMDocument3 *iface,
1763 VARIANT_BOOL* isSuccessful )
1765 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1766 xmlDocPtr xmldoc = NULL;
1767 HRESULT hr = S_FALSE, hr2;
1771 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
1773 assert ( &This->node );
1777 *isSuccessful = VARIANT_FALSE;
1779 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
1781 xmldoc = doparse( str, len, "UTF-8" );
1784 This->error = E_FAIL;
1787 hr = This->error = S_OK;
1788 *isSuccessful = VARIANT_TRUE;
1789 TRACE("parsed document %p\n", xmldoc);
1794 xmldoc = xmlNewDoc(NULL);
1796 xmldoc->_private = create_priv();
1797 hr2 = attach_xmldoc( &This->node, xmldoc );
1804 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer,
1809 if(!WriteFile(ctx, buffer, len, &written, NULL))
1811 WARN("write error\n");
1818 static int XMLCALL domdoc_save_closecallback(void *ctx)
1820 return CloseHandle(ctx) ? 0 : -1;
1823 static HRESULT WINAPI domdoc_save(
1824 IXMLDOMDocument3 *iface,
1825 VARIANT destination )
1827 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1833 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
1834 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
1836 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
1838 FIXME("Unhandled vt %d\n", V_VT(&destination));
1842 if(V_VT(&destination) == VT_UNKNOWN)
1844 IUnknown *pUnk = V_UNKNOWN(&destination);
1845 IXMLDOMDocument2 *pDocument;
1847 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&pDocument);
1850 VARIANT_BOOL success;
1853 ret = IXMLDOMDocument3_get_xml(iface, &xml);
1856 ret = IXMLDOMDocument3_loadXML(pDocument, xml, &success);
1860 IXMLDOMDocument3_Release(pDocument);
1863 TRACE("ret %d\n", ret);
1868 handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
1869 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1870 if( handle == INVALID_HANDLE_VALUE )
1872 WARN("failed to create file\n");
1876 /* disable top XML declaration */
1877 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
1878 handle, NULL, XML_SAVE_NO_DECL);
1881 CloseHandle(handle);
1885 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
1886 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
1887 xmldoc_link_xmldecl(get_doc(This), xmldecl);
1889 /* will close file through close callback */
1895 static HRESULT WINAPI domdoc_get_validateOnParse(
1896 IXMLDOMDocument3 *iface,
1897 VARIANT_BOOL* isValidating )
1899 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1900 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
1901 *isValidating = This->validating;
1906 static HRESULT WINAPI domdoc_put_validateOnParse(
1907 IXMLDOMDocument3 *iface,
1908 VARIANT_BOOL isValidating )
1910 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1911 TRACE("(%p)->(%d)\n", This, isValidating);
1912 This->validating = isValidating;
1917 static HRESULT WINAPI domdoc_get_resolveExternals(
1918 IXMLDOMDocument3 *iface,
1919 VARIANT_BOOL* isResolving )
1921 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1922 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
1923 *isResolving = This->resolving;
1928 static HRESULT WINAPI domdoc_put_resolveExternals(
1929 IXMLDOMDocument3 *iface,
1930 VARIANT_BOOL isResolving )
1932 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1933 TRACE("(%p)->(%d)\n", This, isResolving);
1934 This->resolving = isResolving;
1939 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
1940 IXMLDOMDocument3 *iface,
1941 VARIANT_BOOL* isPreserving )
1943 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1944 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->preserving);
1945 *isPreserving = This->preserving;
1950 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
1951 IXMLDOMDocument3 *iface,
1952 VARIANT_BOOL isPreserving )
1954 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1955 TRACE("(%p)->(%d)\n", This, isPreserving);
1956 This->preserving = isPreserving;
1961 static HRESULT WINAPI domdoc_put_onReadyStateChange(
1962 IXMLDOMDocument3 *iface,
1963 VARIANT readyStateChangeSink )
1965 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1966 FIXME("%p\n", This);
1971 static HRESULT WINAPI domdoc_put_onDataAvailable(
1972 IXMLDOMDocument3 *iface,
1973 VARIANT onDataAvailableSink )
1975 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1976 FIXME("%p\n", This);
1980 static HRESULT WINAPI domdoc_put_onTransformNode(
1981 IXMLDOMDocument3 *iface,
1982 VARIANT onTransformNodeSink )
1984 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1985 FIXME("%p\n", This);
1989 static HRESULT WINAPI domdoc_get_namespaces(
1990 IXMLDOMDocument3* iface,
1991 IXMLDOMSchemaCollection** schemaCollection )
1993 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1994 FIXME("(%p)->(%p)\n", This, schemaCollection);
1998 static HRESULT WINAPI domdoc_get_schemas(
1999 IXMLDOMDocument3* iface,
2002 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2003 HRESULT hr = S_FALSE;
2004 IXMLDOMSchemaCollection *cur_schema = This->schema;
2006 TRACE("(%p)->(%p)\n", This, var1);
2008 VariantInit(var1); /* Test shows we don't call VariantClear here */
2009 V_VT(var1) = VT_NULL;
2013 hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2015 V_VT(var1) = VT_DISPATCH;
2020 static HRESULT WINAPI domdoc_putref_schemas(
2021 IXMLDOMDocument3* iface,
2024 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2025 HRESULT hr = E_FAIL;
2026 IXMLDOMSchemaCollection *new_schema = NULL;
2028 FIXME("(%p): semi-stub\n", This);
2032 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2036 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2045 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2050 IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
2051 if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
2057 static HRESULT WINAPI domdoc_validate(
2058 IXMLDOMDocument3* iface,
2059 IXMLDOMParseError** err)
2061 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2062 FIXME("(%p)->(%p)\n", This, err);
2066 static HRESULT WINAPI domdoc_setProperty(
2067 IXMLDOMDocument3* iface,
2071 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2073 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2075 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2081 V_VT(&varStr) = VT_EMPTY;
2082 if (V_VT(&var) != VT_BSTR)
2084 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2086 bstr = V_BSTR(&varStr);
2089 bstr = V_BSTR(&var);
2092 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2093 This->bUseXPath = TRUE;
2094 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2095 This->bUseXPath = FALSE;
2099 VariantClear(&varStr);
2102 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0)
2105 FIXME("Ignoring property ProhibitDTD, value %d\n", V_BOOL(&var));
2108 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2110 if (V_VT(&var) == VT_BSTR)
2111 FIXME("Unsupported SelectionNamespaces: %s\n", wine_dbgstr_w(V_BSTR(&var)));
2115 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2119 static HRESULT WINAPI domdoc_getProperty(
2120 IXMLDOMDocument3* iface,
2124 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2126 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2129 return E_INVALIDARG;
2131 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2133 V_VT(var) = VT_BSTR;
2134 if (This->bUseXPath)
2135 V_BSTR(var) = SysAllocString(PropValueXPathW);
2137 V_BSTR(var) = SysAllocString(PropValueXSLPatternW);
2141 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2145 static HRESULT WINAPI domdoc_validateNode(
2146 IXMLDOMDocument3* iface,
2148 IXMLDOMParseError** error)
2150 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2151 FIXME("(%p)->(%p %p): stub\n", This, node, error);
2155 static HRESULT WINAPI domdoc_importNode(
2156 IXMLDOMDocument3* iface,
2159 IXMLDOMNode** clone)
2161 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2162 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
2166 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
2168 domdoc_QueryInterface,
2171 domdoc_GetTypeInfoCount,
2173 domdoc_GetIDsOfNames,
2175 domdoc_get_nodeName,
2176 domdoc_get_nodeValue,
2177 domdoc_put_nodeValue,
2178 domdoc_get_nodeType,
2179 domdoc_get_parentNode,
2180 domdoc_get_childNodes,
2181 domdoc_get_firstChild,
2182 domdoc_get_lastChild,
2183 domdoc_get_previousSibling,
2184 domdoc_get_nextSibling,
2185 domdoc_get_attributes,
2186 domdoc_insertBefore,
2187 domdoc_replaceChild,
2190 domdoc_hasChildNodes,
2191 domdoc_get_ownerDocument,
2193 domdoc_get_nodeTypeString,
2196 domdoc_get_specified,
2197 domdoc_get_definition,
2198 domdoc_get_nodeTypedValue,
2199 domdoc_put_nodeTypedValue,
2200 domdoc_get_dataType,
2201 domdoc_put_dataType,
2203 domdoc_transformNode,
2205 domdoc_selectSingleNode,
2207 domdoc_get_namespaceURI,
2209 domdoc_get_baseName,
2210 domdoc_transformNodeToObject,
2212 domdoc_get_implementation,
2213 domdoc_get_documentElement,
2214 domdoc_put_documentElement,
2215 domdoc_createElement,
2216 domdoc_createDocumentFragment,
2217 domdoc_createTextNode,
2218 domdoc_createComment,
2219 domdoc_createCDATASection,
2220 domdoc_createProcessingInstruction,
2221 domdoc_createAttribute,
2222 domdoc_createEntityReference,
2223 domdoc_getElementsByTagName,
2227 domdoc_get_readyState,
2228 domdoc_get_parseError,
2235 domdoc_get_validateOnParse,
2236 domdoc_put_validateOnParse,
2237 domdoc_get_resolveExternals,
2238 domdoc_put_resolveExternals,
2239 domdoc_get_preserveWhiteSpace,
2240 domdoc_put_preserveWhiteSpace,
2241 domdoc_put_onReadyStateChange,
2242 domdoc_put_onDataAvailable,
2243 domdoc_put_onTransformNode,
2244 domdoc_get_namespaces,
2246 domdoc_putref_schemas,
2250 domdoc_validateNode,
2254 /* xmldoc implementation of IObjectWithSite */
2255 static HRESULT WINAPI
2256 xmldoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
2258 domdoc *This = impl_from_IObjectWithSite(iface);
2259 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppvObject );
2263 xmldoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
2265 domdoc *This = impl_from_IObjectWithSite(iface);
2266 return IXMLDocument_AddRef((IXMLDocument *)This);
2270 xmldoc_ObjectWithSite_Release( IObjectWithSite* iface )
2272 domdoc *This = impl_from_IObjectWithSite(iface);
2273 return IXMLDocument_Release((IXMLDocument *)This);
2276 static HRESULT WINAPI
2277 xmldoc_GetSite( IObjectWithSite *iface, REFIID iid, void ** ppvSite )
2279 domdoc *This = impl_from_IObjectWithSite(iface);
2281 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
2286 return IUnknown_QueryInterface( This->site, iid, ppvSite );
2289 static HRESULT WINAPI
2290 xmldoc_SetSite( IObjectWithSite *iface, IUnknown *punk )
2292 domdoc *This = impl_from_IObjectWithSite(iface);
2294 TRACE("(%p)->(%p)\n", iface, punk);
2300 IUnknown_Release( This->site );
2307 IUnknown_AddRef( punk );
2310 IUnknown_Release( This->site );
2317 static const IObjectWithSiteVtbl domdocObjectSite =
2319 xmldoc_ObjectWithSite_QueryInterface,
2320 xmldoc_ObjectWithSite_AddRef,
2321 xmldoc_ObjectWithSite_Release,
2326 static HRESULT WINAPI xmldoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
2328 domdoc *This = impl_from_IObjectSafety(iface);
2329 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppv );
2332 static ULONG WINAPI xmldoc_Safety_AddRef(IObjectSafety *iface)
2334 domdoc *This = impl_from_IObjectSafety(iface);
2335 return IXMLDocument_AddRef((IXMLDocument *)This);
2338 static ULONG WINAPI xmldoc_Safety_Release(IObjectSafety *iface)
2340 domdoc *This = impl_from_IObjectSafety(iface);
2341 return IXMLDocument_Release((IXMLDocument *)This);
2344 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
2346 static HRESULT WINAPI xmldoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2347 DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
2349 domdoc *This = impl_from_IObjectSafety(iface);
2351 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
2353 if(!pdwSupportedOptions || !pdwEnabledOptions)
2356 *pdwSupportedOptions = SAFETY_SUPPORTED_OPTIONS;
2357 *pdwEnabledOptions = This->safeopt;
2362 static HRESULT WINAPI xmldoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2363 DWORD dwOptionSetMask, DWORD dwEnabledOptions)
2365 domdoc *This = impl_from_IObjectSafety(iface);
2366 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
2368 if ((dwOptionSetMask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
2371 This->safeopt = dwEnabledOptions & dwOptionSetMask & SAFETY_SUPPORTED_OPTIONS;
2375 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
2376 xmldoc_Safety_QueryInterface,
2377 xmldoc_Safety_AddRef,
2378 xmldoc_Safety_Release,
2379 xmldoc_Safety_GetInterfaceSafetyOptions,
2380 xmldoc_Safety_SetInterfaceSafetyOptions
2384 static const tid_t domdoc_iface_tids[] = {
2386 IXMLDOMDocument_tid,
2387 IXMLDOMDocument2_tid,
2390 static dispex_static_data_t domdoc_dispex = {
2392 IXMLDOMDocument2_tid,
2397 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
2401 doc = heap_alloc( sizeof (*doc) );
2403 return E_OUTOFMEMORY;
2405 doc->lpVtbl = &domdoc_vtbl;
2406 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
2407 doc->lpvtblIObjectWithSite = &domdocObjectSite;
2408 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
2409 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
2411 doc->async = VARIANT_TRUE;
2412 doc->validating = 0;
2414 doc->preserving = 0;
2415 doc->bUseXPath = FALSE;
2423 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->lpVtbl, &domdoc_dispex);
2425 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
2427 TRACE("returning iface %p\n", *document);
2431 HRESULT DOMDocument_create(IUnknown *pUnkOuter, void **ppObj)
2436 TRACE("(%p, %p)\n", pUnkOuter, ppObj);
2438 xmldoc = xmlNewDoc(NULL);
2440 return E_OUTOFMEMORY;
2442 xmldoc->_private = create_priv();
2444 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
2451 IUnknown* create_domdoc( xmlNodePtr document )
2456 TRACE("(%p)\n", document);
2458 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
2467 HRESULT DOMDocument_create(IUnknown *pUnkOuter, void **ppObj)
2469 MESSAGE("This program tried to use a DOMDocument object, but\n"
2470 "libxml2 support was not present at compile time.\n");