2 * DOM Document implementation
4 * Copyright 2005 Mike McCormack
5 * Copyright 2010-2011 Adam Martinson for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define NONAMELESSUNION
30 # include <libxml/parser.h>
31 # include <libxml/xmlerror.h>
32 # include <libxml/xpathInternals.h>
33 # include <libxml/xmlsave.h>
34 # include <libxml/SAX2.h>
35 # include <libxml/parserInternals.h>
51 #include "wine/debug.h"
52 #include "wine/list.h"
54 #include "msxml_private.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
60 /* not defined in older versions */
61 #define XML_SAVE_FORMAT 1
62 #define XML_SAVE_NO_DECL 2
63 #define XML_SAVE_NO_EMPTY 4
64 #define XML_SAVE_NO_XHTML 8
65 #define XML_SAVE_XHTML 16
66 #define XML_SAVE_AS_XML 32
67 #define XML_SAVE_AS_HTML 64
69 static const WCHAR PropertySelectionLanguageW[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
70 static const WCHAR PropertySelectionNamespacesW[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
71 static const WCHAR PropertyProhibitDTDW[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
72 static const WCHAR PropertyNewParserW[] = {'N','e','w','P','a','r','s','e','r',0};
73 static const WCHAR PropValueXPathW[] = {'X','P','a','t','h',0};
74 static const WCHAR PropValueXSLPatternW[] = {'X','S','L','P','a','t','t','e','r','n',0};
75 static const WCHAR PropertyResolveExternalsW[] = {'R','e','s','o','l','v','e','E','x','t','e','r','n','a','l','s',0};
77 /* Anything that passes the test_get_ownerDocument()
78 * tests can go here (data shared between all instances).
79 * We need to preserve this when reloading a document,
80 * and also need access to it from the libxml backend. */
82 MSXML_VERSION version;
83 VARIANT_BOOL preserving;
84 IXMLDOMSchemaCollection2* schemaCache;
85 struct list selectNsList;
86 xmlChar const* selectNsStr;
91 typedef struct ConnectionPoint ConnectionPoint;
92 typedef struct domdoc domdoc;
94 struct ConnectionPoint
96 IConnectionPoint IConnectionPoint_iface;
99 ConnectionPoint *next;
100 IConnectionPointContainer *container;
107 IPropertyNotifySink *propnotif;
113 EVENTID_READYSTATECHANGE = 0,
114 EVENTID_DATAAVAILABLE,
115 EVENTID_TRANSFORMNODE,
122 IXMLDOMDocument3 IXMLDOMDocument3_iface;
123 IPersistStreamInit IPersistStreamInit_iface;
124 IObjectWithSite IObjectWithSite_iface;
125 IObjectSafety IObjectSafety_iface;
126 IConnectionPointContainer IConnectionPointContainer_iface;
129 VARIANT_BOOL validating;
130 VARIANT_BOOL resolving;
131 domdoc_properties* properties;
144 /* connection list */
145 ConnectionPoint *cp_list;
146 ConnectionPoint cp_domdocevents;
147 ConnectionPoint cp_propnotif;
148 ConnectionPoint cp_dispatch;
151 IDispatch *events[EVENTID_LAST];
153 IXMLDOMSchemaCollection2 *namespaces;
156 static HRESULT set_doc_event(domdoc *doc, eventid_t eid, const VARIANT *v)
164 IUnknown_QueryInterface(V_UNKNOWN(v), &IID_IDispatch, (void**)&disp);
169 disp = V_DISPATCH(v);
170 if (disp) IDispatch_AddRef(disp);
173 return DISP_E_TYPEMISMATCH;
176 if (doc->events[eid]) IDispatch_Release(doc->events[eid]);
177 doc->events[eid] = disp;
182 static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface)
184 return CONTAINING_RECORD(iface, ConnectionPoint, IConnectionPoint_iface);
188 In native windows, the whole lifetime management of XMLDOMNodes is
189 managed automatically using reference counts. Wine emulates that by
190 maintaining a reference count to the document that is increased for
191 each IXMLDOMNode pointer passed out for this document. If all these
192 pointers are gone, the document is unreachable and gets freed, that
193 is, all nodes in the tree of the document get freed.
195 You are able to create nodes that are associated to a document (in
196 fact, in msxml's XMLDOM model, all nodes are associated to a document),
197 but not in the tree of that document, for example using the createFoo
198 functions from IXMLDOMDocument. These nodes do not get cleaned up
199 by libxml, so we have to do it ourselves.
201 To catch these nodes, a list of "orphan nodes" is introduced.
202 It contains pointers to all roots of node trees that are
203 associated with the document without being part of the document
204 tree. All nodes with parent==NULL (except for the document root nodes)
205 should be in the orphan node list of their document. All orphan nodes
206 get freed together with the document itself.
209 typedef struct _xmldoc_priv {
212 domdoc_properties* properties;
215 typedef struct _orphan_entry {
220 typedef struct _select_ns_entry {
222 xmlChar const* prefix;
228 static inline xmldoc_priv * priv_from_xmlDocPtr(const xmlDocPtr doc)
230 return doc->_private;
233 static inline domdoc_properties * properties_from_xmlDocPtr(xmlDocPtr doc)
235 return priv_from_xmlDocPtr(doc)->properties;
238 BOOL is_xpathmode(const xmlDocPtr doc)
240 return properties_from_xmlDocPtr(doc)->XPath;
243 void set_xpathmode(xmlDocPtr doc, BOOL xpath)
245 properties_from_xmlDocPtr(doc)->XPath = xpath;
248 int registerNamespaces(xmlXPathContextPtr ctxt)
251 const select_ns_entry* ns = NULL;
252 const struct list* pNsList = &properties_from_xmlDocPtr(ctxt->doc)->selectNsList;
254 TRACE("(%p)\n", ctxt);
256 LIST_FOR_EACH_ENTRY( ns, pNsList, select_ns_entry, entry )
258 xmlXPathRegisterNs(ctxt, ns->prefix, ns->href);
265 static inline void clear_selectNsList(struct list* pNsList)
267 select_ns_entry *ns, *ns2;
268 LIST_FOR_EACH_ENTRY_SAFE( ns, ns2, pNsList, select_ns_entry, entry )
275 static xmldoc_priv * create_priv(void)
278 priv = heap_alloc( sizeof (*priv) );
283 list_init( &priv->orphans );
284 priv->properties = NULL;
290 static domdoc_properties *create_properties(MSXML_VERSION version)
292 domdoc_properties *properties = heap_alloc(sizeof(domdoc_properties));
294 list_init(&properties->selectNsList);
295 properties->preserving = VARIANT_FALSE;
296 properties->schemaCache = NULL;
297 properties->selectNsStr = heap_alloc_zero(sizeof(xmlChar));
298 properties->selectNsStr_len = 0;
300 /* properties that are dependent on object versions */
301 properties->version = version;
302 properties->XPath = (version == MSXML4 || version == MSXML6);
307 static domdoc_properties* copy_properties(domdoc_properties const* properties)
309 domdoc_properties* pcopy = heap_alloc(sizeof(domdoc_properties));
310 select_ns_entry const* ns = NULL;
311 select_ns_entry* new_ns = NULL;
312 int len = (properties->selectNsStr_len+1)*sizeof(xmlChar);
317 pcopy->version = properties->version;
318 pcopy->preserving = properties->preserving;
319 pcopy->schemaCache = properties->schemaCache;
320 if (pcopy->schemaCache)
321 IXMLDOMSchemaCollection2_AddRef(pcopy->schemaCache);
322 pcopy->XPath = properties->XPath;
323 pcopy->selectNsStr_len = properties->selectNsStr_len;
324 list_init( &pcopy->selectNsList );
325 pcopy->selectNsStr = heap_alloc(len);
326 memcpy((xmlChar*)pcopy->selectNsStr, properties->selectNsStr, len);
327 offset = pcopy->selectNsStr - properties->selectNsStr;
329 LIST_FOR_EACH_ENTRY( ns, (&properties->selectNsList), select_ns_entry, entry )
331 new_ns = heap_alloc(sizeof(select_ns_entry));
332 memcpy(new_ns, ns, sizeof(select_ns_entry));
333 new_ns->href += offset;
334 new_ns->prefix += offset;
335 list_add_tail(&pcopy->selectNsList, &new_ns->entry);
343 static void free_properties(domdoc_properties* properties)
347 if (properties->schemaCache)
348 IXMLDOMSchemaCollection2_Release(properties->schemaCache);
349 clear_selectNsList(&properties->selectNsList);
350 heap_free((xmlChar*)properties->selectNsStr);
351 heap_free(properties);
355 static void release_namespaces(domdoc *This)
357 if (This->namespaces)
359 IXMLDOMSchemaCollection2_Release(This->namespaces);
360 This->namespaces = NULL;
364 /* links a "<?xml" node as a first child */
365 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
368 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
371 /* unlinks a first "<?xml" child if it was created */
372 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
378 if (doc->standalone != -1)
380 node = doc->children;
381 xmlUnlinkNode( node );
389 BOOL is_preserving_whitespace(xmlNodePtr node)
391 domdoc_properties* properties = NULL;
392 /* during parsing the xmlDoc._private stuff is not there */
393 if (priv_from_xmlDocPtr(node->doc))
394 properties = properties_from_xmlDocPtr(node->doc);
395 return ((properties && properties->preserving == VARIANT_TRUE) ||
396 xmlNodeGetSpacePreserve(node) == 1);
399 static inline BOOL strn_isspace(xmlChar const* str, int len)
401 for (; str && len > 0 && *str; ++str, --len)
408 static void sax_characters(void *ctx, const xmlChar *ch, int len)
410 xmlParserCtxtPtr ctxt;
413 ctxt = (xmlParserCtxtPtr) ctx;
414 This = (const domdoc*) ctxt->_private;
418 /* during domdoc_loadXML() the xmlDocPtr->_private data is not available */
419 if (!This->properties->preserving &&
420 !is_preserving_whitespace(ctxt->node) &&
421 strn_isspace(ch, len))
425 xmlSAX2Characters(ctxt, ch, len);
428 static void LIBXML2_LOG_CALLBACK sax_error(void* ctx, char const* msg, ...)
432 LIBXML2_CALLBACK_ERR(doparse, msg, ap);
436 static void LIBXML2_LOG_CALLBACK sax_warning(void* ctx, char const* msg, ...)
440 LIBXML2_CALLBACK_WARN(doparse, msg, ap);
444 static void sax_serror(void* ctx, xmlErrorPtr err)
446 LIBXML2_CALLBACK_SERROR(doparse, err);
449 static xmlDocPtr doparse(domdoc* This, char const* ptr, int len, xmlCharEncoding encoding)
451 xmlDocPtr doc = NULL;
452 xmlParserCtxtPtr pctx;
453 static xmlSAXHandler sax_handler = {
454 xmlSAX2InternalSubset, /* internalSubset */
455 xmlSAX2IsStandalone, /* isStandalone */
456 xmlSAX2HasInternalSubset, /* hasInternalSubset */
457 xmlSAX2HasExternalSubset, /* hasExternalSubset */
458 xmlSAX2ResolveEntity, /* resolveEntity */
459 xmlSAX2GetEntity, /* getEntity */
460 xmlSAX2EntityDecl, /* entityDecl */
461 xmlSAX2NotationDecl, /* notationDecl */
462 xmlSAX2AttributeDecl, /* attributeDecl */
463 xmlSAX2ElementDecl, /* elementDecl */
464 xmlSAX2UnparsedEntityDecl, /* unparsedEntityDecl */
465 xmlSAX2SetDocumentLocator, /* setDocumentLocator */
466 xmlSAX2StartDocument, /* startDocument */
467 xmlSAX2EndDocument, /* endDocument */
468 xmlSAX2StartElement, /* startElement */
469 xmlSAX2EndElement, /* endElement */
470 xmlSAX2Reference, /* reference */
471 sax_characters, /* characters */
472 sax_characters, /* ignorableWhitespace */
473 xmlSAX2ProcessingInstruction, /* processingInstruction */
474 xmlSAX2Comment, /* comment */
475 sax_warning, /* warning */
476 sax_error, /* error */
477 sax_error, /* fatalError */
478 xmlSAX2GetParameterEntity, /* getParameterEntity */
479 xmlSAX2CDataBlock, /* cdataBlock */
480 xmlSAX2ExternalSubset, /* externalSubset */
483 xmlSAX2StartElementNs, /* startElementNs */
484 xmlSAX2EndElementNs, /* endElementNs */
485 sax_serror /* serror */
489 pctx = xmlCreateMemoryParserCtxt(ptr, len);
492 ERR("Failed to create parser context\n");
496 if (pctx->sax) xmlFree(pctx->sax);
497 pctx->sax = &sax_handler;
498 pctx->_private = This;
501 if (encoding != XML_CHAR_ENCODING_NONE)
502 xmlSwitchEncoding(pctx, encoding);
504 xmlParseDocument(pctx);
506 if (pctx->wellFormed)
512 xmlFreeDoc(pctx->myDoc);
516 xmlFreeParserCtxt(pctx);
518 /* TODO: put this in one of the SAX callbacks */
519 /* create first child as a <?xml...?> */
520 if (doc && doc->standalone != -1)
524 xmlChar *xmlbuff = (xmlChar*)buff;
526 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
528 /* version attribute can't be omitted */
529 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
530 xmlNodeAddContent( node, xmlbuff );
534 sprintf(buff, " encoding=\"%s\"", doc->encoding);
535 xmlNodeAddContent( node, xmlbuff );
538 if (doc->standalone != -2)
540 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
541 xmlNodeAddContent( node, xmlbuff );
544 xmldoc_link_xmldecl( doc, node );
550 void xmldoc_init(xmlDocPtr doc, MSXML_VERSION version)
552 doc->_private = create_priv();
553 priv_from_xmlDocPtr(doc)->properties = create_properties(version);
556 LONG xmldoc_add_ref(xmlDocPtr doc)
558 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
559 TRACE("(%p)->(%d)\n", doc, ref);
563 LONG xmldoc_release(xmlDocPtr doc)
565 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
566 LONG ref = InterlockedDecrement(&priv->refs);
567 TRACE("(%p)->(%d)\n", doc, ref);
570 orphan_entry *orphan, *orphan2;
571 TRACE("freeing docptr %p\n", doc);
573 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
575 xmlFreeNode( orphan->node );
578 free_properties(priv->properties);
579 heap_free(doc->_private);
587 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
589 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
592 entry = heap_alloc( sizeof (*entry) );
594 return E_OUTOFMEMORY;
597 list_add_head( &priv->orphans, &entry->entry );
601 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
603 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
604 orphan_entry *entry, *entry2;
606 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
608 if( entry->node == node )
610 list_remove( &entry->entry );
619 static inline xmlDocPtr get_doc( domdoc *This )
621 return (xmlDocPtr)This->node.node;
624 static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
626 release_namespaces(This);
630 priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
631 if (xmldoc_release(get_doc(This)) != 0)
632 priv_from_xmlDocPtr(get_doc(This))->properties =
633 copy_properties(This->properties);
636 This->node.node = (xmlNodePtr) xml;
640 xmldoc_add_ref(get_doc(This));
641 priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
647 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
649 return CONTAINING_RECORD(iface, domdoc, IXMLDOMDocument3_iface);
652 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
654 return CONTAINING_RECORD(iface, domdoc, IPersistStreamInit_iface);
657 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
659 return CONTAINING_RECORD(iface, domdoc, IObjectWithSite_iface);
662 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
664 return CONTAINING_RECORD(iface, domdoc, IObjectSafety_iface);
667 static inline domdoc *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
669 return CONTAINING_RECORD(iface, domdoc, IConnectionPointContainer_iface);
672 /************************************************************************
673 * domdoc implementation of IPersistStream.
675 static HRESULT WINAPI PersistStreamInit_QueryInterface(
676 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
678 domdoc* This = impl_from_IPersistStreamInit(iface);
679 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppvObj);
682 static ULONG WINAPI PersistStreamInit_AddRef(
683 IPersistStreamInit *iface)
685 domdoc* This = impl_from_IPersistStreamInit(iface);
686 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
689 static ULONG WINAPI PersistStreamInit_Release(
690 IPersistStreamInit *iface)
692 domdoc* This = impl_from_IPersistStreamInit(iface);
693 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
696 static HRESULT WINAPI PersistStreamInit_GetClassID(
697 IPersistStreamInit *iface, CLSID *classid)
699 domdoc* This = impl_from_IPersistStreamInit(iface);
700 TRACE("(%p)->(%p)\n", This, classid);
705 *classid = *DOMDocument_version(This->properties->version);
710 static HRESULT WINAPI PersistStreamInit_IsDirty(
711 IPersistStreamInit *iface)
713 domdoc *This = impl_from_IPersistStreamInit(iface);
714 FIXME("(%p): stub!\n", This);
718 static HRESULT WINAPI PersistStreamInit_Load(
719 IPersistStreamInit *iface, LPSTREAM pStm)
721 domdoc *This = impl_from_IPersistStreamInit(iface);
724 DWORD read, written, len;
727 xmlDocPtr xmldoc = NULL;
729 TRACE("(%p)->(%p)\n", This, pStm);
734 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
740 IStream_Read(pStm, buf, sizeof(buf), &read);
741 hr = IStream_Write(This->stream, buf, read, &written);
742 } while(SUCCEEDED(hr) && written != 0 && read != 0);
746 ERR("Failed to copy stream\n");
750 hr = GetHGlobalFromStream(This->stream, &hglobal);
754 len = GlobalSize(hglobal);
755 ptr = GlobalLock(hglobal);
757 xmldoc = doparse(This, ptr, len, XML_CHAR_ENCODING_NONE);
758 GlobalUnlock(hglobal);
762 ERR("Failed to parse xml\n");
766 xmldoc->_private = create_priv();
768 return attach_xmldoc(This, xmldoc);
771 static HRESULT WINAPI PersistStreamInit_Save(
772 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
774 domdoc *This = impl_from_IPersistStreamInit(iface);
778 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
780 hr = IXMLDOMDocument3_get_xml(&This->IXMLDOMDocument3_iface, &xmlString);
783 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
785 hr = IStream_Write( stream, xmlString, len, NULL );
786 SysFreeString(xmlString);
789 TRACE("ret 0x%08x\n", hr);
794 static HRESULT WINAPI PersistStreamInit_GetSizeMax(
795 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
797 domdoc *This = impl_from_IPersistStreamInit(iface);
798 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
802 static HRESULT WINAPI PersistStreamInit_InitNew(
803 IPersistStreamInit *iface)
805 domdoc *This = impl_from_IPersistStreamInit(iface);
806 TRACE("(%p)\n", This);
810 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
812 PersistStreamInit_QueryInterface,
813 PersistStreamInit_AddRef,
814 PersistStreamInit_Release,
815 PersistStreamInit_GetClassID,
816 PersistStreamInit_IsDirty,
817 PersistStreamInit_Load,
818 PersistStreamInit_Save,
819 PersistStreamInit_GetSizeMax,
820 PersistStreamInit_InitNew
823 /* IXMLDOMDocument3 interface */
825 static const tid_t domdoc_se_tids[] = {
828 IXMLDOMDocument2_tid,
829 IXMLDOMDocument3_tid,
833 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
835 domdoc *This = impl_from_IXMLDOMDocument3( iface );
837 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
841 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
842 IsEqualGUID( riid, &IID_IDispatch ) ||
843 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
844 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
845 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
846 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
850 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
851 IsEqualGUID(&IID_IPersistStreamInit, riid))
853 *ppvObject = &This->IPersistStreamInit_iface;
855 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
857 *ppvObject = &This->IObjectWithSite_iface;
859 else if (IsEqualGUID(&IID_IObjectSafety, riid))
861 *ppvObject = &This->IObjectSafety_iface;
863 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
865 return node_create_supporterrorinfo(domdoc_se_tids, ppvObject);
867 else if(node_query_interface(&This->node, riid, ppvObject))
869 return *ppvObject ? S_OK : E_NOINTERFACE;
871 else if (IsEqualGUID( riid, &IID_IConnectionPointContainer ))
873 *ppvObject = &This->IConnectionPointContainer_iface;
877 TRACE("interface %s not implemented\n", debugstr_guid(riid));
878 return E_NOINTERFACE;
881 IUnknown_AddRef((IUnknown*)*ppvObject);
886 static ULONG WINAPI domdoc_AddRef( IXMLDOMDocument3 *iface )
888 domdoc *This = impl_from_IXMLDOMDocument3( iface );
889 ULONG ref = InterlockedIncrement( &This->ref );
890 TRACE("(%p)->(%d)\n", This, ref );
894 static ULONG WINAPI domdoc_Release( IXMLDOMDocument3 *iface )
896 domdoc *This = impl_from_IXMLDOMDocument3( iface );
897 LONG ref = InterlockedDecrement( &This->ref );
899 TRACE("(%p)->(%d)\n", This, ref );
906 detach_bsc(This->bsc);
909 IUnknown_Release( This->site );
910 destroy_xmlnode(&This->node);
912 IStream_Release(This->stream);
914 for (eid = 0; eid < EVENTID_LAST; eid++)
915 if (This->events[eid]) IDispatch_Release(This->events[eid]);
917 release_namespaces(This);
924 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
926 domdoc *This = impl_from_IXMLDOMDocument3( iface );
927 return IDispatchEx_GetTypeInfoCount(&This->node.dispex.IDispatchEx_iface, pctinfo);
930 static HRESULT WINAPI domdoc_GetTypeInfo(
931 IXMLDOMDocument3 *iface,
932 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
934 domdoc *This = impl_from_IXMLDOMDocument3( iface );
935 return IDispatchEx_GetTypeInfo(&This->node.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
938 static HRESULT WINAPI domdoc_GetIDsOfNames(
939 IXMLDOMDocument3 *iface,
946 domdoc *This = impl_from_IXMLDOMDocument3( iface );
947 return IDispatchEx_GetIDsOfNames(&This->node.dispex.IDispatchEx_iface,
948 riid, rgszNames, cNames, lcid, rgDispId);
951 static HRESULT WINAPI domdoc_Invoke(
952 IXMLDOMDocument3 *iface,
957 DISPPARAMS* pDispParams,
959 EXCEPINFO* pExcepInfo,
962 domdoc *This = impl_from_IXMLDOMDocument3( iface );
963 return IDispatchEx_Invoke(&This->node.dispex.IDispatchEx_iface,
964 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
967 static HRESULT WINAPI domdoc_get_nodeName(
968 IXMLDOMDocument3 *iface,
971 domdoc *This = impl_from_IXMLDOMDocument3( iface );
973 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
975 TRACE("(%p)->(%p)\n", This, name);
977 return return_bstr(documentW, name);
981 static HRESULT WINAPI domdoc_get_nodeValue(
982 IXMLDOMDocument3 *iface,
985 domdoc *This = impl_from_IXMLDOMDocument3( iface );
987 TRACE("(%p)->(%p)\n", This, value);
992 V_VT(value) = VT_NULL;
993 V_BSTR(value) = NULL; /* tests show that we should do this */
998 static HRESULT WINAPI domdoc_put_nodeValue(
999 IXMLDOMDocument3 *iface,
1002 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1003 TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
1008 static HRESULT WINAPI domdoc_get_nodeType(
1009 IXMLDOMDocument3 *iface,
1012 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1014 TRACE("(%p)->(%p)\n", This, type);
1016 *type = NODE_DOCUMENT;
1021 static HRESULT WINAPI domdoc_get_parentNode(
1022 IXMLDOMDocument3 *iface,
1023 IXMLDOMNode** parent )
1025 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1027 TRACE("(%p)->(%p)\n", This, parent);
1029 return node_get_parent(&This->node, parent);
1033 static HRESULT WINAPI domdoc_get_childNodes(
1034 IXMLDOMDocument3 *iface,
1035 IXMLDOMNodeList** childList )
1037 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1039 TRACE("(%p)->(%p)\n", This, childList);
1041 return node_get_child_nodes(&This->node, childList);
1045 static HRESULT WINAPI domdoc_get_firstChild(
1046 IXMLDOMDocument3 *iface,
1047 IXMLDOMNode** firstChild )
1049 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1051 TRACE("(%p)->(%p)\n", This, firstChild);
1053 return node_get_first_child(&This->node, firstChild);
1057 static HRESULT WINAPI domdoc_get_lastChild(
1058 IXMLDOMDocument3 *iface,
1059 IXMLDOMNode** lastChild )
1061 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1063 TRACE("(%p)->(%p)\n", This, lastChild);
1065 return node_get_last_child(&This->node, lastChild);
1069 static HRESULT WINAPI domdoc_get_previousSibling(
1070 IXMLDOMDocument3 *iface,
1071 IXMLDOMNode** previousSibling )
1073 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1075 TRACE("(%p)->(%p)\n", This, previousSibling);
1077 return return_null_node(previousSibling);
1081 static HRESULT WINAPI domdoc_get_nextSibling(
1082 IXMLDOMDocument3 *iface,
1083 IXMLDOMNode** nextSibling )
1085 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1087 TRACE("(%p)->(%p)\n", This, nextSibling);
1089 return return_null_node(nextSibling);
1093 static HRESULT WINAPI domdoc_get_attributes(
1094 IXMLDOMDocument3 *iface,
1095 IXMLDOMNamedNodeMap** attributeMap )
1097 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1099 TRACE("(%p)->(%p)\n", This, attributeMap);
1101 return return_null_ptr((void**)attributeMap);
1105 static HRESULT WINAPI domdoc_insertBefore(
1106 IXMLDOMDocument3 *iface,
1107 IXMLDOMNode* newChild,
1109 IXMLDOMNode** outNewChild )
1111 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1113 TRACE("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), outNewChild);
1115 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1119 static HRESULT WINAPI domdoc_replaceChild(
1120 IXMLDOMDocument3 *iface,
1121 IXMLDOMNode* newChild,
1122 IXMLDOMNode* oldChild,
1123 IXMLDOMNode** outOldChild)
1125 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1127 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1129 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1133 static HRESULT WINAPI domdoc_removeChild(
1134 IXMLDOMDocument3 *iface,
1136 IXMLDOMNode **oldChild)
1138 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1139 TRACE("(%p)->(%p %p)\n", This, child, oldChild);
1140 return node_remove_child(&This->node, child, oldChild);
1144 static HRESULT WINAPI domdoc_appendChild(
1145 IXMLDOMDocument3 *iface,
1147 IXMLDOMNode **outChild)
1149 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1150 TRACE("(%p)->(%p %p)\n", This, child, outChild);
1151 return node_append_child(&This->node, child, outChild);
1155 static HRESULT WINAPI domdoc_hasChildNodes(
1156 IXMLDOMDocument3 *iface,
1159 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1160 TRACE("(%p)->(%p)\n", This, ret);
1161 return node_has_childnodes(&This->node, ret);
1165 static HRESULT WINAPI domdoc_get_ownerDocument(
1166 IXMLDOMDocument3 *iface,
1167 IXMLDOMDocument **doc)
1169 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1170 TRACE("(%p)->(%p)\n", This, doc);
1171 return node_get_owner_doc(&This->node, doc);
1175 static HRESULT WINAPI domdoc_cloneNode(
1176 IXMLDOMDocument3 *iface,
1178 IXMLDOMNode** outNode)
1180 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1181 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
1182 return node_clone( &This->node, deep, outNode );
1186 static HRESULT WINAPI domdoc_get_nodeTypeString(
1187 IXMLDOMDocument3 *iface,
1190 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1191 static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
1193 TRACE("(%p)->(%p)\n", This, p);
1195 return return_bstr(documentW, p);
1199 static HRESULT WINAPI domdoc_get_text(
1200 IXMLDOMDocument3 *iface,
1203 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1204 TRACE("(%p)->(%p)\n", This, p);
1205 return node_get_text(&This->node, p);
1209 static HRESULT WINAPI domdoc_put_text(
1210 IXMLDOMDocument3 *iface,
1213 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1214 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1219 static HRESULT WINAPI domdoc_get_specified(
1220 IXMLDOMDocument3 *iface,
1221 VARIANT_BOOL* isSpecified )
1223 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1224 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1225 *isSpecified = VARIANT_TRUE;
1230 static HRESULT WINAPI domdoc_get_definition(
1231 IXMLDOMDocument3 *iface,
1232 IXMLDOMNode** definitionNode )
1234 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1235 FIXME("(%p)->(%p)\n", This, definitionNode);
1240 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1241 IXMLDOMDocument3 *iface,
1244 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1245 TRACE("(%p)->(%p)\n", This, v);
1246 return return_null_var(v);
1249 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1250 IXMLDOMDocument3 *iface,
1251 VARIANT typedValue )
1253 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1254 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1259 static HRESULT WINAPI domdoc_get_dataType(
1260 IXMLDOMDocument3 *iface,
1263 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1264 TRACE("(%p)->(%p)\n", This, typename);
1265 return return_null_var( typename );
1269 static HRESULT WINAPI domdoc_put_dataType(
1270 IXMLDOMDocument3 *iface,
1273 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1275 FIXME("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
1278 return E_INVALIDARG;
1283 static int XMLCALL domdoc_get_xml_writecallback(void *ctx, const char *data, int len)
1285 return xmlBufferAdd((xmlBufferPtr)ctx, (xmlChar*)data, len) == 0 ? len : 0;
1288 static HRESULT WINAPI domdoc_get_xml(
1289 IXMLDOMDocument3 *iface,
1292 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1293 xmlSaveCtxtPtr ctxt;
1298 TRACE("(%p)->(%p)\n", This, p);
1301 return E_INVALIDARG;
1305 buf = xmlBufferCreate();
1307 return E_OUTOFMEMORY;
1309 options = XML_SAVE_FORMAT | XML_SAVE_NO_DECL;
1310 ctxt = xmlSaveToIO(domdoc_get_xml_writecallback, NULL, buf, "UTF-8", options);
1315 return E_OUTOFMEMORY;
1318 ret = xmlSaveDoc(ctxt, get_doc(This));
1319 /* flushes on close */
1322 TRACE("%ld, len=%d\n", ret, xmlBufferLength(buf));
1323 if(ret != -1 && xmlBufferLength(buf) > 0)
1327 content = bstr_from_xmlChar(xmlBufferContent(buf));
1328 content = EnsureCorrectEOL(content);
1334 *p = SysAllocStringLen(NULL, 0);
1339 return *p ? S_OK : E_OUTOFMEMORY;
1343 static HRESULT WINAPI domdoc_transformNode(
1344 IXMLDOMDocument3 *iface,
1348 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1349 TRACE("(%p)->(%p %p)\n", This, node, p);
1350 return node_transform_node(&This->node, node, p);
1354 static HRESULT WINAPI domdoc_selectNodes(
1355 IXMLDOMDocument3 *iface,
1357 IXMLDOMNodeList **outList)
1359 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1360 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList);
1361 return node_select_nodes(&This->node, p, outList);
1365 static HRESULT WINAPI domdoc_selectSingleNode(
1366 IXMLDOMDocument3 *iface,
1368 IXMLDOMNode **outNode)
1370 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1371 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode);
1372 return node_select_singlenode(&This->node, p, outNode);
1376 static HRESULT WINAPI domdoc_get_parsed(
1377 IXMLDOMDocument3 *iface,
1378 VARIANT_BOOL* isParsed )
1380 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1381 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1382 *isParsed = VARIANT_TRUE;
1386 static HRESULT WINAPI domdoc_get_namespaceURI(
1387 IXMLDOMDocument3 *iface,
1388 BSTR* namespaceURI )
1390 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1391 TRACE("(%p)->(%p)\n", This, namespaceURI);
1392 return return_null_bstr( namespaceURI );
1395 static HRESULT WINAPI domdoc_get_prefix(
1396 IXMLDOMDocument3 *iface,
1399 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1400 TRACE("(%p)->(%p)\n", This, prefix);
1401 return return_null_bstr( prefix );
1405 static HRESULT WINAPI domdoc_get_baseName(
1406 IXMLDOMDocument3 *iface,
1409 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1410 TRACE("(%p)->(%p)\n", This, name);
1411 return return_null_bstr( name );
1415 static HRESULT WINAPI domdoc_transformNodeToObject(
1416 IXMLDOMDocument3 *iface,
1417 IXMLDOMNode* stylesheet,
1418 VARIANT outputObject)
1420 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1421 FIXME("(%p)->(%p %s)\n", This, stylesheet, debugstr_variant(&outputObject));
1426 static HRESULT WINAPI domdoc_get_doctype(
1427 IXMLDOMDocument3 *iface,
1428 IXMLDOMDocumentType** doctype )
1430 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1435 TRACE("(%p)->(%p)\n", This, doctype);
1437 if (!doctype) return E_INVALIDARG;
1441 dtd = xmlGetIntSubset(get_doc(This));
1442 if (!dtd) return S_FALSE;
1444 node = create_node((xmlNodePtr)dtd);
1445 if (!node) return S_FALSE;
1447 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentType, (void**)doctype);
1448 IXMLDOMNode_Release(node);
1454 static HRESULT WINAPI domdoc_get_implementation(
1455 IXMLDOMDocument3 *iface,
1456 IXMLDOMImplementation** impl )
1458 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1460 TRACE("(%p)->(%p)\n", This, impl);
1463 return E_INVALIDARG;
1465 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1470 static HRESULT WINAPI domdoc_get_documentElement(
1471 IXMLDOMDocument3 *iface,
1472 IXMLDOMElement** DOMElement )
1474 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1475 IXMLDOMNode *element_node;
1479 TRACE("(%p)->(%p)\n", This, DOMElement);
1482 return E_INVALIDARG;
1486 root = xmlDocGetRootElement( get_doc(This) );
1490 element_node = create_node( root );
1491 if(!element_node) return S_FALSE;
1493 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1494 IXMLDOMNode_Release(element_node);
1500 static HRESULT WINAPI domdoc_put_documentElement(
1501 IXMLDOMDocument3 *iface,
1502 IXMLDOMElement* DOMElement )
1504 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1505 IXMLDOMNode *elementNode;
1510 TRACE("(%p)->(%p)\n", This, DOMElement);
1512 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1516 xmlNode = get_node_obj( elementNode );
1517 if(!xmlNode) return E_FAIL;
1519 if(!xmlNode->node->parent)
1520 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1521 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1523 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1524 IXMLDOMNode_Release( elementNode );
1527 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1533 static HRESULT WINAPI domdoc_createElement(
1534 IXMLDOMDocument3 *iface,
1536 IXMLDOMElement** element )
1538 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1543 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1545 if (!element || !tagname) return E_INVALIDARG;
1547 V_VT(&type) = VT_I1;
1548 V_I1(&type) = NODE_ELEMENT;
1550 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1553 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1554 IXMLDOMNode_Release(node);
1561 static HRESULT WINAPI domdoc_createDocumentFragment(
1562 IXMLDOMDocument3 *iface,
1563 IXMLDOMDocumentFragment** frag )
1565 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1570 TRACE("(%p)->(%p)\n", This, frag);
1572 if (!frag) return E_INVALIDARG;
1576 V_VT(&type) = VT_I1;
1577 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1579 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1582 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1583 IXMLDOMNode_Release(node);
1590 static HRESULT WINAPI domdoc_createTextNode(
1591 IXMLDOMDocument3 *iface,
1593 IXMLDOMText** text )
1595 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1600 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1602 if (!text) return E_INVALIDARG;
1606 V_VT(&type) = VT_I1;
1607 V_I1(&type) = NODE_TEXT;
1609 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1612 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1613 IXMLDOMNode_Release(node);
1614 hr = IXMLDOMText_put_data(*text, data);
1621 static HRESULT WINAPI domdoc_createComment(
1622 IXMLDOMDocument3 *iface,
1624 IXMLDOMComment** comment )
1626 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1631 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1633 if (!comment) return E_INVALIDARG;
1637 V_VT(&type) = VT_I1;
1638 V_I1(&type) = NODE_COMMENT;
1640 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1643 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1644 IXMLDOMNode_Release(node);
1645 hr = IXMLDOMComment_put_data(*comment, data);
1652 static HRESULT WINAPI domdoc_createCDATASection(
1653 IXMLDOMDocument3 *iface,
1655 IXMLDOMCDATASection** cdata )
1657 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1662 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1664 if (!cdata) return E_INVALIDARG;
1668 V_VT(&type) = VT_I1;
1669 V_I1(&type) = NODE_CDATA_SECTION;
1671 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1674 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1675 IXMLDOMNode_Release(node);
1676 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1683 static HRESULT WINAPI domdoc_createProcessingInstruction(
1684 IXMLDOMDocument3 *iface,
1687 IXMLDOMProcessingInstruction** pi )
1689 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1694 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1696 if (!pi) return E_INVALIDARG;
1700 V_VT(&type) = VT_I1;
1701 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1703 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1708 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1709 node_obj = get_node_obj(node);
1710 hr = node_set_content(node_obj, data);
1712 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1713 IXMLDOMNode_Release(node);
1720 static HRESULT WINAPI domdoc_createAttribute(
1721 IXMLDOMDocument3 *iface,
1723 IXMLDOMAttribute** attribute )
1725 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1730 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1732 if (!attribute || !name) return E_INVALIDARG;
1734 V_VT(&type) = VT_I1;
1735 V_I1(&type) = NODE_ATTRIBUTE;
1737 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1740 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1741 IXMLDOMNode_Release(node);
1748 static HRESULT WINAPI domdoc_createEntityReference(
1749 IXMLDOMDocument3 *iface,
1751 IXMLDOMEntityReference** entityref )
1753 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1758 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1760 if (!entityref) return E_INVALIDARG;
1764 V_VT(&type) = VT_I1;
1765 V_I1(&type) = NODE_ENTITY_REFERENCE;
1767 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1770 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1771 IXMLDOMNode_Release(node);
1777 xmlChar* tagName_to_XPath(const BSTR tagName)
1779 xmlChar *query, *tmp;
1780 static const xmlChar mod_pre[] = "*[local-name()='";
1781 static const xmlChar mod_post[] = "']";
1782 static const xmlChar prefix[] = "descendant::";
1783 const WCHAR *tokBegin, *tokEnd;
1786 query = xmlStrdup(prefix);
1789 while (tokBegin && *tokBegin)
1794 query = xmlStrcat(query, BAD_CAST "/");
1798 query = xmlStrcat(query, BAD_CAST "*");
1802 query = xmlStrcat(query, mod_pre);
1804 while (*tokEnd && *tokEnd != '/')
1806 len = WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, NULL, 0, NULL, NULL);
1807 tmp = xmlMalloc(len);
1808 WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, (char*)tmp, len, NULL, NULL);
1809 query = xmlStrncat(query, tmp, len);
1812 query = xmlStrcat(query, mod_post);
1819 static HRESULT WINAPI domdoc_getElementsByTagName(
1820 IXMLDOMDocument3 *iface,
1822 IXMLDOMNodeList** resultList )
1824 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1829 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1831 if (!tagName || !resultList) return E_INVALIDARG;
1833 XPath = This->properties->XPath;
1834 This->properties->XPath = TRUE;
1835 query = tagName_to_XPath(tagName);
1836 hr = create_selection((xmlNodePtr)get_doc(This), query, resultList);
1838 This->properties->XPath = XPath;
1843 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1849 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1851 return E_INVALIDARG;
1858 static HRESULT WINAPI domdoc_createNode(
1859 IXMLDOMDocument3 *iface,
1863 IXMLDOMNode** node )
1865 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1866 DOMNodeType node_type;
1868 xmlChar *xml_name, *href;
1871 TRACE("(%p)->(%s %s %s %p)\n", This, debugstr_variant(&Type), debugstr_w(name), debugstr_w(namespaceURI), node);
1873 if(!node) return E_INVALIDARG;
1875 hr = get_node_type(Type, &node_type);
1876 if(FAILED(hr)) return hr;
1878 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1879 FIXME("nodes with namespaces currently not supported.\n");
1881 TRACE("node_type %d\n", node_type);
1883 /* exit earlier for types that need name */
1887 case NODE_ATTRIBUTE:
1888 case NODE_ENTITY_REFERENCE:
1889 case NODE_PROCESSING_INSTRUCTION:
1890 if (!name || *name == 0) return E_FAIL;
1896 xml_name = xmlchar_from_wchar(name);
1897 /* prevent empty href to be allocated */
1898 href = namespaceURI ? xmlchar_from_wchar(namespaceURI) : NULL;
1904 xmlChar *local, *prefix;
1906 local = xmlSplitQName2(xml_name, &prefix);
1908 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
1910 /* allow to create default namespace xmlns= */
1911 if (local || (href && *href))
1913 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
1914 xmlSetNs(xmlnode, ns);
1922 case NODE_ATTRIBUTE:
1923 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1926 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1928 case NODE_CDATA_SECTION:
1929 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1931 case NODE_ENTITY_REFERENCE:
1932 xmlnode = xmlNewReference(get_doc(This), xml_name);
1934 case NODE_PROCESSING_INSTRUCTION:
1935 #ifdef HAVE_XMLNEWDOCPI
1936 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1938 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1943 xmlnode = xmlNewDocComment(get_doc(This), NULL);
1945 case NODE_DOCUMENT_FRAGMENT:
1946 xmlnode = xmlNewDocFragment(get_doc(This));
1948 /* unsupported types */
1950 case NODE_DOCUMENT_TYPE:
1953 heap_free(xml_name);
1954 return E_INVALIDARG;
1956 FIXME("unhandled node type %d\n", node_type);
1961 *node = create_node(xmlnode);
1962 heap_free(xml_name);
1967 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1968 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1975 static HRESULT WINAPI domdoc_nodeFromID(
1976 IXMLDOMDocument3 *iface,
1978 IXMLDOMNode** node )
1980 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1981 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1985 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1990 xmldoc = doparse(This, ptr, len, XML_CHAR_ENCODING_NONE);
1992 xmldoc->_private = create_priv();
1993 return attach_xmldoc(This, xmldoc);
1999 HRESULT domdoc_load_moniker(IXMLDOMDocument3 *iface, IMoniker *mon)
2001 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2005 hr = bind_url(mon, domdoc_onDataAvailable, This, &bsc);
2010 hr = detach_bsc(This->bsc);
2019 static HRESULT WINAPI domdoc_load(
2020 IXMLDOMDocument3 *iface,
2022 VARIANT_BOOL* isSuccessful )
2024 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2025 LPWSTR filename = NULL;
2026 HRESULT hr = S_FALSE;
2027 IXMLDOMDocument3 *pNewDoc = NULL;
2028 IStream *pStream = NULL;
2031 TRACE("(%p)->(%s)\n", This, debugstr_variant(&source));
2035 *isSuccessful = VARIANT_FALSE;
2037 assert( &This->node );
2039 switch( V_VT(&source) )
2042 filename = V_BSTR(&source);
2044 case VT_BSTR|VT_BYREF:
2045 if (!V_BSTRREF(&source)) return E_INVALIDARG;
2046 filename = *V_BSTRREF(&source);
2048 case VT_ARRAY|VT_UI1:
2050 SAFEARRAY *psa = V_ARRAY(&source);
2053 UINT dim = SafeArrayGetDim(psa);
2058 ERR("SAFEARRAY == NULL\n");
2059 hr = This->error = E_INVALIDARG;
2062 /* Only takes UTF-8 strings.
2063 * NOT NULL-terminated. */
2064 SafeArrayAccessData(psa, (void**)&str);
2065 SafeArrayGetUBound(psa, 1, &len);
2067 if ((xmldoc = doparse(This, str, ++len, XML_CHAR_ENCODING_UTF8)))
2069 hr = This->error = S_OK;
2070 *isSuccessful = VARIANT_TRUE;
2071 TRACE("parsed document %p\n", xmldoc);
2075 This->error = E_FAIL;
2076 TRACE("failed to parse document\n");
2079 SafeArrayUnaccessData(psa);
2083 xmldoc->_private = create_priv();
2084 return attach_xmldoc(This, xmldoc);
2088 FIXME("unhandled SAFEARRAY dim: %d\n", dim);
2089 hr = This->error = E_NOTIMPL;
2094 hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
2099 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
2101 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
2102 xmldoc->_private = create_priv();
2103 hr = attach_xmldoc(This, xmldoc);
2106 *isSuccessful = VARIANT_TRUE;
2111 hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IStream, (void**)&pStream);
2114 IPersistStream *pDocStream;
2115 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
2118 hr = IPersistStream_Load(pDocStream, pStream);
2119 IStream_Release(pStream);
2122 *isSuccessful = VARIANT_TRUE;
2124 TRACE("Using IStream to load Document\n");
2129 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
2134 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
2139 /* ISequentialStream */
2140 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&source)->lpVtbl);
2144 FIXME("VT type not supported (%d)\n", V_VT(&source));
2151 hr = create_moniker_from_url( filename, &mon);
2152 if ( SUCCEEDED(hr) )
2154 hr = domdoc_load_moniker( iface, mon );
2155 IMoniker_Release(mon);
2159 This->error = E_FAIL;
2162 hr = This->error = S_OK;
2163 *isSuccessful = VARIANT_TRUE;
2167 if(!filename || FAILED(hr)) {
2168 xmldoc = xmlNewDoc(NULL);
2169 xmldoc->_private = create_priv();
2170 hr = attach_xmldoc(This, xmldoc);
2175 TRACE("ret (%d)\n", hr);
2181 static HRESULT WINAPI domdoc_get_readyState(
2182 IXMLDOMDocument3 *iface,
2185 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2186 FIXME("stub! (%p)->(%p)\n", This, value);
2189 return E_INVALIDARG;
2191 *value = READYSTATE_COMPLETE;
2196 static HRESULT WINAPI domdoc_get_parseError(
2197 IXMLDOMDocument3 *iface,
2198 IXMLDOMParseError** errorObj )
2200 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2201 static const WCHAR err[] = {'e','r','r','o','r',0};
2202 BSTR error_string = NULL;
2204 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2207 error_string = SysAllocString(err);
2209 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2210 if(!*errorObj) return E_OUTOFMEMORY;
2215 static HRESULT WINAPI domdoc_get_url(
2216 IXMLDOMDocument3 *iface,
2219 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2220 FIXME("(%p)->(%p)\n", This, urlString);
2225 static HRESULT WINAPI domdoc_get_async(
2226 IXMLDOMDocument3 *iface,
2227 VARIANT_BOOL* isAsync )
2229 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2231 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2232 *isAsync = This->async;
2237 static HRESULT WINAPI domdoc_put_async(
2238 IXMLDOMDocument3 *iface,
2239 VARIANT_BOOL isAsync )
2241 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2243 TRACE("(%p)->(%d)\n", This, isAsync);
2244 This->async = isAsync;
2249 static HRESULT WINAPI domdoc_abort(
2250 IXMLDOMDocument3 *iface )
2252 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2253 FIXME("%p\n", This);
2257 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2258 static HRESULT WINAPI domdoc_loadXML(
2259 IXMLDOMDocument3 *iface,
2261 VARIANT_BOOL* isSuccessful )
2263 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2264 xmlDocPtr xmldoc = NULL;
2265 HRESULT hr = S_FALSE, hr2;
2267 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), isSuccessful );
2269 assert ( &This->node );
2273 *isSuccessful = VARIANT_FALSE;
2279 /* skip leading spaces if needed */
2280 if (This->properties->version == MSXML_DEFAULT || This->properties->version == MSXML26)
2282 if (isspaceW(*ptr)) ptr++; else break;
2284 xmldoc = doparse(This, (char*)ptr, strlenW(ptr)*sizeof(WCHAR), XML_CHAR_ENCODING_UTF16LE);
2287 This->error = E_FAIL;
2288 TRACE("failed to parse document\n");
2292 hr = This->error = S_OK;
2293 *isSuccessful = VARIANT_TRUE;
2294 TRACE("parsed document %p\n", xmldoc);
2300 xmldoc = xmlNewDoc(NULL);
2301 xmldoc->_private = create_priv();
2302 hr2 = attach_xmldoc(This, xmldoc);
2309 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2313 if(!WriteFile(ctx, buffer, len, &written, NULL))
2315 WARN("write error\n");
2322 static int XMLCALL domdoc_save_closecallback(void *ctx)
2324 return CloseHandle(ctx) ? 0 : -1;
2327 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2332 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2335 WARN("stream write error: 0x%08x\n", hr);
2342 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2344 IStream_Release((IStream*)ctx);
2348 static HRESULT WINAPI domdoc_save(
2349 IXMLDOMDocument3 *iface,
2350 VARIANT destination )
2352 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2353 xmlSaveCtxtPtr ctx = NULL;
2357 TRACE("(%p)->(%s)\n", This, debugstr_variant(&destination));
2359 switch (V_VT(&destination))
2363 IUnknown *pUnk = V_UNKNOWN(&destination);
2364 IXMLDOMDocument3 *document;
2367 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2370 VARIANT_BOOL success;
2373 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2376 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2380 IXMLDOMDocument3_Release(document);
2384 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2387 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2388 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2392 IStream_Release(stream);
2400 case VT_BSTR | VT_BYREF:
2402 /* save with file path */
2403 HANDLE handle = CreateFileW( (V_VT(&destination) & VT_BYREF)? *V_BSTRREF(&destination) : V_BSTR(&destination),
2404 GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2405 if( handle == INVALID_HANDLE_VALUE )
2407 WARN("failed to create file\n");
2411 /* disable top XML declaration */
2412 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2413 handle, NULL, XML_SAVE_NO_DECL);
2416 CloseHandle(handle);
2423 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination));
2427 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2428 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2429 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2431 /* will release resources through close callback */
2437 static HRESULT WINAPI domdoc_get_validateOnParse(
2438 IXMLDOMDocument3 *iface,
2439 VARIANT_BOOL* isValidating )
2441 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2442 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2443 *isValidating = This->validating;
2448 static HRESULT WINAPI domdoc_put_validateOnParse(
2449 IXMLDOMDocument3 *iface,
2450 VARIANT_BOOL isValidating )
2452 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2453 TRACE("(%p)->(%d)\n", This, isValidating);
2454 This->validating = isValidating;
2459 static HRESULT WINAPI domdoc_get_resolveExternals(
2460 IXMLDOMDocument3 *iface,
2461 VARIANT_BOOL* isResolving )
2463 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2464 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2465 *isResolving = This->resolving;
2470 static HRESULT WINAPI domdoc_put_resolveExternals(
2471 IXMLDOMDocument3 *iface,
2472 VARIANT_BOOL isResolving )
2474 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2475 TRACE("(%p)->(%d)\n", This, isResolving);
2476 This->resolving = isResolving;
2481 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2482 IXMLDOMDocument3 *iface,
2483 VARIANT_BOOL* isPreserving )
2485 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2486 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->properties->preserving);
2487 *isPreserving = This->properties->preserving;
2492 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2493 IXMLDOMDocument3 *iface,
2494 VARIANT_BOOL isPreserving )
2496 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2497 TRACE("(%p)->(%d)\n", This, isPreserving);
2498 This->properties->preserving = isPreserving;
2503 static HRESULT WINAPI domdoc_put_onreadystatechange(
2504 IXMLDOMDocument3 *iface,
2507 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2509 TRACE("(%p)->(%s)\n", This, debugstr_variant(&event));
2510 return set_doc_event(This, EVENTID_READYSTATECHANGE, &event);
2514 static HRESULT WINAPI domdoc_put_onDataAvailable(IXMLDOMDocument3 *iface, VARIANT sink)
2516 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2517 FIXME("(%p)->(%s): stub\n", This, debugstr_variant(&sink));
2521 static HRESULT WINAPI domdoc_put_onTransformNode(IXMLDOMDocument3 *iface, VARIANT sink )
2523 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2524 FIXME("(%p)->(%s): stub\n", This, debugstr_variant(&sink));
2528 static HRESULT WINAPI domdoc_get_namespaces(
2529 IXMLDOMDocument3* iface,
2530 IXMLDOMSchemaCollection** collection )
2532 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2535 FIXME("(%p)->(%p): semi-stub\n", This, collection);
2537 if (!collection) return E_POINTER;
2539 if (!This->namespaces)
2541 hr = SchemaCache_create(This->properties->version, NULL, (void**)&This->namespaces);
2542 if (hr != S_OK) return hr;
2544 hr = cache_from_doc_ns(This->namespaces, &This->node);
2546 release_namespaces(This);
2549 if (This->namespaces)
2550 return IXMLDOMSchemaCollection2_QueryInterface(This->namespaces,
2551 &IID_IXMLDOMSchemaCollection, (void**)collection);
2556 static HRESULT WINAPI domdoc_get_schemas(
2557 IXMLDOMDocument3* iface,
2560 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2561 HRESULT hr = S_FALSE;
2562 IXMLDOMSchemaCollection2* cur_schema = This->properties->schemaCache;
2564 TRACE("(%p)->(%p)\n", This, var1);
2566 VariantInit(var1); /* Test shows we don't call VariantClear here */
2567 V_VT(var1) = VT_NULL;
2571 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2573 V_VT(var1) = VT_DISPATCH;
2578 static HRESULT WINAPI domdoc_putref_schemas(
2579 IXMLDOMDocument3* iface,
2582 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2583 HRESULT hr = E_FAIL;
2584 IXMLDOMSchemaCollection2* new_schema = NULL;
2586 FIXME("(%p)->(%s): semi-stub\n", This, debugstr_variant(&schema));
2587 switch(V_VT(&schema))
2590 hr = IUnknown_QueryInterface(V_UNKNOWN(&schema), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2594 hr = IDispatch_QueryInterface(V_DISPATCH(&schema), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2603 WARN("Can't get schema from vt %x\n", V_VT(&schema));
2608 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->properties->schemaCache, new_schema);
2609 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2615 static inline BOOL is_wellformed(xmlDocPtr doc)
2617 #ifdef HAVE_XMLDOC_PROPERTIES
2618 return doc->properties & XML_DOC_WELLFORMED;
2620 /* Not a full check, but catches the worst violations */
2624 for (child = doc->children; child != NULL; child = child->next)
2626 switch (child->type)
2628 case XML_ELEMENT_NODE:
2633 case XML_CDATA_SECTION_NODE:
2645 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2649 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2653 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2657 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2661 static HRESULT WINAPI domdoc_validateNode(
2662 IXMLDOMDocument3* iface,
2664 IXMLDOMParseError** err)
2666 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2667 LONG state, err_code = 0;
2671 TRACE("(%p)->(%p, %p)\n", This, node, err);
2672 IXMLDOMDocument3_get_readyState(iface, &state);
2673 if (state != READYSTATE_COMPLETE)
2676 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2683 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2687 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2690 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2694 if (!is_wellformed(get_doc(This)))
2696 ERR("doc not well-formed\n");
2698 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2702 /* DTD validation */
2703 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2705 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2706 vctx->error = validate_error;
2707 vctx->warning = validate_warning;
2710 if (!((node == (IXMLDOMNode*)iface)?
2711 xmlValidateDocument(vctx, get_doc(This)) :
2712 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2714 /* TODO: get a real error code here */
2715 TRACE("DTD validation failed\n");
2716 err_code = E_XML_INVALID;
2719 xmlFreeValidCtxt(vctx);
2722 /* Schema validation */
2723 if (hr == S_OK && This->properties->schemaCache != NULL)
2726 hr = SchemaCache_validate_tree(This->properties->schemaCache, get_node_obj(node)->node);
2730 /* TODO: get a real error code here */
2733 TRACE("schema validation succeeded\n");
2737 ERR("schema validation failed\n");
2738 err_code = E_XML_INVALID;
2743 /* not really OK, just didn't find a schema for the ns */
2750 ERR("no DTD or schema found\n");
2751 err_code = E_XML_NODTD;
2756 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2761 static HRESULT WINAPI domdoc_validate(
2762 IXMLDOMDocument3* iface,
2763 IXMLDOMParseError** err)
2765 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2766 TRACE("(%p)->(%p)\n", This, err);
2767 return IXMLDOMDocument3_validateNode(iface, (IXMLDOMNode*)iface, err);
2770 static HRESULT WINAPI domdoc_setProperty(
2771 IXMLDOMDocument3* iface,
2775 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2777 TRACE("(%p)->(%s %s)\n", This, debugstr_w(p), debugstr_variant(&value));
2779 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2785 V_VT(&varStr) = VT_EMPTY;
2786 if (V_VT(&value) != VT_BSTR)
2788 if (FAILED(hr = VariantChangeType(&varStr, &value, 0, VT_BSTR)))
2790 bstr = V_BSTR(&varStr);
2793 bstr = V_BSTR(&value);
2796 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2797 This->properties->XPath = TRUE;
2798 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2799 This->properties->XPath = FALSE;
2803 VariantClear(&varStr);
2806 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2808 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2809 struct list *pNsList;
2814 V_VT(&varStr) = VT_EMPTY;
2815 if (V_VT(&value) != VT_BSTR)
2817 if (FAILED(hr = VariantChangeType(&varStr, &value, 0, VT_BSTR)))
2819 bstr = V_BSTR(&varStr);
2822 bstr = V_BSTR(&value);
2826 pNsList = &(This->properties->selectNsList);
2827 clear_selectNsList(pNsList);
2829 nsStr = xmlchar_from_wchar(bstr);
2831 TRACE("property value: \"%s\"\n", debugstr_w(bstr));
2833 This->properties->selectNsStr = nsStr;
2834 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2837 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2838 select_ns_entry* ns_entry = NULL;
2839 xmlXPathContextPtr ctx;
2841 ctx = xmlXPathNewContext(This->node.node->doc);
2844 /* skip leading spaces */
2845 while (*pTokBegin == ' ' || *pTokBegin == '\n' ||
2846 *pTokBegin == '\t' || *pTokBegin == '\r')
2849 for (; *pTokBegin; pTokBegin = pTokEnd)
2852 memset(ns_entry, 0, sizeof(select_ns_entry));
2854 ns_entry = heap_alloc_zero(sizeof(select_ns_entry));
2856 while (*pTokBegin == ' ')
2858 pTokEnd = pTokBegin;
2859 while (*pTokEnd != ' ' && *pTokEnd != 0)
2862 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2865 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2866 debugstr_w(bstr), debugstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2871 if (*pTokBegin == '=')
2873 /*valid for XSLPattern?*/
2874 FIXME("Setting default xmlns not supported - skipping.\n");
2877 else if (*pTokBegin == ':')
2879 ns_entry->prefix = ++pTokBegin;
2880 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2883 if (pTokInner == pTokEnd)
2886 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2887 debugstr_w(bstr), debugstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2891 ns_entry->prefix_end = *pTokInner;
2895 if (pTokEnd-pTokInner > 1 &&
2896 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2897 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2899 ns_entry->href = ++pTokInner;
2900 ns_entry->href_end = *(pTokEnd-1);
2902 list_add_tail(pNsList, &ns_entry->entry);
2903 /*let libxml figure out if they're valid from here ;)*/
2904 if (xmlXPathRegisterNs(ctx, ns_entry->prefix, ns_entry->href) != 0)
2913 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2914 debugstr_w(bstr), debugstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2915 list_add_tail(pNsList, &ns_entry->entry);
2928 heap_free(ns_entry);
2929 xmlXPathFreeContext(ctx);
2932 VariantClear(&varStr);
2935 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2936 lstrcmpiW(p, PropertyNewParserW) == 0 ||
2937 lstrcmpiW(p, PropertyResolveExternalsW) == 0)
2940 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&value));
2944 FIXME("Unknown property %s\n", debugstr_w(p));
2948 static HRESULT WINAPI domdoc_getProperty(
2949 IXMLDOMDocument3* iface,
2953 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2955 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2958 return E_INVALIDARG;
2960 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2962 V_VT(var) = VT_BSTR;
2963 V_BSTR(var) = This->properties->XPath ?
2964 SysAllocString(PropValueXPathW) :
2965 SysAllocString(PropValueXSLPatternW);
2966 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2968 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2971 BSTR rebuiltStr, cur;
2972 const xmlChar *nsStr;
2973 struct list *pNsList;
2974 select_ns_entry* pNsEntry;
2976 V_VT(var) = VT_BSTR;
2977 nsStr = This->properties->selectNsStr;
2978 pNsList = &This->properties->selectNsList;
2979 lenA = This->properties->selectNsStr_len;
2980 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
2981 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
2982 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
2984 /* this is fine because all of the chars that end tokens are ASCII*/
2985 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
2987 while (*cur != 0) ++cur;
2988 if (pNsEntry->prefix_end)
2990 *cur = pNsEntry->prefix_end;
2991 while (*cur != 0) ++cur;
2994 if (pNsEntry->href_end)
2996 *cur = pNsEntry->href_end;
2999 V_BSTR(var) = SysAllocString(rebuiltStr);
3000 heap_free(rebuiltStr);
3004 FIXME("Unknown property %s\n", debugstr_w(p));
3008 static HRESULT WINAPI domdoc_importNode(
3009 IXMLDOMDocument3* iface,
3012 IXMLDOMNode** clone)
3014 domdoc *This = impl_from_IXMLDOMDocument3( iface );
3015 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
3019 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl =
3021 domdoc_QueryInterface,
3024 domdoc_GetTypeInfoCount,
3026 domdoc_GetIDsOfNames,
3028 domdoc_get_nodeName,
3029 domdoc_get_nodeValue,
3030 domdoc_put_nodeValue,
3031 domdoc_get_nodeType,
3032 domdoc_get_parentNode,
3033 domdoc_get_childNodes,
3034 domdoc_get_firstChild,
3035 domdoc_get_lastChild,
3036 domdoc_get_previousSibling,
3037 domdoc_get_nextSibling,
3038 domdoc_get_attributes,
3039 domdoc_insertBefore,
3040 domdoc_replaceChild,
3043 domdoc_hasChildNodes,
3044 domdoc_get_ownerDocument,
3046 domdoc_get_nodeTypeString,
3049 domdoc_get_specified,
3050 domdoc_get_definition,
3051 domdoc_get_nodeTypedValue,
3052 domdoc_put_nodeTypedValue,
3053 domdoc_get_dataType,
3054 domdoc_put_dataType,
3056 domdoc_transformNode,
3058 domdoc_selectSingleNode,
3060 domdoc_get_namespaceURI,
3062 domdoc_get_baseName,
3063 domdoc_transformNodeToObject,
3065 domdoc_get_implementation,
3066 domdoc_get_documentElement,
3067 domdoc_put_documentElement,
3068 domdoc_createElement,
3069 domdoc_createDocumentFragment,
3070 domdoc_createTextNode,
3071 domdoc_createComment,
3072 domdoc_createCDATASection,
3073 domdoc_createProcessingInstruction,
3074 domdoc_createAttribute,
3075 domdoc_createEntityReference,
3076 domdoc_getElementsByTagName,
3080 domdoc_get_readyState,
3081 domdoc_get_parseError,
3088 domdoc_get_validateOnParse,
3089 domdoc_put_validateOnParse,
3090 domdoc_get_resolveExternals,
3091 domdoc_put_resolveExternals,
3092 domdoc_get_preserveWhiteSpace,
3093 domdoc_put_preserveWhiteSpace,
3094 domdoc_put_onreadystatechange,
3095 domdoc_put_onDataAvailable,
3096 domdoc_put_onTransformNode,
3097 domdoc_get_namespaces,
3099 domdoc_putref_schemas,
3103 domdoc_validateNode,
3107 /* IConnectionPointContainer */
3108 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
3109 REFIID riid, void **ppv)
3111 domdoc *This = impl_from_IConnectionPointContainer(iface);
3112 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppv);
3115 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
3117 domdoc *This = impl_from_IConnectionPointContainer(iface);
3118 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3121 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
3123 domdoc *This = impl_from_IConnectionPointContainer(iface);
3124 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3127 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
3128 IEnumConnectionPoints **ppEnum)
3130 domdoc *This = impl_from_IConnectionPointContainer(iface);
3131 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3135 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
3136 REFIID riid, IConnectionPoint **cp)
3138 domdoc *This = impl_from_IConnectionPointContainer(iface);
3139 ConnectionPoint *iter;
3141 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
3145 for(iter = This->cp_list; iter; iter = iter->next)
3147 if (IsEqualGUID(iter->iid, riid))
3148 *cp = &iter->IConnectionPoint_iface;
3153 IConnectionPoint_AddRef(*cp);
3157 FIXME("unsupported riid %s\n", debugstr_guid(riid));
3158 return CONNECT_E_NOCONNECTION;
3162 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
3164 ConnectionPointContainer_QueryInterface,
3165 ConnectionPointContainer_AddRef,
3166 ConnectionPointContainer_Release,
3167 ConnectionPointContainer_EnumConnectionPoints,
3168 ConnectionPointContainer_FindConnectionPoint
3171 /* IConnectionPoint */
3172 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
3173 REFIID riid, void **ppv)
3175 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3177 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3181 if (IsEqualGUID(&IID_IUnknown, riid) ||
3182 IsEqualGUID(&IID_IConnectionPoint, riid))
3189 IConnectionPoint_AddRef(iface);
3193 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3194 return E_NOINTERFACE;
3197 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3199 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3200 return IConnectionPointContainer_AddRef(This->container);
3203 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3205 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3206 return IConnectionPointContainer_Release(This->container);
3209 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3211 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3213 TRACE("(%p)->(%p)\n", This, iid);
3215 if (!iid) return E_POINTER;
3221 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3222 IConnectionPointContainer **container)
3224 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3226 TRACE("(%p)->(%p)\n", This, container);
3228 if (!container) return E_POINTER;
3230 *container = This->container;
3231 IConnectionPointContainer_AddRef(*container);
3235 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
3238 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3239 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
3243 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3245 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3247 TRACE("(%p)->(%d)\n", This, cookie);
3249 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3250 return CONNECT_E_NOCONNECTION;
3252 IUnknown_Release(This->sinks[cookie-1].unk);
3253 This->sinks[cookie-1].unk = NULL;
3258 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3259 IEnumConnections **ppEnum)
3261 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3262 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3266 static const IConnectionPointVtbl ConnectionPointVtbl =
3268 ConnectionPoint_QueryInterface,
3269 ConnectionPoint_AddRef,
3270 ConnectionPoint_Release,
3271 ConnectionPoint_GetConnectionInterface,
3272 ConnectionPoint_GetConnectionPointContainer,
3273 ConnectionPoint_Advise,
3274 ConnectionPoint_Unadvise,
3275 ConnectionPoint_EnumConnections
3278 static void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3280 cp->IConnectionPoint_iface.lpVtbl = &ConnectionPointVtbl;
3286 cp->next = doc->cp_list;
3289 cp->container = &doc->IConnectionPointContainer_iface;
3292 /* domdoc implementation of IObjectWithSite */
3293 static HRESULT WINAPI
3294 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3296 domdoc *This = impl_from_IObjectWithSite(iface);
3297 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppvObject);
3300 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3302 domdoc *This = impl_from_IObjectWithSite(iface);
3303 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3306 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3308 domdoc *This = impl_from_IObjectWithSite(iface);
3309 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3312 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3314 domdoc *This = impl_from_IObjectWithSite(iface);
3316 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3321 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3324 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3326 domdoc *This = impl_from_IObjectWithSite(iface);
3328 TRACE("(%p)->(%p)\n", iface, punk);
3334 IUnknown_Release( This->site );
3341 IUnknown_AddRef( punk );
3344 IUnknown_Release( This->site );
3351 static const IObjectWithSiteVtbl domdocObjectSite =
3353 domdoc_ObjectWithSite_QueryInterface,
3354 domdoc_ObjectWithSite_AddRef,
3355 domdoc_ObjectWithSite_Release,
3356 domdoc_ObjectWithSite_SetSite,
3357 domdoc_ObjectWithSite_GetSite
3360 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3362 domdoc *This = impl_from_IObjectSafety(iface);
3363 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppv);
3366 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3368 domdoc *This = impl_from_IObjectSafety(iface);
3369 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3372 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3374 domdoc *This = impl_from_IObjectSafety(iface);
3375 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3378 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3380 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3381 DWORD *supported, DWORD *enabled)
3383 domdoc *This = impl_from_IObjectSafety(iface);
3385 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3387 if(!supported || !enabled) return E_POINTER;
3389 *supported = SAFETY_SUPPORTED_OPTIONS;
3390 *enabled = This->safeopt;
3395 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3396 DWORD mask, DWORD enabled)
3398 domdoc *This = impl_from_IObjectSafety(iface);
3399 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3401 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3404 This->safeopt = (This->safeopt & ~mask) | (mask & enabled);
3409 #undef SAFETY_SUPPORTED_OPTIONS
3411 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3412 domdoc_Safety_QueryInterface,
3413 domdoc_Safety_AddRef,
3414 domdoc_Safety_Release,
3415 domdoc_Safety_GetInterfaceSafetyOptions,
3416 domdoc_Safety_SetInterfaceSafetyOptions
3419 static const tid_t domdoc_iface_tids[] = {
3420 IXMLDOMDocument3_tid,
3424 static dispex_static_data_t domdoc_dispex = {
3426 IXMLDOMDocument3_tid,
3431 HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3435 doc = heap_alloc( sizeof (*doc) );
3437 return E_OUTOFMEMORY;
3439 doc->IXMLDOMDocument3_iface.lpVtbl = &XMLDOMDocument3Vtbl;
3440 doc->IPersistStreamInit_iface.lpVtbl = &xmldoc_IPersistStreamInit_VTable;
3441 doc->IObjectWithSite_iface.lpVtbl = &domdocObjectSite;
3442 doc->IObjectSafety_iface.lpVtbl = &domdocObjectSafetyVtbl;
3443 doc->IConnectionPointContainer_iface.lpVtbl = &ConnectionPointContainerVtbl;
3445 doc->async = VARIANT_TRUE;
3446 doc->validating = 0;
3448 doc->properties = properties_from_xmlDocPtr(xmldoc);
3454 doc->cp_list = NULL;
3455 doc->namespaces = NULL;
3456 memset(doc->events, 0, sizeof(doc->events));
3458 /* events connection points */
3459 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3460 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3461 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3463 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->IXMLDOMDocument3_iface,
3466 *document = &doc->IXMLDOMDocument3_iface;
3468 TRACE("returning iface %p\n", *document);
3472 HRESULT DOMDocument_create(MSXML_VERSION version, IUnknown *pUnkOuter, void **ppObj)
3477 TRACE("(%d, %p, %p)\n", version, pUnkOuter, ppObj);
3479 xmldoc = xmlNewDoc(NULL);
3481 return E_OUTOFMEMORY;
3483 xmldoc_init(xmldoc, version);
3485 hr = get_domdoc_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3488 free_properties(properties_from_xmlDocPtr(xmldoc));
3489 heap_free(xmldoc->_private);
3497 IUnknown* create_domdoc( xmlNodePtr document )
3502 TRACE("(%p)\n", document);
3504 hr = get_domdoc_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3513 HRESULT DOMDocument_create(MSXML_VERSION version, IUnknown *pUnkOuter, void **ppObj)
3515 MESSAGE("This program tried to use a DOMDocument object, but\n"
3516 "libxml2 support was not present at compile time.\n");