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(MSXML_VERSION version)
292 domdoc_properties *properties = heap_alloc(sizeof(domdoc_properties));
294 list_init(&properties->selectNsList);
295 properties->preserving = VARIANT_FALSE;
296 properties->schemaCache = NULL;
297 properties->selectNsStr = heap_alloc_zero(sizeof(xmlChar));
298 properties->selectNsStr_len = 0;
300 /* properties that are dependent on object versions */
301 properties->version = version;
302 properties->XPath = (version == MSXML4 || version == MSXML6);
307 static domdoc_properties* copy_properties(domdoc_properties const* properties)
309 domdoc_properties* pcopy = heap_alloc(sizeof(domdoc_properties));
310 select_ns_entry const* ns = NULL;
311 select_ns_entry* new_ns = NULL;
312 int len = (properties->selectNsStr_len+1)*sizeof(xmlChar);
317 pcopy->version = properties->version;
318 pcopy->preserving = properties->preserving;
319 pcopy->schemaCache = properties->schemaCache;
320 if (pcopy->schemaCache)
321 IXMLDOMSchemaCollection2_AddRef(pcopy->schemaCache);
322 pcopy->XPath = properties->XPath;
323 pcopy->selectNsStr_len = properties->selectNsStr_len;
324 list_init( &pcopy->selectNsList );
325 pcopy->selectNsStr = heap_alloc(len);
326 memcpy((xmlChar*)pcopy->selectNsStr, properties->selectNsStr, len);
327 offset = pcopy->selectNsStr - properties->selectNsStr;
329 LIST_FOR_EACH_ENTRY( ns, (&properties->selectNsList), select_ns_entry, entry )
331 new_ns = heap_alloc(sizeof(select_ns_entry));
332 memcpy(new_ns, ns, sizeof(select_ns_entry));
333 new_ns->href += offset;
334 new_ns->prefix += offset;
335 list_add_tail(&pcopy->selectNsList, &new_ns->entry);
343 static void free_properties(domdoc_properties* properties)
347 if (properties->schemaCache)
348 IXMLDOMSchemaCollection2_Release(properties->schemaCache);
349 clear_selectNsList(&properties->selectNsList);
350 heap_free((xmlChar*)properties->selectNsStr);
351 heap_free(properties);
355 /* links a "<?xml" node as a first child */
356 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
359 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
362 /* unlinks a first "<?xml" child if it was created */
363 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
369 if (doc->standalone != -1)
371 node = doc->children;
372 xmlUnlinkNode( node );
380 BOOL is_preserving_whitespace(xmlNodePtr node)
382 domdoc_properties* properties = NULL;
383 /* during parsing the xmlDoc._private stuff is not there */
384 if (priv_from_xmlDocPtr(node->doc))
385 properties = properties_from_xmlDocPtr(node->doc);
386 return ((properties && properties->preserving == VARIANT_TRUE) ||
387 xmlNodeGetSpacePreserve(node) == 1);
390 static inline BOOL strn_isspace(xmlChar const* str, int len)
392 for (; str && len > 0 && *str; ++str, --len)
399 static void sax_characters(void *ctx, const xmlChar *ch, int len)
401 xmlParserCtxtPtr ctxt;
404 ctxt = (xmlParserCtxtPtr) ctx;
405 This = (const domdoc*) ctxt->_private;
409 /* during domdoc_loadXML() the xmlDocPtr->_private data is not available */
410 if (!This->properties->preserving &&
411 !is_preserving_whitespace(ctxt->node) &&
412 strn_isspace(ch, len))
416 xmlSAX2Characters(ctxt, ch, len);
419 static void LIBXML2_LOG_CALLBACK sax_error(void* ctx, char const* msg, ...)
423 LIBXML2_CALLBACK_ERR(doparse, msg, ap);
427 static void LIBXML2_LOG_CALLBACK sax_warning(void* ctx, char const* msg, ...)
431 LIBXML2_CALLBACK_WARN(doparse, msg, ap);
435 static void sax_serror(void* ctx, xmlErrorPtr err)
437 LIBXML2_CALLBACK_SERROR(doparse, err);
440 static xmlDocPtr doparse(domdoc* This, char const* ptr, int len, xmlCharEncoding encoding)
442 xmlDocPtr doc = NULL;
443 xmlParserCtxtPtr pctx;
444 static xmlSAXHandler sax_handler = {
445 xmlSAX2InternalSubset, /* internalSubset */
446 xmlSAX2IsStandalone, /* isStandalone */
447 xmlSAX2HasInternalSubset, /* hasInternalSubset */
448 xmlSAX2HasExternalSubset, /* hasExternalSubset */
449 xmlSAX2ResolveEntity, /* resolveEntity */
450 xmlSAX2GetEntity, /* getEntity */
451 xmlSAX2EntityDecl, /* entityDecl */
452 xmlSAX2NotationDecl, /* notationDecl */
453 xmlSAX2AttributeDecl, /* attributeDecl */
454 xmlSAX2ElementDecl, /* elementDecl */
455 xmlSAX2UnparsedEntityDecl, /* unparsedEntityDecl */
456 xmlSAX2SetDocumentLocator, /* setDocumentLocator */
457 xmlSAX2StartDocument, /* startDocument */
458 xmlSAX2EndDocument, /* endDocument */
459 xmlSAX2StartElement, /* startElement */
460 xmlSAX2EndElement, /* endElement */
461 xmlSAX2Reference, /* reference */
462 sax_characters, /* characters */
463 sax_characters, /* ignorableWhitespace */
464 xmlSAX2ProcessingInstruction, /* processingInstruction */
465 xmlSAX2Comment, /* comment */
466 sax_warning, /* warning */
467 sax_error, /* error */
468 sax_error, /* fatalError */
469 xmlSAX2GetParameterEntity, /* getParameterEntity */
470 xmlSAX2CDataBlock, /* cdataBlock */
471 xmlSAX2ExternalSubset, /* externalSubset */
474 xmlSAX2StartElementNs, /* startElementNs */
475 xmlSAX2EndElementNs, /* endElementNs */
476 sax_serror /* serror */
480 pctx = xmlCreateMemoryParserCtxt(ptr, len);
483 ERR("Failed to create parser context\n");
487 if (pctx->sax) xmlFree(pctx->sax);
488 pctx->sax = &sax_handler;
489 pctx->_private = This;
492 if (encoding != XML_CHAR_ENCODING_NONE)
493 xmlSwitchEncoding(pctx, encoding);
495 xmlParseDocument(pctx);
497 if (pctx->wellFormed)
503 xmlFreeDoc(pctx->myDoc);
507 xmlFreeParserCtxt(pctx);
509 /* TODO: put this in one of the SAX callbacks */
510 /* create first child as a <?xml...?> */
511 if (doc && doc->standalone != -1)
515 xmlChar *xmlbuff = (xmlChar*)buff;
517 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
519 /* version attribute can't be omitted */
520 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
521 xmlNodeAddContent( node, xmlbuff );
525 sprintf(buff, " encoding=\"%s\"", doc->encoding);
526 xmlNodeAddContent( node, xmlbuff );
529 if (doc->standalone != -2)
531 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
532 xmlNodeAddContent( node, xmlbuff );
535 xmldoc_link_xmldecl( doc, node );
541 void xmldoc_init(xmlDocPtr doc, MSXML_VERSION version)
543 doc->_private = create_priv();
544 priv_from_xmlDocPtr(doc)->properties = create_properties(version);
547 LONG xmldoc_add_ref(xmlDocPtr doc)
549 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
550 TRACE("(%p)->(%d)\n", doc, ref);
554 LONG xmldoc_release(xmlDocPtr doc)
556 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
557 LONG ref = InterlockedDecrement(&priv->refs);
558 TRACE("(%p)->(%d)\n", doc, ref);
561 orphan_entry *orphan, *orphan2;
562 TRACE("freeing docptr %p\n", doc);
564 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
566 xmlFreeNode( orphan->node );
569 free_properties(priv->properties);
570 heap_free(doc->_private);
578 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
580 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
583 entry = heap_alloc( sizeof (*entry) );
585 return E_OUTOFMEMORY;
588 list_add_head( &priv->orphans, &entry->entry );
592 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
594 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
595 orphan_entry *entry, *entry2;
597 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
599 if( entry->node == node )
601 list_remove( &entry->entry );
610 static inline xmlDocPtr get_doc( domdoc *This )
612 return (xmlDocPtr)This->node.node;
615 static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
619 priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
620 if (xmldoc_release(get_doc(This)) != 0)
621 priv_from_xmlDocPtr(get_doc(This))->properties =
622 copy_properties(This->properties);
625 This->node.node = (xmlNodePtr) xml;
629 xmldoc_add_ref(get_doc(This));
630 priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
636 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
638 return CONTAINING_RECORD(iface, domdoc, IXMLDOMDocument3_iface);
641 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
643 return CONTAINING_RECORD(iface, domdoc, IPersistStreamInit_iface);
646 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
648 return CONTAINING_RECORD(iface, domdoc, IObjectWithSite_iface);
651 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
653 return CONTAINING_RECORD(iface, domdoc, IObjectSafety_iface);
656 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
658 return CONTAINING_RECORD(iface, domdoc, ISupportErrorInfo_iface);
661 static inline domdoc *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
663 return CONTAINING_RECORD(iface, domdoc, IConnectionPointContainer_iface);
666 /************************************************************************
667 * domdoc implementation of IPersistStream.
669 static HRESULT WINAPI domdoc_IPersistStreamInit_QueryInterface(
670 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
672 domdoc* This = impl_from_IPersistStreamInit(iface);
673 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppvObj);
676 static ULONG WINAPI domdoc_IPersistStreamInit_AddRef(
677 IPersistStreamInit *iface)
679 domdoc* This = impl_from_IPersistStreamInit(iface);
680 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
683 static ULONG WINAPI domdoc_IPersistStreamInit_Release(
684 IPersistStreamInit *iface)
686 domdoc* This = impl_from_IPersistStreamInit(iface);
687 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
690 static HRESULT WINAPI domdoc_IPersistStreamInit_GetClassID(
691 IPersistStreamInit *iface, CLSID *classid)
693 domdoc* This = impl_from_IPersistStreamInit(iface);
694 TRACE("(%p)->(%p)\n", This, classid);
699 *classid = *DOMDocument_version(This->properties->version);
704 static HRESULT WINAPI domdoc_IPersistStreamInit_IsDirty(
705 IPersistStreamInit *iface)
707 domdoc *This = impl_from_IPersistStreamInit(iface);
708 FIXME("(%p): stub!\n", This);
712 static HRESULT WINAPI domdoc_IPersistStreamInit_Load(
713 IPersistStreamInit *iface, LPSTREAM pStm)
715 domdoc *This = impl_from_IPersistStreamInit(iface);
718 DWORD read, written, len;
721 xmlDocPtr xmldoc = NULL;
723 TRACE("(%p)->(%p)\n", This, pStm);
728 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
734 IStream_Read(pStm, buf, sizeof(buf), &read);
735 hr = IStream_Write(This->stream, buf, read, &written);
736 } while(SUCCEEDED(hr) && written != 0 && read != 0);
740 ERR("Failed to copy stream\n");
744 hr = GetHGlobalFromStream(This->stream, &hglobal);
748 len = GlobalSize(hglobal);
749 ptr = GlobalLock(hglobal);
751 xmldoc = doparse(This, ptr, len, XML_CHAR_ENCODING_NONE);
752 GlobalUnlock(hglobal);
756 ERR("Failed to parse xml\n");
760 xmldoc->_private = create_priv();
762 return attach_xmldoc(This, xmldoc);
765 static HRESULT WINAPI domdoc_IPersistStreamInit_Save(
766 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
768 domdoc *This = impl_from_IPersistStreamInit(iface);
772 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
774 hr = IXMLDOMDocument3_get_xml(&This->IXMLDOMDocument3_iface, &xmlString);
777 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
779 hr = IStream_Write( stream, xmlString, len, NULL );
780 SysFreeString(xmlString);
783 TRACE("ret 0x%08x\n", hr);
788 static HRESULT WINAPI domdoc_IPersistStreamInit_GetSizeMax(
789 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
791 domdoc *This = impl_from_IPersistStreamInit(iface);
792 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
796 static HRESULT WINAPI domdoc_IPersistStreamInit_InitNew(
797 IPersistStreamInit *iface)
799 domdoc *This = impl_from_IPersistStreamInit(iface);
800 TRACE("(%p)\n", This);
804 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
806 domdoc_IPersistStreamInit_QueryInterface,
807 domdoc_IPersistStreamInit_AddRef,
808 domdoc_IPersistStreamInit_Release,
809 domdoc_IPersistStreamInit_GetClassID,
810 domdoc_IPersistStreamInit_IsDirty,
811 domdoc_IPersistStreamInit_Load,
812 domdoc_IPersistStreamInit_Save,
813 domdoc_IPersistStreamInit_GetSizeMax,
814 domdoc_IPersistStreamInit_InitNew
817 /* ISupportErrorInfo interface */
818 static HRESULT WINAPI support_error_QueryInterface(
819 ISupportErrorInfo *iface,
820 REFIID riid, void** ppvObj )
822 domdoc *This = impl_from_ISupportErrorInfo(iface);
823 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppvObj);
826 static ULONG WINAPI support_error_AddRef(
827 ISupportErrorInfo *iface )
829 domdoc *This = impl_from_ISupportErrorInfo(iface);
830 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
833 static ULONG WINAPI support_error_Release(
834 ISupportErrorInfo *iface )
836 domdoc *This = impl_from_ISupportErrorInfo(iface);
837 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
840 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
841 ISupportErrorInfo *iface,
844 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
848 static const struct ISupportErrorInfoVtbl support_error_vtbl =
850 support_error_QueryInterface,
851 support_error_AddRef,
852 support_error_Release,
853 support_error_InterfaceSupportsErrorInfo
856 /* IXMLDOMDocument2 interface */
857 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
859 domdoc *This = impl_from_IXMLDOMDocument3( iface );
861 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
865 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
866 IsEqualGUID( riid, &IID_IDispatch ) ||
867 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
868 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
869 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
870 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
874 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
875 IsEqualGUID(&IID_IPersistStreamInit, riid))
877 *ppvObject = &This->IPersistStreamInit_iface;
879 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
881 *ppvObject = &This->IObjectWithSite_iface;
883 else if (IsEqualGUID(&IID_IObjectSafety, riid))
885 *ppvObject = &This->IObjectSafety_iface;
887 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
889 *ppvObject = &This->ISupportErrorInfo_iface;
891 else if(node_query_interface(&This->node, riid, ppvObject))
893 return *ppvObject ? S_OK : E_NOINTERFACE;
895 else if (IsEqualGUID( riid, &IID_IConnectionPointContainer ))
897 *ppvObject = &This->IConnectionPointContainer_iface;
901 TRACE("interface %s not implemented\n", debugstr_guid(riid));
902 return E_NOINTERFACE;
905 IUnknown_AddRef((IUnknown*)*ppvObject);
911 static ULONG WINAPI domdoc_AddRef(
912 IXMLDOMDocument3 *iface )
914 domdoc *This = impl_from_IXMLDOMDocument3( iface );
915 ULONG ref = InterlockedIncrement( &This->ref );
916 TRACE("(%p)->(%d)\n", This, ref );
921 static ULONG WINAPI domdoc_Release(
922 IXMLDOMDocument3 *iface )
924 domdoc *This = impl_from_IXMLDOMDocument3( iface );
925 LONG ref = InterlockedDecrement( &This->ref );
927 TRACE("(%p)->(%d)\n", This, ref );
934 detach_bsc(This->bsc);
937 IUnknown_Release( This->site );
938 destroy_xmlnode(&This->node);
940 IStream_Release(This->stream);
942 for (eid = 0; eid < EVENTID_LAST; eid++)
943 if (This->events[eid]) IDispatch_Release(This->events[eid]);
951 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
953 domdoc *This = impl_from_IXMLDOMDocument3( iface );
955 TRACE("(%p)->(%p)\n", This, pctinfo);
962 static HRESULT WINAPI domdoc_GetTypeInfo(
963 IXMLDOMDocument3 *iface,
964 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
966 domdoc *This = impl_from_IXMLDOMDocument3( iface );
969 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
971 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
976 static HRESULT WINAPI domdoc_GetIDsOfNames(
977 IXMLDOMDocument3 *iface,
984 domdoc *This = impl_from_IXMLDOMDocument3( iface );
988 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
991 if(!rgszNames || cNames == 0 || !rgDispId)
994 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
997 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
998 ITypeInfo_Release(typeinfo);
1005 static HRESULT WINAPI domdoc_Invoke(
1006 IXMLDOMDocument3 *iface,
1007 DISPID dispIdMember,
1011 DISPPARAMS* pDispParams,
1012 VARIANT* pVarResult,
1013 EXCEPINFO* pExcepInfo,
1016 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1017 ITypeInfo *typeinfo;
1020 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1021 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1023 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
1026 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMDocument3_iface, dispIdMember, wFlags,
1027 pDispParams, pVarResult, pExcepInfo, puArgErr);
1028 ITypeInfo_Release(typeinfo);
1035 static HRESULT WINAPI domdoc_get_nodeName(
1036 IXMLDOMDocument3 *iface,
1039 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1041 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
1043 TRACE("(%p)->(%p)\n", This, name);
1045 return return_bstr(documentW, name);
1049 static HRESULT WINAPI domdoc_get_nodeValue(
1050 IXMLDOMDocument3 *iface,
1053 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1055 TRACE("(%p)->(%p)\n", This, value);
1058 return E_INVALIDARG;
1060 V_VT(value) = VT_NULL;
1061 V_BSTR(value) = NULL; /* tests show that we should do this */
1066 static HRESULT WINAPI domdoc_put_nodeValue(
1067 IXMLDOMDocument3 *iface,
1070 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1071 TRACE("(%p)->(v%d)\n", This, V_VT(&value));
1076 static HRESULT WINAPI domdoc_get_nodeType(
1077 IXMLDOMDocument3 *iface,
1080 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1082 TRACE("(%p)->(%p)\n", This, type);
1084 *type = NODE_DOCUMENT;
1089 static HRESULT WINAPI domdoc_get_parentNode(
1090 IXMLDOMDocument3 *iface,
1091 IXMLDOMNode** parent )
1093 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1095 TRACE("(%p)->(%p)\n", This, parent);
1097 return node_get_parent(&This->node, parent);
1101 static HRESULT WINAPI domdoc_get_childNodes(
1102 IXMLDOMDocument3 *iface,
1103 IXMLDOMNodeList** childList )
1105 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1107 TRACE("(%p)->(%p)\n", This, childList);
1109 return node_get_child_nodes(&This->node, childList);
1113 static HRESULT WINAPI domdoc_get_firstChild(
1114 IXMLDOMDocument3 *iface,
1115 IXMLDOMNode** firstChild )
1117 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1119 TRACE("(%p)->(%p)\n", This, firstChild);
1121 return node_get_first_child(&This->node, firstChild);
1125 static HRESULT WINAPI domdoc_get_lastChild(
1126 IXMLDOMDocument3 *iface,
1127 IXMLDOMNode** lastChild )
1129 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1131 TRACE("(%p)->(%p)\n", This, lastChild);
1133 return node_get_last_child(&This->node, lastChild);
1137 static HRESULT WINAPI domdoc_get_previousSibling(
1138 IXMLDOMDocument3 *iface,
1139 IXMLDOMNode** previousSibling )
1141 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1143 TRACE("(%p)->(%p)\n", This, previousSibling);
1145 return return_null_node(previousSibling);
1149 static HRESULT WINAPI domdoc_get_nextSibling(
1150 IXMLDOMDocument3 *iface,
1151 IXMLDOMNode** nextSibling )
1153 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1155 TRACE("(%p)->(%p)\n", This, nextSibling);
1157 return return_null_node(nextSibling);
1161 static HRESULT WINAPI domdoc_get_attributes(
1162 IXMLDOMDocument3 *iface,
1163 IXMLDOMNamedNodeMap** attributeMap )
1165 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1167 TRACE("(%p)->(%p)\n", This, attributeMap);
1169 return return_null_ptr((void**)attributeMap);
1173 static HRESULT WINAPI domdoc_insertBefore(
1174 IXMLDOMDocument3 *iface,
1175 IXMLDOMNode* newChild,
1177 IXMLDOMNode** outNewChild )
1179 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1181 TRACE("(%p)->(%p x%d %p)\n", This, newChild, V_VT(&refChild), outNewChild);
1183 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1187 static HRESULT WINAPI domdoc_replaceChild(
1188 IXMLDOMDocument3 *iface,
1189 IXMLDOMNode* newChild,
1190 IXMLDOMNode* oldChild,
1191 IXMLDOMNode** outOldChild)
1193 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1195 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1197 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1201 static HRESULT WINAPI domdoc_removeChild(
1202 IXMLDOMDocument3 *iface,
1204 IXMLDOMNode **oldChild)
1206 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1207 TRACE("(%p)->(%p %p)\n", This, child, oldChild);
1208 return node_remove_child(&This->node, child, oldChild);
1212 static HRESULT WINAPI domdoc_appendChild(
1213 IXMLDOMDocument3 *iface,
1215 IXMLDOMNode **outChild)
1217 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1218 TRACE("(%p)->(%p %p)\n", This, child, outChild);
1219 return node_append_child(&This->node, child, outChild);
1223 static HRESULT WINAPI domdoc_hasChildNodes(
1224 IXMLDOMDocument3 *iface,
1227 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1228 TRACE("(%p)->(%p)\n", This, ret);
1229 return node_has_childnodes(&This->node, ret);
1233 static HRESULT WINAPI domdoc_get_ownerDocument(
1234 IXMLDOMDocument3 *iface,
1235 IXMLDOMDocument **doc)
1237 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1238 TRACE("(%p)->(%p)\n", This, doc);
1239 return node_get_owner_doc(&This->node, doc);
1243 static HRESULT WINAPI domdoc_cloneNode(
1244 IXMLDOMDocument3 *iface,
1246 IXMLDOMNode** outNode)
1248 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1249 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
1250 return node_clone( &This->node, deep, outNode );
1254 static HRESULT WINAPI domdoc_get_nodeTypeString(
1255 IXMLDOMDocument3 *iface,
1258 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1259 static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
1261 TRACE("(%p)->(%p)\n", This, p);
1263 return return_bstr(documentW, p);
1267 static HRESULT WINAPI domdoc_get_text(
1268 IXMLDOMDocument3 *iface,
1271 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1272 TRACE("(%p)->(%p)\n", This, p);
1273 return node_get_text(&This->node, p);
1277 static HRESULT WINAPI domdoc_put_text(
1278 IXMLDOMDocument3 *iface,
1281 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1282 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1287 static HRESULT WINAPI domdoc_get_specified(
1288 IXMLDOMDocument3 *iface,
1289 VARIANT_BOOL* isSpecified )
1291 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1292 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1293 *isSpecified = VARIANT_TRUE;
1298 static HRESULT WINAPI domdoc_get_definition(
1299 IXMLDOMDocument3 *iface,
1300 IXMLDOMNode** definitionNode )
1302 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1303 FIXME("(%p)->(%p)\n", This, definitionNode);
1308 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1309 IXMLDOMDocument3 *iface,
1312 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1313 TRACE("(%p)->(%p)\n", This, v);
1314 return return_null_var(v);
1317 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1318 IXMLDOMDocument3 *iface,
1319 VARIANT typedValue )
1321 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1322 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1327 static HRESULT WINAPI domdoc_get_dataType(
1328 IXMLDOMDocument3 *iface,
1331 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1332 TRACE("(%p)->(%p)\n", This, typename);
1333 return return_null_var( typename );
1337 static HRESULT WINAPI domdoc_put_dataType(
1338 IXMLDOMDocument3 *iface,
1341 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1343 FIXME("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
1346 return E_INVALIDARG;
1351 static int XMLCALL domdoc_get_xml_writecallback(void *ctx, const char *data, int len)
1353 return xmlBufferAdd((xmlBufferPtr)ctx, (xmlChar*)data, len) == 0 ? len : 0;
1356 static HRESULT WINAPI domdoc_get_xml(
1357 IXMLDOMDocument3 *iface,
1360 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1361 xmlSaveCtxtPtr ctxt;
1366 TRACE("(%p)->(%p)\n", This, p);
1369 return E_INVALIDARG;
1373 buf = xmlBufferCreate();
1375 return E_OUTOFMEMORY;
1377 options = XML_SAVE_FORMAT | XML_SAVE_NO_DECL;
1378 ctxt = xmlSaveToIO(domdoc_get_xml_writecallback, NULL, buf, "UTF-8", options);
1383 return E_OUTOFMEMORY;
1386 ret = xmlSaveDoc(ctxt, get_doc(This));
1387 /* flushes on close */
1390 TRACE("%ld, len=%d\n", ret, xmlBufferLength(buf));
1391 if(ret != -1 && xmlBufferLength(buf) > 0)
1395 content = bstr_from_xmlChar(xmlBufferContent(buf));
1396 content = EnsureCorrectEOL(content);
1402 *p = SysAllocStringLen(NULL, 0);
1407 return *p ? S_OK : E_OUTOFMEMORY;
1411 static HRESULT WINAPI domdoc_transformNode(
1412 IXMLDOMDocument3 *iface,
1416 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1417 TRACE("(%p)->(%p %p)\n", This, node, p);
1418 return node_transform_node(&This->node, node, p);
1422 static HRESULT WINAPI domdoc_selectNodes(
1423 IXMLDOMDocument3 *iface,
1425 IXMLDOMNodeList **outList)
1427 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1428 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList);
1429 return node_select_nodes(&This->node, p, outList);
1433 static HRESULT WINAPI domdoc_selectSingleNode(
1434 IXMLDOMDocument3 *iface,
1436 IXMLDOMNode **outNode)
1438 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1439 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode);
1440 return node_select_singlenode(&This->node, p, outNode);
1444 static HRESULT WINAPI domdoc_get_parsed(
1445 IXMLDOMDocument3 *iface,
1446 VARIANT_BOOL* isParsed )
1448 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1449 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1450 *isParsed = VARIANT_TRUE;
1455 static HRESULT WINAPI domdoc_get_namespaceURI(
1456 IXMLDOMDocument3 *iface,
1457 BSTR* namespaceURI )
1459 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1460 TRACE("(%p)->(%p)\n", This, namespaceURI);
1461 return node_get_namespaceURI(&This->node, namespaceURI);
1465 static HRESULT WINAPI domdoc_get_prefix(
1466 IXMLDOMDocument3 *iface,
1469 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1470 TRACE("(%p)->(%p)\n", This, prefix);
1471 return return_null_bstr( prefix );
1475 static HRESULT WINAPI domdoc_get_baseName(
1476 IXMLDOMDocument3 *iface,
1479 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1480 TRACE("(%p)->(%p)\n", This, name);
1481 return return_null_bstr( name );
1485 static HRESULT WINAPI domdoc_transformNodeToObject(
1486 IXMLDOMDocument3 *iface,
1487 IXMLDOMNode* stylesheet,
1488 VARIANT outputObject)
1490 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1491 FIXME("(%p)->(%p %s)\n", This, stylesheet, debugstr_variant(&outputObject));
1496 static HRESULT WINAPI domdoc_get_doctype(
1497 IXMLDOMDocument3 *iface,
1498 IXMLDOMDocumentType** doctype )
1500 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1505 TRACE("(%p)->(%p)\n", This, doctype);
1507 if (!doctype) return E_INVALIDARG;
1511 dtd = xmlGetIntSubset(get_doc(This));
1512 if (!dtd) return S_FALSE;
1514 node = create_node((xmlNodePtr)dtd);
1515 if (!node) return S_FALSE;
1517 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentType, (void**)doctype);
1518 IXMLDOMNode_Release(node);
1524 static HRESULT WINAPI domdoc_get_implementation(
1525 IXMLDOMDocument3 *iface,
1526 IXMLDOMImplementation** impl )
1528 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1530 TRACE("(%p)->(%p)\n", This, impl);
1533 return E_INVALIDARG;
1535 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1540 static HRESULT WINAPI domdoc_get_documentElement(
1541 IXMLDOMDocument3 *iface,
1542 IXMLDOMElement** DOMElement )
1544 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1545 IXMLDOMNode *element_node;
1549 TRACE("(%p)->(%p)\n", This, DOMElement);
1552 return E_INVALIDARG;
1556 root = xmlDocGetRootElement( get_doc(This) );
1560 element_node = create_node( root );
1561 if(!element_node) return S_FALSE;
1563 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1564 IXMLDOMNode_Release(element_node);
1570 static HRESULT WINAPI domdoc_put_documentElement(
1571 IXMLDOMDocument3 *iface,
1572 IXMLDOMElement* DOMElement )
1574 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1575 IXMLDOMNode *elementNode;
1580 TRACE("(%p)->(%p)\n", This, DOMElement);
1582 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1586 xmlNode = get_node_obj( elementNode );
1587 if(!xmlNode) return E_FAIL;
1589 if(!xmlNode->node->parent)
1590 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1591 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1593 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1594 IXMLDOMNode_Release( elementNode );
1597 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1603 static HRESULT WINAPI domdoc_createElement(
1604 IXMLDOMDocument3 *iface,
1606 IXMLDOMElement** element )
1608 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1613 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1615 if (!element || !tagname) return E_INVALIDARG;
1617 V_VT(&type) = VT_I1;
1618 V_I1(&type) = NODE_ELEMENT;
1620 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1623 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1624 IXMLDOMNode_Release(node);
1631 static HRESULT WINAPI domdoc_createDocumentFragment(
1632 IXMLDOMDocument3 *iface,
1633 IXMLDOMDocumentFragment** frag )
1635 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1640 TRACE("(%p)->(%p)\n", This, frag);
1642 if (!frag) return E_INVALIDARG;
1646 V_VT(&type) = VT_I1;
1647 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1649 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1652 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1653 IXMLDOMNode_Release(node);
1660 static HRESULT WINAPI domdoc_createTextNode(
1661 IXMLDOMDocument3 *iface,
1663 IXMLDOMText** text )
1665 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1670 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1672 if (!text) return E_INVALIDARG;
1676 V_VT(&type) = VT_I1;
1677 V_I1(&type) = NODE_TEXT;
1679 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1682 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1683 IXMLDOMNode_Release(node);
1684 hr = IXMLDOMText_put_data(*text, data);
1691 static HRESULT WINAPI domdoc_createComment(
1692 IXMLDOMDocument3 *iface,
1694 IXMLDOMComment** comment )
1696 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1701 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1703 if (!comment) return E_INVALIDARG;
1707 V_VT(&type) = VT_I1;
1708 V_I1(&type) = NODE_COMMENT;
1710 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1713 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1714 IXMLDOMNode_Release(node);
1715 hr = IXMLDOMComment_put_data(*comment, data);
1722 static HRESULT WINAPI domdoc_createCDATASection(
1723 IXMLDOMDocument3 *iface,
1725 IXMLDOMCDATASection** cdata )
1727 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1732 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1734 if (!cdata) return E_INVALIDARG;
1738 V_VT(&type) = VT_I1;
1739 V_I1(&type) = NODE_CDATA_SECTION;
1741 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1744 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1745 IXMLDOMNode_Release(node);
1746 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1753 static HRESULT WINAPI domdoc_createProcessingInstruction(
1754 IXMLDOMDocument3 *iface,
1757 IXMLDOMProcessingInstruction** pi )
1759 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1764 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1766 if (!pi) return E_INVALIDARG;
1770 V_VT(&type) = VT_I1;
1771 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1773 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1778 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1779 node_obj = get_node_obj(node);
1780 hr = node_set_content(node_obj, data);
1782 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1783 IXMLDOMNode_Release(node);
1790 static HRESULT WINAPI domdoc_createAttribute(
1791 IXMLDOMDocument3 *iface,
1793 IXMLDOMAttribute** attribute )
1795 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1800 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1802 if (!attribute || !name) return E_INVALIDARG;
1804 V_VT(&type) = VT_I1;
1805 V_I1(&type) = NODE_ATTRIBUTE;
1807 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1810 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1811 IXMLDOMNode_Release(node);
1818 static HRESULT WINAPI domdoc_createEntityReference(
1819 IXMLDOMDocument3 *iface,
1821 IXMLDOMEntityReference** entityref )
1823 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1828 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1830 if (!entityref) return E_INVALIDARG;
1834 V_VT(&type) = VT_I1;
1835 V_I1(&type) = NODE_ENTITY_REFERENCE;
1837 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1840 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1841 IXMLDOMNode_Release(node);
1847 xmlChar* tagName_to_XPath(const BSTR tagName)
1849 xmlChar *query, *tmp;
1850 static const xmlChar mod_pre[] = "*[local-name()='";
1851 static const xmlChar mod_post[] = "']";
1852 static const xmlChar prefix[] = "descendant::";
1853 const WCHAR *tokBegin, *tokEnd;
1856 query = xmlStrdup(prefix);
1859 while (tokBegin && *tokBegin)
1864 query = xmlStrcat(query, BAD_CAST "/");
1868 query = xmlStrcat(query, BAD_CAST "*");
1872 query = xmlStrcat(query, mod_pre);
1874 while (*tokEnd && *tokEnd != '/')
1876 len = WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, NULL, 0, NULL, NULL);
1877 tmp = xmlMalloc(len);
1878 WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, (char*)tmp, len, NULL, NULL);
1879 query = xmlStrncat(query, tmp, len);
1882 query = xmlStrcat(query, mod_post);
1889 static HRESULT WINAPI domdoc_getElementsByTagName(
1890 IXMLDOMDocument3 *iface,
1892 IXMLDOMNodeList** resultList )
1894 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1899 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1901 if (!tagName || !resultList) return E_INVALIDARG;
1903 XPath = This->properties->XPath;
1904 This->properties->XPath = TRUE;
1905 query = tagName_to_XPath(tagName);
1906 hr = create_selection((xmlNodePtr)get_doc(This), query, resultList);
1908 This->properties->XPath = XPath;
1913 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1919 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1921 return E_INVALIDARG;
1928 static HRESULT WINAPI domdoc_createNode(
1929 IXMLDOMDocument3 *iface,
1933 IXMLDOMNode** node )
1935 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1936 DOMNodeType node_type;
1938 xmlChar *xml_name, *href;
1941 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1943 if(!node) return E_INVALIDARG;
1945 hr = get_node_type(Type, &node_type);
1946 if(FAILED(hr)) return hr;
1948 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1949 FIXME("nodes with namespaces currently not supported.\n");
1951 TRACE("node_type %d\n", node_type);
1953 /* exit earlier for types that need name */
1957 case NODE_ATTRIBUTE:
1958 case NODE_ENTITY_REFERENCE:
1959 case NODE_PROCESSING_INSTRUCTION:
1960 if (!name || *name == 0) return E_FAIL;
1966 xml_name = xmlchar_from_wchar(name);
1967 /* prevent empty href to be allocated */
1968 href = namespaceURI ? xmlchar_from_wchar(namespaceURI) : NULL;
1974 xmlChar *local, *prefix;
1976 local = xmlSplitQName2(xml_name, &prefix);
1978 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
1980 /* allow to create default namespace xmlns= */
1981 if (local || (href && *href))
1983 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
1984 xmlSetNs(xmlnode, ns);
1992 case NODE_ATTRIBUTE:
1993 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1996 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1998 case NODE_CDATA_SECTION:
1999 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
2001 case NODE_ENTITY_REFERENCE:
2002 xmlnode = xmlNewReference(get_doc(This), xml_name);
2004 case NODE_PROCESSING_INSTRUCTION:
2005 #ifdef HAVE_XMLNEWDOCPI
2006 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
2008 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2013 xmlnode = xmlNewDocComment(get_doc(This), NULL);
2015 case NODE_DOCUMENT_FRAGMENT:
2016 xmlnode = xmlNewDocFragment(get_doc(This));
2018 /* unsupported types */
2020 case NODE_DOCUMENT_TYPE:
2023 heap_free(xml_name);
2024 return E_INVALIDARG;
2026 FIXME("unhandled node type %d\n", node_type);
2031 *node = create_node(xmlnode);
2032 heap_free(xml_name);
2037 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
2038 xmldoc_add_orphan(xmlnode->doc, xmlnode);
2045 static HRESULT WINAPI domdoc_nodeFromID(
2046 IXMLDOMDocument3 *iface,
2048 IXMLDOMNode** node )
2050 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2051 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
2055 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
2060 xmldoc = doparse(This, ptr, len, XML_CHAR_ENCODING_NONE);
2062 xmldoc->_private = create_priv();
2063 return attach_xmldoc(This, xmldoc);
2069 static HRESULT doread( domdoc *This, LPWSTR filename )
2074 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
2079 hr = detach_bsc(This->bsc);
2088 static HRESULT WINAPI domdoc_load(
2089 IXMLDOMDocument3 *iface,
2091 VARIANT_BOOL* isSuccessful )
2093 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2094 LPWSTR filename = NULL;
2095 HRESULT hr = S_FALSE;
2096 IXMLDOMDocument3 *pNewDoc = NULL;
2097 IStream *pStream = NULL;
2100 TRACE("(%p)->(%s)\n", This, debugstr_variant(&source));
2104 *isSuccessful = VARIANT_FALSE;
2106 assert( &This->node );
2108 switch( V_VT(&source) )
2111 filename = V_BSTR(&source);
2113 case VT_BSTR|VT_BYREF:
2114 if (!V_BSTRREF(&source)) return E_INVALIDARG;
2115 filename = *V_BSTRREF(&source);
2117 case VT_ARRAY|VT_UI1:
2119 SAFEARRAY *psa = V_ARRAY(&source);
2122 UINT dim = SafeArrayGetDim(psa);
2127 ERR("SAFEARRAY == NULL\n");
2128 hr = This->error = E_INVALIDARG;
2131 /* Only takes UTF-8 strings.
2132 * NOT NULL-terminated. */
2133 SafeArrayAccessData(psa, (void**)&str);
2134 SafeArrayGetUBound(psa, 1, &len);
2136 if ((xmldoc = doparse(This, str, ++len, XML_CHAR_ENCODING_UTF8)))
2138 hr = This->error = S_OK;
2139 *isSuccessful = VARIANT_TRUE;
2140 TRACE("parsed document %p\n", xmldoc);
2144 This->error = E_FAIL;
2145 TRACE("failed to parse document\n");
2148 SafeArrayUnaccessData(psa);
2152 xmldoc->_private = create_priv();
2153 return attach_xmldoc(This, xmldoc);
2157 FIXME("unhandled SAFEARRAY dim: %d\n", dim);
2158 hr = This->error = E_NOTIMPL;
2163 hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
2168 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
2169 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
2170 hr = attach_xmldoc(This, xmldoc);
2173 *isSuccessful = VARIANT_TRUE;
2178 hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IStream, (void**)&pStream);
2181 IPersistStream *pDocStream;
2182 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
2185 hr = IPersistStream_Load(pDocStream, pStream);
2186 IStream_Release(pStream);
2189 *isSuccessful = VARIANT_TRUE;
2191 TRACE("Using IStream to load Document\n");
2196 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
2201 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
2206 /* ISequentialStream */
2207 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&source)->lpVtbl);
2211 FIXME("VT type not supported (%d)\n", V_VT(&source));
2216 hr = doread( This, filename );
2219 This->error = E_FAIL;
2222 hr = This->error = S_OK;
2223 *isSuccessful = VARIANT_TRUE;
2227 if(!filename || FAILED(hr)) {
2228 xmldoc = xmlNewDoc(NULL);
2229 xmldoc->_private = create_priv();
2230 hr = attach_xmldoc(This, xmldoc);
2235 TRACE("ret (%d)\n", hr);
2241 static HRESULT WINAPI domdoc_get_readyState(
2242 IXMLDOMDocument3 *iface,
2245 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2246 FIXME("stub! (%p)->(%p)\n", This, value);
2249 return E_INVALIDARG;
2251 *value = READYSTATE_COMPLETE;
2256 static HRESULT WINAPI domdoc_get_parseError(
2257 IXMLDOMDocument3 *iface,
2258 IXMLDOMParseError** errorObj )
2260 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2261 static const WCHAR err[] = {'e','r','r','o','r',0};
2262 BSTR error_string = NULL;
2264 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2267 error_string = SysAllocString(err);
2269 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2270 if(!*errorObj) return E_OUTOFMEMORY;
2275 static HRESULT WINAPI domdoc_get_url(
2276 IXMLDOMDocument3 *iface,
2279 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2280 FIXME("(%p)->(%p)\n", This, urlString);
2285 static HRESULT WINAPI domdoc_get_async(
2286 IXMLDOMDocument3 *iface,
2287 VARIANT_BOOL* isAsync )
2289 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2291 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2292 *isAsync = This->async;
2297 static HRESULT WINAPI domdoc_put_async(
2298 IXMLDOMDocument3 *iface,
2299 VARIANT_BOOL isAsync )
2301 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2303 TRACE("(%p)->(%d)\n", This, isAsync);
2304 This->async = isAsync;
2309 static HRESULT WINAPI domdoc_abort(
2310 IXMLDOMDocument3 *iface )
2312 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2313 FIXME("%p\n", This);
2318 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2319 static HRESULT WINAPI domdoc_loadXML(
2320 IXMLDOMDocument3 *iface,
2322 VARIANT_BOOL* isSuccessful )
2324 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2325 xmlDocPtr xmldoc = NULL;
2326 HRESULT hr = S_FALSE, hr2;
2328 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2330 assert ( &This->node );
2334 *isSuccessful = VARIANT_FALSE;
2338 xmldoc = doparse(This, (LPCSTR)bstrXML, lstrlenW(bstrXML) * sizeof(*bstrXML), XML_CHAR_ENCODING_UTF16LE);
2341 This->error = E_FAIL;
2342 TRACE("failed to parse document\n");
2346 hr = This->error = S_OK;
2347 *isSuccessful = VARIANT_TRUE;
2348 TRACE("parsed document %p\n", xmldoc);
2353 xmldoc = xmlNewDoc(NULL);
2355 xmldoc->_private = create_priv();
2357 hr2 = attach_xmldoc(This, xmldoc);
2364 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2368 if(!WriteFile(ctx, buffer, len, &written, NULL))
2370 WARN("write error\n");
2377 static int XMLCALL domdoc_save_closecallback(void *ctx)
2379 return CloseHandle(ctx) ? 0 : -1;
2382 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2387 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2390 WARN("stream write error: 0x%08x\n", hr);
2397 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2399 IStream_Release((IStream*)ctx);
2403 static HRESULT WINAPI domdoc_save(
2404 IXMLDOMDocument3 *iface,
2405 VARIANT destination )
2407 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2408 xmlSaveCtxtPtr ctx = NULL;
2412 TRACE("(%p)->(%s)\n", This, debugstr_variant(&destination));
2414 switch (V_VT(&destination))
2418 IUnknown *pUnk = V_UNKNOWN(&destination);
2419 IXMLDOMDocument2 *document;
2422 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2425 VARIANT_BOOL success;
2428 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2431 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2435 IXMLDOMDocument3_Release(document);
2439 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2442 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2443 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2447 IStream_Release(stream);
2455 case VT_BSTR | VT_BYREF:
2457 /* save with file path */
2458 HANDLE handle = CreateFileW( (V_VT(&destination) & VT_BYREF)? *V_BSTRREF(&destination) : V_BSTR(&destination),
2459 GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2460 if( handle == INVALID_HANDLE_VALUE )
2462 WARN("failed to create file\n");
2466 /* disable top XML declaration */
2467 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2468 handle, NULL, XML_SAVE_NO_DECL);
2471 CloseHandle(handle);
2478 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination));
2482 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2483 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2484 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2486 /* will release resources through close callback */
2492 static HRESULT WINAPI domdoc_get_validateOnParse(
2493 IXMLDOMDocument3 *iface,
2494 VARIANT_BOOL* isValidating )
2496 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2497 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2498 *isValidating = This->validating;
2503 static HRESULT WINAPI domdoc_put_validateOnParse(
2504 IXMLDOMDocument3 *iface,
2505 VARIANT_BOOL isValidating )
2507 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2508 TRACE("(%p)->(%d)\n", This, isValidating);
2509 This->validating = isValidating;
2514 static HRESULT WINAPI domdoc_get_resolveExternals(
2515 IXMLDOMDocument3 *iface,
2516 VARIANT_BOOL* isResolving )
2518 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2519 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2520 *isResolving = This->resolving;
2525 static HRESULT WINAPI domdoc_put_resolveExternals(
2526 IXMLDOMDocument3 *iface,
2527 VARIANT_BOOL isResolving )
2529 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2530 TRACE("(%p)->(%d)\n", This, isResolving);
2531 This->resolving = isResolving;
2536 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2537 IXMLDOMDocument3 *iface,
2538 VARIANT_BOOL* isPreserving )
2540 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2541 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->properties->preserving);
2542 *isPreserving = This->properties->preserving;
2547 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2548 IXMLDOMDocument3 *iface,
2549 VARIANT_BOOL isPreserving )
2551 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2552 TRACE("(%p)->(%d)\n", This, isPreserving);
2553 This->properties->preserving = isPreserving;
2558 static HRESULT WINAPI domdoc_put_onreadystatechange(
2559 IXMLDOMDocument3 *iface,
2562 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2564 TRACE("(%p)->(%s)\n", This, debugstr_variant(&event));
2565 return set_doc_event(This, EVENTID_READYSTATECHANGE, &event);
2569 static HRESULT WINAPI domdoc_put_onDataAvailable(
2570 IXMLDOMDocument3 *iface,
2571 VARIANT onDataAvailableSink )
2573 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2574 FIXME("%p\n", This);
2578 static HRESULT WINAPI domdoc_put_onTransformNode(
2579 IXMLDOMDocument3 *iface,
2580 VARIANT onTransformNodeSink )
2582 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2583 FIXME("%p\n", This);
2587 static HRESULT WINAPI domdoc_get_namespaces(
2588 IXMLDOMDocument3* iface,
2589 IXMLDOMSchemaCollection** schemaCollection )
2591 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2592 FIXME("(%p)->(%p)\n", This, schemaCollection);
2596 static HRESULT WINAPI domdoc_get_schemas(
2597 IXMLDOMDocument3* iface,
2600 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2601 HRESULT hr = S_FALSE;
2602 IXMLDOMSchemaCollection2* cur_schema = This->properties->schemaCache;
2604 TRACE("(%p)->(%p)\n", This, var1);
2606 VariantInit(var1); /* Test shows we don't call VariantClear here */
2607 V_VT(var1) = VT_NULL;
2611 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2613 V_VT(var1) = VT_DISPATCH;
2618 static HRESULT WINAPI domdoc_putref_schemas(
2619 IXMLDOMDocument3* iface,
2622 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2623 HRESULT hr = E_FAIL;
2624 IXMLDOMSchemaCollection2* new_schema = NULL;
2626 FIXME("(%p): semi-stub\n", This);
2630 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2634 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2643 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2648 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->properties->schemaCache, new_schema);
2649 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2655 static inline BOOL is_wellformed(xmlDocPtr doc)
2657 #ifdef HAVE_XMLDOC_PROPERTIES
2658 return doc->properties & XML_DOC_WELLFORMED;
2660 /* Not a full check, but catches the worst violations */
2664 for (child = doc->children; child != NULL; child = child->next)
2666 switch (child->type)
2668 case XML_ELEMENT_NODE:
2673 case XML_CDATA_SECTION_NODE:
2685 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2689 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2693 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2697 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2701 static HRESULT WINAPI domdoc_validateNode(
2702 IXMLDOMDocument3* iface,
2704 IXMLDOMParseError** err)
2706 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2707 LONG state, err_code = 0;
2711 TRACE("(%p)->(%p, %p)\n", This, node, err);
2712 domdoc_get_readyState(iface, &state);
2713 if (state != READYSTATE_COMPLETE)
2716 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2723 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2727 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2730 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2734 if (!is_wellformed(get_doc(This)))
2736 ERR("doc not well-formed\n");
2738 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2742 /* DTD validation */
2743 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2745 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2746 vctx->error = validate_error;
2747 vctx->warning = validate_warning;
2750 if (!((node == (IXMLDOMNode*)iface)?
2751 xmlValidateDocument(vctx, get_doc(This)) :
2752 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2754 /* TODO: get a real error code here */
2755 TRACE("DTD validation failed\n");
2756 err_code = E_XML_INVALID;
2759 xmlFreeValidCtxt(vctx);
2762 /* Schema validation */
2763 if (hr == S_OK && This->properties->schemaCache != NULL)
2766 hr = SchemaCache_validate_tree(This->properties->schemaCache, get_node_obj(node)->node);
2770 /* TODO: get a real error code here */
2773 TRACE("schema validation succeeded\n");
2777 ERR("schema validation failed\n");
2778 err_code = E_XML_INVALID;
2783 /* not really OK, just didn't find a schema for the ns */
2790 ERR("no DTD or schema found\n");
2791 err_code = E_XML_NODTD;
2796 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2801 static HRESULT WINAPI domdoc_validate(
2802 IXMLDOMDocument3* iface,
2803 IXMLDOMParseError** err)
2805 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2806 TRACE("(%p)->(%p)\n", This, err);
2807 return domdoc_validateNode(iface, (IXMLDOMNode*)iface, err);
2810 static HRESULT WINAPI domdoc_setProperty(
2811 IXMLDOMDocument3* iface,
2815 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2817 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2819 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2825 V_VT(&varStr) = VT_EMPTY;
2826 if (V_VT(&var) != VT_BSTR)
2828 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2830 bstr = V_BSTR(&varStr);
2833 bstr = V_BSTR(&var);
2836 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2837 This->properties->XPath = TRUE;
2838 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2839 This->properties->XPath = FALSE;
2843 VariantClear(&varStr);
2846 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2851 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2852 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2853 xmlXPathContextPtr ctx;
2854 struct list *pNsList;
2855 select_ns_entry* pNsEntry = NULL;
2857 V_VT(&varStr) = VT_EMPTY;
2858 if (V_VT(&var) != VT_BSTR)
2860 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2862 bstr = V_BSTR(&varStr);
2865 bstr = V_BSTR(&var);
2869 pNsList = &(This->properties->selectNsList);
2870 clear_selectNsList(pNsList);
2872 nsStr = xmlchar_from_wchar(bstr);
2874 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2876 This->properties->selectNsStr = nsStr;
2877 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2880 ctx = xmlXPathNewContext(This->node.node->doc);
2882 for (; *pTokBegin; pTokBegin = pTokEnd)
2884 if (pNsEntry != NULL)
2885 memset(pNsEntry, 0, sizeof(select_ns_entry));
2887 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2889 while (*pTokBegin == ' ')
2891 pTokEnd = pTokBegin;
2892 while (*pTokEnd != ' ' && *pTokEnd != 0)
2895 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2898 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2899 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2904 if (*pTokBegin == '=')
2906 /*valid for XSLPattern?*/
2907 FIXME("Setting default xmlns not supported - skipping.\n");
2910 else if (*pTokBegin == ':')
2912 pNsEntry->prefix = ++pTokBegin;
2913 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2916 if (pTokInner == pTokEnd)
2919 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2920 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2924 pNsEntry->prefix_end = *pTokInner;
2928 if (pTokEnd-pTokInner > 1 &&
2929 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2930 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2932 pNsEntry->href = ++pTokInner;
2933 pNsEntry->href_end = *(pTokEnd-1);
2935 list_add_tail(pNsList, &pNsEntry->entry);
2936 /*let libxml figure out if they're valid from here ;)*/
2937 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2946 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2947 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2948 list_add_tail(pNsList, &pNsEntry->entry);
2961 heap_free(pNsEntry);
2962 xmlXPathFreeContext(ctx);
2965 VariantClear(&varStr);
2968 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2969 lstrcmpiW(p, PropertyNewParserW) == 0 ||
2970 lstrcmpiW(p, PropertyResolveExternalsW) == 0)
2973 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2977 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2981 static HRESULT WINAPI domdoc_getProperty(
2982 IXMLDOMDocument3* iface,
2986 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2988 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2991 return E_INVALIDARG;
2993 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2995 V_VT(var) = VT_BSTR;
2996 V_BSTR(var) = This->properties->XPath ?
2997 SysAllocString(PropValueXPathW) :
2998 SysAllocString(PropValueXSLPatternW);
2999 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
3001 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
3004 BSTR rebuiltStr, cur;
3005 const xmlChar *nsStr;
3006 struct list *pNsList;
3007 select_ns_entry* pNsEntry;
3009 V_VT(var) = VT_BSTR;
3010 nsStr = This->properties->selectNsStr;
3011 pNsList = &This->properties->selectNsList;
3012 lenA = This->properties->selectNsStr_len;
3013 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
3014 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
3015 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
3017 /* this is fine because all of the chars that end tokens are ASCII*/
3018 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
3020 while (*cur != 0) ++cur;
3021 if (pNsEntry->prefix_end)
3023 *cur = pNsEntry->prefix_end;
3024 while (*cur != 0) ++cur;
3027 if (pNsEntry->href_end)
3029 *cur = pNsEntry->href_end;
3032 V_BSTR(var) = SysAllocString(rebuiltStr);
3033 heap_free(rebuiltStr);
3037 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
3041 static HRESULT WINAPI domdoc_importNode(
3042 IXMLDOMDocument3* iface,
3045 IXMLDOMNode** clone)
3047 domdoc *This = impl_from_IXMLDOMDocument3( iface );
3048 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
3052 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
3054 domdoc_QueryInterface,
3057 domdoc_GetTypeInfoCount,
3059 domdoc_GetIDsOfNames,
3061 domdoc_get_nodeName,
3062 domdoc_get_nodeValue,
3063 domdoc_put_nodeValue,
3064 domdoc_get_nodeType,
3065 domdoc_get_parentNode,
3066 domdoc_get_childNodes,
3067 domdoc_get_firstChild,
3068 domdoc_get_lastChild,
3069 domdoc_get_previousSibling,
3070 domdoc_get_nextSibling,
3071 domdoc_get_attributes,
3072 domdoc_insertBefore,
3073 domdoc_replaceChild,
3076 domdoc_hasChildNodes,
3077 domdoc_get_ownerDocument,
3079 domdoc_get_nodeTypeString,
3082 domdoc_get_specified,
3083 domdoc_get_definition,
3084 domdoc_get_nodeTypedValue,
3085 domdoc_put_nodeTypedValue,
3086 domdoc_get_dataType,
3087 domdoc_put_dataType,
3089 domdoc_transformNode,
3091 domdoc_selectSingleNode,
3093 domdoc_get_namespaceURI,
3095 domdoc_get_baseName,
3096 domdoc_transformNodeToObject,
3098 domdoc_get_implementation,
3099 domdoc_get_documentElement,
3100 domdoc_put_documentElement,
3101 domdoc_createElement,
3102 domdoc_createDocumentFragment,
3103 domdoc_createTextNode,
3104 domdoc_createComment,
3105 domdoc_createCDATASection,
3106 domdoc_createProcessingInstruction,
3107 domdoc_createAttribute,
3108 domdoc_createEntityReference,
3109 domdoc_getElementsByTagName,
3113 domdoc_get_readyState,
3114 domdoc_get_parseError,
3121 domdoc_get_validateOnParse,
3122 domdoc_put_validateOnParse,
3123 domdoc_get_resolveExternals,
3124 domdoc_put_resolveExternals,
3125 domdoc_get_preserveWhiteSpace,
3126 domdoc_put_preserveWhiteSpace,
3127 domdoc_put_onreadystatechange,
3128 domdoc_put_onDataAvailable,
3129 domdoc_put_onTransformNode,
3130 domdoc_get_namespaces,
3132 domdoc_putref_schemas,
3136 domdoc_validateNode,
3140 /* IConnectionPointContainer */
3141 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
3142 REFIID riid, void **ppv)
3144 domdoc *This = impl_from_IConnectionPointContainer(iface);
3145 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppv);
3148 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
3150 domdoc *This = impl_from_IConnectionPointContainer(iface);
3151 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3154 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
3156 domdoc *This = impl_from_IConnectionPointContainer(iface);
3157 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3160 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
3161 IEnumConnectionPoints **ppEnum)
3163 domdoc *This = impl_from_IConnectionPointContainer(iface);
3164 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3168 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
3169 REFIID riid, IConnectionPoint **cp)
3171 domdoc *This = impl_from_IConnectionPointContainer(iface);
3172 ConnectionPoint *iter;
3174 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
3178 for(iter = This->cp_list; iter; iter = iter->next)
3180 if (IsEqualGUID(iter->iid, riid))
3181 *cp = &iter->IConnectionPoint_iface;
3186 IConnectionPoint_AddRef(*cp);
3190 FIXME("unsupported riid %s\n", debugstr_guid(riid));
3191 return CONNECT_E_NOCONNECTION;
3195 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
3197 ConnectionPointContainer_QueryInterface,
3198 ConnectionPointContainer_AddRef,
3199 ConnectionPointContainer_Release,
3200 ConnectionPointContainer_EnumConnectionPoints,
3201 ConnectionPointContainer_FindConnectionPoint
3204 /* IConnectionPoint */
3205 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
3206 REFIID riid, void **ppv)
3208 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3210 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3214 if (IsEqualGUID(&IID_IUnknown, riid) ||
3215 IsEqualGUID(&IID_IConnectionPoint, riid))
3222 IConnectionPoint_AddRef(iface);
3226 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3227 return E_NOINTERFACE;
3230 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3232 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3233 return IConnectionPointContainer_AddRef(This->container);
3236 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3238 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3239 return IConnectionPointContainer_Release(This->container);
3242 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3244 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3246 TRACE("(%p)->(%p)\n", This, iid);
3248 if (!iid) return E_POINTER;
3254 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3255 IConnectionPointContainer **container)
3257 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3259 TRACE("(%p)->(%p)\n", This, container);
3261 if (!container) return E_POINTER;
3263 *container = This->container;
3264 IConnectionPointContainer_AddRef(*container);
3268 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
3271 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3272 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
3276 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3278 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3280 TRACE("(%p)->(%d)\n", This, cookie);
3282 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3283 return CONNECT_E_NOCONNECTION;
3285 IUnknown_Release(This->sinks[cookie-1].unk);
3286 This->sinks[cookie-1].unk = NULL;
3291 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3292 IEnumConnections **ppEnum)
3294 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3295 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3299 static const IConnectionPointVtbl ConnectionPointVtbl =
3301 ConnectionPoint_QueryInterface,
3302 ConnectionPoint_AddRef,
3303 ConnectionPoint_Release,
3304 ConnectionPoint_GetConnectionInterface,
3305 ConnectionPoint_GetConnectionPointContainer,
3306 ConnectionPoint_Advise,
3307 ConnectionPoint_Unadvise,
3308 ConnectionPoint_EnumConnections
3311 static void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3313 cp->IConnectionPoint_iface.lpVtbl = &ConnectionPointVtbl;
3319 cp->next = doc->cp_list;
3322 cp->container = &doc->IConnectionPointContainer_iface;
3325 /* domdoc implementation of IObjectWithSite */
3326 static HRESULT WINAPI
3327 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3329 domdoc *This = impl_from_IObjectWithSite(iface);
3330 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppvObject);
3333 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3335 domdoc *This = impl_from_IObjectWithSite(iface);
3336 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3339 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3341 domdoc *This = impl_from_IObjectWithSite(iface);
3342 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3345 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3347 domdoc *This = impl_from_IObjectWithSite(iface);
3349 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3354 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3357 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3359 domdoc *This = impl_from_IObjectWithSite(iface);
3361 TRACE("(%p)->(%p)\n", iface, punk);
3367 IUnknown_Release( This->site );
3374 IUnknown_AddRef( punk );
3377 IUnknown_Release( This->site );
3384 static const IObjectWithSiteVtbl domdocObjectSite =
3386 domdoc_ObjectWithSite_QueryInterface,
3387 domdoc_ObjectWithSite_AddRef,
3388 domdoc_ObjectWithSite_Release,
3389 domdoc_ObjectWithSite_SetSite,
3390 domdoc_ObjectWithSite_GetSite
3393 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3395 domdoc *This = impl_from_IObjectSafety(iface);
3396 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppv);
3399 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3401 domdoc *This = impl_from_IObjectSafety(iface);
3402 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3405 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3407 domdoc *This = impl_from_IObjectSafety(iface);
3408 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3411 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3413 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3414 DWORD *supported, DWORD *enabled)
3416 domdoc *This = impl_from_IObjectSafety(iface);
3418 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3420 if(!supported || !enabled) return E_POINTER;
3422 *supported = SAFETY_SUPPORTED_OPTIONS;
3423 *enabled = This->safeopt;
3428 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3429 DWORD mask, DWORD enabled)
3431 domdoc *This = impl_from_IObjectSafety(iface);
3432 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3434 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3437 This->safeopt = (This->safeopt & ~mask) | (mask & enabled);
3442 #undef SAFETY_SUPPORTED_OPTIONS
3444 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3445 domdoc_Safety_QueryInterface,
3446 domdoc_Safety_AddRef,
3447 domdoc_Safety_Release,
3448 domdoc_Safety_GetInterfaceSafetyOptions,
3449 domdoc_Safety_SetInterfaceSafetyOptions
3452 static const tid_t domdoc_iface_tids[] = {
3454 IXMLDOMDocument_tid,
3455 IXMLDOMDocument2_tid,
3458 static dispex_static_data_t domdoc_dispex = {
3460 IXMLDOMDocument2_tid,
3465 HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3469 doc = heap_alloc( sizeof (*doc) );
3471 return E_OUTOFMEMORY;
3473 doc->IXMLDOMDocument3_iface.lpVtbl = &domdoc_vtbl;
3474 doc->IPersistStreamInit_iface.lpVtbl = &xmldoc_IPersistStreamInit_VTable;
3475 doc->IObjectWithSite_iface.lpVtbl = &domdocObjectSite;
3476 doc->IObjectSafety_iface.lpVtbl = &domdocObjectSafetyVtbl;
3477 doc->ISupportErrorInfo_iface.lpVtbl = &support_error_vtbl;
3478 doc->IConnectionPointContainer_iface.lpVtbl = &ConnectionPointContainerVtbl;
3480 doc->async = VARIANT_TRUE;
3481 doc->validating = 0;
3483 doc->properties = properties_from_xmlDocPtr(xmldoc);
3489 doc->cp_list = NULL;
3490 memset(doc->events, 0, sizeof(doc->events));
3492 /* events connection points */
3493 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3494 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3495 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3497 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->IXMLDOMDocument3_iface,
3500 *document = &doc->IXMLDOMDocument3_iface;
3502 TRACE("returning iface %p\n", *document);
3506 HRESULT DOMDocument_create(MSXML_VERSION version, IUnknown *pUnkOuter, void **ppObj)
3511 TRACE("(%d, %p, %p)\n", version, pUnkOuter, ppObj);
3513 xmldoc = xmlNewDoc(NULL);
3515 return E_OUTOFMEMORY;
3517 xmldoc->_private = create_priv();
3518 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(version);
3520 hr = get_domdoc_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3523 free_properties(properties_from_xmlDocPtr(xmldoc));
3524 heap_free(xmldoc->_private);
3532 IUnknown* create_domdoc( xmlNodePtr document )
3537 TRACE("(%p)\n", document);
3539 hr = get_domdoc_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3548 HRESULT DOMDocument_create(MSXML_VERSION version, IUnknown *pUnkOuter, void **ppObj)
3550 MESSAGE("This program tried to use a DOMDocument object, but\n"
3551 "libxml2 support was not present at compile time.\n");