2 * DOM Document implementation
4 * Copyright 2005 Mike McCormack
5 * Copyright 2010 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
43 #include "wine/debug.h"
44 #include "wine/list.h"
46 #include "msxml_private.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
52 #include <libxml/xpathInternals.h>
53 #include <libxml/xmlsave.h>
54 #include <libxml/SAX2.h>
55 #include <libxml/parserInternals.h>
57 /* not defined in older versions */
58 #define XML_SAVE_FORMAT 1
59 #define XML_SAVE_NO_DECL 2
60 #define XML_SAVE_NO_EMPTY 4
61 #define XML_SAVE_NO_XHTML 8
62 #define XML_SAVE_XHTML 16
63 #define XML_SAVE_AS_XML 32
64 #define XML_SAVE_AS_HTML 64
66 static const WCHAR PropertySelectionLanguageW[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
67 static const WCHAR PropertySelectionNamespacesW[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
68 static const WCHAR PropertyProhibitDTDW[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
69 static const WCHAR PropertyNewParserW[] = {'N','e','w','P','a','r','s','e','r',0};
70 static const WCHAR PropValueXPathW[] = {'X','P','a','t','h',0};
71 static const WCHAR PropValueXSLPatternW[] = {'X','S','L','P','a','t','t','e','r','n',0};
73 /* Anything that passes the test_get_ownerDocument()
74 * tests can go here (data shared between all instances).
75 * We need to preserve this when reloading a document,
76 * and also need access to it from the libxml backend. */
77 typedef struct _domdoc_properties {
78 MSXML_VERSION version;
79 VARIANT_BOOL preserving;
80 IXMLDOMSchemaCollection2* schemaCache;
81 struct list selectNsList;
82 xmlChar const* selectNsStr;
87 typedef struct ConnectionPoint ConnectionPoint;
88 typedef struct domdoc domdoc;
90 struct ConnectionPoint
92 const IConnectionPointVtbl *lpVtblConnectionPoint;
95 ConnectionPoint *next;
96 IConnectionPointContainer *container;
103 IPropertyNotifySink *propnotif;
111 const struct IXMLDOMDocument3Vtbl *lpVtbl;
112 const struct IPersistStreamInitVtbl *lpvtblIPersistStreamInit;
113 const struct IObjectWithSiteVtbl *lpvtblIObjectWithSite;
114 const struct IObjectSafetyVtbl *lpvtblIObjectSafety;
115 const struct ISupportErrorInfoVtbl *lpvtblISupportErrorInfo;
116 const struct IConnectionPointContainerVtbl *lpVtblConnectionPointContainer;
119 VARIANT_BOOL validating;
120 VARIANT_BOOL resolving;
121 domdoc_properties* properties;
134 /* connection list */
135 ConnectionPoint *cp_list;
136 ConnectionPoint cp_domdocevents;
137 ConnectionPoint cp_propnotif;
138 ConnectionPoint cp_dispatch;
141 static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface)
143 return (ConnectionPoint *)((char*)iface - FIELD_OFFSET(ConnectionPoint, lpVtblConnectionPoint));
147 In native windows, the whole lifetime management of XMLDOMNodes is
148 managed automatically using reference counts. Wine emulates that by
149 maintaining a reference count to the document that is increased for
150 each IXMLDOMNode pointer passed out for this document. If all these
151 pointers are gone, the document is unreachable and gets freed, that
152 is, all nodes in the tree of the document get freed.
154 You are able to create nodes that are associated to a document (in
155 fact, in msxml's XMLDOM model, all nodes are associated to a document),
156 but not in the tree of that document, for example using the createFoo
157 functions from IXMLDOMDocument. These nodes do not get cleaned up
158 by libxml, so we have to do it ourselves.
160 To catch these nodes, a list of "orphan nodes" is introduced.
161 It contains pointers to all roots of node trees that are
162 associated with the document without being part of the document
163 tree. All nodes with parent==NULL (except for the document root nodes)
164 should be in the orphan node list of their document. All orphan nodes
165 get freed together with the document itself.
168 typedef struct _xmldoc_priv {
171 domdoc_properties* properties;
174 typedef struct _orphan_entry {
179 typedef struct _select_ns_entry {
181 xmlChar const* prefix;
187 static inline xmldoc_priv * priv_from_xmlDocPtr(const xmlDocPtr doc)
189 return doc->_private;
192 static inline domdoc_properties * properties_from_xmlDocPtr(xmlDocPtr doc)
194 return priv_from_xmlDocPtr(doc)->properties;
197 BOOL is_xpathmode(const xmlDocPtr doc)
199 return properties_from_xmlDocPtr(doc)->XPath;
202 void set_xpathmode(xmlDocPtr doc, BOOL xpath)
204 properties_from_xmlDocPtr(doc)->XPath = xpath;
207 int registerNamespaces(xmlXPathContextPtr ctxt)
210 const select_ns_entry* ns = NULL;
211 const struct list* pNsList = &properties_from_xmlDocPtr(ctxt->doc)->selectNsList;
213 TRACE("(%p)\n", ctxt);
215 LIST_FOR_EACH_ENTRY( ns, pNsList, select_ns_entry, entry )
217 xmlXPathRegisterNs(ctxt, ns->prefix, ns->href);
224 static inline void clear_selectNsList(struct list* pNsList)
226 select_ns_entry *ns, *ns2;
227 LIST_FOR_EACH_ENTRY_SAFE( ns, ns2, pNsList, select_ns_entry, entry )
234 static xmldoc_priv * create_priv(void)
237 priv = heap_alloc( sizeof (*priv) );
242 list_init( &priv->orphans );
243 priv->properties = NULL;
249 static domdoc_properties * create_properties(const GUID *clsid)
251 domdoc_properties *properties = heap_alloc(sizeof(domdoc_properties));
253 list_init(&properties->selectNsList);
254 properties->preserving = VARIANT_FALSE;
255 properties->schemaCache = NULL;
256 properties->selectNsStr = heap_alloc_zero(sizeof(xmlChar));
257 properties->selectNsStr_len = 0;
259 /* properties that are dependent on object versions */
260 if (IsEqualCLSID(clsid, &CLSID_DOMDocument30))
262 properties->version = MSXML3;
263 properties->XPath = FALSE;
265 else if (IsEqualCLSID(clsid, &CLSID_DOMDocument40))
267 properties->version = MSXML4;
268 properties->XPath = TRUE;
270 else if (IsEqualCLSID(clsid, &CLSID_DOMDocument60))
272 properties->version = MSXML6;
273 properties->XPath = TRUE;
277 properties->version = MSXML_DEFAULT;
278 properties->XPath = FALSE;
284 static domdoc_properties* copy_properties(domdoc_properties const* properties)
286 domdoc_properties* pcopy = heap_alloc(sizeof(domdoc_properties));
287 select_ns_entry const* ns = NULL;
288 select_ns_entry* new_ns = NULL;
289 int len = (properties->selectNsStr_len+1)*sizeof(xmlChar);
294 pcopy->version = properties->version;
295 pcopy->preserving = properties->preserving;
296 pcopy->schemaCache = properties->schemaCache;
297 pcopy->XPath = properties->XPath;
298 pcopy->selectNsStr_len = properties->selectNsStr_len;
299 list_init( &pcopy->selectNsList );
300 pcopy->selectNsStr = heap_alloc(len);
301 memcpy((xmlChar*)pcopy->selectNsStr, properties->selectNsStr, len);
302 offset = pcopy->selectNsStr - properties->selectNsStr;
304 LIST_FOR_EACH_ENTRY( ns, (&properties->selectNsList), select_ns_entry, entry )
306 new_ns = heap_alloc(sizeof(select_ns_entry));
307 memcpy(new_ns, ns, sizeof(select_ns_entry));
308 new_ns->href += offset;
309 new_ns->prefix += offset;
310 list_add_tail(&pcopy->selectNsList, &new_ns->entry);
318 static void free_properties(domdoc_properties* properties)
322 if (properties->schemaCache)
323 IXMLDOMSchemaCollection2_Release(properties->schemaCache);
324 clear_selectNsList(&properties->selectNsList);
325 heap_free((xmlChar*)properties->selectNsStr);
326 heap_free(properties);
330 static BOOL xmldoc_has_decl(xmlDocPtr doc)
332 return doc->children && (xmlStrEqual(doc->children->name, (xmlChar*)"xml") == 1);
335 /* links a "<?xml" node as a first child */
336 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
339 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
342 /* unlinks a first "<?xml" child if it was created */
343 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
349 if (doc->standalone != -1)
351 node = doc->children;
352 xmlUnlinkNode( node );
360 BOOL is_preserving_whitespace(xmlNodePtr node)
362 domdoc_properties* properties = NULL;
363 /* during parsing the xmlDoc._private stuff is not there */
364 if (priv_from_xmlDocPtr(node->doc))
365 properties = properties_from_xmlDocPtr(node->doc);
366 return ((properties && properties->preserving == VARIANT_TRUE) ||
367 xmlNodeGetSpacePreserve(node) == 1);
370 static inline BOOL strn_isspace(xmlChar const* str, int len)
372 for (; str && len > 0 && *str; ++str, --len)
379 static void sax_characters(void *ctx, const xmlChar *ch, int len)
381 xmlParserCtxtPtr pctx;
384 pctx = (xmlParserCtxtPtr) ctx;
385 This = (domdoc const*) pctx->_private;
387 /* during domdoc_loadXML() the xmlDocPtr->_private data is not available */
388 if (!This->properties->preserving &&
389 !is_preserving_whitespace(pctx->node) &&
390 strn_isspace(ch, len))
393 xmlSAX2Characters(ctx, ch, len);
396 static void LIBXML2_LOG_CALLBACK sax_error(void* ctx, char const* msg, ...)
400 LIBXML2_CALLBACK_ERR(doparse, msg, ap);
404 static void LIBXML2_LOG_CALLBACK sax_warning(void* ctx, char const* msg, ...)
408 LIBXML2_CALLBACK_WARN(doparse, msg, ap);
412 static void sax_serror(void* ctx, xmlErrorPtr err)
414 LIBXML2_CALLBACK_SERROR(doparse, err);
417 static xmlDocPtr doparse(domdoc* This, char *ptr, int len, xmlChar const* encoding)
419 xmlDocPtr doc = NULL;
420 xmlParserCtxtPtr pctx;
421 static xmlSAXHandler sax_handler = {
422 xmlSAX2InternalSubset, /* internalSubset */
423 xmlSAX2IsStandalone, /* isStandalone */
424 xmlSAX2HasInternalSubset, /* hasInternalSubset */
425 xmlSAX2HasExternalSubset, /* hasExternalSubset */
426 xmlSAX2ResolveEntity, /* resolveEntity */
427 xmlSAX2GetEntity, /* getEntity */
428 xmlSAX2EntityDecl, /* entityDecl */
429 xmlSAX2NotationDecl, /* notationDecl */
430 xmlSAX2AttributeDecl, /* attributeDecl */
431 xmlSAX2ElementDecl, /* elementDecl */
432 xmlSAX2UnparsedEntityDecl, /* unparsedEntityDecl */
433 xmlSAX2SetDocumentLocator, /* setDocumentLocator */
434 xmlSAX2StartDocument, /* startDocument */
435 xmlSAX2EndDocument, /* endDocument */
436 xmlSAX2StartElement, /* startElement */
437 xmlSAX2EndElement, /* endElement */
438 xmlSAX2Reference, /* reference */
439 sax_characters, /* characters */
440 sax_characters, /* ignorableWhitespace */
441 xmlSAX2ProcessingInstruction, /* processingInstruction */
442 xmlSAX2Comment, /* comment */
443 sax_warning, /* warning */
444 sax_error, /* error */
445 sax_error, /* fatalError */
446 xmlSAX2GetParameterEntity, /* getParameterEntity */
447 xmlSAX2CDataBlock, /* cdataBlock */
448 xmlSAX2ExternalSubset, /* externalSubset */
451 xmlSAX2StartElementNs, /* startElementNs */
452 xmlSAX2EndElementNs, /* endElementNs */
453 sax_serror /* serror */
457 pctx = xmlCreateMemoryParserCtxt(ptr, len);
460 ERR("Failed to create parser context\n");
464 if (pctx->sax) xmlFree(pctx->sax);
465 pctx->sax = &sax_handler;
466 pctx->_private = This;
468 pctx->encoding = xmlStrdup(encoding);
469 xmlParseDocument(pctx);
471 if (pctx->wellFormed)
477 xmlFreeDoc(pctx->myDoc);
481 xmlFreeParserCtxt(pctx);
483 /* TODO: put this in one of the SAX callbacks */
484 /* create first child as a <?xml...?> */
485 if (doc && doc->standalone != -1)
489 xmlChar *xmlbuff = (xmlChar*)buff;
491 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
493 /* version attribute can't be omitted */
494 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
495 xmlNodeAddContent( node, xmlbuff );
499 sprintf(buff, " encoding=\"%s\"", doc->encoding);
500 xmlNodeAddContent( node, xmlbuff );
503 if (doc->standalone != -2)
505 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
506 xmlNodeAddContent( node, xmlbuff );
509 xmldoc_link_xmldecl( doc, node );
515 void xmldoc_init(xmlDocPtr doc, const GUID *clsid)
517 doc->_private = create_priv();
518 priv_from_xmlDocPtr(doc)->properties = create_properties(clsid);
521 LONG xmldoc_add_ref(xmlDocPtr doc)
523 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
524 TRACE("(%p)->(%d)\n", doc, ref);
528 LONG xmldoc_release(xmlDocPtr doc)
530 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
531 LONG ref = InterlockedDecrement(&priv->refs);
532 TRACE("(%p)->(%d)\n", doc, ref);
535 orphan_entry *orphan, *orphan2;
536 TRACE("freeing docptr %p\n", doc);
538 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
540 xmlFreeNode( orphan->node );
543 free_properties(priv->properties);
544 heap_free(doc->_private);
552 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
554 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
557 entry = heap_alloc( sizeof (*entry) );
559 return E_OUTOFMEMORY;
562 list_add_head( &priv->orphans, &entry->entry );
566 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
568 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
569 orphan_entry *entry, *entry2;
571 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
573 if( entry->node == node )
575 list_remove( &entry->entry );
584 static inline xmlDocPtr get_doc( domdoc *This )
586 return (xmlDocPtr)This->node.node;
589 static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
593 priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
594 if (xmldoc_release(get_doc(This)) != 0)
595 priv_from_xmlDocPtr(get_doc(This))->properties =
596 copy_properties(This->properties);
599 This->node.node = (xmlNodePtr) xml;
603 xmldoc_add_ref(get_doc(This));
604 priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
610 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
612 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
615 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
617 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStreamInit));
620 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
622 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
625 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
627 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
630 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
632 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblISupportErrorInfo));
635 static inline domdoc *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
637 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtblConnectionPointContainer));
640 /************************************************************************
641 * domdoc implementation of IPersistStream.
643 static HRESULT WINAPI domdoc_IPersistStreamInit_QueryInterface(
644 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
646 domdoc* This = impl_from_IPersistStreamInit(iface);
647 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)&This->lpVtbl, riid, ppvObj);
650 static ULONG WINAPI domdoc_IPersistStreamInit_AddRef(
651 IPersistStreamInit *iface)
653 domdoc* This = impl_from_IPersistStreamInit(iface);
654 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)&This->lpVtbl);
657 static ULONG WINAPI domdoc_IPersistStreamInit_Release(
658 IPersistStreamInit *iface)
660 domdoc* This = impl_from_IPersistStreamInit(iface);
661 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)&This->lpVtbl);
664 static HRESULT WINAPI domdoc_IPersistStreamInit_GetClassID(
665 IPersistStreamInit *iface, CLSID *classid)
667 domdoc* This = impl_from_IPersistStreamInit(iface);
668 TRACE("(%p)->(%p)\n", This, classid);
673 *classid = *DOMDocument_version(This->properties->version);
678 static HRESULT WINAPI domdoc_IPersistStreamInit_IsDirty(
679 IPersistStreamInit *iface)
681 domdoc *This = impl_from_IPersistStreamInit(iface);
682 FIXME("(%p): stub!\n", This);
686 static HRESULT WINAPI domdoc_IPersistStreamInit_Load(
687 IPersistStreamInit *iface, LPSTREAM pStm)
689 domdoc *This = impl_from_IPersistStreamInit(iface);
692 DWORD read, written, len;
695 xmlDocPtr xmldoc = NULL;
697 TRACE("(%p)->(%p)\n", This, pStm);
702 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
708 IStream_Read(pStm, buf, sizeof(buf), &read);
709 hr = IStream_Write(This->stream, buf, read, &written);
710 } while(SUCCEEDED(hr) && written != 0 && read != 0);
714 ERR("Failed to copy stream\n");
718 hr = GetHGlobalFromStream(This->stream, &hglobal);
722 len = GlobalSize(hglobal);
723 ptr = GlobalLock(hglobal);
725 xmldoc = doparse(This, ptr, len, NULL);
726 GlobalUnlock(hglobal);
730 ERR("Failed to parse xml\n");
734 xmldoc->_private = create_priv();
736 return attach_xmldoc(This, xmldoc);
739 static HRESULT WINAPI domdoc_IPersistStreamInit_Save(
740 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
742 domdoc *This = impl_from_IPersistStreamInit(iface);
746 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
748 hr = IXMLDOMDocument3_get_xml( (IXMLDOMDocument3*)&This->lpVtbl, &xmlString );
751 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
753 hr = IStream_Write( stream, xmlString, len, NULL );
754 SysFreeString(xmlString);
757 TRACE("ret 0x%08x\n", hr);
762 static HRESULT WINAPI domdoc_IPersistStreamInit_GetSizeMax(
763 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
765 domdoc *This = impl_from_IPersistStreamInit(iface);
766 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
770 static HRESULT WINAPI domdoc_IPersistStreamInit_InitNew(
771 IPersistStreamInit *iface)
773 domdoc *This = impl_from_IPersistStreamInit(iface);
774 TRACE("(%p)\n", This);
778 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
780 domdoc_IPersistStreamInit_QueryInterface,
781 domdoc_IPersistStreamInit_AddRef,
782 domdoc_IPersistStreamInit_Release,
783 domdoc_IPersistStreamInit_GetClassID,
784 domdoc_IPersistStreamInit_IsDirty,
785 domdoc_IPersistStreamInit_Load,
786 domdoc_IPersistStreamInit_Save,
787 domdoc_IPersistStreamInit_GetSizeMax,
788 domdoc_IPersistStreamInit_InitNew
791 /* ISupportErrorInfo interface */
792 static HRESULT WINAPI support_error_QueryInterface(
793 ISupportErrorInfo *iface,
794 REFIID riid, void** ppvObj )
796 domdoc *This = impl_from_ISupportErrorInfo(iface);
797 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3 *)This, riid, ppvObj);
800 static ULONG WINAPI support_error_AddRef(
801 ISupportErrorInfo *iface )
803 domdoc *This = impl_from_ISupportErrorInfo(iface);
804 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
807 static ULONG WINAPI support_error_Release(
808 ISupportErrorInfo *iface )
810 domdoc *This = impl_from_ISupportErrorInfo(iface);
811 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
814 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
815 ISupportErrorInfo *iface,
818 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
822 static const struct ISupportErrorInfoVtbl support_error_vtbl =
824 support_error_QueryInterface,
825 support_error_AddRef,
826 support_error_Release,
827 support_error_InterfaceSupportsErrorInfo
830 /* IXMLDOMDocument2 interface */
831 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
833 domdoc *This = impl_from_IXMLDOMDocument3( iface );
835 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
839 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
840 IsEqualGUID( riid, &IID_IDispatch ) ||
841 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
842 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
843 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
844 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
848 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
849 IsEqualGUID(&IID_IPersistStreamInit, riid))
851 *ppvObject = &(This->lpvtblIPersistStreamInit);
853 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
855 *ppvObject = &(This->lpvtblIObjectWithSite);
857 else if (IsEqualGUID(&IID_IObjectSafety, riid))
859 *ppvObject = &(This->lpvtblIObjectSafety);
861 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
863 *ppvObject = &This->lpvtblISupportErrorInfo;
865 else if(node_query_interface(&This->node, riid, ppvObject))
867 return *ppvObject ? S_OK : E_NOINTERFACE;
869 else if (IsEqualGUID( riid, &IID_IConnectionPointContainer ))
871 *ppvObject = &This->lpVtblConnectionPointContainer;
873 else if(IsEqualGUID(&IID_IRunnableObject, riid))
875 TRACE("IID_IRunnableObject not supported returning NULL\n");
876 return E_NOINTERFACE;
880 FIXME("interface %s not implemented\n", debugstr_guid(riid));
881 return E_NOINTERFACE;
884 IUnknown_AddRef((IUnknown*)*ppvObject);
890 static ULONG WINAPI domdoc_AddRef(
891 IXMLDOMDocument3 *iface )
893 domdoc *This = impl_from_IXMLDOMDocument3( iface );
894 ULONG ref = InterlockedIncrement( &This->ref );
895 TRACE("(%p)->(%d)\n", This, ref );
900 static ULONG WINAPI domdoc_Release(
901 IXMLDOMDocument3 *iface )
903 domdoc *This = impl_from_IXMLDOMDocument3( iface );
904 LONG ref = InterlockedDecrement( &This->ref );
906 TRACE("(%p)->(%d)\n", This, ref );
911 detach_bsc(This->bsc);
914 IUnknown_Release( This->site );
915 destroy_xmlnode(&This->node);
917 IStream_Release(This->stream);
924 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
926 domdoc *This = impl_from_IXMLDOMDocument3( iface );
928 TRACE("(%p)->(%p)\n", This, pctinfo);
935 static HRESULT WINAPI domdoc_GetTypeInfo(
936 IXMLDOMDocument3 *iface,
937 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
939 domdoc *This = impl_from_IXMLDOMDocument3( iface );
942 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
944 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
949 static HRESULT WINAPI domdoc_GetIDsOfNames(
950 IXMLDOMDocument3 *iface,
957 domdoc *This = impl_from_IXMLDOMDocument3( iface );
961 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
964 if(!rgszNames || cNames == 0 || !rgDispId)
967 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
970 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
971 ITypeInfo_Release(typeinfo);
978 static HRESULT WINAPI domdoc_Invoke(
979 IXMLDOMDocument3 *iface,
984 DISPPARAMS* pDispParams,
986 EXCEPINFO* pExcepInfo,
989 domdoc *This = impl_from_IXMLDOMDocument3( iface );
993 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
994 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
996 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
999 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
1000 pVarResult, pExcepInfo, puArgErr);
1001 ITypeInfo_Release(typeinfo);
1008 static HRESULT WINAPI domdoc_get_nodeName(
1009 IXMLDOMDocument3 *iface,
1012 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1014 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
1016 TRACE("(%p)->(%p)\n", This, name);
1018 return return_bstr(documentW, name);
1022 static HRESULT WINAPI domdoc_get_nodeValue(
1023 IXMLDOMDocument3 *iface,
1026 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1028 TRACE("(%p)->(%p)\n", This, value);
1031 return E_INVALIDARG;
1033 V_VT(value) = VT_NULL;
1034 V_BSTR(value) = NULL; /* tests show that we should do this */
1039 static HRESULT WINAPI domdoc_put_nodeValue(
1040 IXMLDOMDocument3 *iface,
1043 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1044 TRACE("(%p)->(v%d)\n", This, V_VT(&value));
1049 static HRESULT WINAPI domdoc_get_nodeType(
1050 IXMLDOMDocument3 *iface,
1053 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1055 TRACE("(%p)->(%p)\n", This, type);
1057 *type = NODE_DOCUMENT;
1062 static HRESULT WINAPI domdoc_get_parentNode(
1063 IXMLDOMDocument3 *iface,
1064 IXMLDOMNode** parent )
1066 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1068 TRACE("(%p)->(%p)\n", This, parent);
1070 return node_get_parent(&This->node, parent);
1074 static HRESULT WINAPI domdoc_get_childNodes(
1075 IXMLDOMDocument3 *iface,
1076 IXMLDOMNodeList** childList )
1078 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1080 TRACE("(%p)->(%p)\n", This, childList);
1082 return node_get_child_nodes(&This->node, childList);
1086 static HRESULT WINAPI domdoc_get_firstChild(
1087 IXMLDOMDocument3 *iface,
1088 IXMLDOMNode** firstChild )
1090 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1092 TRACE("(%p)->(%p)\n", This, firstChild);
1094 return node_get_first_child(&This->node, firstChild);
1098 static HRESULT WINAPI domdoc_get_lastChild(
1099 IXMLDOMDocument3 *iface,
1100 IXMLDOMNode** lastChild )
1102 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1104 TRACE("(%p)->(%p)\n", This, lastChild);
1106 return node_get_last_child(&This->node, lastChild);
1110 static HRESULT WINAPI domdoc_get_previousSibling(
1111 IXMLDOMDocument3 *iface,
1112 IXMLDOMNode** previousSibling )
1114 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1116 TRACE("(%p)->(%p)\n", This, previousSibling);
1118 return return_null_node(previousSibling);
1122 static HRESULT WINAPI domdoc_get_nextSibling(
1123 IXMLDOMDocument3 *iface,
1124 IXMLDOMNode** nextSibling )
1126 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1128 TRACE("(%p)->(%p)\n", This, nextSibling);
1130 return return_null_node(nextSibling);
1134 static HRESULT WINAPI domdoc_get_attributes(
1135 IXMLDOMDocument3 *iface,
1136 IXMLDOMNamedNodeMap** attributeMap )
1138 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1140 TRACE("(%p)->(%p)\n", This, attributeMap);
1142 return return_null_ptr((void**)attributeMap);
1146 static HRESULT WINAPI domdoc_insertBefore(
1147 IXMLDOMDocument3 *iface,
1148 IXMLDOMNode* newChild,
1150 IXMLDOMNode** outNewChild )
1152 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1154 TRACE("(%p)->(%p x%d %p)\n", This, newChild, V_VT(&refChild), outNewChild);
1156 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1160 static HRESULT WINAPI domdoc_replaceChild(
1161 IXMLDOMDocument3 *iface,
1162 IXMLDOMNode* newChild,
1163 IXMLDOMNode* oldChild,
1164 IXMLDOMNode** outOldChild)
1166 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1168 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1170 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1174 static HRESULT WINAPI domdoc_removeChild(
1175 IXMLDOMDocument3 *iface,
1176 IXMLDOMNode* childNode,
1177 IXMLDOMNode** oldChild)
1179 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1180 return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), childNode, oldChild );
1184 static HRESULT WINAPI domdoc_appendChild(
1185 IXMLDOMDocument3 *iface,
1186 IXMLDOMNode* newChild,
1187 IXMLDOMNode** outNewChild)
1189 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1190 return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newChild, outNewChild );
1194 static HRESULT WINAPI domdoc_hasChildNodes(
1195 IXMLDOMDocument3 *iface,
1196 VARIANT_BOOL* hasChild)
1198 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1199 return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), hasChild );
1203 static HRESULT WINAPI domdoc_get_ownerDocument(
1204 IXMLDOMDocument3 *iface,
1205 IXMLDOMDocument** DOMDocument)
1207 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1208 return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), DOMDocument );
1212 static HRESULT WINAPI domdoc_cloneNode(
1213 IXMLDOMDocument3 *iface,
1215 IXMLDOMNode** outNode)
1217 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1218 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
1219 return node_clone( &This->node, deep, outNode );
1223 static HRESULT WINAPI domdoc_get_nodeTypeString(
1224 IXMLDOMDocument3 *iface,
1227 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1228 static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
1230 TRACE("(%p)->(%p)\n", This, p);
1232 return return_bstr(documentW, p);
1236 static HRESULT WINAPI domdoc_get_text(
1237 IXMLDOMDocument3 *iface,
1240 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1241 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), text );
1245 static HRESULT WINAPI domdoc_put_text(
1246 IXMLDOMDocument3 *iface,
1249 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1250 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1255 static HRESULT WINAPI domdoc_get_specified(
1256 IXMLDOMDocument3 *iface,
1257 VARIANT_BOOL* isSpecified )
1259 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1260 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1261 *isSpecified = VARIANT_TRUE;
1266 static HRESULT WINAPI domdoc_get_definition(
1267 IXMLDOMDocument3 *iface,
1268 IXMLDOMNode** definitionNode )
1270 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1271 FIXME("(%p)->(%p)\n", This, definitionNode);
1276 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1277 IXMLDOMDocument3 *iface,
1278 VARIANT* typedValue )
1280 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1281 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
1284 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1285 IXMLDOMDocument3 *iface,
1286 VARIANT typedValue )
1288 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1289 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
1293 static HRESULT WINAPI domdoc_get_dataType(
1294 IXMLDOMDocument3 *iface,
1297 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1298 TRACE("(%p)->(%p)\n", This, typename);
1299 return return_null_var( typename );
1303 static HRESULT WINAPI domdoc_put_dataType(
1304 IXMLDOMDocument3 *iface,
1307 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1308 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
1311 static int XMLCALL domdoc_get_xml_writecallback(void *ctx, const char *data, int len)
1313 return xmlBufferAdd((xmlBufferPtr)ctx, (xmlChar*)data, len) == 0 ? len : 0;
1316 static HRESULT WINAPI domdoc_get_xml(
1317 IXMLDOMDocument3 *iface,
1320 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1321 xmlSaveCtxtPtr ctxt;
1326 TRACE("(%p)->(%p)\n", This, p);
1329 return E_INVALIDARG;
1333 buf = xmlBufferCreate();
1335 return E_OUTOFMEMORY;
1337 options = xmldoc_has_decl(get_doc(This)) ? XML_SAVE_NO_DECL : 0;
1338 options |= XML_SAVE_FORMAT;
1339 ctxt = xmlSaveToIO(domdoc_get_xml_writecallback, NULL, buf, "UTF-8", options);
1344 return E_OUTOFMEMORY;
1347 ret = xmlSaveDoc(ctxt, get_doc(This));
1348 /* flushes on close */
1351 TRACE("%ld, len=%d\n", ret, xmlBufferLength(buf));
1352 if(ret != -1 && xmlBufferLength(buf) > 0)
1356 content = bstr_from_xmlChar(xmlBufferContent(buf));
1357 content = EnsureCorrectEOL(content);
1363 *p = SysAllocStringLen(NULL, 0);
1368 return *p ? S_OK : E_OUTOFMEMORY;
1372 static HRESULT WINAPI domdoc_transformNode(
1373 IXMLDOMDocument3 *iface,
1374 IXMLDOMNode* styleSheet,
1377 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1378 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), styleSheet, xmlString );
1382 static HRESULT WINAPI domdoc_selectNodes(
1383 IXMLDOMDocument3 *iface,
1385 IXMLDOMNodeList** resultList )
1387 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1388 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), queryString, resultList );
1392 static HRESULT WINAPI domdoc_selectSingleNode(
1393 IXMLDOMDocument3 *iface,
1395 IXMLDOMNode** resultNode )
1397 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1398 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), queryString, resultNode );
1402 static HRESULT WINAPI domdoc_get_parsed(
1403 IXMLDOMDocument3 *iface,
1404 VARIANT_BOOL* isParsed )
1406 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1407 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1408 *isParsed = VARIANT_TRUE;
1413 static HRESULT WINAPI domdoc_get_namespaceURI(
1414 IXMLDOMDocument3 *iface,
1415 BSTR* namespaceURI )
1417 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1418 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), namespaceURI );
1422 static HRESULT WINAPI domdoc_get_prefix(
1423 IXMLDOMDocument3 *iface,
1426 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1427 TRACE("(%p)->(%p)\n", This, prefix);
1428 return return_null_bstr( prefix );
1432 static HRESULT WINAPI domdoc_get_baseName(
1433 IXMLDOMDocument3 *iface,
1436 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1437 TRACE("(%p)->(%p)\n", This, name);
1438 return return_null_bstr( name );
1442 static HRESULT WINAPI domdoc_transformNodeToObject(
1443 IXMLDOMDocument3 *iface,
1444 IXMLDOMNode* stylesheet,
1445 VARIANT outputObject)
1447 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1448 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), stylesheet, outputObject );
1452 static HRESULT WINAPI domdoc_get_doctype(
1453 IXMLDOMDocument3 *iface,
1454 IXMLDOMDocumentType** documentType )
1456 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1457 FIXME("(%p)\n", This);
1462 static HRESULT WINAPI domdoc_get_implementation(
1463 IXMLDOMDocument3 *iface,
1464 IXMLDOMImplementation** impl )
1466 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1468 TRACE("(%p)->(%p)\n", This, impl);
1471 return E_INVALIDARG;
1473 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1478 static HRESULT WINAPI domdoc_get_documentElement(
1479 IXMLDOMDocument3 *iface,
1480 IXMLDOMElement** DOMElement )
1482 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1483 IXMLDOMNode *element_node;
1487 TRACE("(%p)->(%p)\n", This, DOMElement);
1490 return E_INVALIDARG;
1494 root = xmlDocGetRootElement( get_doc(This) );
1498 element_node = create_node( root );
1499 if(!element_node) return S_FALSE;
1501 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1502 IXMLDOMNode_Release(element_node);
1508 static HRESULT WINAPI domdoc_put_documentElement(
1509 IXMLDOMDocument3 *iface,
1510 IXMLDOMElement* DOMElement )
1512 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1513 IXMLDOMNode *elementNode;
1518 TRACE("(%p)->(%p)\n", This, DOMElement);
1520 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1524 xmlNode = get_node_obj( elementNode );
1526 FIXME("elementNode is not our object\n");
1530 if(!xmlNode->node->parent)
1531 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1532 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1534 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1535 IXMLDOMNode_Release( elementNode );
1538 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1544 static HRESULT WINAPI domdoc_createElement(
1545 IXMLDOMDocument3 *iface,
1547 IXMLDOMElement** element )
1549 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1554 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1556 if (!element || !tagname) return E_INVALIDARG;
1558 V_VT(&type) = VT_I1;
1559 V_I1(&type) = NODE_ELEMENT;
1561 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1564 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1565 IXMLDOMNode_Release(node);
1572 static HRESULT WINAPI domdoc_createDocumentFragment(
1573 IXMLDOMDocument3 *iface,
1574 IXMLDOMDocumentFragment** frag )
1576 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1581 TRACE("(%p)->(%p)\n", This, frag);
1583 if (!frag) return E_INVALIDARG;
1587 V_VT(&type) = VT_I1;
1588 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1590 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1593 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1594 IXMLDOMNode_Release(node);
1601 static HRESULT WINAPI domdoc_createTextNode(
1602 IXMLDOMDocument3 *iface,
1604 IXMLDOMText** text )
1606 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1611 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1613 if (!text) return E_INVALIDARG;
1617 V_VT(&type) = VT_I1;
1618 V_I1(&type) = NODE_TEXT;
1620 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1623 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1624 IXMLDOMNode_Release(node);
1625 hr = IXMLDOMText_put_data(*text, data);
1632 static HRESULT WINAPI domdoc_createComment(
1633 IXMLDOMDocument3 *iface,
1635 IXMLDOMComment** comment )
1637 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1642 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1644 if (!comment) return E_INVALIDARG;
1648 V_VT(&type) = VT_I1;
1649 V_I1(&type) = NODE_COMMENT;
1651 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1654 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1655 IXMLDOMNode_Release(node);
1656 hr = IXMLDOMComment_put_data(*comment, data);
1663 static HRESULT WINAPI domdoc_createCDATASection(
1664 IXMLDOMDocument3 *iface,
1666 IXMLDOMCDATASection** cdata )
1668 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1673 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1675 if (!cdata) return E_INVALIDARG;
1679 V_VT(&type) = VT_I1;
1680 V_I1(&type) = NODE_CDATA_SECTION;
1682 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1685 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1686 IXMLDOMNode_Release(node);
1687 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1694 static HRESULT WINAPI domdoc_createProcessingInstruction(
1695 IXMLDOMDocument3 *iface,
1698 IXMLDOMProcessingInstruction** pi )
1700 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1705 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1707 if (!pi) return E_INVALIDARG;
1711 V_VT(&type) = VT_I1;
1712 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1714 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1719 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1720 node_obj = get_node_obj(node);
1721 hr = node_set_content(node_obj, data);
1723 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1724 IXMLDOMNode_Release(node);
1731 static HRESULT WINAPI domdoc_createAttribute(
1732 IXMLDOMDocument3 *iface,
1734 IXMLDOMAttribute** attribute )
1736 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1741 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1743 if (!attribute || !name) return E_INVALIDARG;
1745 V_VT(&type) = VT_I1;
1746 V_I1(&type) = NODE_ATTRIBUTE;
1748 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1751 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1752 IXMLDOMNode_Release(node);
1759 static HRESULT WINAPI domdoc_createEntityReference(
1760 IXMLDOMDocument3 *iface,
1762 IXMLDOMEntityReference** entityref )
1764 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1769 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1771 if (!entityref) return E_INVALIDARG;
1775 V_VT(&type) = VT_I1;
1776 V_I1(&type) = NODE_ENTITY_REFERENCE;
1778 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1781 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1782 IXMLDOMNode_Release(node);
1788 xmlChar* tagName_to_XPath(const BSTR tagName)
1790 xmlChar *query, *tmp;
1791 static const xmlChar mod_pre[] = "*[local-name()='";
1792 static const xmlChar mod_post[] = "']";
1793 static const xmlChar prefix[] = "descendant::";
1794 const WCHAR *tokBegin, *tokEnd;
1797 query = xmlStrdup(prefix);
1800 while (tokBegin && *tokBegin)
1805 query = xmlStrcat(query, BAD_CAST "/");
1809 query = xmlStrcat(query, BAD_CAST "*");
1813 query = xmlStrcat(query, mod_pre);
1815 while (*tokEnd && *tokEnd != '/')
1817 len = WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, NULL, 0, NULL, NULL);
1818 tmp = xmlMalloc(len);
1819 WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, (char*)tmp, len, NULL, NULL);
1820 query = xmlStrncat(query, tmp, len);
1823 query = xmlStrcat(query, mod_post);
1830 static HRESULT WINAPI domdoc_getElementsByTagName(
1831 IXMLDOMDocument3 *iface,
1833 IXMLDOMNodeList** resultList )
1835 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1840 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1842 if (!tagName || !resultList) return E_INVALIDARG;
1844 XPath = This->properties->XPath;
1845 This->properties->XPath = TRUE;
1846 query = tagName_to_XPath(tagName);
1847 hr = queryresult_create((xmlNodePtr)get_doc(This), query, resultList);
1849 This->properties->XPath = XPath;
1854 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1860 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1862 return E_INVALIDARG;
1869 static HRESULT WINAPI domdoc_createNode(
1870 IXMLDOMDocument3 *iface,
1874 IXMLDOMNode** node )
1876 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1877 DOMNodeType node_type;
1879 xmlChar *xml_name, *href;
1882 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1884 if(!node) return E_INVALIDARG;
1886 hr = get_node_type(Type, &node_type);
1887 if(FAILED(hr)) return hr;
1889 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1890 FIXME("nodes with namespaces currently not supported.\n");
1892 TRACE("node_type %d\n", node_type);
1894 /* exit earlier for types that need name */
1898 case NODE_ATTRIBUTE:
1899 case NODE_ENTITY_REFERENCE:
1900 case NODE_PROCESSING_INSTRUCTION:
1901 if (!name || *name == 0) return E_FAIL;
1906 xml_name = xmlChar_from_wchar(name);
1907 /* prevent empty href to be allocated */
1908 href = namespaceURI ? xmlChar_from_wchar(namespaceURI) : NULL;
1914 xmlChar *local, *prefix;
1916 local = xmlSplitQName2(xml_name, &prefix);
1918 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
1920 /* allow to create default namespace xmlns= */
1921 if (local || (href && *href))
1923 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
1924 xmlSetNs(xmlnode, ns);
1932 case NODE_ATTRIBUTE:
1933 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1936 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1938 case NODE_CDATA_SECTION:
1939 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1941 case NODE_ENTITY_REFERENCE:
1942 xmlnode = xmlNewReference(get_doc(This), xml_name);
1944 case NODE_PROCESSING_INSTRUCTION:
1945 #ifdef HAVE_XMLNEWDOCPI
1946 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1948 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1953 xmlnode = xmlNewDocComment(get_doc(This), NULL);
1955 case NODE_DOCUMENT_FRAGMENT:
1956 xmlnode = xmlNewDocFragment(get_doc(This));
1958 /* unsupported types */
1960 case NODE_DOCUMENT_TYPE:
1963 heap_free(xml_name);
1964 return E_INVALIDARG;
1966 FIXME("unhandled node type %d\n", node_type);
1971 *node = create_node(xmlnode);
1972 heap_free(xml_name);
1977 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1978 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1985 static HRESULT WINAPI domdoc_nodeFromID(
1986 IXMLDOMDocument3 *iface,
1988 IXMLDOMNode** node )
1990 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1991 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1995 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
2000 xmldoc = doparse(This, ptr, len, NULL);
2002 xmldoc->_private = create_priv();
2003 return attach_xmldoc(This, xmldoc);
2009 static HRESULT doread( domdoc *This, LPWSTR filename )
2014 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
2019 detach_bsc(This->bsc);
2025 static HRESULT WINAPI domdoc_load(
2026 IXMLDOMDocument3 *iface,
2028 VARIANT_BOOL* isSuccessful )
2030 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2031 LPWSTR filename = NULL;
2032 HRESULT hr = S_FALSE;
2033 IXMLDOMDocument3 *pNewDoc = NULL;
2034 IStream *pStream = NULL;
2037 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
2039 *isSuccessful = VARIANT_FALSE;
2041 assert( &This->node );
2043 switch( V_VT(&xmlSource) )
2046 filename = V_BSTR(&xmlSource);
2049 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
2054 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
2055 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
2056 hr = attach_xmldoc(This, xmldoc);
2059 *isSuccessful = VARIANT_TRUE;
2064 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
2067 IPersistStream *pDocStream;
2068 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
2071 hr = IPersistStream_Load(pDocStream, pStream);
2072 IStream_Release(pStream);
2075 *isSuccessful = VARIANT_TRUE;
2077 TRACE("Using IStream to load Document\n");
2082 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
2087 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
2092 /* ISequentialStream */
2093 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
2097 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
2100 TRACE("filename (%s)\n", debugstr_w(filename));
2104 hr = doread( This, filename );
2107 This->error = E_FAIL;
2110 hr = This->error = S_OK;
2111 *isSuccessful = VARIANT_TRUE;
2115 if(!filename || FAILED(hr)) {
2116 xmldoc = xmlNewDoc(NULL);
2117 xmldoc->_private = create_priv();
2118 hr = attach_xmldoc(This, xmldoc);
2123 TRACE("ret (%d)\n", hr);
2129 static HRESULT WINAPI domdoc_get_readyState(
2130 IXMLDOMDocument3 *iface,
2133 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2134 FIXME("stub! (%p)->(%p)\n", This, value);
2137 return E_INVALIDARG;
2139 *value = READYSTATE_COMPLETE;
2144 static HRESULT WINAPI domdoc_get_parseError(
2145 IXMLDOMDocument3 *iface,
2146 IXMLDOMParseError** errorObj )
2148 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2149 static const WCHAR err[] = {'e','r','r','o','r',0};
2150 BSTR error_string = NULL;
2152 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2155 error_string = SysAllocString(err);
2157 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2158 if(!*errorObj) return E_OUTOFMEMORY;
2163 static HRESULT WINAPI domdoc_get_url(
2164 IXMLDOMDocument3 *iface,
2167 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2168 FIXME("(%p)->(%p)\n", This, urlString);
2173 static HRESULT WINAPI domdoc_get_async(
2174 IXMLDOMDocument3 *iface,
2175 VARIANT_BOOL* isAsync )
2177 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2179 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2180 *isAsync = This->async;
2185 static HRESULT WINAPI domdoc_put_async(
2186 IXMLDOMDocument3 *iface,
2187 VARIANT_BOOL isAsync )
2189 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2191 TRACE("(%p)->(%d)\n", This, isAsync);
2192 This->async = isAsync;
2197 static HRESULT WINAPI domdoc_abort(
2198 IXMLDOMDocument3 *iface )
2200 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2201 FIXME("%p\n", This);
2206 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
2211 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
2212 str = heap_alloc( len );
2215 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
2221 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2222 static HRESULT WINAPI domdoc_loadXML(
2223 IXMLDOMDocument3 *iface,
2225 VARIANT_BOOL* isSuccessful )
2227 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2228 static const xmlChar encoding[] = "UTF-8";
2229 xmlDocPtr xmldoc = NULL;
2230 HRESULT hr = S_FALSE, hr2;
2234 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2236 assert ( &This->node );
2240 *isSuccessful = VARIANT_FALSE;
2242 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
2244 xmldoc = doparse(This, str, len, encoding);
2248 This->error = E_FAIL;
2249 TRACE("failed to parse document\n");
2253 hr = This->error = S_OK;
2254 *isSuccessful = VARIANT_TRUE;
2255 TRACE("parsed document %p\n", xmldoc);
2260 xmldoc = xmlNewDoc(NULL);
2262 xmldoc->_private = create_priv();
2264 hr2 = attach_xmldoc(This, xmldoc);
2271 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2275 if(!WriteFile(ctx, buffer, len, &written, NULL))
2277 WARN("write error\n");
2284 static int XMLCALL domdoc_save_closecallback(void *ctx)
2286 return CloseHandle(ctx) ? 0 : -1;
2289 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2294 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2297 WARN("stream write error: 0x%08x\n", hr);
2304 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2306 IStream_Release((IStream*)ctx);
2310 static HRESULT WINAPI domdoc_save(
2311 IXMLDOMDocument3 *iface,
2312 VARIANT destination )
2314 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2315 xmlSaveCtxtPtr ctx = NULL;
2319 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
2320 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
2322 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
2324 FIXME("Unhandled vt %d\n", V_VT(&destination));
2328 if(V_VT(&destination) == VT_UNKNOWN)
2330 IUnknown *pUnk = V_UNKNOWN(&destination);
2331 IXMLDOMDocument2 *document;
2334 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2337 VARIANT_BOOL success;
2340 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2343 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2347 IXMLDOMDocument3_Release(document);
2351 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2354 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2355 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2359 IStream_Release(stream);
2366 /* save with file path */
2367 HANDLE handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
2368 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2369 if( handle == INVALID_HANDLE_VALUE )
2371 WARN("failed to create file\n");
2375 /* disable top XML declaration */
2376 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2377 handle, NULL, XML_SAVE_NO_DECL);
2380 CloseHandle(handle);
2385 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2386 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2387 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2389 /* will release resources through close callback */
2395 static HRESULT WINAPI domdoc_get_validateOnParse(
2396 IXMLDOMDocument3 *iface,
2397 VARIANT_BOOL* isValidating )
2399 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2400 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2401 *isValidating = This->validating;
2406 static HRESULT WINAPI domdoc_put_validateOnParse(
2407 IXMLDOMDocument3 *iface,
2408 VARIANT_BOOL isValidating )
2410 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2411 TRACE("(%p)->(%d)\n", This, isValidating);
2412 This->validating = isValidating;
2417 static HRESULT WINAPI domdoc_get_resolveExternals(
2418 IXMLDOMDocument3 *iface,
2419 VARIANT_BOOL* isResolving )
2421 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2422 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2423 *isResolving = This->resolving;
2428 static HRESULT WINAPI domdoc_put_resolveExternals(
2429 IXMLDOMDocument3 *iface,
2430 VARIANT_BOOL isResolving )
2432 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2433 TRACE("(%p)->(%d)\n", This, isResolving);
2434 This->resolving = isResolving;
2439 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2440 IXMLDOMDocument3 *iface,
2441 VARIANT_BOOL* isPreserving )
2443 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2444 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->properties->preserving);
2445 *isPreserving = This->properties->preserving;
2450 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2451 IXMLDOMDocument3 *iface,
2452 VARIANT_BOOL isPreserving )
2454 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2455 TRACE("(%p)->(%d)\n", This, isPreserving);
2456 This->properties->preserving = isPreserving;
2461 static HRESULT WINAPI domdoc_put_onReadyStateChange(
2462 IXMLDOMDocument3 *iface,
2463 VARIANT readyStateChangeSink )
2465 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2466 FIXME("%p\n", This);
2471 static HRESULT WINAPI domdoc_put_onDataAvailable(
2472 IXMLDOMDocument3 *iface,
2473 VARIANT onDataAvailableSink )
2475 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2476 FIXME("%p\n", This);
2480 static HRESULT WINAPI domdoc_put_onTransformNode(
2481 IXMLDOMDocument3 *iface,
2482 VARIANT onTransformNodeSink )
2484 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2485 FIXME("%p\n", This);
2489 static HRESULT WINAPI domdoc_get_namespaces(
2490 IXMLDOMDocument3* iface,
2491 IXMLDOMSchemaCollection** schemaCollection )
2493 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2494 FIXME("(%p)->(%p)\n", This, schemaCollection);
2498 static HRESULT WINAPI domdoc_get_schemas(
2499 IXMLDOMDocument3* iface,
2502 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2503 HRESULT hr = S_FALSE;
2504 IXMLDOMSchemaCollection2* cur_schema = This->properties->schemaCache;
2506 TRACE("(%p)->(%p)\n", This, var1);
2508 VariantInit(var1); /* Test shows we don't call VariantClear here */
2509 V_VT(var1) = VT_NULL;
2513 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2515 V_VT(var1) = VT_DISPATCH;
2520 static HRESULT WINAPI domdoc_putref_schemas(
2521 IXMLDOMDocument3* iface,
2524 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2525 HRESULT hr = E_FAIL;
2526 IXMLDOMSchemaCollection2* new_schema = NULL;
2528 FIXME("(%p): semi-stub\n", This);
2532 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2536 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2545 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2550 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->properties->schemaCache, new_schema);
2551 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2557 static inline BOOL is_wellformed(xmlDocPtr doc)
2559 #ifdef HAVE_XMLDOC_PROPERTIES
2560 return doc->properties & XML_DOC_WELLFORMED;
2562 /* Not a full check, but catches the worst violations */
2566 for (child = doc->children; child != NULL; child = child->next)
2568 switch (child->type)
2570 case XML_ELEMENT_NODE:
2575 case XML_CDATA_SECTION_NODE:
2587 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2591 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2595 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2599 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2603 static HRESULT WINAPI domdoc_validateNode(
2604 IXMLDOMDocument3* iface,
2606 IXMLDOMParseError** err)
2608 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2609 LONG state, err_code = 0;
2613 TRACE("(%p)->(%p, %p)\n", This, node, err);
2614 domdoc_get_readyState(iface, &state);
2615 if (state != READYSTATE_COMPLETE)
2618 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2625 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2629 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2632 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2636 if (!is_wellformed(get_doc(This)))
2638 ERR("doc not well-formed");
2640 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2644 /* DTD validation */
2645 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2647 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2648 vctx->error = validate_error;
2649 vctx->warning = validate_warning;
2652 if (!((node == (IXMLDOMNode*)iface)?
2653 xmlValidateDocument(vctx, get_doc(This)) :
2654 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2656 /* TODO: get a real error code here */
2657 TRACE("DTD validation failed\n");
2658 err_code = E_XML_INVALID;
2661 xmlFreeValidCtxt(vctx);
2664 /* Schema validation */
2665 if (hr == S_OK && This->properties->schemaCache != NULL)
2668 hr = SchemaCache_validate_tree(This->properties->schemaCache, get_node_obj(node)->node);
2672 /* TODO: get a real error code here */
2675 TRACE("schema validation succeeded\n");
2679 ERR("schema validation failed\n");
2680 err_code = E_XML_INVALID;
2685 /* not really OK, just didn't find a schema for the ns */
2692 ERR("no DTD or schema found\n");
2693 err_code = E_XML_NODTD;
2698 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2703 static HRESULT WINAPI domdoc_validate(
2704 IXMLDOMDocument3* iface,
2705 IXMLDOMParseError** err)
2707 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2708 TRACE("(%p)->(%p)\n", This, err);
2709 return domdoc_validateNode(iface, (IXMLDOMNode*)iface, err);
2712 static HRESULT WINAPI domdoc_setProperty(
2713 IXMLDOMDocument3* iface,
2717 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2719 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2721 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2727 V_VT(&varStr) = VT_EMPTY;
2728 if (V_VT(&var) != VT_BSTR)
2730 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2732 bstr = V_BSTR(&varStr);
2735 bstr = V_BSTR(&var);
2738 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2739 This->properties->XPath = TRUE;
2740 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2741 This->properties->XPath = FALSE;
2745 VariantClear(&varStr);
2748 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2753 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2754 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2755 xmlXPathContextPtr ctx;
2756 struct list *pNsList;
2757 select_ns_entry* pNsEntry = NULL;
2759 V_VT(&varStr) = VT_EMPTY;
2760 if (V_VT(&var) != VT_BSTR)
2762 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2764 bstr = V_BSTR(&varStr);
2767 bstr = V_BSTR(&var);
2771 pNsList = &(This->properties->selectNsList);
2772 clear_selectNsList(pNsList);
2774 nsStr = xmlChar_from_wchar(bstr);
2777 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2779 This->properties->selectNsStr = nsStr;
2780 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2783 ctx = xmlXPathNewContext(This->node.node->doc);
2786 for (; *pTokBegin; pTokBegin = pTokEnd)
2788 if (pNsEntry != NULL)
2789 memset(pNsEntry, 0, sizeof(select_ns_entry));
2791 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2793 while (*pTokBegin == ' ')
2795 pTokEnd = pTokBegin;
2796 while (*pTokEnd != ' ' && *pTokEnd != 0)
2799 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2802 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2803 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2808 if (*pTokBegin == '=')
2810 /*valid for XSLPattern?*/
2811 FIXME("Setting default xmlns not supported - skipping.\n");
2812 pTokBegin = pTokEnd;
2815 else if (*pTokBegin == ':')
2817 pNsEntry->prefix = ++pTokBegin;
2818 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2821 if (pTokInner == pTokEnd)
2824 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2825 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2829 pNsEntry->prefix_end = *pTokInner;
2833 if (pTokEnd-pTokInner > 1 &&
2834 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2835 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2837 pNsEntry->href = ++pTokInner;
2838 pNsEntry->href_end = *(pTokEnd-1);
2840 list_add_tail(pNsList, &pNsEntry->entry);
2841 /*let libxml figure out if they're valid from here ;)*/
2842 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2851 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2852 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2853 list_add_tail(pNsList, &pNsEntry->entry);
2866 heap_free(pNsEntry);
2867 xmlXPathFreeContext(ctx);
2870 VariantClear(&varStr);
2873 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2874 lstrcmpiW(p, PropertyNewParserW) == 0)
2877 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2881 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2885 static HRESULT WINAPI domdoc_getProperty(
2886 IXMLDOMDocument3* iface,
2890 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2892 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2895 return E_INVALIDARG;
2897 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2899 V_VT(var) = VT_BSTR;
2900 V_BSTR(var) = This->properties->XPath ?
2901 SysAllocString(PropValueXPathW) :
2902 SysAllocString(PropValueXSLPatternW);
2903 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2905 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2908 BSTR rebuiltStr, cur;
2909 const xmlChar *nsStr;
2910 struct list *pNsList;
2911 select_ns_entry* pNsEntry;
2913 V_VT(var) = VT_BSTR;
2914 nsStr = This->properties->selectNsStr;
2915 pNsList = &This->properties->selectNsList;
2916 lenA = This->properties->selectNsStr_len;
2917 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
2918 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
2919 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
2921 /* this is fine because all of the chars that end tokens are ASCII*/
2922 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
2924 while (*cur != 0) ++cur;
2925 if (pNsEntry->prefix_end)
2927 *cur = pNsEntry->prefix_end;
2928 while (*cur != 0) ++cur;
2931 if (pNsEntry->href_end)
2933 *cur = pNsEntry->href_end;
2936 V_BSTR(var) = SysAllocString(rebuiltStr);
2937 heap_free(rebuiltStr);
2941 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2945 static HRESULT WINAPI domdoc_importNode(
2946 IXMLDOMDocument3* iface,
2949 IXMLDOMNode** clone)
2951 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2952 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
2956 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
2958 domdoc_QueryInterface,
2961 domdoc_GetTypeInfoCount,
2963 domdoc_GetIDsOfNames,
2965 domdoc_get_nodeName,
2966 domdoc_get_nodeValue,
2967 domdoc_put_nodeValue,
2968 domdoc_get_nodeType,
2969 domdoc_get_parentNode,
2970 domdoc_get_childNodes,
2971 domdoc_get_firstChild,
2972 domdoc_get_lastChild,
2973 domdoc_get_previousSibling,
2974 domdoc_get_nextSibling,
2975 domdoc_get_attributes,
2976 domdoc_insertBefore,
2977 domdoc_replaceChild,
2980 domdoc_hasChildNodes,
2981 domdoc_get_ownerDocument,
2983 domdoc_get_nodeTypeString,
2986 domdoc_get_specified,
2987 domdoc_get_definition,
2988 domdoc_get_nodeTypedValue,
2989 domdoc_put_nodeTypedValue,
2990 domdoc_get_dataType,
2991 domdoc_put_dataType,
2993 domdoc_transformNode,
2995 domdoc_selectSingleNode,
2997 domdoc_get_namespaceURI,
2999 domdoc_get_baseName,
3000 domdoc_transformNodeToObject,
3002 domdoc_get_implementation,
3003 domdoc_get_documentElement,
3004 domdoc_put_documentElement,
3005 domdoc_createElement,
3006 domdoc_createDocumentFragment,
3007 domdoc_createTextNode,
3008 domdoc_createComment,
3009 domdoc_createCDATASection,
3010 domdoc_createProcessingInstruction,
3011 domdoc_createAttribute,
3012 domdoc_createEntityReference,
3013 domdoc_getElementsByTagName,
3017 domdoc_get_readyState,
3018 domdoc_get_parseError,
3025 domdoc_get_validateOnParse,
3026 domdoc_put_validateOnParse,
3027 domdoc_get_resolveExternals,
3028 domdoc_put_resolveExternals,
3029 domdoc_get_preserveWhiteSpace,
3030 domdoc_put_preserveWhiteSpace,
3031 domdoc_put_onReadyStateChange,
3032 domdoc_put_onDataAvailable,
3033 domdoc_put_onTransformNode,
3034 domdoc_get_namespaces,
3036 domdoc_putref_schemas,
3040 domdoc_validateNode,
3044 /* IConnectionPointContainer */
3045 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
3046 REFIID riid, void **ppv)
3048 domdoc *This = impl_from_IConnectionPointContainer(iface);
3049 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)This, riid, ppv);
3052 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
3054 domdoc *This = impl_from_IConnectionPointContainer(iface);
3055 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)This);
3058 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
3060 domdoc *This = impl_from_IConnectionPointContainer(iface);
3061 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)This);
3064 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
3065 IEnumConnectionPoints **ppEnum)
3067 domdoc *This = impl_from_IConnectionPointContainer(iface);
3068 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3072 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
3073 REFIID riid, IConnectionPoint **cp)
3075 domdoc *This = impl_from_IConnectionPointContainer(iface);
3076 ConnectionPoint *iter;
3078 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
3082 for(iter = This->cp_list; iter; iter = iter->next)
3084 if (IsEqualGUID(iter->iid, riid))
3085 *cp = (IConnectionPoint*)&iter->lpVtblConnectionPoint;
3090 IConnectionPoint_AddRef(*cp);
3094 FIXME("unsupported riid %s\n", debugstr_guid(riid));
3095 return CONNECT_E_NOCONNECTION;
3099 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
3101 ConnectionPointContainer_QueryInterface,
3102 ConnectionPointContainer_AddRef,
3103 ConnectionPointContainer_Release,
3104 ConnectionPointContainer_EnumConnectionPoints,
3105 ConnectionPointContainer_FindConnectionPoint
3108 /* IConnectionPoint */
3109 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
3110 REFIID riid, void **ppv)
3112 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3114 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3118 if (IsEqualGUID(&IID_IUnknown, riid) ||
3119 IsEqualGUID(&IID_IConnectionPoint, riid))
3126 IConnectionPoint_AddRef(iface);
3130 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3131 return E_NOINTERFACE;
3134 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3136 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3137 return IConnectionPointContainer_AddRef(This->container);
3140 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3142 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3143 return IConnectionPointContainer_Release(This->container);
3146 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3148 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3150 TRACE("(%p)->(%p)\n", This, iid);
3152 if (!iid) return E_POINTER;
3158 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3159 IConnectionPointContainer **container)
3161 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3163 TRACE("(%p)->(%p)\n", This, container);
3165 if (!container) return E_POINTER;
3167 *container = This->container;
3168 IConnectionPointContainer_AddRef(*container);
3172 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
3175 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3176 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
3180 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3182 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3184 TRACE("(%p)->(%d)\n", This, cookie);
3186 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3187 return CONNECT_E_NOCONNECTION;
3189 IUnknown_Release(This->sinks[cookie-1].unk);
3190 This->sinks[cookie-1].unk = NULL;
3195 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3196 IEnumConnections **ppEnum)
3198 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3199 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3203 static const IConnectionPointVtbl ConnectionPointVtbl =
3205 ConnectionPoint_QueryInterface,
3206 ConnectionPoint_AddRef,
3207 ConnectionPoint_Release,
3208 ConnectionPoint_GetConnectionInterface,
3209 ConnectionPoint_GetConnectionPointContainer,
3210 ConnectionPoint_Advise,
3211 ConnectionPoint_Unadvise,
3212 ConnectionPoint_EnumConnections
3215 void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3217 cp->lpVtblConnectionPoint = &ConnectionPointVtbl;
3223 cp->next = doc->cp_list;
3226 cp->container = (IConnectionPointContainer*)&doc->lpVtblConnectionPointContainer;
3229 /* domdoc implementation of IObjectWithSite */
3230 static HRESULT WINAPI
3231 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3233 domdoc *This = impl_from_IObjectWithSite(iface);
3234 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppvObject );
3237 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3239 domdoc *This = impl_from_IObjectWithSite(iface);
3240 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3243 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3245 domdoc *This = impl_from_IObjectWithSite(iface);
3246 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3249 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3251 domdoc *This = impl_from_IObjectWithSite(iface);
3253 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3258 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3261 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3263 domdoc *This = impl_from_IObjectWithSite(iface);
3265 TRACE("(%p)->(%p)\n", iface, punk);
3271 IUnknown_Release( This->site );
3278 IUnknown_AddRef( punk );
3281 IUnknown_Release( This->site );
3288 static const IObjectWithSiteVtbl domdocObjectSite =
3290 domdoc_ObjectWithSite_QueryInterface,
3291 domdoc_ObjectWithSite_AddRef,
3292 domdoc_ObjectWithSite_Release,
3293 domdoc_ObjectWithSite_SetSite,
3294 domdoc_ObjectWithSite_GetSite
3297 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3299 domdoc *This = impl_from_IObjectSafety(iface);
3300 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppv );
3303 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3305 domdoc *This = impl_from_IObjectSafety(iface);
3306 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3309 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3311 domdoc *This = impl_from_IObjectSafety(iface);
3312 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3315 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3317 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3318 DWORD *supported, DWORD *enabled)
3320 domdoc *This = impl_from_IObjectSafety(iface);
3322 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3324 if(!supported || !enabled) return E_POINTER;
3326 *supported = SAFETY_SUPPORTED_OPTIONS;
3327 *enabled = This->safeopt;
3332 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3333 DWORD mask, DWORD enabled)
3335 domdoc *This = impl_from_IObjectSafety(iface);
3336 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3338 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3341 This->safeopt = enabled & mask & SAFETY_SUPPORTED_OPTIONS;
3345 #undef SAFETY_SUPPORTED_OPTIONS
3347 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3348 domdoc_Safety_QueryInterface,
3349 domdoc_Safety_AddRef,
3350 domdoc_Safety_Release,
3351 domdoc_Safety_GetInterfaceSafetyOptions,
3352 domdoc_Safety_SetInterfaceSafetyOptions
3355 static const tid_t domdoc_iface_tids[] = {
3357 IXMLDOMDocument_tid,
3358 IXMLDOMDocument2_tid,
3361 static dispex_static_data_t domdoc_dispex = {
3363 IXMLDOMDocument2_tid,
3368 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3372 doc = heap_alloc( sizeof (*doc) );
3374 return E_OUTOFMEMORY;
3376 doc->lpVtbl = &domdoc_vtbl;
3377 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
3378 doc->lpvtblIObjectWithSite = &domdocObjectSite;
3379 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
3380 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
3381 doc->lpVtblConnectionPointContainer = &ConnectionPointContainerVtbl;
3383 doc->async = VARIANT_TRUE;
3384 doc->validating = 0;
3386 doc->properties = properties_from_xmlDocPtr(xmldoc);
3392 doc->cp_list = NULL;
3394 /* events connection points */
3395 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3396 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3397 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3399 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->lpVtbl, &domdoc_dispex);
3401 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
3403 TRACE("returning iface %p\n", *document);
3407 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3412 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
3414 xmldoc = xmlNewDoc(NULL);
3416 return E_OUTOFMEMORY;
3418 xmldoc->_private = create_priv();
3419 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
3421 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3424 free_properties(properties_from_xmlDocPtr(xmldoc));
3425 heap_free(xmldoc->_private);
3433 IUnknown* create_domdoc( xmlNodePtr document )
3438 TRACE("(%p)\n", document);
3440 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3449 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3451 MESSAGE("This program tried to use a DOMDocument object, but\n"
3452 "libxml2 support was not present at compile time.\n");