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>
52 #include "wine/debug.h"
53 #include "wine/list.h"
55 #include "msxml_private.h"
57 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
61 /* not defined in older versions */
62 #define XML_SAVE_FORMAT 1
63 #define XML_SAVE_NO_DECL 2
64 #define XML_SAVE_NO_EMPTY 4
65 #define XML_SAVE_NO_XHTML 8
66 #define XML_SAVE_XHTML 16
67 #define XML_SAVE_AS_XML 32
68 #define XML_SAVE_AS_HTML 64
70 static const WCHAR PropertySelectionLanguageW[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
71 static const WCHAR PropertySelectionNamespacesW[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
72 static const WCHAR PropertyProhibitDTDW[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
73 static const WCHAR PropertyNewParserW[] = {'N','e','w','P','a','r','s','e','r',0};
74 static const WCHAR PropValueXPathW[] = {'X','P','a','t','h',0};
75 static const WCHAR PropValueXSLPatternW[] = {'X','S','L','P','a','t','t','e','r','n',0};
76 static const WCHAR PropertyResolveExternalsW[] = {'R','e','s','o','l','v','e','E','x','t','e','r','n','a','l','s',0};
78 /* Anything that passes the test_get_ownerDocument()
79 * tests can go here (data shared between all instances).
80 * We need to preserve this when reloading a document,
81 * and also need access to it from the libxml backend. */
82 typedef struct _domdoc_properties {
83 MSXML_VERSION version;
84 VARIANT_BOOL preserving;
85 IXMLDOMSchemaCollection2* schemaCache;
86 struct list selectNsList;
87 xmlChar const* selectNsStr;
92 typedef struct ConnectionPoint ConnectionPoint;
93 typedef struct domdoc domdoc;
95 struct ConnectionPoint
97 IConnectionPoint IConnectionPoint_iface;
100 ConnectionPoint *next;
101 IConnectionPointContainer *container;
108 IPropertyNotifySink *propnotif;
114 EVENTID_READYSTATECHANGE = 0,
115 EVENTID_DATAAVAILABLE,
116 EVENTID_TRANSFORMNODE,
123 IXMLDOMDocument3 IXMLDOMDocument3_iface;
124 IPersistStreamInit IPersistStreamInit_iface;
125 IObjectWithSite IObjectWithSite_iface;
126 IObjectSafety IObjectSafety_iface;
127 ISupportErrorInfo ISupportErrorInfo_iface;
128 IConnectionPointContainer IConnectionPointContainer_iface;
131 VARIANT_BOOL validating;
132 VARIANT_BOOL resolving;
133 domdoc_properties* properties;
146 /* connection list */
147 ConnectionPoint *cp_list;
148 ConnectionPoint cp_domdocevents;
149 ConnectionPoint cp_propnotif;
150 ConnectionPoint cp_dispatch;
153 IDispatch *events[EVENTID_LAST];
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(const GUID *clsid)
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 if (IsEqualCLSID(clsid, &CLSID_DOMDocument30))
303 properties->version = MSXML3;
304 properties->XPath = FALSE;
306 else if (IsEqualCLSID(clsid, &CLSID_DOMDocument40))
308 properties->version = MSXML4;
309 properties->XPath = TRUE;
311 else if (IsEqualCLSID(clsid, &CLSID_DOMDocument60))
313 properties->version = MSXML6;
314 properties->XPath = TRUE;
318 properties->version = MSXML_DEFAULT;
319 properties->XPath = FALSE;
325 static domdoc_properties* copy_properties(domdoc_properties const* properties)
327 domdoc_properties* pcopy = heap_alloc(sizeof(domdoc_properties));
328 select_ns_entry const* ns = NULL;
329 select_ns_entry* new_ns = NULL;
330 int len = (properties->selectNsStr_len+1)*sizeof(xmlChar);
335 pcopy->version = properties->version;
336 pcopy->preserving = properties->preserving;
337 pcopy->schemaCache = properties->schemaCache;
338 if (pcopy->schemaCache)
339 IXMLDOMSchemaCollection2_AddRef(pcopy->schemaCache);
340 pcopy->XPath = properties->XPath;
341 pcopy->selectNsStr_len = properties->selectNsStr_len;
342 list_init( &pcopy->selectNsList );
343 pcopy->selectNsStr = heap_alloc(len);
344 memcpy((xmlChar*)pcopy->selectNsStr, properties->selectNsStr, len);
345 offset = pcopy->selectNsStr - properties->selectNsStr;
347 LIST_FOR_EACH_ENTRY( ns, (&properties->selectNsList), select_ns_entry, entry )
349 new_ns = heap_alloc(sizeof(select_ns_entry));
350 memcpy(new_ns, ns, sizeof(select_ns_entry));
351 new_ns->href += offset;
352 new_ns->prefix += offset;
353 list_add_tail(&pcopy->selectNsList, &new_ns->entry);
361 static void free_properties(domdoc_properties* properties)
365 if (properties->schemaCache)
366 IXMLDOMSchemaCollection2_Release(properties->schemaCache);
367 clear_selectNsList(&properties->selectNsList);
368 heap_free((xmlChar*)properties->selectNsStr);
369 heap_free(properties);
373 /* links a "<?xml" node as a first child */
374 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
377 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
380 /* unlinks a first "<?xml" child if it was created */
381 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
387 if (doc->standalone != -1)
389 node = doc->children;
390 xmlUnlinkNode( node );
398 BOOL is_preserving_whitespace(xmlNodePtr node)
400 domdoc_properties* properties = NULL;
401 /* during parsing the xmlDoc._private stuff is not there */
402 if (priv_from_xmlDocPtr(node->doc))
403 properties = properties_from_xmlDocPtr(node->doc);
404 return ((properties && properties->preserving == VARIANT_TRUE) ||
405 xmlNodeGetSpacePreserve(node) == 1);
408 static inline BOOL strn_isspace(xmlChar const* str, int len)
410 for (; str && len > 0 && *str; ++str, --len)
417 static void sax_characters(void *ctx, const xmlChar *ch, int len)
419 xmlParserCtxtPtr ctxt;
422 ctxt = (xmlParserCtxtPtr) ctx;
423 This = (const domdoc*) ctxt->_private;
427 /* during domdoc_loadXML() the xmlDocPtr->_private data is not available */
428 if (!This->properties->preserving &&
429 !is_preserving_whitespace(ctxt->node) &&
430 strn_isspace(ch, len))
434 xmlSAX2Characters(ctxt, ch, len);
437 static void LIBXML2_LOG_CALLBACK sax_error(void* ctx, char const* msg, ...)
441 LIBXML2_CALLBACK_ERR(doparse, msg, ap);
445 static void LIBXML2_LOG_CALLBACK sax_warning(void* ctx, char const* msg, ...)
449 LIBXML2_CALLBACK_WARN(doparse, msg, ap);
453 static void sax_serror(void* ctx, xmlErrorPtr err)
455 LIBXML2_CALLBACK_SERROR(doparse, err);
458 static xmlDocPtr doparse(domdoc* This, char const* ptr, int len, xmlCharEncoding encoding)
460 xmlDocPtr doc = NULL;
461 xmlParserCtxtPtr pctx;
462 static xmlSAXHandler sax_handler = {
463 xmlSAX2InternalSubset, /* internalSubset */
464 xmlSAX2IsStandalone, /* isStandalone */
465 xmlSAX2HasInternalSubset, /* hasInternalSubset */
466 xmlSAX2HasExternalSubset, /* hasExternalSubset */
467 xmlSAX2ResolveEntity, /* resolveEntity */
468 xmlSAX2GetEntity, /* getEntity */
469 xmlSAX2EntityDecl, /* entityDecl */
470 xmlSAX2NotationDecl, /* notationDecl */
471 xmlSAX2AttributeDecl, /* attributeDecl */
472 xmlSAX2ElementDecl, /* elementDecl */
473 xmlSAX2UnparsedEntityDecl, /* unparsedEntityDecl */
474 xmlSAX2SetDocumentLocator, /* setDocumentLocator */
475 xmlSAX2StartDocument, /* startDocument */
476 xmlSAX2EndDocument, /* endDocument */
477 xmlSAX2StartElement, /* startElement */
478 xmlSAX2EndElement, /* endElement */
479 xmlSAX2Reference, /* reference */
480 sax_characters, /* characters */
481 sax_characters, /* ignorableWhitespace */
482 xmlSAX2ProcessingInstruction, /* processingInstruction */
483 xmlSAX2Comment, /* comment */
484 sax_warning, /* warning */
485 sax_error, /* error */
486 sax_error, /* fatalError */
487 xmlSAX2GetParameterEntity, /* getParameterEntity */
488 xmlSAX2CDataBlock, /* cdataBlock */
489 xmlSAX2ExternalSubset, /* externalSubset */
492 xmlSAX2StartElementNs, /* startElementNs */
493 xmlSAX2EndElementNs, /* endElementNs */
494 sax_serror /* serror */
498 pctx = xmlCreateMemoryParserCtxt(ptr, len);
501 ERR("Failed to create parser context\n");
505 if (pctx->sax) xmlFree(pctx->sax);
506 pctx->sax = &sax_handler;
507 pctx->_private = This;
510 if (encoding != XML_CHAR_ENCODING_NONE)
511 xmlSwitchEncoding(pctx, encoding);
513 xmlParseDocument(pctx);
515 if (pctx->wellFormed)
521 xmlFreeDoc(pctx->myDoc);
525 xmlFreeParserCtxt(pctx);
527 /* TODO: put this in one of the SAX callbacks */
528 /* create first child as a <?xml...?> */
529 if (doc && doc->standalone != -1)
533 xmlChar *xmlbuff = (xmlChar*)buff;
535 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
537 /* version attribute can't be omitted */
538 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
539 xmlNodeAddContent( node, xmlbuff );
543 sprintf(buff, " encoding=\"%s\"", doc->encoding);
544 xmlNodeAddContent( node, xmlbuff );
547 if (doc->standalone != -2)
549 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
550 xmlNodeAddContent( node, xmlbuff );
553 xmldoc_link_xmldecl( doc, node );
559 void xmldoc_init(xmlDocPtr doc, const GUID *clsid)
561 doc->_private = create_priv();
562 priv_from_xmlDocPtr(doc)->properties = create_properties(clsid);
565 LONG xmldoc_add_ref(xmlDocPtr doc)
567 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
568 TRACE("(%p)->(%d)\n", doc, ref);
572 LONG xmldoc_release(xmlDocPtr doc)
574 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
575 LONG ref = InterlockedDecrement(&priv->refs);
576 TRACE("(%p)->(%d)\n", doc, ref);
579 orphan_entry *orphan, *orphan2;
580 TRACE("freeing docptr %p\n", doc);
582 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
584 xmlFreeNode( orphan->node );
587 free_properties(priv->properties);
588 heap_free(doc->_private);
596 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
598 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
601 entry = heap_alloc( sizeof (*entry) );
603 return E_OUTOFMEMORY;
606 list_add_head( &priv->orphans, &entry->entry );
610 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
612 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
613 orphan_entry *entry, *entry2;
615 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
617 if( entry->node == node )
619 list_remove( &entry->entry );
628 static inline xmlDocPtr get_doc( domdoc *This )
630 return (xmlDocPtr)This->node.node;
633 static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
637 priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
638 if (xmldoc_release(get_doc(This)) != 0)
639 priv_from_xmlDocPtr(get_doc(This))->properties =
640 copy_properties(This->properties);
643 This->node.node = (xmlNodePtr) xml;
647 xmldoc_add_ref(get_doc(This));
648 priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
654 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
656 return CONTAINING_RECORD(iface, domdoc, IXMLDOMDocument3_iface);
659 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
661 return CONTAINING_RECORD(iface, domdoc, IPersistStreamInit_iface);
664 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
666 return CONTAINING_RECORD(iface, domdoc, IObjectWithSite_iface);
669 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
671 return CONTAINING_RECORD(iface, domdoc, IObjectSafety_iface);
674 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
676 return CONTAINING_RECORD(iface, domdoc, ISupportErrorInfo_iface);
679 static inline domdoc *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
681 return CONTAINING_RECORD(iface, domdoc, IConnectionPointContainer_iface);
684 /************************************************************************
685 * domdoc implementation of IPersistStream.
687 static HRESULT WINAPI domdoc_IPersistStreamInit_QueryInterface(
688 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
690 domdoc* This = impl_from_IPersistStreamInit(iface);
691 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppvObj);
694 static ULONG WINAPI domdoc_IPersistStreamInit_AddRef(
695 IPersistStreamInit *iface)
697 domdoc* This = impl_from_IPersistStreamInit(iface);
698 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
701 static ULONG WINAPI domdoc_IPersistStreamInit_Release(
702 IPersistStreamInit *iface)
704 domdoc* This = impl_from_IPersistStreamInit(iface);
705 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
708 static HRESULT WINAPI domdoc_IPersistStreamInit_GetClassID(
709 IPersistStreamInit *iface, CLSID *classid)
711 domdoc* This = impl_from_IPersistStreamInit(iface);
712 TRACE("(%p)->(%p)\n", This, classid);
717 *classid = *DOMDocument_version(This->properties->version);
722 static HRESULT WINAPI domdoc_IPersistStreamInit_IsDirty(
723 IPersistStreamInit *iface)
725 domdoc *This = impl_from_IPersistStreamInit(iface);
726 FIXME("(%p): stub!\n", This);
730 static HRESULT WINAPI domdoc_IPersistStreamInit_Load(
731 IPersistStreamInit *iface, LPSTREAM pStm)
733 domdoc *This = impl_from_IPersistStreamInit(iface);
736 DWORD read, written, len;
739 xmlDocPtr xmldoc = NULL;
741 TRACE("(%p)->(%p)\n", This, pStm);
746 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
752 IStream_Read(pStm, buf, sizeof(buf), &read);
753 hr = IStream_Write(This->stream, buf, read, &written);
754 } while(SUCCEEDED(hr) && written != 0 && read != 0);
758 ERR("Failed to copy stream\n");
762 hr = GetHGlobalFromStream(This->stream, &hglobal);
766 len = GlobalSize(hglobal);
767 ptr = GlobalLock(hglobal);
769 xmldoc = doparse(This, ptr, len, XML_CHAR_ENCODING_NONE);
770 GlobalUnlock(hglobal);
774 ERR("Failed to parse xml\n");
778 xmldoc->_private = create_priv();
780 return attach_xmldoc(This, xmldoc);
783 static HRESULT WINAPI domdoc_IPersistStreamInit_Save(
784 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
786 domdoc *This = impl_from_IPersistStreamInit(iface);
790 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
792 hr = IXMLDOMDocument3_get_xml(&This->IXMLDOMDocument3_iface, &xmlString);
795 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
797 hr = IStream_Write( stream, xmlString, len, NULL );
798 SysFreeString(xmlString);
801 TRACE("ret 0x%08x\n", hr);
806 static HRESULT WINAPI domdoc_IPersistStreamInit_GetSizeMax(
807 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
809 domdoc *This = impl_from_IPersistStreamInit(iface);
810 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
814 static HRESULT WINAPI domdoc_IPersistStreamInit_InitNew(
815 IPersistStreamInit *iface)
817 domdoc *This = impl_from_IPersistStreamInit(iface);
818 TRACE("(%p)\n", This);
822 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
824 domdoc_IPersistStreamInit_QueryInterface,
825 domdoc_IPersistStreamInit_AddRef,
826 domdoc_IPersistStreamInit_Release,
827 domdoc_IPersistStreamInit_GetClassID,
828 domdoc_IPersistStreamInit_IsDirty,
829 domdoc_IPersistStreamInit_Load,
830 domdoc_IPersistStreamInit_Save,
831 domdoc_IPersistStreamInit_GetSizeMax,
832 domdoc_IPersistStreamInit_InitNew
835 /* ISupportErrorInfo interface */
836 static HRESULT WINAPI support_error_QueryInterface(
837 ISupportErrorInfo *iface,
838 REFIID riid, void** ppvObj )
840 domdoc *This = impl_from_ISupportErrorInfo(iface);
841 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppvObj);
844 static ULONG WINAPI support_error_AddRef(
845 ISupportErrorInfo *iface )
847 domdoc *This = impl_from_ISupportErrorInfo(iface);
848 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
851 static ULONG WINAPI support_error_Release(
852 ISupportErrorInfo *iface )
854 domdoc *This = impl_from_ISupportErrorInfo(iface);
855 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
858 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
859 ISupportErrorInfo *iface,
862 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
866 static const struct ISupportErrorInfoVtbl support_error_vtbl =
868 support_error_QueryInterface,
869 support_error_AddRef,
870 support_error_Release,
871 support_error_InterfaceSupportsErrorInfo
874 /* IXMLDOMDocument2 interface */
875 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
877 domdoc *This = impl_from_IXMLDOMDocument3( iface );
879 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
883 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
884 IsEqualGUID( riid, &IID_IDispatch ) ||
885 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
886 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
887 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
888 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
892 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
893 IsEqualGUID(&IID_IPersistStreamInit, riid))
895 *ppvObject = &This->IPersistStreamInit_iface;
897 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
899 *ppvObject = &This->IObjectWithSite_iface;
901 else if (IsEqualGUID(&IID_IObjectSafety, riid))
903 *ppvObject = &This->IObjectSafety_iface;
905 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
907 *ppvObject = &This->ISupportErrorInfo_iface;
909 else if(node_query_interface(&This->node, riid, ppvObject))
911 return *ppvObject ? S_OK : E_NOINTERFACE;
913 else if (IsEqualGUID( riid, &IID_IConnectionPointContainer ))
915 *ppvObject = &This->IConnectionPointContainer_iface;
919 TRACE("interface %s not implemented\n", debugstr_guid(riid));
920 return E_NOINTERFACE;
923 IUnknown_AddRef((IUnknown*)*ppvObject);
929 static ULONG WINAPI domdoc_AddRef(
930 IXMLDOMDocument3 *iface )
932 domdoc *This = impl_from_IXMLDOMDocument3( iface );
933 ULONG ref = InterlockedIncrement( &This->ref );
934 TRACE("(%p)->(%d)\n", This, ref );
939 static ULONG WINAPI domdoc_Release(
940 IXMLDOMDocument3 *iface )
942 domdoc *This = impl_from_IXMLDOMDocument3( iface );
943 LONG ref = InterlockedDecrement( &This->ref );
945 TRACE("(%p)->(%d)\n", This, ref );
952 detach_bsc(This->bsc);
955 IUnknown_Release( This->site );
956 destroy_xmlnode(&This->node);
958 IStream_Release(This->stream);
960 for (eid = 0; eid < EVENTID_LAST; eid++)
961 if (This->events[eid]) IDispatch_Release(This->events[eid]);
969 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
971 domdoc *This = impl_from_IXMLDOMDocument3( iface );
973 TRACE("(%p)->(%p)\n", This, pctinfo);
980 static HRESULT WINAPI domdoc_GetTypeInfo(
981 IXMLDOMDocument3 *iface,
982 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
984 domdoc *This = impl_from_IXMLDOMDocument3( iface );
987 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
989 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
994 static HRESULT WINAPI domdoc_GetIDsOfNames(
995 IXMLDOMDocument3 *iface,
1002 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1003 ITypeInfo *typeinfo;
1006 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1009 if(!rgszNames || cNames == 0 || !rgDispId)
1010 return E_INVALIDARG;
1012 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
1015 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1016 ITypeInfo_Release(typeinfo);
1023 static HRESULT WINAPI domdoc_Invoke(
1024 IXMLDOMDocument3 *iface,
1025 DISPID dispIdMember,
1029 DISPPARAMS* pDispParams,
1030 VARIANT* pVarResult,
1031 EXCEPINFO* pExcepInfo,
1034 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1035 ITypeInfo *typeinfo;
1038 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1039 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1041 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
1044 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMDocument3_iface, dispIdMember, wFlags,
1045 pDispParams, pVarResult, pExcepInfo, puArgErr);
1046 ITypeInfo_Release(typeinfo);
1053 static HRESULT WINAPI domdoc_get_nodeName(
1054 IXMLDOMDocument3 *iface,
1057 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1059 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
1061 TRACE("(%p)->(%p)\n", This, name);
1063 return return_bstr(documentW, name);
1067 static HRESULT WINAPI domdoc_get_nodeValue(
1068 IXMLDOMDocument3 *iface,
1071 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1073 TRACE("(%p)->(%p)\n", This, value);
1076 return E_INVALIDARG;
1078 V_VT(value) = VT_NULL;
1079 V_BSTR(value) = NULL; /* tests show that we should do this */
1084 static HRESULT WINAPI domdoc_put_nodeValue(
1085 IXMLDOMDocument3 *iface,
1088 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1089 TRACE("(%p)->(v%d)\n", This, V_VT(&value));
1094 static HRESULT WINAPI domdoc_get_nodeType(
1095 IXMLDOMDocument3 *iface,
1098 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1100 TRACE("(%p)->(%p)\n", This, type);
1102 *type = NODE_DOCUMENT;
1107 static HRESULT WINAPI domdoc_get_parentNode(
1108 IXMLDOMDocument3 *iface,
1109 IXMLDOMNode** parent )
1111 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1113 TRACE("(%p)->(%p)\n", This, parent);
1115 return node_get_parent(&This->node, parent);
1119 static HRESULT WINAPI domdoc_get_childNodes(
1120 IXMLDOMDocument3 *iface,
1121 IXMLDOMNodeList** childList )
1123 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1125 TRACE("(%p)->(%p)\n", This, childList);
1127 return node_get_child_nodes(&This->node, childList);
1131 static HRESULT WINAPI domdoc_get_firstChild(
1132 IXMLDOMDocument3 *iface,
1133 IXMLDOMNode** firstChild )
1135 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1137 TRACE("(%p)->(%p)\n", This, firstChild);
1139 return node_get_first_child(&This->node, firstChild);
1143 static HRESULT WINAPI domdoc_get_lastChild(
1144 IXMLDOMDocument3 *iface,
1145 IXMLDOMNode** lastChild )
1147 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1149 TRACE("(%p)->(%p)\n", This, lastChild);
1151 return node_get_last_child(&This->node, lastChild);
1155 static HRESULT WINAPI domdoc_get_previousSibling(
1156 IXMLDOMDocument3 *iface,
1157 IXMLDOMNode** previousSibling )
1159 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1161 TRACE("(%p)->(%p)\n", This, previousSibling);
1163 return return_null_node(previousSibling);
1167 static HRESULT WINAPI domdoc_get_nextSibling(
1168 IXMLDOMDocument3 *iface,
1169 IXMLDOMNode** nextSibling )
1171 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1173 TRACE("(%p)->(%p)\n", This, nextSibling);
1175 return return_null_node(nextSibling);
1179 static HRESULT WINAPI domdoc_get_attributes(
1180 IXMLDOMDocument3 *iface,
1181 IXMLDOMNamedNodeMap** attributeMap )
1183 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1185 TRACE("(%p)->(%p)\n", This, attributeMap);
1187 return return_null_ptr((void**)attributeMap);
1191 static HRESULT WINAPI domdoc_insertBefore(
1192 IXMLDOMDocument3 *iface,
1193 IXMLDOMNode* newChild,
1195 IXMLDOMNode** outNewChild )
1197 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1199 TRACE("(%p)->(%p x%d %p)\n", This, newChild, V_VT(&refChild), outNewChild);
1201 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1205 static HRESULT WINAPI domdoc_replaceChild(
1206 IXMLDOMDocument3 *iface,
1207 IXMLDOMNode* newChild,
1208 IXMLDOMNode* oldChild,
1209 IXMLDOMNode** outOldChild)
1211 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1213 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1215 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1219 static HRESULT WINAPI domdoc_removeChild(
1220 IXMLDOMDocument3 *iface,
1222 IXMLDOMNode **oldChild)
1224 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1225 TRACE("(%p)->(%p %p)\n", This, child, oldChild);
1226 return node_remove_child(&This->node, child, oldChild);
1230 static HRESULT WINAPI domdoc_appendChild(
1231 IXMLDOMDocument3 *iface,
1233 IXMLDOMNode **outChild)
1235 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1236 TRACE("(%p)->(%p %p)\n", This, child, outChild);
1237 return node_append_child(&This->node, child, outChild);
1241 static HRESULT WINAPI domdoc_hasChildNodes(
1242 IXMLDOMDocument3 *iface,
1245 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1246 TRACE("(%p)->(%p)\n", This, ret);
1247 return node_has_childnodes(&This->node, ret);
1251 static HRESULT WINAPI domdoc_get_ownerDocument(
1252 IXMLDOMDocument3 *iface,
1253 IXMLDOMDocument **doc)
1255 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1256 TRACE("(%p)->(%p)\n", This, doc);
1257 return node_get_owner_doc(&This->node, doc);
1261 static HRESULT WINAPI domdoc_cloneNode(
1262 IXMLDOMDocument3 *iface,
1264 IXMLDOMNode** outNode)
1266 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1267 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
1268 return node_clone( &This->node, deep, outNode );
1272 static HRESULT WINAPI domdoc_get_nodeTypeString(
1273 IXMLDOMDocument3 *iface,
1276 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1277 static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
1279 TRACE("(%p)->(%p)\n", This, p);
1281 return return_bstr(documentW, p);
1285 static HRESULT WINAPI domdoc_get_text(
1286 IXMLDOMDocument3 *iface,
1289 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1290 TRACE("(%p)->(%p)\n", This, p);
1291 return node_get_text(&This->node, p);
1295 static HRESULT WINAPI domdoc_put_text(
1296 IXMLDOMDocument3 *iface,
1299 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1300 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1305 static HRESULT WINAPI domdoc_get_specified(
1306 IXMLDOMDocument3 *iface,
1307 VARIANT_BOOL* isSpecified )
1309 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1310 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1311 *isSpecified = VARIANT_TRUE;
1316 static HRESULT WINAPI domdoc_get_definition(
1317 IXMLDOMDocument3 *iface,
1318 IXMLDOMNode** definitionNode )
1320 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1321 FIXME("(%p)->(%p)\n", This, definitionNode);
1326 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1327 IXMLDOMDocument3 *iface,
1330 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1331 TRACE("(%p)->(%p)\n", This, v);
1332 return return_null_var(v);
1335 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1336 IXMLDOMDocument3 *iface,
1337 VARIANT typedValue )
1339 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1340 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1345 static HRESULT WINAPI domdoc_get_dataType(
1346 IXMLDOMDocument3 *iface,
1349 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1350 TRACE("(%p)->(%p)\n", This, typename);
1351 return return_null_var( typename );
1355 static HRESULT WINAPI domdoc_put_dataType(
1356 IXMLDOMDocument3 *iface,
1359 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1361 FIXME("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
1364 return E_INVALIDARG;
1369 static int XMLCALL domdoc_get_xml_writecallback(void *ctx, const char *data, int len)
1371 return xmlBufferAdd((xmlBufferPtr)ctx, (xmlChar*)data, len) == 0 ? len : 0;
1374 static HRESULT WINAPI domdoc_get_xml(
1375 IXMLDOMDocument3 *iface,
1378 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1379 xmlSaveCtxtPtr ctxt;
1384 TRACE("(%p)->(%p)\n", This, p);
1387 return E_INVALIDARG;
1391 buf = xmlBufferCreate();
1393 return E_OUTOFMEMORY;
1395 options = XML_SAVE_FORMAT | XML_SAVE_NO_DECL;
1396 ctxt = xmlSaveToIO(domdoc_get_xml_writecallback, NULL, buf, "UTF-8", options);
1401 return E_OUTOFMEMORY;
1404 ret = xmlSaveDoc(ctxt, get_doc(This));
1405 /* flushes on close */
1408 TRACE("%ld, len=%d\n", ret, xmlBufferLength(buf));
1409 if(ret != -1 && xmlBufferLength(buf) > 0)
1413 content = bstr_from_xmlChar(xmlBufferContent(buf));
1414 content = EnsureCorrectEOL(content);
1420 *p = SysAllocStringLen(NULL, 0);
1425 return *p ? S_OK : E_OUTOFMEMORY;
1429 static HRESULT WINAPI domdoc_transformNode(
1430 IXMLDOMDocument3 *iface,
1434 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1435 TRACE("(%p)->(%p %p)\n", This, node, p);
1436 return node_transform_node(&This->node, node, p);
1440 static HRESULT WINAPI domdoc_selectNodes(
1441 IXMLDOMDocument3 *iface,
1443 IXMLDOMNodeList **outList)
1445 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1446 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList);
1447 return node_select_nodes(&This->node, p, outList);
1451 static HRESULT WINAPI domdoc_selectSingleNode(
1452 IXMLDOMDocument3 *iface,
1454 IXMLDOMNode **outNode)
1456 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1457 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode);
1458 return node_select_singlenode(&This->node, p, outNode);
1462 static HRESULT WINAPI domdoc_get_parsed(
1463 IXMLDOMDocument3 *iface,
1464 VARIANT_BOOL* isParsed )
1466 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1467 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1468 *isParsed = VARIANT_TRUE;
1473 static HRESULT WINAPI domdoc_get_namespaceURI(
1474 IXMLDOMDocument3 *iface,
1475 BSTR* namespaceURI )
1477 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1478 TRACE("(%p)->(%p)\n", This, namespaceURI);
1479 return node_get_namespaceURI(&This->node, namespaceURI);
1483 static HRESULT WINAPI domdoc_get_prefix(
1484 IXMLDOMDocument3 *iface,
1487 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1488 TRACE("(%p)->(%p)\n", This, prefix);
1489 return return_null_bstr( prefix );
1493 static HRESULT WINAPI domdoc_get_baseName(
1494 IXMLDOMDocument3 *iface,
1497 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1498 TRACE("(%p)->(%p)\n", This, name);
1499 return return_null_bstr( name );
1503 static HRESULT WINAPI domdoc_transformNodeToObject(
1504 IXMLDOMDocument3 *iface,
1505 IXMLDOMNode* stylesheet,
1506 VARIANT outputObject)
1508 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1509 FIXME("(%p)->(%p %s)\n", This, stylesheet, debugstr_variant(&outputObject));
1514 static HRESULT WINAPI domdoc_get_doctype(
1515 IXMLDOMDocument3 *iface,
1516 IXMLDOMDocumentType** doctype )
1518 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1523 TRACE("(%p)->(%p)\n", This, doctype);
1525 if (!doctype) return E_INVALIDARG;
1529 dtd = xmlGetIntSubset(get_doc(This));
1530 if (!dtd) return S_FALSE;
1532 node = create_node((xmlNodePtr)dtd);
1533 if (!node) return S_FALSE;
1535 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentType, (void**)doctype);
1536 IXMLDOMNode_Release(node);
1542 static HRESULT WINAPI domdoc_get_implementation(
1543 IXMLDOMDocument3 *iface,
1544 IXMLDOMImplementation** impl )
1546 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1548 TRACE("(%p)->(%p)\n", This, impl);
1551 return E_INVALIDARG;
1553 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1558 static HRESULT WINAPI domdoc_get_documentElement(
1559 IXMLDOMDocument3 *iface,
1560 IXMLDOMElement** DOMElement )
1562 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1563 IXMLDOMNode *element_node;
1567 TRACE("(%p)->(%p)\n", This, DOMElement);
1570 return E_INVALIDARG;
1574 root = xmlDocGetRootElement( get_doc(This) );
1578 element_node = create_node( root );
1579 if(!element_node) return S_FALSE;
1581 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1582 IXMLDOMNode_Release(element_node);
1588 static HRESULT WINAPI domdoc_put_documentElement(
1589 IXMLDOMDocument3 *iface,
1590 IXMLDOMElement* DOMElement )
1592 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1593 IXMLDOMNode *elementNode;
1598 TRACE("(%p)->(%p)\n", This, DOMElement);
1600 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1604 xmlNode = get_node_obj( elementNode );
1605 if(!xmlNode) return E_FAIL;
1607 if(!xmlNode->node->parent)
1608 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1609 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1611 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1612 IXMLDOMNode_Release( elementNode );
1615 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1621 static HRESULT WINAPI domdoc_createElement(
1622 IXMLDOMDocument3 *iface,
1624 IXMLDOMElement** element )
1626 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1631 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1633 if (!element || !tagname) return E_INVALIDARG;
1635 V_VT(&type) = VT_I1;
1636 V_I1(&type) = NODE_ELEMENT;
1638 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1641 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1642 IXMLDOMNode_Release(node);
1649 static HRESULT WINAPI domdoc_createDocumentFragment(
1650 IXMLDOMDocument3 *iface,
1651 IXMLDOMDocumentFragment** frag )
1653 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1658 TRACE("(%p)->(%p)\n", This, frag);
1660 if (!frag) return E_INVALIDARG;
1664 V_VT(&type) = VT_I1;
1665 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1667 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1670 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1671 IXMLDOMNode_Release(node);
1678 static HRESULT WINAPI domdoc_createTextNode(
1679 IXMLDOMDocument3 *iface,
1681 IXMLDOMText** text )
1683 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1688 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1690 if (!text) return E_INVALIDARG;
1694 V_VT(&type) = VT_I1;
1695 V_I1(&type) = NODE_TEXT;
1697 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1700 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1701 IXMLDOMNode_Release(node);
1702 hr = IXMLDOMText_put_data(*text, data);
1709 static HRESULT WINAPI domdoc_createComment(
1710 IXMLDOMDocument3 *iface,
1712 IXMLDOMComment** comment )
1714 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1719 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1721 if (!comment) return E_INVALIDARG;
1725 V_VT(&type) = VT_I1;
1726 V_I1(&type) = NODE_COMMENT;
1728 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1731 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1732 IXMLDOMNode_Release(node);
1733 hr = IXMLDOMComment_put_data(*comment, data);
1740 static HRESULT WINAPI domdoc_createCDATASection(
1741 IXMLDOMDocument3 *iface,
1743 IXMLDOMCDATASection** cdata )
1745 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1750 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1752 if (!cdata) return E_INVALIDARG;
1756 V_VT(&type) = VT_I1;
1757 V_I1(&type) = NODE_CDATA_SECTION;
1759 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1762 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1763 IXMLDOMNode_Release(node);
1764 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1771 static HRESULT WINAPI domdoc_createProcessingInstruction(
1772 IXMLDOMDocument3 *iface,
1775 IXMLDOMProcessingInstruction** pi )
1777 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1782 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1784 if (!pi) return E_INVALIDARG;
1788 V_VT(&type) = VT_I1;
1789 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1791 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1796 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1797 node_obj = get_node_obj(node);
1798 hr = node_set_content(node_obj, data);
1800 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1801 IXMLDOMNode_Release(node);
1808 static HRESULT WINAPI domdoc_createAttribute(
1809 IXMLDOMDocument3 *iface,
1811 IXMLDOMAttribute** attribute )
1813 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1818 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1820 if (!attribute || !name) return E_INVALIDARG;
1822 V_VT(&type) = VT_I1;
1823 V_I1(&type) = NODE_ATTRIBUTE;
1825 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1828 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1829 IXMLDOMNode_Release(node);
1836 static HRESULT WINAPI domdoc_createEntityReference(
1837 IXMLDOMDocument3 *iface,
1839 IXMLDOMEntityReference** entityref )
1841 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1846 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1848 if (!entityref) return E_INVALIDARG;
1852 V_VT(&type) = VT_I1;
1853 V_I1(&type) = NODE_ENTITY_REFERENCE;
1855 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1858 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1859 IXMLDOMNode_Release(node);
1865 xmlChar* tagName_to_XPath(const BSTR tagName)
1867 xmlChar *query, *tmp;
1868 static const xmlChar mod_pre[] = "*[local-name()='";
1869 static const xmlChar mod_post[] = "']";
1870 static const xmlChar prefix[] = "descendant::";
1871 const WCHAR *tokBegin, *tokEnd;
1874 query = xmlStrdup(prefix);
1877 while (tokBegin && *tokBegin)
1882 query = xmlStrcat(query, BAD_CAST "/");
1886 query = xmlStrcat(query, BAD_CAST "*");
1890 query = xmlStrcat(query, mod_pre);
1892 while (*tokEnd && *tokEnd != '/')
1894 len = WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, NULL, 0, NULL, NULL);
1895 tmp = xmlMalloc(len);
1896 WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, (char*)tmp, len, NULL, NULL);
1897 query = xmlStrncat(query, tmp, len);
1900 query = xmlStrcat(query, mod_post);
1907 static HRESULT WINAPI domdoc_getElementsByTagName(
1908 IXMLDOMDocument3 *iface,
1910 IXMLDOMNodeList** resultList )
1912 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1917 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1919 if (!tagName || !resultList) return E_INVALIDARG;
1921 XPath = This->properties->XPath;
1922 This->properties->XPath = TRUE;
1923 query = tagName_to_XPath(tagName);
1924 hr = create_selection((xmlNodePtr)get_doc(This), query, resultList);
1926 This->properties->XPath = XPath;
1931 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1937 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1939 return E_INVALIDARG;
1946 static HRESULT WINAPI domdoc_createNode(
1947 IXMLDOMDocument3 *iface,
1951 IXMLDOMNode** node )
1953 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1954 DOMNodeType node_type;
1956 xmlChar *xml_name, *href;
1959 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1961 if(!node) return E_INVALIDARG;
1963 hr = get_node_type(Type, &node_type);
1964 if(FAILED(hr)) return hr;
1966 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1967 FIXME("nodes with namespaces currently not supported.\n");
1969 TRACE("node_type %d\n", node_type);
1971 /* exit earlier for types that need name */
1975 case NODE_ATTRIBUTE:
1976 case NODE_ENTITY_REFERENCE:
1977 case NODE_PROCESSING_INSTRUCTION:
1978 if (!name || *name == 0) return E_FAIL;
1983 xml_name = xmlchar_from_wchar(name);
1984 /* prevent empty href to be allocated */
1985 href = namespaceURI ? xmlchar_from_wchar(namespaceURI) : NULL;
1991 xmlChar *local, *prefix;
1993 local = xmlSplitQName2(xml_name, &prefix);
1995 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
1997 /* allow to create default namespace xmlns= */
1998 if (local || (href && *href))
2000 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
2001 xmlSetNs(xmlnode, ns);
2009 case NODE_ATTRIBUTE:
2010 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
2013 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
2015 case NODE_CDATA_SECTION:
2016 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
2018 case NODE_ENTITY_REFERENCE:
2019 xmlnode = xmlNewReference(get_doc(This), xml_name);
2021 case NODE_PROCESSING_INSTRUCTION:
2022 #ifdef HAVE_XMLNEWDOCPI
2023 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
2025 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2030 xmlnode = xmlNewDocComment(get_doc(This), NULL);
2032 case NODE_DOCUMENT_FRAGMENT:
2033 xmlnode = xmlNewDocFragment(get_doc(This));
2035 /* unsupported types */
2037 case NODE_DOCUMENT_TYPE:
2040 heap_free(xml_name);
2041 return E_INVALIDARG;
2043 FIXME("unhandled node type %d\n", node_type);
2048 *node = create_node(xmlnode);
2049 heap_free(xml_name);
2054 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
2055 xmldoc_add_orphan(xmlnode->doc, xmlnode);
2062 static HRESULT WINAPI domdoc_nodeFromID(
2063 IXMLDOMDocument3 *iface,
2065 IXMLDOMNode** node )
2067 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2068 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
2072 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
2077 xmldoc = doparse(This, ptr, len, XML_CHAR_ENCODING_NONE);
2079 xmldoc->_private = create_priv();
2080 return attach_xmldoc(This, xmldoc);
2086 static HRESULT doread( domdoc *This, LPWSTR filename )
2091 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
2096 detach_bsc(This->bsc);
2102 static HRESULT WINAPI domdoc_load(
2103 IXMLDOMDocument3 *iface,
2105 VARIANT_BOOL* isSuccessful )
2107 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2108 LPWSTR filename = NULL;
2109 HRESULT hr = S_FALSE;
2110 IXMLDOMDocument3 *pNewDoc = NULL;
2111 IStream *pStream = NULL;
2114 TRACE("(%p)->(%s)\n", This, debugstr_variant(&source));
2118 *isSuccessful = VARIANT_FALSE;
2120 assert( &This->node );
2122 switch( V_VT(&source) )
2125 filename = V_BSTR(&source);
2127 case VT_BSTR|VT_BYREF:
2128 if (!V_BSTRREF(&source)) return E_INVALIDARG;
2129 filename = *V_BSTRREF(&source);
2131 case VT_ARRAY|VT_UI1:
2133 SAFEARRAY *psa = V_ARRAY(&source);
2136 UINT dim = SafeArrayGetDim(psa);
2141 ERR("SAFEARRAY == NULL\n");
2142 hr = This->error = E_INVALIDARG;
2145 /* Only takes UTF-8 strings.
2146 * NOT NULL-terminated. */
2147 SafeArrayAccessData(psa, (void**)&str);
2148 SafeArrayGetUBound(psa, 1, &len);
2150 if ((xmldoc = doparse(This, str, ++len, XML_CHAR_ENCODING_UTF8)))
2152 hr = This->error = S_OK;
2153 *isSuccessful = VARIANT_TRUE;
2154 TRACE("parsed document %p\n", xmldoc);
2158 This->error = E_FAIL;
2159 TRACE("failed to parse document\n");
2162 SafeArrayUnaccessData(psa);
2166 xmldoc->_private = create_priv();
2167 return attach_xmldoc(This, xmldoc);
2171 FIXME("unhandled SAFEARRAY dim: %d\n", dim);
2172 hr = This->error = E_NOTIMPL;
2177 hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
2182 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
2183 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
2184 hr = attach_xmldoc(This, xmldoc);
2187 *isSuccessful = VARIANT_TRUE;
2192 hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IStream, (void**)&pStream);
2195 IPersistStream *pDocStream;
2196 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
2199 hr = IPersistStream_Load(pDocStream, pStream);
2200 IStream_Release(pStream);
2203 *isSuccessful = VARIANT_TRUE;
2205 TRACE("Using IStream to load Document\n");
2210 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
2215 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
2220 /* ISequentialStream */
2221 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&source)->lpVtbl);
2225 FIXME("VT type not supported (%d)\n", V_VT(&source));
2230 hr = doread( This, filename );
2233 This->error = E_FAIL;
2236 hr = This->error = S_OK;
2237 *isSuccessful = VARIANT_TRUE;
2241 if(!filename || FAILED(hr)) {
2242 xmldoc = xmlNewDoc(NULL);
2243 xmldoc->_private = create_priv();
2244 hr = attach_xmldoc(This, xmldoc);
2249 TRACE("ret (%d)\n", hr);
2255 static HRESULT WINAPI domdoc_get_readyState(
2256 IXMLDOMDocument3 *iface,
2259 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2260 FIXME("stub! (%p)->(%p)\n", This, value);
2263 return E_INVALIDARG;
2265 *value = READYSTATE_COMPLETE;
2270 static HRESULT WINAPI domdoc_get_parseError(
2271 IXMLDOMDocument3 *iface,
2272 IXMLDOMParseError** errorObj )
2274 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2275 static const WCHAR err[] = {'e','r','r','o','r',0};
2276 BSTR error_string = NULL;
2278 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2281 error_string = SysAllocString(err);
2283 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2284 if(!*errorObj) return E_OUTOFMEMORY;
2289 static HRESULT WINAPI domdoc_get_url(
2290 IXMLDOMDocument3 *iface,
2293 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2294 FIXME("(%p)->(%p)\n", This, urlString);
2299 static HRESULT WINAPI domdoc_get_async(
2300 IXMLDOMDocument3 *iface,
2301 VARIANT_BOOL* isAsync )
2303 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2305 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2306 *isAsync = This->async;
2311 static HRESULT WINAPI domdoc_put_async(
2312 IXMLDOMDocument3 *iface,
2313 VARIANT_BOOL isAsync )
2315 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2317 TRACE("(%p)->(%d)\n", This, isAsync);
2318 This->async = isAsync;
2323 static HRESULT WINAPI domdoc_abort(
2324 IXMLDOMDocument3 *iface )
2326 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2327 FIXME("%p\n", This);
2332 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2333 static HRESULT WINAPI domdoc_loadXML(
2334 IXMLDOMDocument3 *iface,
2336 VARIANT_BOOL* isSuccessful )
2338 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2339 xmlDocPtr xmldoc = NULL;
2340 HRESULT hr = S_FALSE, hr2;
2342 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2344 assert ( &This->node );
2348 *isSuccessful = VARIANT_FALSE;
2352 xmldoc = doparse(This, (LPCSTR)bstrXML, lstrlenW(bstrXML) * sizeof(*bstrXML), XML_CHAR_ENCODING_UTF16LE);
2355 This->error = E_FAIL;
2356 TRACE("failed to parse document\n");
2360 hr = This->error = S_OK;
2361 *isSuccessful = VARIANT_TRUE;
2362 TRACE("parsed document %p\n", xmldoc);
2367 xmldoc = xmlNewDoc(NULL);
2369 xmldoc->_private = create_priv();
2371 hr2 = attach_xmldoc(This, xmldoc);
2378 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2382 if(!WriteFile(ctx, buffer, len, &written, NULL))
2384 WARN("write error\n");
2391 static int XMLCALL domdoc_save_closecallback(void *ctx)
2393 return CloseHandle(ctx) ? 0 : -1;
2396 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2401 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2404 WARN("stream write error: 0x%08x\n", hr);
2411 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2413 IStream_Release((IStream*)ctx);
2417 static HRESULT WINAPI domdoc_save(
2418 IXMLDOMDocument3 *iface,
2419 VARIANT destination )
2421 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2422 xmlSaveCtxtPtr ctx = NULL;
2426 TRACE("(%p)->(%s)\n", This, debugstr_variant(&destination));
2428 switch (V_VT(&destination))
2432 IUnknown *pUnk = V_UNKNOWN(&destination);
2433 IXMLDOMDocument2 *document;
2436 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2439 VARIANT_BOOL success;
2442 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2445 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2449 IXMLDOMDocument3_Release(document);
2453 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2456 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2457 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2461 IStream_Release(stream);
2469 case VT_BSTR | VT_BYREF:
2471 /* save with file path */
2472 HANDLE handle = CreateFileW( (V_VT(&destination) & VT_BYREF)? *V_BSTRREF(&destination) : V_BSTR(&destination),
2473 GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2474 if( handle == INVALID_HANDLE_VALUE )
2476 WARN("failed to create file\n");
2480 /* disable top XML declaration */
2481 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2482 handle, NULL, XML_SAVE_NO_DECL);
2485 CloseHandle(handle);
2492 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination));
2496 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2497 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2498 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2500 /* will release resources through close callback */
2506 static HRESULT WINAPI domdoc_get_validateOnParse(
2507 IXMLDOMDocument3 *iface,
2508 VARIANT_BOOL* isValidating )
2510 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2511 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2512 *isValidating = This->validating;
2517 static HRESULT WINAPI domdoc_put_validateOnParse(
2518 IXMLDOMDocument3 *iface,
2519 VARIANT_BOOL isValidating )
2521 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2522 TRACE("(%p)->(%d)\n", This, isValidating);
2523 This->validating = isValidating;
2528 static HRESULT WINAPI domdoc_get_resolveExternals(
2529 IXMLDOMDocument3 *iface,
2530 VARIANT_BOOL* isResolving )
2532 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2533 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2534 *isResolving = This->resolving;
2539 static HRESULT WINAPI domdoc_put_resolveExternals(
2540 IXMLDOMDocument3 *iface,
2541 VARIANT_BOOL isResolving )
2543 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2544 TRACE("(%p)->(%d)\n", This, isResolving);
2545 This->resolving = isResolving;
2550 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2551 IXMLDOMDocument3 *iface,
2552 VARIANT_BOOL* isPreserving )
2554 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2555 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->properties->preserving);
2556 *isPreserving = This->properties->preserving;
2561 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2562 IXMLDOMDocument3 *iface,
2563 VARIANT_BOOL isPreserving )
2565 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2566 TRACE("(%p)->(%d)\n", This, isPreserving);
2567 This->properties->preserving = isPreserving;
2572 static HRESULT WINAPI domdoc_put_onreadystatechange(
2573 IXMLDOMDocument3 *iface,
2576 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2578 TRACE("(%p)->(%s)\n", This, debugstr_variant(&event));
2579 return set_doc_event(This, EVENTID_READYSTATECHANGE, &event);
2583 static HRESULT WINAPI domdoc_put_onDataAvailable(
2584 IXMLDOMDocument3 *iface,
2585 VARIANT onDataAvailableSink )
2587 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2588 FIXME("%p\n", This);
2592 static HRESULT WINAPI domdoc_put_onTransformNode(
2593 IXMLDOMDocument3 *iface,
2594 VARIANT onTransformNodeSink )
2596 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2597 FIXME("%p\n", This);
2601 static HRESULT WINAPI domdoc_get_namespaces(
2602 IXMLDOMDocument3* iface,
2603 IXMLDOMSchemaCollection** schemaCollection )
2605 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2606 FIXME("(%p)->(%p)\n", This, schemaCollection);
2610 static HRESULT WINAPI domdoc_get_schemas(
2611 IXMLDOMDocument3* iface,
2614 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2615 HRESULT hr = S_FALSE;
2616 IXMLDOMSchemaCollection2* cur_schema = This->properties->schemaCache;
2618 TRACE("(%p)->(%p)\n", This, var1);
2620 VariantInit(var1); /* Test shows we don't call VariantClear here */
2621 V_VT(var1) = VT_NULL;
2625 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2627 V_VT(var1) = VT_DISPATCH;
2632 static HRESULT WINAPI domdoc_putref_schemas(
2633 IXMLDOMDocument3* iface,
2636 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2637 HRESULT hr = E_FAIL;
2638 IXMLDOMSchemaCollection2* new_schema = NULL;
2640 FIXME("(%p): semi-stub\n", This);
2644 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2648 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2657 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2662 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->properties->schemaCache, new_schema);
2663 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2669 static inline BOOL is_wellformed(xmlDocPtr doc)
2671 #ifdef HAVE_XMLDOC_PROPERTIES
2672 return doc->properties & XML_DOC_WELLFORMED;
2674 /* Not a full check, but catches the worst violations */
2678 for (child = doc->children; child != NULL; child = child->next)
2680 switch (child->type)
2682 case XML_ELEMENT_NODE:
2687 case XML_CDATA_SECTION_NODE:
2699 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2703 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2707 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2711 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2715 static HRESULT WINAPI domdoc_validateNode(
2716 IXMLDOMDocument3* iface,
2718 IXMLDOMParseError** err)
2720 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2721 LONG state, err_code = 0;
2725 TRACE("(%p)->(%p, %p)\n", This, node, err);
2726 domdoc_get_readyState(iface, &state);
2727 if (state != READYSTATE_COMPLETE)
2730 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2737 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2741 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2744 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2748 if (!is_wellformed(get_doc(This)))
2750 ERR("doc not well-formed\n");
2752 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2756 /* DTD validation */
2757 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2759 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2760 vctx->error = validate_error;
2761 vctx->warning = validate_warning;
2764 if (!((node == (IXMLDOMNode*)iface)?
2765 xmlValidateDocument(vctx, get_doc(This)) :
2766 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2768 /* TODO: get a real error code here */
2769 TRACE("DTD validation failed\n");
2770 err_code = E_XML_INVALID;
2773 xmlFreeValidCtxt(vctx);
2776 /* Schema validation */
2777 if (hr == S_OK && This->properties->schemaCache != NULL)
2780 hr = SchemaCache_validate_tree(This->properties->schemaCache, get_node_obj(node)->node);
2784 /* TODO: get a real error code here */
2787 TRACE("schema validation succeeded\n");
2791 ERR("schema validation failed\n");
2792 err_code = E_XML_INVALID;
2797 /* not really OK, just didn't find a schema for the ns */
2804 ERR("no DTD or schema found\n");
2805 err_code = E_XML_NODTD;
2810 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2815 static HRESULT WINAPI domdoc_validate(
2816 IXMLDOMDocument3* iface,
2817 IXMLDOMParseError** err)
2819 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2820 TRACE("(%p)->(%p)\n", This, err);
2821 return domdoc_validateNode(iface, (IXMLDOMNode*)iface, err);
2824 static HRESULT WINAPI domdoc_setProperty(
2825 IXMLDOMDocument3* iface,
2829 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2831 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2833 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2839 V_VT(&varStr) = VT_EMPTY;
2840 if (V_VT(&var) != VT_BSTR)
2842 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2844 bstr = V_BSTR(&varStr);
2847 bstr = V_BSTR(&var);
2850 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2851 This->properties->XPath = TRUE;
2852 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2853 This->properties->XPath = FALSE;
2857 VariantClear(&varStr);
2860 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2865 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2866 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2867 xmlXPathContextPtr ctx;
2868 struct list *pNsList;
2869 select_ns_entry* pNsEntry = NULL;
2871 V_VT(&varStr) = VT_EMPTY;
2872 if (V_VT(&var) != VT_BSTR)
2874 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2876 bstr = V_BSTR(&varStr);
2879 bstr = V_BSTR(&var);
2883 pNsList = &(This->properties->selectNsList);
2884 clear_selectNsList(pNsList);
2886 nsStr = xmlchar_from_wchar(bstr);
2888 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2890 This->properties->selectNsStr = nsStr;
2891 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2894 ctx = xmlXPathNewContext(This->node.node->doc);
2897 for (; *pTokBegin; pTokBegin = pTokEnd)
2899 if (pNsEntry != NULL)
2900 memset(pNsEntry, 0, sizeof(select_ns_entry));
2902 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2904 while (*pTokBegin == ' ')
2906 pTokEnd = pTokBegin;
2907 while (*pTokEnd != ' ' && *pTokEnd != 0)
2910 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2913 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2914 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2919 if (*pTokBegin == '=')
2921 /*valid for XSLPattern?*/
2922 FIXME("Setting default xmlns not supported - skipping.\n");
2923 pTokBegin = pTokEnd;
2926 else if (*pTokBegin == ':')
2928 pNsEntry->prefix = ++pTokBegin;
2929 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2932 if (pTokInner == pTokEnd)
2935 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2936 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2940 pNsEntry->prefix_end = *pTokInner;
2944 if (pTokEnd-pTokInner > 1 &&
2945 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2946 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2948 pNsEntry->href = ++pTokInner;
2949 pNsEntry->href_end = *(pTokEnd-1);
2951 list_add_tail(pNsList, &pNsEntry->entry);
2952 /*let libxml figure out if they're valid from here ;)*/
2953 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2962 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2963 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2964 list_add_tail(pNsList, &pNsEntry->entry);
2977 heap_free(pNsEntry);
2978 xmlXPathFreeContext(ctx);
2981 VariantClear(&varStr);
2984 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2985 lstrcmpiW(p, PropertyNewParserW) == 0 ||
2986 lstrcmpiW(p, PropertyResolveExternalsW) == 0)
2989 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2993 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2997 static HRESULT WINAPI domdoc_getProperty(
2998 IXMLDOMDocument3* iface,
3002 domdoc *This = impl_from_IXMLDOMDocument3( iface );
3004 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
3007 return E_INVALIDARG;
3009 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
3011 V_VT(var) = VT_BSTR;
3012 V_BSTR(var) = This->properties->XPath ?
3013 SysAllocString(PropValueXPathW) :
3014 SysAllocString(PropValueXSLPatternW);
3015 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
3017 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
3020 BSTR rebuiltStr, cur;
3021 const xmlChar *nsStr;
3022 struct list *pNsList;
3023 select_ns_entry* pNsEntry;
3025 V_VT(var) = VT_BSTR;
3026 nsStr = This->properties->selectNsStr;
3027 pNsList = &This->properties->selectNsList;
3028 lenA = This->properties->selectNsStr_len;
3029 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
3030 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
3031 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
3033 /* this is fine because all of the chars that end tokens are ASCII*/
3034 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
3036 while (*cur != 0) ++cur;
3037 if (pNsEntry->prefix_end)
3039 *cur = pNsEntry->prefix_end;
3040 while (*cur != 0) ++cur;
3043 if (pNsEntry->href_end)
3045 *cur = pNsEntry->href_end;
3048 V_BSTR(var) = SysAllocString(rebuiltStr);
3049 heap_free(rebuiltStr);
3053 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
3057 static HRESULT WINAPI domdoc_importNode(
3058 IXMLDOMDocument3* iface,
3061 IXMLDOMNode** clone)
3063 domdoc *This = impl_from_IXMLDOMDocument3( iface );
3064 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
3068 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
3070 domdoc_QueryInterface,
3073 domdoc_GetTypeInfoCount,
3075 domdoc_GetIDsOfNames,
3077 domdoc_get_nodeName,
3078 domdoc_get_nodeValue,
3079 domdoc_put_nodeValue,
3080 domdoc_get_nodeType,
3081 domdoc_get_parentNode,
3082 domdoc_get_childNodes,
3083 domdoc_get_firstChild,
3084 domdoc_get_lastChild,
3085 domdoc_get_previousSibling,
3086 domdoc_get_nextSibling,
3087 domdoc_get_attributes,
3088 domdoc_insertBefore,
3089 domdoc_replaceChild,
3092 domdoc_hasChildNodes,
3093 domdoc_get_ownerDocument,
3095 domdoc_get_nodeTypeString,
3098 domdoc_get_specified,
3099 domdoc_get_definition,
3100 domdoc_get_nodeTypedValue,
3101 domdoc_put_nodeTypedValue,
3102 domdoc_get_dataType,
3103 domdoc_put_dataType,
3105 domdoc_transformNode,
3107 domdoc_selectSingleNode,
3109 domdoc_get_namespaceURI,
3111 domdoc_get_baseName,
3112 domdoc_transformNodeToObject,
3114 domdoc_get_implementation,
3115 domdoc_get_documentElement,
3116 domdoc_put_documentElement,
3117 domdoc_createElement,
3118 domdoc_createDocumentFragment,
3119 domdoc_createTextNode,
3120 domdoc_createComment,
3121 domdoc_createCDATASection,
3122 domdoc_createProcessingInstruction,
3123 domdoc_createAttribute,
3124 domdoc_createEntityReference,
3125 domdoc_getElementsByTagName,
3129 domdoc_get_readyState,
3130 domdoc_get_parseError,
3137 domdoc_get_validateOnParse,
3138 domdoc_put_validateOnParse,
3139 domdoc_get_resolveExternals,
3140 domdoc_put_resolveExternals,
3141 domdoc_get_preserveWhiteSpace,
3142 domdoc_put_preserveWhiteSpace,
3143 domdoc_put_onreadystatechange,
3144 domdoc_put_onDataAvailable,
3145 domdoc_put_onTransformNode,
3146 domdoc_get_namespaces,
3148 domdoc_putref_schemas,
3152 domdoc_validateNode,
3156 /* IConnectionPointContainer */
3157 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
3158 REFIID riid, void **ppv)
3160 domdoc *This = impl_from_IConnectionPointContainer(iface);
3161 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppv);
3164 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
3166 domdoc *This = impl_from_IConnectionPointContainer(iface);
3167 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3170 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
3172 domdoc *This = impl_from_IConnectionPointContainer(iface);
3173 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3176 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
3177 IEnumConnectionPoints **ppEnum)
3179 domdoc *This = impl_from_IConnectionPointContainer(iface);
3180 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3184 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
3185 REFIID riid, IConnectionPoint **cp)
3187 domdoc *This = impl_from_IConnectionPointContainer(iface);
3188 ConnectionPoint *iter;
3190 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
3194 for(iter = This->cp_list; iter; iter = iter->next)
3196 if (IsEqualGUID(iter->iid, riid))
3197 *cp = &iter->IConnectionPoint_iface;
3202 IConnectionPoint_AddRef(*cp);
3206 FIXME("unsupported riid %s\n", debugstr_guid(riid));
3207 return CONNECT_E_NOCONNECTION;
3211 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
3213 ConnectionPointContainer_QueryInterface,
3214 ConnectionPointContainer_AddRef,
3215 ConnectionPointContainer_Release,
3216 ConnectionPointContainer_EnumConnectionPoints,
3217 ConnectionPointContainer_FindConnectionPoint
3220 /* IConnectionPoint */
3221 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
3222 REFIID riid, void **ppv)
3224 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3226 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3230 if (IsEqualGUID(&IID_IUnknown, riid) ||
3231 IsEqualGUID(&IID_IConnectionPoint, riid))
3238 IConnectionPoint_AddRef(iface);
3242 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3243 return E_NOINTERFACE;
3246 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3248 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3249 return IConnectionPointContainer_AddRef(This->container);
3252 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3254 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3255 return IConnectionPointContainer_Release(This->container);
3258 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3260 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3262 TRACE("(%p)->(%p)\n", This, iid);
3264 if (!iid) return E_POINTER;
3270 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3271 IConnectionPointContainer **container)
3273 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3275 TRACE("(%p)->(%p)\n", This, container);
3277 if (!container) return E_POINTER;
3279 *container = This->container;
3280 IConnectionPointContainer_AddRef(*container);
3284 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
3287 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3288 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
3292 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3294 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3296 TRACE("(%p)->(%d)\n", This, cookie);
3298 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3299 return CONNECT_E_NOCONNECTION;
3301 IUnknown_Release(This->sinks[cookie-1].unk);
3302 This->sinks[cookie-1].unk = NULL;
3307 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3308 IEnumConnections **ppEnum)
3310 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3311 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3315 static const IConnectionPointVtbl ConnectionPointVtbl =
3317 ConnectionPoint_QueryInterface,
3318 ConnectionPoint_AddRef,
3319 ConnectionPoint_Release,
3320 ConnectionPoint_GetConnectionInterface,
3321 ConnectionPoint_GetConnectionPointContainer,
3322 ConnectionPoint_Advise,
3323 ConnectionPoint_Unadvise,
3324 ConnectionPoint_EnumConnections
3327 static void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3329 cp->IConnectionPoint_iface.lpVtbl = &ConnectionPointVtbl;
3335 cp->next = doc->cp_list;
3338 cp->container = &doc->IConnectionPointContainer_iface;
3341 /* domdoc implementation of IObjectWithSite */
3342 static HRESULT WINAPI
3343 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3345 domdoc *This = impl_from_IObjectWithSite(iface);
3346 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppvObject);
3349 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3351 domdoc *This = impl_from_IObjectWithSite(iface);
3352 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3355 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3357 domdoc *This = impl_from_IObjectWithSite(iface);
3358 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3361 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3363 domdoc *This = impl_from_IObjectWithSite(iface);
3365 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3370 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3373 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3375 domdoc *This = impl_from_IObjectWithSite(iface);
3377 TRACE("(%p)->(%p)\n", iface, punk);
3383 IUnknown_Release( This->site );
3390 IUnknown_AddRef( punk );
3393 IUnknown_Release( This->site );
3400 static const IObjectWithSiteVtbl domdocObjectSite =
3402 domdoc_ObjectWithSite_QueryInterface,
3403 domdoc_ObjectWithSite_AddRef,
3404 domdoc_ObjectWithSite_Release,
3405 domdoc_ObjectWithSite_SetSite,
3406 domdoc_ObjectWithSite_GetSite
3409 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3411 domdoc *This = impl_from_IObjectSafety(iface);
3412 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppv);
3415 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3417 domdoc *This = impl_from_IObjectSafety(iface);
3418 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3421 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3423 domdoc *This = impl_from_IObjectSafety(iface);
3424 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3427 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3429 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3430 DWORD *supported, DWORD *enabled)
3432 domdoc *This = impl_from_IObjectSafety(iface);
3434 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3436 if(!supported || !enabled) return E_POINTER;
3438 *supported = SAFETY_SUPPORTED_OPTIONS;
3439 *enabled = This->safeopt;
3444 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3445 DWORD mask, DWORD enabled)
3447 domdoc *This = impl_from_IObjectSafety(iface);
3448 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3450 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3453 This->safeopt = enabled & mask & SAFETY_SUPPORTED_OPTIONS;
3457 #undef SAFETY_SUPPORTED_OPTIONS
3459 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3460 domdoc_Safety_QueryInterface,
3461 domdoc_Safety_AddRef,
3462 domdoc_Safety_Release,
3463 domdoc_Safety_GetInterfaceSafetyOptions,
3464 domdoc_Safety_SetInterfaceSafetyOptions
3467 static const tid_t domdoc_iface_tids[] = {
3469 IXMLDOMDocument_tid,
3470 IXMLDOMDocument2_tid,
3473 static dispex_static_data_t domdoc_dispex = {
3475 IXMLDOMDocument2_tid,
3480 HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3484 doc = heap_alloc( sizeof (*doc) );
3486 return E_OUTOFMEMORY;
3488 doc->IXMLDOMDocument3_iface.lpVtbl = &domdoc_vtbl;
3489 doc->IPersistStreamInit_iface.lpVtbl = &xmldoc_IPersistStreamInit_VTable;
3490 doc->IObjectWithSite_iface.lpVtbl = &domdocObjectSite;
3491 doc->IObjectSafety_iface.lpVtbl = &domdocObjectSafetyVtbl;
3492 doc->ISupportErrorInfo_iface.lpVtbl = &support_error_vtbl;
3493 doc->IConnectionPointContainer_iface.lpVtbl = &ConnectionPointContainerVtbl;
3495 doc->async = VARIANT_TRUE;
3496 doc->validating = 0;
3498 doc->properties = properties_from_xmlDocPtr(xmldoc);
3504 doc->cp_list = NULL;
3505 memset(doc->events, 0, sizeof(doc->events));
3507 /* events connection points */
3508 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3509 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3510 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3512 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->IXMLDOMDocument3_iface,
3515 *document = &doc->IXMLDOMDocument3_iface;
3517 TRACE("returning iface %p\n", *document);
3521 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3526 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
3528 xmldoc = xmlNewDoc(NULL);
3530 return E_OUTOFMEMORY;
3532 xmldoc->_private = create_priv();
3533 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
3535 hr = get_domdoc_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3538 free_properties(properties_from_xmlDocPtr(xmldoc));
3539 heap_free(xmldoc->_private);
3547 IUnknown* create_domdoc( xmlNodePtr document )
3552 TRACE("(%p)\n", document);
3554 hr = get_domdoc_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3563 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3565 MESSAGE("This program tried to use a DOMDocument object, but\n"
3566 "libxml2 support was not present at compile time.\n");