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)->(var(vt %d, %s))\n", This, V_VT(&destination),
2427 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
2429 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
2431 FIXME("Unhandled vt %d\n", V_VT(&destination));
2435 if(V_VT(&destination) == VT_UNKNOWN)
2437 IUnknown *pUnk = V_UNKNOWN(&destination);
2438 IXMLDOMDocument2 *document;
2441 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2444 VARIANT_BOOL success;
2447 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2450 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2454 IXMLDOMDocument3_Release(document);
2458 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2461 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2462 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2466 IStream_Release(stream);
2473 /* save with file path */
2474 HANDLE handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
2475 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2476 if( handle == INVALID_HANDLE_VALUE )
2478 WARN("failed to create file\n");
2482 /* disable top XML declaration */
2483 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2484 handle, NULL, XML_SAVE_NO_DECL);
2487 CloseHandle(handle);
2492 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2493 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2494 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2496 /* will release resources through close callback */
2502 static HRESULT WINAPI domdoc_get_validateOnParse(
2503 IXMLDOMDocument3 *iface,
2504 VARIANT_BOOL* isValidating )
2506 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2507 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2508 *isValidating = This->validating;
2513 static HRESULT WINAPI domdoc_put_validateOnParse(
2514 IXMLDOMDocument3 *iface,
2515 VARIANT_BOOL isValidating )
2517 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2518 TRACE("(%p)->(%d)\n", This, isValidating);
2519 This->validating = isValidating;
2524 static HRESULT WINAPI domdoc_get_resolveExternals(
2525 IXMLDOMDocument3 *iface,
2526 VARIANT_BOOL* isResolving )
2528 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2529 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2530 *isResolving = This->resolving;
2535 static HRESULT WINAPI domdoc_put_resolveExternals(
2536 IXMLDOMDocument3 *iface,
2537 VARIANT_BOOL isResolving )
2539 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2540 TRACE("(%p)->(%d)\n", This, isResolving);
2541 This->resolving = isResolving;
2546 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2547 IXMLDOMDocument3 *iface,
2548 VARIANT_BOOL* isPreserving )
2550 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2551 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->properties->preserving);
2552 *isPreserving = This->properties->preserving;
2557 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2558 IXMLDOMDocument3 *iface,
2559 VARIANT_BOOL isPreserving )
2561 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2562 TRACE("(%p)->(%d)\n", This, isPreserving);
2563 This->properties->preserving = isPreserving;
2568 static HRESULT WINAPI domdoc_put_onreadystatechange(
2569 IXMLDOMDocument3 *iface,
2572 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2574 TRACE("(%p)->(%s)\n", This, debugstr_variant(&event));
2575 return set_doc_event(This, EVENTID_READYSTATECHANGE, &event);
2579 static HRESULT WINAPI domdoc_put_onDataAvailable(
2580 IXMLDOMDocument3 *iface,
2581 VARIANT onDataAvailableSink )
2583 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2584 FIXME("%p\n", This);
2588 static HRESULT WINAPI domdoc_put_onTransformNode(
2589 IXMLDOMDocument3 *iface,
2590 VARIANT onTransformNodeSink )
2592 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2593 FIXME("%p\n", This);
2597 static HRESULT WINAPI domdoc_get_namespaces(
2598 IXMLDOMDocument3* iface,
2599 IXMLDOMSchemaCollection** schemaCollection )
2601 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2602 FIXME("(%p)->(%p)\n", This, schemaCollection);
2606 static HRESULT WINAPI domdoc_get_schemas(
2607 IXMLDOMDocument3* iface,
2610 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2611 HRESULT hr = S_FALSE;
2612 IXMLDOMSchemaCollection2* cur_schema = This->properties->schemaCache;
2614 TRACE("(%p)->(%p)\n", This, var1);
2616 VariantInit(var1); /* Test shows we don't call VariantClear here */
2617 V_VT(var1) = VT_NULL;
2621 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2623 V_VT(var1) = VT_DISPATCH;
2628 static HRESULT WINAPI domdoc_putref_schemas(
2629 IXMLDOMDocument3* iface,
2632 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2633 HRESULT hr = E_FAIL;
2634 IXMLDOMSchemaCollection2* new_schema = NULL;
2636 FIXME("(%p): semi-stub\n", This);
2640 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2644 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2653 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2658 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->properties->schemaCache, new_schema);
2659 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2665 static inline BOOL is_wellformed(xmlDocPtr doc)
2667 #ifdef HAVE_XMLDOC_PROPERTIES
2668 return doc->properties & XML_DOC_WELLFORMED;
2670 /* Not a full check, but catches the worst violations */
2674 for (child = doc->children; child != NULL; child = child->next)
2676 switch (child->type)
2678 case XML_ELEMENT_NODE:
2683 case XML_CDATA_SECTION_NODE:
2695 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2699 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2703 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2707 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2711 static HRESULT WINAPI domdoc_validateNode(
2712 IXMLDOMDocument3* iface,
2714 IXMLDOMParseError** err)
2716 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2717 LONG state, err_code = 0;
2721 TRACE("(%p)->(%p, %p)\n", This, node, err);
2722 domdoc_get_readyState(iface, &state);
2723 if (state != READYSTATE_COMPLETE)
2726 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2733 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2737 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2740 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2744 if (!is_wellformed(get_doc(This)))
2746 ERR("doc not well-formed\n");
2748 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2752 /* DTD validation */
2753 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2755 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2756 vctx->error = validate_error;
2757 vctx->warning = validate_warning;
2760 if (!((node == (IXMLDOMNode*)iface)?
2761 xmlValidateDocument(vctx, get_doc(This)) :
2762 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2764 /* TODO: get a real error code here */
2765 TRACE("DTD validation failed\n");
2766 err_code = E_XML_INVALID;
2769 xmlFreeValidCtxt(vctx);
2772 /* Schema validation */
2773 if (hr == S_OK && This->properties->schemaCache != NULL)
2776 hr = SchemaCache_validate_tree(This->properties->schemaCache, get_node_obj(node)->node);
2780 /* TODO: get a real error code here */
2783 TRACE("schema validation succeeded\n");
2787 ERR("schema validation failed\n");
2788 err_code = E_XML_INVALID;
2793 /* not really OK, just didn't find a schema for the ns */
2800 ERR("no DTD or schema found\n");
2801 err_code = E_XML_NODTD;
2806 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2811 static HRESULT WINAPI domdoc_validate(
2812 IXMLDOMDocument3* iface,
2813 IXMLDOMParseError** err)
2815 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2816 TRACE("(%p)->(%p)\n", This, err);
2817 return domdoc_validateNode(iface, (IXMLDOMNode*)iface, err);
2820 static HRESULT WINAPI domdoc_setProperty(
2821 IXMLDOMDocument3* iface,
2825 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2827 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2829 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2835 V_VT(&varStr) = VT_EMPTY;
2836 if (V_VT(&var) != VT_BSTR)
2838 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2840 bstr = V_BSTR(&varStr);
2843 bstr = V_BSTR(&var);
2846 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2847 This->properties->XPath = TRUE;
2848 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2849 This->properties->XPath = FALSE;
2853 VariantClear(&varStr);
2856 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2861 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2862 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2863 xmlXPathContextPtr ctx;
2864 struct list *pNsList;
2865 select_ns_entry* pNsEntry = NULL;
2867 V_VT(&varStr) = VT_EMPTY;
2868 if (V_VT(&var) != VT_BSTR)
2870 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2872 bstr = V_BSTR(&varStr);
2875 bstr = V_BSTR(&var);
2879 pNsList = &(This->properties->selectNsList);
2880 clear_selectNsList(pNsList);
2882 nsStr = xmlchar_from_wchar(bstr);
2884 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2886 This->properties->selectNsStr = nsStr;
2887 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2890 ctx = xmlXPathNewContext(This->node.node->doc);
2893 for (; *pTokBegin; pTokBegin = pTokEnd)
2895 if (pNsEntry != NULL)
2896 memset(pNsEntry, 0, sizeof(select_ns_entry));
2898 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2900 while (*pTokBegin == ' ')
2902 pTokEnd = pTokBegin;
2903 while (*pTokEnd != ' ' && *pTokEnd != 0)
2906 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2909 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2910 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2915 if (*pTokBegin == '=')
2917 /*valid for XSLPattern?*/
2918 FIXME("Setting default xmlns not supported - skipping.\n");
2919 pTokBegin = pTokEnd;
2922 else if (*pTokBegin == ':')
2924 pNsEntry->prefix = ++pTokBegin;
2925 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2928 if (pTokInner == pTokEnd)
2931 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2932 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2936 pNsEntry->prefix_end = *pTokInner;
2940 if (pTokEnd-pTokInner > 1 &&
2941 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2942 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2944 pNsEntry->href = ++pTokInner;
2945 pNsEntry->href_end = *(pTokEnd-1);
2947 list_add_tail(pNsList, &pNsEntry->entry);
2948 /*let libxml figure out if they're valid from here ;)*/
2949 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2958 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2959 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2960 list_add_tail(pNsList, &pNsEntry->entry);
2973 heap_free(pNsEntry);
2974 xmlXPathFreeContext(ctx);
2977 VariantClear(&varStr);
2980 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2981 lstrcmpiW(p, PropertyNewParserW) == 0 ||
2982 lstrcmpiW(p, PropertyResolveExternalsW) == 0)
2985 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2989 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2993 static HRESULT WINAPI domdoc_getProperty(
2994 IXMLDOMDocument3* iface,
2998 domdoc *This = impl_from_IXMLDOMDocument3( iface );
3000 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
3003 return E_INVALIDARG;
3005 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
3007 V_VT(var) = VT_BSTR;
3008 V_BSTR(var) = This->properties->XPath ?
3009 SysAllocString(PropValueXPathW) :
3010 SysAllocString(PropValueXSLPatternW);
3011 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
3013 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
3016 BSTR rebuiltStr, cur;
3017 const xmlChar *nsStr;
3018 struct list *pNsList;
3019 select_ns_entry* pNsEntry;
3021 V_VT(var) = VT_BSTR;
3022 nsStr = This->properties->selectNsStr;
3023 pNsList = &This->properties->selectNsList;
3024 lenA = This->properties->selectNsStr_len;
3025 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
3026 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
3027 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
3029 /* this is fine because all of the chars that end tokens are ASCII*/
3030 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
3032 while (*cur != 0) ++cur;
3033 if (pNsEntry->prefix_end)
3035 *cur = pNsEntry->prefix_end;
3036 while (*cur != 0) ++cur;
3039 if (pNsEntry->href_end)
3041 *cur = pNsEntry->href_end;
3044 V_BSTR(var) = SysAllocString(rebuiltStr);
3045 heap_free(rebuiltStr);
3049 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
3053 static HRESULT WINAPI domdoc_importNode(
3054 IXMLDOMDocument3* iface,
3057 IXMLDOMNode** clone)
3059 domdoc *This = impl_from_IXMLDOMDocument3( iface );
3060 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
3064 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
3066 domdoc_QueryInterface,
3069 domdoc_GetTypeInfoCount,
3071 domdoc_GetIDsOfNames,
3073 domdoc_get_nodeName,
3074 domdoc_get_nodeValue,
3075 domdoc_put_nodeValue,
3076 domdoc_get_nodeType,
3077 domdoc_get_parentNode,
3078 domdoc_get_childNodes,
3079 domdoc_get_firstChild,
3080 domdoc_get_lastChild,
3081 domdoc_get_previousSibling,
3082 domdoc_get_nextSibling,
3083 domdoc_get_attributes,
3084 domdoc_insertBefore,
3085 domdoc_replaceChild,
3088 domdoc_hasChildNodes,
3089 domdoc_get_ownerDocument,
3091 domdoc_get_nodeTypeString,
3094 domdoc_get_specified,
3095 domdoc_get_definition,
3096 domdoc_get_nodeTypedValue,
3097 domdoc_put_nodeTypedValue,
3098 domdoc_get_dataType,
3099 domdoc_put_dataType,
3101 domdoc_transformNode,
3103 domdoc_selectSingleNode,
3105 domdoc_get_namespaceURI,
3107 domdoc_get_baseName,
3108 domdoc_transformNodeToObject,
3110 domdoc_get_implementation,
3111 domdoc_get_documentElement,
3112 domdoc_put_documentElement,
3113 domdoc_createElement,
3114 domdoc_createDocumentFragment,
3115 domdoc_createTextNode,
3116 domdoc_createComment,
3117 domdoc_createCDATASection,
3118 domdoc_createProcessingInstruction,
3119 domdoc_createAttribute,
3120 domdoc_createEntityReference,
3121 domdoc_getElementsByTagName,
3125 domdoc_get_readyState,
3126 domdoc_get_parseError,
3133 domdoc_get_validateOnParse,
3134 domdoc_put_validateOnParse,
3135 domdoc_get_resolveExternals,
3136 domdoc_put_resolveExternals,
3137 domdoc_get_preserveWhiteSpace,
3138 domdoc_put_preserveWhiteSpace,
3139 domdoc_put_onreadystatechange,
3140 domdoc_put_onDataAvailable,
3141 domdoc_put_onTransformNode,
3142 domdoc_get_namespaces,
3144 domdoc_putref_schemas,
3148 domdoc_validateNode,
3152 /* IConnectionPointContainer */
3153 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
3154 REFIID riid, void **ppv)
3156 domdoc *This = impl_from_IConnectionPointContainer(iface);
3157 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppv);
3160 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
3162 domdoc *This = impl_from_IConnectionPointContainer(iface);
3163 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3166 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
3168 domdoc *This = impl_from_IConnectionPointContainer(iface);
3169 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3172 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
3173 IEnumConnectionPoints **ppEnum)
3175 domdoc *This = impl_from_IConnectionPointContainer(iface);
3176 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3180 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
3181 REFIID riid, IConnectionPoint **cp)
3183 domdoc *This = impl_from_IConnectionPointContainer(iface);
3184 ConnectionPoint *iter;
3186 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
3190 for(iter = This->cp_list; iter; iter = iter->next)
3192 if (IsEqualGUID(iter->iid, riid))
3193 *cp = &iter->IConnectionPoint_iface;
3198 IConnectionPoint_AddRef(*cp);
3202 FIXME("unsupported riid %s\n", debugstr_guid(riid));
3203 return CONNECT_E_NOCONNECTION;
3207 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
3209 ConnectionPointContainer_QueryInterface,
3210 ConnectionPointContainer_AddRef,
3211 ConnectionPointContainer_Release,
3212 ConnectionPointContainer_EnumConnectionPoints,
3213 ConnectionPointContainer_FindConnectionPoint
3216 /* IConnectionPoint */
3217 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
3218 REFIID riid, void **ppv)
3220 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3222 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3226 if (IsEqualGUID(&IID_IUnknown, riid) ||
3227 IsEqualGUID(&IID_IConnectionPoint, riid))
3234 IConnectionPoint_AddRef(iface);
3238 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3239 return E_NOINTERFACE;
3242 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3244 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3245 return IConnectionPointContainer_AddRef(This->container);
3248 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3250 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3251 return IConnectionPointContainer_Release(This->container);
3254 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3256 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3258 TRACE("(%p)->(%p)\n", This, iid);
3260 if (!iid) return E_POINTER;
3266 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3267 IConnectionPointContainer **container)
3269 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3271 TRACE("(%p)->(%p)\n", This, container);
3273 if (!container) return E_POINTER;
3275 *container = This->container;
3276 IConnectionPointContainer_AddRef(*container);
3280 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
3283 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3284 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
3288 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3290 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3292 TRACE("(%p)->(%d)\n", This, cookie);
3294 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3295 return CONNECT_E_NOCONNECTION;
3297 IUnknown_Release(This->sinks[cookie-1].unk);
3298 This->sinks[cookie-1].unk = NULL;
3303 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3304 IEnumConnections **ppEnum)
3306 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3307 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3311 static const IConnectionPointVtbl ConnectionPointVtbl =
3313 ConnectionPoint_QueryInterface,
3314 ConnectionPoint_AddRef,
3315 ConnectionPoint_Release,
3316 ConnectionPoint_GetConnectionInterface,
3317 ConnectionPoint_GetConnectionPointContainer,
3318 ConnectionPoint_Advise,
3319 ConnectionPoint_Unadvise,
3320 ConnectionPoint_EnumConnections
3323 static void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3325 cp->IConnectionPoint_iface.lpVtbl = &ConnectionPointVtbl;
3331 cp->next = doc->cp_list;
3334 cp->container = &doc->IConnectionPointContainer_iface;
3337 /* domdoc implementation of IObjectWithSite */
3338 static HRESULT WINAPI
3339 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3341 domdoc *This = impl_from_IObjectWithSite(iface);
3342 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppvObject);
3345 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3347 domdoc *This = impl_from_IObjectWithSite(iface);
3348 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3351 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3353 domdoc *This = impl_from_IObjectWithSite(iface);
3354 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3357 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3359 domdoc *This = impl_from_IObjectWithSite(iface);
3361 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3366 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3369 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3371 domdoc *This = impl_from_IObjectWithSite(iface);
3373 TRACE("(%p)->(%p)\n", iface, punk);
3379 IUnknown_Release( This->site );
3386 IUnknown_AddRef( punk );
3389 IUnknown_Release( This->site );
3396 static const IObjectWithSiteVtbl domdocObjectSite =
3398 domdoc_ObjectWithSite_QueryInterface,
3399 domdoc_ObjectWithSite_AddRef,
3400 domdoc_ObjectWithSite_Release,
3401 domdoc_ObjectWithSite_SetSite,
3402 domdoc_ObjectWithSite_GetSite
3405 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3407 domdoc *This = impl_from_IObjectSafety(iface);
3408 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppv);
3411 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3413 domdoc *This = impl_from_IObjectSafety(iface);
3414 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3417 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3419 domdoc *This = impl_from_IObjectSafety(iface);
3420 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3423 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3425 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3426 DWORD *supported, DWORD *enabled)
3428 domdoc *This = impl_from_IObjectSafety(iface);
3430 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3432 if(!supported || !enabled) return E_POINTER;
3434 *supported = SAFETY_SUPPORTED_OPTIONS;
3435 *enabled = This->safeopt;
3440 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3441 DWORD mask, DWORD enabled)
3443 domdoc *This = impl_from_IObjectSafety(iface);
3444 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3446 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3449 This->safeopt = enabled & mask & SAFETY_SUPPORTED_OPTIONS;
3453 #undef SAFETY_SUPPORTED_OPTIONS
3455 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3456 domdoc_Safety_QueryInterface,
3457 domdoc_Safety_AddRef,
3458 domdoc_Safety_Release,
3459 domdoc_Safety_GetInterfaceSafetyOptions,
3460 domdoc_Safety_SetInterfaceSafetyOptions
3463 static const tid_t domdoc_iface_tids[] = {
3465 IXMLDOMDocument_tid,
3466 IXMLDOMDocument2_tid,
3469 static dispex_static_data_t domdoc_dispex = {
3471 IXMLDOMDocument2_tid,
3476 HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3480 doc = heap_alloc( sizeof (*doc) );
3482 return E_OUTOFMEMORY;
3484 doc->IXMLDOMDocument3_iface.lpVtbl = &domdoc_vtbl;
3485 doc->IPersistStreamInit_iface.lpVtbl = &xmldoc_IPersistStreamInit_VTable;
3486 doc->IObjectWithSite_iface.lpVtbl = &domdocObjectSite;
3487 doc->IObjectSafety_iface.lpVtbl = &domdocObjectSafetyVtbl;
3488 doc->ISupportErrorInfo_iface.lpVtbl = &support_error_vtbl;
3489 doc->IConnectionPointContainer_iface.lpVtbl = &ConnectionPointContainerVtbl;
3491 doc->async = VARIANT_TRUE;
3492 doc->validating = 0;
3494 doc->properties = properties_from_xmlDocPtr(xmldoc);
3500 doc->cp_list = NULL;
3501 memset(doc->events, 0, sizeof(doc->events));
3503 /* events connection points */
3504 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3505 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3506 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3508 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->IXMLDOMDocument3_iface,
3511 *document = &doc->IXMLDOMDocument3_iface;
3513 TRACE("returning iface %p\n", *document);
3517 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3522 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
3524 xmldoc = xmlNewDoc(NULL);
3526 return E_OUTOFMEMORY;
3528 xmldoc->_private = create_priv();
3529 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
3531 hr = get_domdoc_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3534 free_properties(properties_from_xmlDocPtr(xmldoc));
3535 heap_free(xmldoc->_private);
3543 IUnknown* create_domdoc( xmlNodePtr document )
3548 TRACE("(%p)\n", document);
3550 hr = get_domdoc_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3559 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3561 MESSAGE("This program tried to use a DOMDocument object, but\n"
3562 "libxml2 support was not present at compile time.\n");