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 detach_bsc(This->bsc);
2085 static HRESULT WINAPI domdoc_load(
2086 IXMLDOMDocument3 *iface,
2088 VARIANT_BOOL* isSuccessful )
2090 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2091 LPWSTR filename = NULL;
2092 HRESULT hr = S_FALSE;
2093 IXMLDOMDocument3 *pNewDoc = NULL;
2094 IStream *pStream = NULL;
2097 TRACE("(%p)->(%s)\n", This, debugstr_variant(&source));
2101 *isSuccessful = VARIANT_FALSE;
2103 assert( &This->node );
2105 switch( V_VT(&source) )
2108 filename = V_BSTR(&source);
2110 case VT_BSTR|VT_BYREF:
2111 if (!V_BSTRREF(&source)) return E_INVALIDARG;
2112 filename = *V_BSTRREF(&source);
2114 case VT_ARRAY|VT_UI1:
2116 SAFEARRAY *psa = V_ARRAY(&source);
2119 UINT dim = SafeArrayGetDim(psa);
2124 ERR("SAFEARRAY == NULL\n");
2125 hr = This->error = E_INVALIDARG;
2128 /* Only takes UTF-8 strings.
2129 * NOT NULL-terminated. */
2130 SafeArrayAccessData(psa, (void**)&str);
2131 SafeArrayGetUBound(psa, 1, &len);
2133 if ((xmldoc = doparse(This, str, ++len, XML_CHAR_ENCODING_UTF8)))
2135 hr = This->error = S_OK;
2136 *isSuccessful = VARIANT_TRUE;
2137 TRACE("parsed document %p\n", xmldoc);
2141 This->error = E_FAIL;
2142 TRACE("failed to parse document\n");
2145 SafeArrayUnaccessData(psa);
2149 xmldoc->_private = create_priv();
2150 return attach_xmldoc(This, xmldoc);
2154 FIXME("unhandled SAFEARRAY dim: %d\n", dim);
2155 hr = This->error = E_NOTIMPL;
2160 hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
2165 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
2166 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
2167 hr = attach_xmldoc(This, xmldoc);
2170 *isSuccessful = VARIANT_TRUE;
2175 hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IStream, (void**)&pStream);
2178 IPersistStream *pDocStream;
2179 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
2182 hr = IPersistStream_Load(pDocStream, pStream);
2183 IStream_Release(pStream);
2186 *isSuccessful = VARIANT_TRUE;
2188 TRACE("Using IStream to load Document\n");
2193 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
2198 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
2203 /* ISequentialStream */
2204 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&source)->lpVtbl);
2208 FIXME("VT type not supported (%d)\n", V_VT(&source));
2213 hr = doread( This, filename );
2216 This->error = E_FAIL;
2219 hr = This->error = S_OK;
2220 *isSuccessful = VARIANT_TRUE;
2224 if(!filename || FAILED(hr)) {
2225 xmldoc = xmlNewDoc(NULL);
2226 xmldoc->_private = create_priv();
2227 hr = attach_xmldoc(This, xmldoc);
2232 TRACE("ret (%d)\n", hr);
2238 static HRESULT WINAPI domdoc_get_readyState(
2239 IXMLDOMDocument3 *iface,
2242 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2243 FIXME("stub! (%p)->(%p)\n", This, value);
2246 return E_INVALIDARG;
2248 *value = READYSTATE_COMPLETE;
2253 static HRESULT WINAPI domdoc_get_parseError(
2254 IXMLDOMDocument3 *iface,
2255 IXMLDOMParseError** errorObj )
2257 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2258 static const WCHAR err[] = {'e','r','r','o','r',0};
2259 BSTR error_string = NULL;
2261 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2264 error_string = SysAllocString(err);
2266 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2267 if(!*errorObj) return E_OUTOFMEMORY;
2272 static HRESULT WINAPI domdoc_get_url(
2273 IXMLDOMDocument3 *iface,
2276 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2277 FIXME("(%p)->(%p)\n", This, urlString);
2282 static HRESULT WINAPI domdoc_get_async(
2283 IXMLDOMDocument3 *iface,
2284 VARIANT_BOOL* isAsync )
2286 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2288 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2289 *isAsync = This->async;
2294 static HRESULT WINAPI domdoc_put_async(
2295 IXMLDOMDocument3 *iface,
2296 VARIANT_BOOL isAsync )
2298 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2300 TRACE("(%p)->(%d)\n", This, isAsync);
2301 This->async = isAsync;
2306 static HRESULT WINAPI domdoc_abort(
2307 IXMLDOMDocument3 *iface )
2309 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2310 FIXME("%p\n", This);
2315 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2316 static HRESULT WINAPI domdoc_loadXML(
2317 IXMLDOMDocument3 *iface,
2319 VARIANT_BOOL* isSuccessful )
2321 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2322 xmlDocPtr xmldoc = NULL;
2323 HRESULT hr = S_FALSE, hr2;
2325 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2327 assert ( &This->node );
2331 *isSuccessful = VARIANT_FALSE;
2335 xmldoc = doparse(This, (LPCSTR)bstrXML, lstrlenW(bstrXML) * sizeof(*bstrXML), XML_CHAR_ENCODING_UTF16LE);
2338 This->error = E_FAIL;
2339 TRACE("failed to parse document\n");
2343 hr = This->error = S_OK;
2344 *isSuccessful = VARIANT_TRUE;
2345 TRACE("parsed document %p\n", xmldoc);
2350 xmldoc = xmlNewDoc(NULL);
2352 xmldoc->_private = create_priv();
2354 hr2 = attach_xmldoc(This, xmldoc);
2361 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2365 if(!WriteFile(ctx, buffer, len, &written, NULL))
2367 WARN("write error\n");
2374 static int XMLCALL domdoc_save_closecallback(void *ctx)
2376 return CloseHandle(ctx) ? 0 : -1;
2379 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2384 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2387 WARN("stream write error: 0x%08x\n", hr);
2394 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2396 IStream_Release((IStream*)ctx);
2400 static HRESULT WINAPI domdoc_save(
2401 IXMLDOMDocument3 *iface,
2402 VARIANT destination )
2404 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2405 xmlSaveCtxtPtr ctx = NULL;
2409 TRACE("(%p)->(%s)\n", This, debugstr_variant(&destination));
2411 switch (V_VT(&destination))
2415 IUnknown *pUnk = V_UNKNOWN(&destination);
2416 IXMLDOMDocument2 *document;
2419 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2422 VARIANT_BOOL success;
2425 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2428 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2432 IXMLDOMDocument3_Release(document);
2436 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2439 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2440 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2444 IStream_Release(stream);
2452 case VT_BSTR | VT_BYREF:
2454 /* save with file path */
2455 HANDLE handle = CreateFileW( (V_VT(&destination) & VT_BYREF)? *V_BSTRREF(&destination) : V_BSTR(&destination),
2456 GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2457 if( handle == INVALID_HANDLE_VALUE )
2459 WARN("failed to create file\n");
2463 /* disable top XML declaration */
2464 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2465 handle, NULL, XML_SAVE_NO_DECL);
2468 CloseHandle(handle);
2475 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination));
2479 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2480 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2481 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2483 /* will release resources through close callback */
2489 static HRESULT WINAPI domdoc_get_validateOnParse(
2490 IXMLDOMDocument3 *iface,
2491 VARIANT_BOOL* isValidating )
2493 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2494 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2495 *isValidating = This->validating;
2500 static HRESULT WINAPI domdoc_put_validateOnParse(
2501 IXMLDOMDocument3 *iface,
2502 VARIANT_BOOL isValidating )
2504 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2505 TRACE("(%p)->(%d)\n", This, isValidating);
2506 This->validating = isValidating;
2511 static HRESULT WINAPI domdoc_get_resolveExternals(
2512 IXMLDOMDocument3 *iface,
2513 VARIANT_BOOL* isResolving )
2515 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2516 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2517 *isResolving = This->resolving;
2522 static HRESULT WINAPI domdoc_put_resolveExternals(
2523 IXMLDOMDocument3 *iface,
2524 VARIANT_BOOL isResolving )
2526 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2527 TRACE("(%p)->(%d)\n", This, isResolving);
2528 This->resolving = isResolving;
2533 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2534 IXMLDOMDocument3 *iface,
2535 VARIANT_BOOL* isPreserving )
2537 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2538 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->properties->preserving);
2539 *isPreserving = This->properties->preserving;
2544 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2545 IXMLDOMDocument3 *iface,
2546 VARIANT_BOOL isPreserving )
2548 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2549 TRACE("(%p)->(%d)\n", This, isPreserving);
2550 This->properties->preserving = isPreserving;
2555 static HRESULT WINAPI domdoc_put_onreadystatechange(
2556 IXMLDOMDocument3 *iface,
2559 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2561 TRACE("(%p)->(%s)\n", This, debugstr_variant(&event));
2562 return set_doc_event(This, EVENTID_READYSTATECHANGE, &event);
2566 static HRESULT WINAPI domdoc_put_onDataAvailable(
2567 IXMLDOMDocument3 *iface,
2568 VARIANT onDataAvailableSink )
2570 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2571 FIXME("%p\n", This);
2575 static HRESULT WINAPI domdoc_put_onTransformNode(
2576 IXMLDOMDocument3 *iface,
2577 VARIANT onTransformNodeSink )
2579 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2580 FIXME("%p\n", This);
2584 static HRESULT WINAPI domdoc_get_namespaces(
2585 IXMLDOMDocument3* iface,
2586 IXMLDOMSchemaCollection** schemaCollection )
2588 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2589 FIXME("(%p)->(%p)\n", This, schemaCollection);
2593 static HRESULT WINAPI domdoc_get_schemas(
2594 IXMLDOMDocument3* iface,
2597 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2598 HRESULT hr = S_FALSE;
2599 IXMLDOMSchemaCollection2* cur_schema = This->properties->schemaCache;
2601 TRACE("(%p)->(%p)\n", This, var1);
2603 VariantInit(var1); /* Test shows we don't call VariantClear here */
2604 V_VT(var1) = VT_NULL;
2608 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2610 V_VT(var1) = VT_DISPATCH;
2615 static HRESULT WINAPI domdoc_putref_schemas(
2616 IXMLDOMDocument3* iface,
2619 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2620 HRESULT hr = E_FAIL;
2621 IXMLDOMSchemaCollection2* new_schema = NULL;
2623 FIXME("(%p): semi-stub\n", This);
2627 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2631 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2640 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2645 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->properties->schemaCache, new_schema);
2646 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2652 static inline BOOL is_wellformed(xmlDocPtr doc)
2654 #ifdef HAVE_XMLDOC_PROPERTIES
2655 return doc->properties & XML_DOC_WELLFORMED;
2657 /* Not a full check, but catches the worst violations */
2661 for (child = doc->children; child != NULL; child = child->next)
2663 switch (child->type)
2665 case XML_ELEMENT_NODE:
2670 case XML_CDATA_SECTION_NODE:
2682 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2686 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2690 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2694 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2698 static HRESULT WINAPI domdoc_validateNode(
2699 IXMLDOMDocument3* iface,
2701 IXMLDOMParseError** err)
2703 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2704 LONG state, err_code = 0;
2708 TRACE("(%p)->(%p, %p)\n", This, node, err);
2709 domdoc_get_readyState(iface, &state);
2710 if (state != READYSTATE_COMPLETE)
2713 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2720 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2724 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2727 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2731 if (!is_wellformed(get_doc(This)))
2733 ERR("doc not well-formed\n");
2735 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2739 /* DTD validation */
2740 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2742 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2743 vctx->error = validate_error;
2744 vctx->warning = validate_warning;
2747 if (!((node == (IXMLDOMNode*)iface)?
2748 xmlValidateDocument(vctx, get_doc(This)) :
2749 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2751 /* TODO: get a real error code here */
2752 TRACE("DTD validation failed\n");
2753 err_code = E_XML_INVALID;
2756 xmlFreeValidCtxt(vctx);
2759 /* Schema validation */
2760 if (hr == S_OK && This->properties->schemaCache != NULL)
2763 hr = SchemaCache_validate_tree(This->properties->schemaCache, get_node_obj(node)->node);
2767 /* TODO: get a real error code here */
2770 TRACE("schema validation succeeded\n");
2774 ERR("schema validation failed\n");
2775 err_code = E_XML_INVALID;
2780 /* not really OK, just didn't find a schema for the ns */
2787 ERR("no DTD or schema found\n");
2788 err_code = E_XML_NODTD;
2793 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2798 static HRESULT WINAPI domdoc_validate(
2799 IXMLDOMDocument3* iface,
2800 IXMLDOMParseError** err)
2802 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2803 TRACE("(%p)->(%p)\n", This, err);
2804 return domdoc_validateNode(iface, (IXMLDOMNode*)iface, err);
2807 static HRESULT WINAPI domdoc_setProperty(
2808 IXMLDOMDocument3* iface,
2812 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2814 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2816 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2822 V_VT(&varStr) = VT_EMPTY;
2823 if (V_VT(&var) != VT_BSTR)
2825 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2827 bstr = V_BSTR(&varStr);
2830 bstr = V_BSTR(&var);
2833 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2834 This->properties->XPath = TRUE;
2835 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2836 This->properties->XPath = FALSE;
2840 VariantClear(&varStr);
2843 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2848 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2849 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2850 xmlXPathContextPtr ctx;
2851 struct list *pNsList;
2852 select_ns_entry* pNsEntry = NULL;
2854 V_VT(&varStr) = VT_EMPTY;
2855 if (V_VT(&var) != VT_BSTR)
2857 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2859 bstr = V_BSTR(&varStr);
2862 bstr = V_BSTR(&var);
2866 pNsList = &(This->properties->selectNsList);
2867 clear_selectNsList(pNsList);
2869 nsStr = xmlchar_from_wchar(bstr);
2871 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2873 This->properties->selectNsStr = nsStr;
2874 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2877 ctx = xmlXPathNewContext(This->node.node->doc);
2879 for (; *pTokBegin; pTokBegin = pTokEnd)
2881 if (pNsEntry != NULL)
2882 memset(pNsEntry, 0, sizeof(select_ns_entry));
2884 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2886 while (*pTokBegin == ' ')
2888 pTokEnd = pTokBegin;
2889 while (*pTokEnd != ' ' && *pTokEnd != 0)
2892 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2895 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2896 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2901 if (*pTokBegin == '=')
2903 /*valid for XSLPattern?*/
2904 FIXME("Setting default xmlns not supported - skipping.\n");
2907 else if (*pTokBegin == ':')
2909 pNsEntry->prefix = ++pTokBegin;
2910 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2913 if (pTokInner == pTokEnd)
2916 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2917 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2921 pNsEntry->prefix_end = *pTokInner;
2925 if (pTokEnd-pTokInner > 1 &&
2926 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2927 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2929 pNsEntry->href = ++pTokInner;
2930 pNsEntry->href_end = *(pTokEnd-1);
2932 list_add_tail(pNsList, &pNsEntry->entry);
2933 /*let libxml figure out if they're valid from here ;)*/
2934 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2943 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2944 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2945 list_add_tail(pNsList, &pNsEntry->entry);
2958 heap_free(pNsEntry);
2959 xmlXPathFreeContext(ctx);
2962 VariantClear(&varStr);
2965 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2966 lstrcmpiW(p, PropertyNewParserW) == 0 ||
2967 lstrcmpiW(p, PropertyResolveExternalsW) == 0)
2970 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2974 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2978 static HRESULT WINAPI domdoc_getProperty(
2979 IXMLDOMDocument3* iface,
2983 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2985 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2988 return E_INVALIDARG;
2990 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2992 V_VT(var) = VT_BSTR;
2993 V_BSTR(var) = This->properties->XPath ?
2994 SysAllocString(PropValueXPathW) :
2995 SysAllocString(PropValueXSLPatternW);
2996 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2998 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
3001 BSTR rebuiltStr, cur;
3002 const xmlChar *nsStr;
3003 struct list *pNsList;
3004 select_ns_entry* pNsEntry;
3006 V_VT(var) = VT_BSTR;
3007 nsStr = This->properties->selectNsStr;
3008 pNsList = &This->properties->selectNsList;
3009 lenA = This->properties->selectNsStr_len;
3010 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
3011 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
3012 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
3014 /* this is fine because all of the chars that end tokens are ASCII*/
3015 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
3017 while (*cur != 0) ++cur;
3018 if (pNsEntry->prefix_end)
3020 *cur = pNsEntry->prefix_end;
3021 while (*cur != 0) ++cur;
3024 if (pNsEntry->href_end)
3026 *cur = pNsEntry->href_end;
3029 V_BSTR(var) = SysAllocString(rebuiltStr);
3030 heap_free(rebuiltStr);
3034 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
3038 static HRESULT WINAPI domdoc_importNode(
3039 IXMLDOMDocument3* iface,
3042 IXMLDOMNode** clone)
3044 domdoc *This = impl_from_IXMLDOMDocument3( iface );
3045 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
3049 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
3051 domdoc_QueryInterface,
3054 domdoc_GetTypeInfoCount,
3056 domdoc_GetIDsOfNames,
3058 domdoc_get_nodeName,
3059 domdoc_get_nodeValue,
3060 domdoc_put_nodeValue,
3061 domdoc_get_nodeType,
3062 domdoc_get_parentNode,
3063 domdoc_get_childNodes,
3064 domdoc_get_firstChild,
3065 domdoc_get_lastChild,
3066 domdoc_get_previousSibling,
3067 domdoc_get_nextSibling,
3068 domdoc_get_attributes,
3069 domdoc_insertBefore,
3070 domdoc_replaceChild,
3073 domdoc_hasChildNodes,
3074 domdoc_get_ownerDocument,
3076 domdoc_get_nodeTypeString,
3079 domdoc_get_specified,
3080 domdoc_get_definition,
3081 domdoc_get_nodeTypedValue,
3082 domdoc_put_nodeTypedValue,
3083 domdoc_get_dataType,
3084 domdoc_put_dataType,
3086 domdoc_transformNode,
3088 domdoc_selectSingleNode,
3090 domdoc_get_namespaceURI,
3092 domdoc_get_baseName,
3093 domdoc_transformNodeToObject,
3095 domdoc_get_implementation,
3096 domdoc_get_documentElement,
3097 domdoc_put_documentElement,
3098 domdoc_createElement,
3099 domdoc_createDocumentFragment,
3100 domdoc_createTextNode,
3101 domdoc_createComment,
3102 domdoc_createCDATASection,
3103 domdoc_createProcessingInstruction,
3104 domdoc_createAttribute,
3105 domdoc_createEntityReference,
3106 domdoc_getElementsByTagName,
3110 domdoc_get_readyState,
3111 domdoc_get_parseError,
3118 domdoc_get_validateOnParse,
3119 domdoc_put_validateOnParse,
3120 domdoc_get_resolveExternals,
3121 domdoc_put_resolveExternals,
3122 domdoc_get_preserveWhiteSpace,
3123 domdoc_put_preserveWhiteSpace,
3124 domdoc_put_onreadystatechange,
3125 domdoc_put_onDataAvailable,
3126 domdoc_put_onTransformNode,
3127 domdoc_get_namespaces,
3129 domdoc_putref_schemas,
3133 domdoc_validateNode,
3137 /* IConnectionPointContainer */
3138 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
3139 REFIID riid, void **ppv)
3141 domdoc *This = impl_from_IConnectionPointContainer(iface);
3142 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppv);
3145 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
3147 domdoc *This = impl_from_IConnectionPointContainer(iface);
3148 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3151 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
3153 domdoc *This = impl_from_IConnectionPointContainer(iface);
3154 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3157 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
3158 IEnumConnectionPoints **ppEnum)
3160 domdoc *This = impl_from_IConnectionPointContainer(iface);
3161 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3165 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
3166 REFIID riid, IConnectionPoint **cp)
3168 domdoc *This = impl_from_IConnectionPointContainer(iface);
3169 ConnectionPoint *iter;
3171 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
3175 for(iter = This->cp_list; iter; iter = iter->next)
3177 if (IsEqualGUID(iter->iid, riid))
3178 *cp = &iter->IConnectionPoint_iface;
3183 IConnectionPoint_AddRef(*cp);
3187 FIXME("unsupported riid %s\n", debugstr_guid(riid));
3188 return CONNECT_E_NOCONNECTION;
3192 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
3194 ConnectionPointContainer_QueryInterface,
3195 ConnectionPointContainer_AddRef,
3196 ConnectionPointContainer_Release,
3197 ConnectionPointContainer_EnumConnectionPoints,
3198 ConnectionPointContainer_FindConnectionPoint
3201 /* IConnectionPoint */
3202 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
3203 REFIID riid, void **ppv)
3205 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3207 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3211 if (IsEqualGUID(&IID_IUnknown, riid) ||
3212 IsEqualGUID(&IID_IConnectionPoint, riid))
3219 IConnectionPoint_AddRef(iface);
3223 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3224 return E_NOINTERFACE;
3227 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3229 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3230 return IConnectionPointContainer_AddRef(This->container);
3233 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3235 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3236 return IConnectionPointContainer_Release(This->container);
3239 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3241 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3243 TRACE("(%p)->(%p)\n", This, iid);
3245 if (!iid) return E_POINTER;
3251 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3252 IConnectionPointContainer **container)
3254 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3256 TRACE("(%p)->(%p)\n", This, container);
3258 if (!container) return E_POINTER;
3260 *container = This->container;
3261 IConnectionPointContainer_AddRef(*container);
3265 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
3268 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3269 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
3273 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3275 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3277 TRACE("(%p)->(%d)\n", This, cookie);
3279 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3280 return CONNECT_E_NOCONNECTION;
3282 IUnknown_Release(This->sinks[cookie-1].unk);
3283 This->sinks[cookie-1].unk = NULL;
3288 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3289 IEnumConnections **ppEnum)
3291 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3292 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3296 static const IConnectionPointVtbl ConnectionPointVtbl =
3298 ConnectionPoint_QueryInterface,
3299 ConnectionPoint_AddRef,
3300 ConnectionPoint_Release,
3301 ConnectionPoint_GetConnectionInterface,
3302 ConnectionPoint_GetConnectionPointContainer,
3303 ConnectionPoint_Advise,
3304 ConnectionPoint_Unadvise,
3305 ConnectionPoint_EnumConnections
3308 static void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3310 cp->IConnectionPoint_iface.lpVtbl = &ConnectionPointVtbl;
3316 cp->next = doc->cp_list;
3319 cp->container = &doc->IConnectionPointContainer_iface;
3322 /* domdoc implementation of IObjectWithSite */
3323 static HRESULT WINAPI
3324 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3326 domdoc *This = impl_from_IObjectWithSite(iface);
3327 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppvObject);
3330 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3332 domdoc *This = impl_from_IObjectWithSite(iface);
3333 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3336 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3338 domdoc *This = impl_from_IObjectWithSite(iface);
3339 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3342 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3344 domdoc *This = impl_from_IObjectWithSite(iface);
3346 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3351 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3354 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3356 domdoc *This = impl_from_IObjectWithSite(iface);
3358 TRACE("(%p)->(%p)\n", iface, punk);
3364 IUnknown_Release( This->site );
3371 IUnknown_AddRef( punk );
3374 IUnknown_Release( This->site );
3381 static const IObjectWithSiteVtbl domdocObjectSite =
3383 domdoc_ObjectWithSite_QueryInterface,
3384 domdoc_ObjectWithSite_AddRef,
3385 domdoc_ObjectWithSite_Release,
3386 domdoc_ObjectWithSite_SetSite,
3387 domdoc_ObjectWithSite_GetSite
3390 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3392 domdoc *This = impl_from_IObjectSafety(iface);
3393 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppv);
3396 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3398 domdoc *This = impl_from_IObjectSafety(iface);
3399 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3402 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3404 domdoc *This = impl_from_IObjectSafety(iface);
3405 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3408 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3410 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3411 DWORD *supported, DWORD *enabled)
3413 domdoc *This = impl_from_IObjectSafety(iface);
3415 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3417 if(!supported || !enabled) return E_POINTER;
3419 *supported = SAFETY_SUPPORTED_OPTIONS;
3420 *enabled = This->safeopt;
3425 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3426 DWORD mask, DWORD enabled)
3428 domdoc *This = impl_from_IObjectSafety(iface);
3429 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3431 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3434 This->safeopt = (This->safeopt & ~mask) | (mask & enabled);
3439 #undef SAFETY_SUPPORTED_OPTIONS
3441 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3442 domdoc_Safety_QueryInterface,
3443 domdoc_Safety_AddRef,
3444 domdoc_Safety_Release,
3445 domdoc_Safety_GetInterfaceSafetyOptions,
3446 domdoc_Safety_SetInterfaceSafetyOptions
3449 static const tid_t domdoc_iface_tids[] = {
3451 IXMLDOMDocument_tid,
3452 IXMLDOMDocument2_tid,
3455 static dispex_static_data_t domdoc_dispex = {
3457 IXMLDOMDocument2_tid,
3462 HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3466 doc = heap_alloc( sizeof (*doc) );
3468 return E_OUTOFMEMORY;
3470 doc->IXMLDOMDocument3_iface.lpVtbl = &domdoc_vtbl;
3471 doc->IPersistStreamInit_iface.lpVtbl = &xmldoc_IPersistStreamInit_VTable;
3472 doc->IObjectWithSite_iface.lpVtbl = &domdocObjectSite;
3473 doc->IObjectSafety_iface.lpVtbl = &domdocObjectSafetyVtbl;
3474 doc->ISupportErrorInfo_iface.lpVtbl = &support_error_vtbl;
3475 doc->IConnectionPointContainer_iface.lpVtbl = &ConnectionPointContainerVtbl;
3477 doc->async = VARIANT_TRUE;
3478 doc->validating = 0;
3480 doc->properties = properties_from_xmlDocPtr(xmldoc);
3486 doc->cp_list = NULL;
3487 memset(doc->events, 0, sizeof(doc->events));
3489 /* events connection points */
3490 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3491 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3492 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3494 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->IXMLDOMDocument3_iface,
3497 *document = &doc->IXMLDOMDocument3_iface;
3499 TRACE("returning iface %p\n", *document);
3503 HRESULT DOMDocument_create(MSXML_VERSION version, IUnknown *pUnkOuter, void **ppObj)
3508 TRACE("(%d, %p, %p)\n", version, pUnkOuter, ppObj);
3510 xmldoc = xmlNewDoc(NULL);
3512 return E_OUTOFMEMORY;
3514 xmldoc->_private = create_priv();
3515 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(version);
3517 hr = get_domdoc_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3520 free_properties(properties_from_xmlDocPtr(xmldoc));
3521 heap_free(xmldoc->_private);
3529 IUnknown* create_domdoc( xmlNodePtr document )
3534 TRACE("(%p)\n", document);
3536 hr = get_domdoc_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3545 HRESULT DOMDocument_create(MSXML_VERSION version, IUnknown *pUnkOuter, void **ppObj)
3547 MESSAGE("This program tried to use a DOMDocument object, but\n"
3548 "libxml2 support was not present at compile time.\n");