2 * DOM Document implementation
4 * Copyright 2005 Mike McCormack
5 * Copyright 2010 Adam Martinson for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define NONAMELESSUNION
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};
77 /* Anything that passes the test_get_ownerDocument()
78 * tests can go here (data shared between all instances).
79 * We need to preserve this when reloading a document,
80 * and also need access to it from the libxml backend. */
81 typedef struct _domdoc_properties {
82 MSXML_VERSION version;
83 VARIANT_BOOL preserving;
84 IXMLDOMSchemaCollection2* schemaCache;
85 struct list selectNsList;
86 xmlChar const* selectNsStr;
91 typedef struct ConnectionPoint ConnectionPoint;
92 typedef struct domdoc domdoc;
94 struct ConnectionPoint
96 const IConnectionPointVtbl *lpVtblConnectionPoint;
99 ConnectionPoint *next;
100 IConnectionPointContainer *container;
107 IPropertyNotifySink *propnotif;
113 EVENTID_READYSTATECHANGE = 0,
114 EVENTID_DATAAVAILABLE,
115 EVENTID_TRANSFORMNODE,
122 const struct IXMLDOMDocument3Vtbl *lpVtbl;
123 const struct IPersistStreamInitVtbl *lpvtblIPersistStreamInit;
124 const struct IObjectWithSiteVtbl *lpvtblIObjectWithSite;
125 const struct IObjectSafetyVtbl *lpvtblIObjectSafety;
126 const struct ISupportErrorInfoVtbl *lpvtblISupportErrorInfo;
127 const struct IConnectionPointContainerVtbl *lpVtblConnectionPointContainer;
130 VARIANT_BOOL validating;
131 VARIANT_BOOL resolving;
132 domdoc_properties* properties;
145 /* connection list */
146 ConnectionPoint *cp_list;
147 ConnectionPoint cp_domdocevents;
148 ConnectionPoint cp_propnotif;
149 ConnectionPoint cp_dispatch;
152 IDispatch *events[EVENTID_LAST];
155 static HRESULT set_doc_event(domdoc *doc, eventid_t eid, const VARIANT *v)
163 IUnknown_QueryInterface(V_UNKNOWN(v), &IID_IDispatch, (void**)&disp);
168 disp = V_DISPATCH(v);
169 if (disp) IDispatch_AddRef(disp);
172 return DISP_E_TYPEMISMATCH;
175 if (doc->events[eid]) IDispatch_Release(doc->events[eid]);
176 doc->events[eid] = disp;
181 static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface)
183 return (ConnectionPoint *)((char*)iface - FIELD_OFFSET(ConnectionPoint, lpVtblConnectionPoint));
187 In native windows, the whole lifetime management of XMLDOMNodes is
188 managed automatically using reference counts. Wine emulates that by
189 maintaining a reference count to the document that is increased for
190 each IXMLDOMNode pointer passed out for this document. If all these
191 pointers are gone, the document is unreachable and gets freed, that
192 is, all nodes in the tree of the document get freed.
194 You are able to create nodes that are associated to a document (in
195 fact, in msxml's XMLDOM model, all nodes are associated to a document),
196 but not in the tree of that document, for example using the createFoo
197 functions from IXMLDOMDocument. These nodes do not get cleaned up
198 by libxml, so we have to do it ourselves.
200 To catch these nodes, a list of "orphan nodes" is introduced.
201 It contains pointers to all roots of node trees that are
202 associated with the document without being part of the document
203 tree. All nodes with parent==NULL (except for the document root nodes)
204 should be in the orphan node list of their document. All orphan nodes
205 get freed together with the document itself.
208 typedef struct _xmldoc_priv {
211 domdoc_properties* properties;
214 typedef struct _orphan_entry {
219 typedef struct _select_ns_entry {
221 xmlChar const* prefix;
227 static inline xmldoc_priv * priv_from_xmlDocPtr(const xmlDocPtr doc)
229 return doc->_private;
232 static inline domdoc_properties * properties_from_xmlDocPtr(xmlDocPtr doc)
234 return priv_from_xmlDocPtr(doc)->properties;
237 BOOL is_xpathmode(const xmlDocPtr doc)
239 return properties_from_xmlDocPtr(doc)->XPath;
242 void set_xpathmode(xmlDocPtr doc, BOOL xpath)
244 properties_from_xmlDocPtr(doc)->XPath = xpath;
247 int registerNamespaces(xmlXPathContextPtr ctxt)
250 const select_ns_entry* ns = NULL;
251 const struct list* pNsList = &properties_from_xmlDocPtr(ctxt->doc)->selectNsList;
253 TRACE("(%p)\n", ctxt);
255 LIST_FOR_EACH_ENTRY( ns, pNsList, select_ns_entry, entry )
257 xmlXPathRegisterNs(ctxt, ns->prefix, ns->href);
264 static inline void clear_selectNsList(struct list* pNsList)
266 select_ns_entry *ns, *ns2;
267 LIST_FOR_EACH_ENTRY_SAFE( ns, ns2, pNsList, select_ns_entry, entry )
274 static xmldoc_priv * create_priv(void)
277 priv = heap_alloc( sizeof (*priv) );
282 list_init( &priv->orphans );
283 priv->properties = NULL;
289 static domdoc_properties * create_properties(const GUID *clsid)
291 domdoc_properties *properties = heap_alloc(sizeof(domdoc_properties));
293 list_init(&properties->selectNsList);
294 properties->preserving = VARIANT_FALSE;
295 properties->schemaCache = NULL;
296 properties->selectNsStr = heap_alloc_zero(sizeof(xmlChar));
297 properties->selectNsStr_len = 0;
299 /* properties that are dependent on object versions */
300 if (IsEqualCLSID(clsid, &CLSID_DOMDocument30))
302 properties->version = MSXML3;
303 properties->XPath = FALSE;
305 else if (IsEqualCLSID(clsid, &CLSID_DOMDocument40))
307 properties->version = MSXML4;
308 properties->XPath = TRUE;
310 else if (IsEqualCLSID(clsid, &CLSID_DOMDocument60))
312 properties->version = MSXML6;
313 properties->XPath = TRUE;
317 properties->version = MSXML_DEFAULT;
318 properties->XPath = FALSE;
324 static domdoc_properties* copy_properties(domdoc_properties const* properties)
326 domdoc_properties* pcopy = heap_alloc(sizeof(domdoc_properties));
327 select_ns_entry const* ns = NULL;
328 select_ns_entry* new_ns = NULL;
329 int len = (properties->selectNsStr_len+1)*sizeof(xmlChar);
334 pcopy->version = properties->version;
335 pcopy->preserving = properties->preserving;
336 pcopy->schemaCache = properties->schemaCache;
337 if (pcopy->schemaCache)
338 IXMLDOMSchemaCollection2_AddRef(pcopy->schemaCache);
339 pcopy->XPath = properties->XPath;
340 pcopy->selectNsStr_len = properties->selectNsStr_len;
341 list_init( &pcopy->selectNsList );
342 pcopy->selectNsStr = heap_alloc(len);
343 memcpy((xmlChar*)pcopy->selectNsStr, properties->selectNsStr, len);
344 offset = pcopy->selectNsStr - properties->selectNsStr;
346 LIST_FOR_EACH_ENTRY( ns, (&properties->selectNsList), select_ns_entry, entry )
348 new_ns = heap_alloc(sizeof(select_ns_entry));
349 memcpy(new_ns, ns, sizeof(select_ns_entry));
350 new_ns->href += offset;
351 new_ns->prefix += offset;
352 list_add_tail(&pcopy->selectNsList, &new_ns->entry);
360 static void free_properties(domdoc_properties* properties)
364 if (properties->schemaCache)
365 IXMLDOMSchemaCollection2_Release(properties->schemaCache);
366 clear_selectNsList(&properties->selectNsList);
367 heap_free((xmlChar*)properties->selectNsStr);
368 heap_free(properties);
372 static BOOL xmldoc_has_decl(xmlDocPtr doc)
374 return doc->children && (xmlStrEqual(doc->children->name, (xmlChar*)"xml") == 1);
377 /* links a "<?xml" node as a first child */
378 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
381 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
384 /* unlinks a first "<?xml" child if it was created */
385 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
391 if (doc->standalone != -1)
393 node = doc->children;
394 xmlUnlinkNode( node );
402 BOOL is_preserving_whitespace(xmlNodePtr node)
404 domdoc_properties* properties = NULL;
405 /* during parsing the xmlDoc._private stuff is not there */
406 if (priv_from_xmlDocPtr(node->doc))
407 properties = properties_from_xmlDocPtr(node->doc);
408 return ((properties && properties->preserving == VARIANT_TRUE) ||
409 xmlNodeGetSpacePreserve(node) == 1);
412 static inline BOOL strn_isspace(xmlChar const* str, int len)
414 for (; str && len > 0 && *str; ++str, --len)
421 static void sax_characters(void *ctx, const xmlChar *ch, int len)
423 xmlParserCtxtPtr pctx;
426 pctx = (xmlParserCtxtPtr) ctx;
427 This = (domdoc const*) pctx->_private;
429 /* during domdoc_loadXML() the xmlDocPtr->_private data is not available */
430 if (!This->properties->preserving &&
431 !is_preserving_whitespace(pctx->node) &&
432 strn_isspace(ch, len))
435 xmlSAX2Characters(ctx, ch, len);
438 static void LIBXML2_LOG_CALLBACK sax_error(void* ctx, char const* msg, ...)
442 LIBXML2_CALLBACK_ERR(doparse, msg, ap);
446 static void LIBXML2_LOG_CALLBACK sax_warning(void* ctx, char const* msg, ...)
450 LIBXML2_CALLBACK_WARN(doparse, msg, ap);
454 static void sax_serror(void* ctx, xmlErrorPtr err)
456 LIBXML2_CALLBACK_SERROR(doparse, err);
459 static xmlDocPtr doparse(domdoc* This, char *ptr, int len, xmlChar const* encoding)
461 xmlDocPtr doc = NULL;
462 xmlParserCtxtPtr pctx;
463 static xmlSAXHandler sax_handler = {
464 xmlSAX2InternalSubset, /* internalSubset */
465 xmlSAX2IsStandalone, /* isStandalone */
466 xmlSAX2HasInternalSubset, /* hasInternalSubset */
467 xmlSAX2HasExternalSubset, /* hasExternalSubset */
468 xmlSAX2ResolveEntity, /* resolveEntity */
469 xmlSAX2GetEntity, /* getEntity */
470 xmlSAX2EntityDecl, /* entityDecl */
471 xmlSAX2NotationDecl, /* notationDecl */
472 xmlSAX2AttributeDecl, /* attributeDecl */
473 xmlSAX2ElementDecl, /* elementDecl */
474 xmlSAX2UnparsedEntityDecl, /* unparsedEntityDecl */
475 xmlSAX2SetDocumentLocator, /* setDocumentLocator */
476 xmlSAX2StartDocument, /* startDocument */
477 xmlSAX2EndDocument, /* endDocument */
478 xmlSAX2StartElement, /* startElement */
479 xmlSAX2EndElement, /* endElement */
480 xmlSAX2Reference, /* reference */
481 sax_characters, /* characters */
482 sax_characters, /* ignorableWhitespace */
483 xmlSAX2ProcessingInstruction, /* processingInstruction */
484 xmlSAX2Comment, /* comment */
485 sax_warning, /* warning */
486 sax_error, /* error */
487 sax_error, /* fatalError */
488 xmlSAX2GetParameterEntity, /* getParameterEntity */
489 xmlSAX2CDataBlock, /* cdataBlock */
490 xmlSAX2ExternalSubset, /* externalSubset */
493 xmlSAX2StartElementNs, /* startElementNs */
494 xmlSAX2EndElementNs, /* endElementNs */
495 sax_serror /* serror */
499 pctx = xmlCreateMemoryParserCtxt(ptr, len);
502 ERR("Failed to create parser context\n");
506 if (pctx->sax) xmlFree(pctx->sax);
507 pctx->sax = &sax_handler;
508 pctx->_private = This;
510 pctx->encoding = xmlStrdup(encoding);
511 xmlParseDocument(pctx);
513 if (pctx->wellFormed)
519 xmlFreeDoc(pctx->myDoc);
523 xmlFreeParserCtxt(pctx);
525 /* TODO: put this in one of the SAX callbacks */
526 /* create first child as a <?xml...?> */
527 if (doc && doc->standalone != -1)
531 xmlChar *xmlbuff = (xmlChar*)buff;
533 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
535 /* version attribute can't be omitted */
536 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
537 xmlNodeAddContent( node, xmlbuff );
541 sprintf(buff, " encoding=\"%s\"", doc->encoding);
542 xmlNodeAddContent( node, xmlbuff );
545 if (doc->standalone != -2)
547 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
548 xmlNodeAddContent( node, xmlbuff );
551 xmldoc_link_xmldecl( doc, node );
557 void xmldoc_init(xmlDocPtr doc, const GUID *clsid)
559 doc->_private = create_priv();
560 priv_from_xmlDocPtr(doc)->properties = create_properties(clsid);
563 LONG xmldoc_add_ref(xmlDocPtr doc)
565 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
566 TRACE("(%p)->(%d)\n", doc, ref);
570 LONG xmldoc_release(xmlDocPtr doc)
572 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
573 LONG ref = InterlockedDecrement(&priv->refs);
574 TRACE("(%p)->(%d)\n", doc, ref);
577 orphan_entry *orphan, *orphan2;
578 TRACE("freeing docptr %p\n", doc);
580 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
582 xmlFreeNode( orphan->node );
585 free_properties(priv->properties);
586 heap_free(doc->_private);
594 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
596 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
599 entry = heap_alloc( sizeof (*entry) );
601 return E_OUTOFMEMORY;
604 list_add_head( &priv->orphans, &entry->entry );
608 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
610 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
611 orphan_entry *entry, *entry2;
613 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
615 if( entry->node == node )
617 list_remove( &entry->entry );
626 static inline xmlDocPtr get_doc( domdoc *This )
628 return (xmlDocPtr)This->node.node;
631 static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
635 priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
636 if (xmldoc_release(get_doc(This)) != 0)
637 priv_from_xmlDocPtr(get_doc(This))->properties =
638 copy_properties(This->properties);
641 This->node.node = (xmlNodePtr) xml;
645 xmldoc_add_ref(get_doc(This));
646 priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
652 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
654 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
657 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
659 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStreamInit));
662 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
664 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
667 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
669 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
672 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
674 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblISupportErrorInfo));
677 static inline domdoc *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
679 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtblConnectionPointContainer));
682 /************************************************************************
683 * domdoc implementation of IPersistStream.
685 static HRESULT WINAPI domdoc_IPersistStreamInit_QueryInterface(
686 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
688 domdoc* This = impl_from_IPersistStreamInit(iface);
689 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)&This->lpVtbl, riid, ppvObj);
692 static ULONG WINAPI domdoc_IPersistStreamInit_AddRef(
693 IPersistStreamInit *iface)
695 domdoc* This = impl_from_IPersistStreamInit(iface);
696 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)&This->lpVtbl);
699 static ULONG WINAPI domdoc_IPersistStreamInit_Release(
700 IPersistStreamInit *iface)
702 domdoc* This = impl_from_IPersistStreamInit(iface);
703 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)&This->lpVtbl);
706 static HRESULT WINAPI domdoc_IPersistStreamInit_GetClassID(
707 IPersistStreamInit *iface, CLSID *classid)
709 domdoc* This = impl_from_IPersistStreamInit(iface);
710 TRACE("(%p)->(%p)\n", This, classid);
715 *classid = *DOMDocument_version(This->properties->version);
720 static HRESULT WINAPI domdoc_IPersistStreamInit_IsDirty(
721 IPersistStreamInit *iface)
723 domdoc *This = impl_from_IPersistStreamInit(iface);
724 FIXME("(%p): stub!\n", This);
728 static HRESULT WINAPI domdoc_IPersistStreamInit_Load(
729 IPersistStreamInit *iface, LPSTREAM pStm)
731 domdoc *This = impl_from_IPersistStreamInit(iface);
734 DWORD read, written, len;
737 xmlDocPtr xmldoc = NULL;
739 TRACE("(%p)->(%p)\n", This, pStm);
744 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
750 IStream_Read(pStm, buf, sizeof(buf), &read);
751 hr = IStream_Write(This->stream, buf, read, &written);
752 } while(SUCCEEDED(hr) && written != 0 && read != 0);
756 ERR("Failed to copy stream\n");
760 hr = GetHGlobalFromStream(This->stream, &hglobal);
764 len = GlobalSize(hglobal);
765 ptr = GlobalLock(hglobal);
767 xmldoc = doparse(This, ptr, len, NULL);
768 GlobalUnlock(hglobal);
772 ERR("Failed to parse xml\n");
776 xmldoc->_private = create_priv();
778 return attach_xmldoc(This, xmldoc);
781 static HRESULT WINAPI domdoc_IPersistStreamInit_Save(
782 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
784 domdoc *This = impl_from_IPersistStreamInit(iface);
788 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
790 hr = IXMLDOMDocument3_get_xml( (IXMLDOMDocument3*)&This->lpVtbl, &xmlString );
793 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
795 hr = IStream_Write( stream, xmlString, len, NULL );
796 SysFreeString(xmlString);
799 TRACE("ret 0x%08x\n", hr);
804 static HRESULT WINAPI domdoc_IPersistStreamInit_GetSizeMax(
805 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
807 domdoc *This = impl_from_IPersistStreamInit(iface);
808 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
812 static HRESULT WINAPI domdoc_IPersistStreamInit_InitNew(
813 IPersistStreamInit *iface)
815 domdoc *This = impl_from_IPersistStreamInit(iface);
816 TRACE("(%p)\n", This);
820 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
822 domdoc_IPersistStreamInit_QueryInterface,
823 domdoc_IPersistStreamInit_AddRef,
824 domdoc_IPersistStreamInit_Release,
825 domdoc_IPersistStreamInit_GetClassID,
826 domdoc_IPersistStreamInit_IsDirty,
827 domdoc_IPersistStreamInit_Load,
828 domdoc_IPersistStreamInit_Save,
829 domdoc_IPersistStreamInit_GetSizeMax,
830 domdoc_IPersistStreamInit_InitNew
833 /* ISupportErrorInfo interface */
834 static HRESULT WINAPI support_error_QueryInterface(
835 ISupportErrorInfo *iface,
836 REFIID riid, void** ppvObj )
838 domdoc *This = impl_from_ISupportErrorInfo(iface);
839 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3 *)This, riid, ppvObj);
842 static ULONG WINAPI support_error_AddRef(
843 ISupportErrorInfo *iface )
845 domdoc *This = impl_from_ISupportErrorInfo(iface);
846 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
849 static ULONG WINAPI support_error_Release(
850 ISupportErrorInfo *iface )
852 domdoc *This = impl_from_ISupportErrorInfo(iface);
853 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
856 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
857 ISupportErrorInfo *iface,
860 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
864 static const struct ISupportErrorInfoVtbl support_error_vtbl =
866 support_error_QueryInterface,
867 support_error_AddRef,
868 support_error_Release,
869 support_error_InterfaceSupportsErrorInfo
872 /* IXMLDOMDocument2 interface */
873 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
875 domdoc *This = impl_from_IXMLDOMDocument3( iface );
877 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
881 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
882 IsEqualGUID( riid, &IID_IDispatch ) ||
883 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
884 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
885 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
886 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
890 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
891 IsEqualGUID(&IID_IPersistStreamInit, riid))
893 *ppvObject = &(This->lpvtblIPersistStreamInit);
895 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
897 *ppvObject = &(This->lpvtblIObjectWithSite);
899 else if (IsEqualGUID(&IID_IObjectSafety, riid))
901 *ppvObject = &(This->lpvtblIObjectSafety);
903 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
905 *ppvObject = &This->lpvtblISupportErrorInfo;
907 else if(node_query_interface(&This->node, riid, ppvObject))
909 return *ppvObject ? S_OK : E_NOINTERFACE;
911 else if (IsEqualGUID( riid, &IID_IConnectionPointContainer ))
913 *ppvObject = &This->lpVtblConnectionPointContainer;
915 else if(IsEqualGUID(&IID_IRunnableObject, riid))
917 TRACE("IID_IRunnableObject not supported returning NULL\n");
918 return E_NOINTERFACE;
922 FIXME("interface %s not implemented\n", debugstr_guid(riid));
923 return E_NOINTERFACE;
926 IUnknown_AddRef((IUnknown*)*ppvObject);
932 static ULONG WINAPI domdoc_AddRef(
933 IXMLDOMDocument3 *iface )
935 domdoc *This = impl_from_IXMLDOMDocument3( iface );
936 ULONG ref = InterlockedIncrement( &This->ref );
937 TRACE("(%p)->(%d)\n", This, ref );
942 static ULONG WINAPI domdoc_Release(
943 IXMLDOMDocument3 *iface )
945 domdoc *This = impl_from_IXMLDOMDocument3( iface );
946 LONG ref = InterlockedDecrement( &This->ref );
948 TRACE("(%p)->(%d)\n", This, ref );
955 detach_bsc(This->bsc);
958 IUnknown_Release( This->site );
959 destroy_xmlnode(&This->node);
961 IStream_Release(This->stream);
963 for (eid = 0; eid < EVENTID_LAST; eid++)
964 if (This->events[eid]) IDispatch_Release(This->events[eid]);
972 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
974 domdoc *This = impl_from_IXMLDOMDocument3( iface );
976 TRACE("(%p)->(%p)\n", This, pctinfo);
983 static HRESULT WINAPI domdoc_GetTypeInfo(
984 IXMLDOMDocument3 *iface,
985 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
987 domdoc *This = impl_from_IXMLDOMDocument3( iface );
990 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
992 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
997 static HRESULT WINAPI domdoc_GetIDsOfNames(
998 IXMLDOMDocument3 *iface,
1000 LPOLESTR* rgszNames,
1005 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1006 ITypeInfo *typeinfo;
1009 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1012 if(!rgszNames || cNames == 0 || !rgDispId)
1013 return E_INVALIDARG;
1015 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
1018 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1019 ITypeInfo_Release(typeinfo);
1026 static HRESULT WINAPI domdoc_Invoke(
1027 IXMLDOMDocument3 *iface,
1028 DISPID dispIdMember,
1032 DISPPARAMS* pDispParams,
1033 VARIANT* pVarResult,
1034 EXCEPINFO* pExcepInfo,
1037 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1038 ITypeInfo *typeinfo;
1041 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1042 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1044 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
1047 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
1048 pVarResult, pExcepInfo, puArgErr);
1049 ITypeInfo_Release(typeinfo);
1056 static HRESULT WINAPI domdoc_get_nodeName(
1057 IXMLDOMDocument3 *iface,
1060 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1062 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
1064 TRACE("(%p)->(%p)\n", This, name);
1066 return return_bstr(documentW, name);
1070 static HRESULT WINAPI domdoc_get_nodeValue(
1071 IXMLDOMDocument3 *iface,
1074 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1076 TRACE("(%p)->(%p)\n", This, value);
1079 return E_INVALIDARG;
1081 V_VT(value) = VT_NULL;
1082 V_BSTR(value) = NULL; /* tests show that we should do this */
1087 static HRESULT WINAPI domdoc_put_nodeValue(
1088 IXMLDOMDocument3 *iface,
1091 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1092 TRACE("(%p)->(v%d)\n", This, V_VT(&value));
1097 static HRESULT WINAPI domdoc_get_nodeType(
1098 IXMLDOMDocument3 *iface,
1101 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1103 TRACE("(%p)->(%p)\n", This, type);
1105 *type = NODE_DOCUMENT;
1110 static HRESULT WINAPI domdoc_get_parentNode(
1111 IXMLDOMDocument3 *iface,
1112 IXMLDOMNode** parent )
1114 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1116 TRACE("(%p)->(%p)\n", This, parent);
1118 return node_get_parent(&This->node, parent);
1122 static HRESULT WINAPI domdoc_get_childNodes(
1123 IXMLDOMDocument3 *iface,
1124 IXMLDOMNodeList** childList )
1126 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1128 TRACE("(%p)->(%p)\n", This, childList);
1130 return node_get_child_nodes(&This->node, childList);
1134 static HRESULT WINAPI domdoc_get_firstChild(
1135 IXMLDOMDocument3 *iface,
1136 IXMLDOMNode** firstChild )
1138 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1140 TRACE("(%p)->(%p)\n", This, firstChild);
1142 return node_get_first_child(&This->node, firstChild);
1146 static HRESULT WINAPI domdoc_get_lastChild(
1147 IXMLDOMDocument3 *iface,
1148 IXMLDOMNode** lastChild )
1150 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1152 TRACE("(%p)->(%p)\n", This, lastChild);
1154 return node_get_last_child(&This->node, lastChild);
1158 static HRESULT WINAPI domdoc_get_previousSibling(
1159 IXMLDOMDocument3 *iface,
1160 IXMLDOMNode** previousSibling )
1162 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1164 TRACE("(%p)->(%p)\n", This, previousSibling);
1166 return return_null_node(previousSibling);
1170 static HRESULT WINAPI domdoc_get_nextSibling(
1171 IXMLDOMDocument3 *iface,
1172 IXMLDOMNode** nextSibling )
1174 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1176 TRACE("(%p)->(%p)\n", This, nextSibling);
1178 return return_null_node(nextSibling);
1182 static HRESULT WINAPI domdoc_get_attributes(
1183 IXMLDOMDocument3 *iface,
1184 IXMLDOMNamedNodeMap** attributeMap )
1186 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1188 TRACE("(%p)->(%p)\n", This, attributeMap);
1190 return return_null_ptr((void**)attributeMap);
1194 static HRESULT WINAPI domdoc_insertBefore(
1195 IXMLDOMDocument3 *iface,
1196 IXMLDOMNode* newChild,
1198 IXMLDOMNode** outNewChild )
1200 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1202 TRACE("(%p)->(%p x%d %p)\n", This, newChild, V_VT(&refChild), outNewChild);
1204 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1208 static HRESULT WINAPI domdoc_replaceChild(
1209 IXMLDOMDocument3 *iface,
1210 IXMLDOMNode* newChild,
1211 IXMLDOMNode* oldChild,
1212 IXMLDOMNode** outOldChild)
1214 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1216 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1218 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1222 static HRESULT WINAPI domdoc_removeChild(
1223 IXMLDOMDocument3 *iface,
1225 IXMLDOMNode **oldChild)
1227 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1228 TRACE("(%p)->(%p %p)\n", This, child, oldChild);
1229 return node_remove_child(&This->node, child, oldChild);
1233 static HRESULT WINAPI domdoc_appendChild(
1234 IXMLDOMDocument3 *iface,
1236 IXMLDOMNode **outChild)
1238 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1239 TRACE("(%p)->(%p %p)\n", This, child, outChild);
1240 return node_append_child(&This->node, child, outChild);
1244 static HRESULT WINAPI domdoc_hasChildNodes(
1245 IXMLDOMDocument3 *iface,
1248 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1249 TRACE("(%p)->(%p)\n", This, ret);
1250 return node_has_childnodes(&This->node, ret);
1254 static HRESULT WINAPI domdoc_get_ownerDocument(
1255 IXMLDOMDocument3 *iface,
1256 IXMLDOMDocument **doc)
1258 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1259 TRACE("(%p)->(%p)\n", This, doc);
1260 return node_get_owner_doc(&This->node, doc);
1264 static HRESULT WINAPI domdoc_cloneNode(
1265 IXMLDOMDocument3 *iface,
1267 IXMLDOMNode** outNode)
1269 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1270 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
1271 return node_clone( &This->node, deep, outNode );
1275 static HRESULT WINAPI domdoc_get_nodeTypeString(
1276 IXMLDOMDocument3 *iface,
1279 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1280 static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
1282 TRACE("(%p)->(%p)\n", This, p);
1284 return return_bstr(documentW, p);
1288 static HRESULT WINAPI domdoc_get_text(
1289 IXMLDOMDocument3 *iface,
1292 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1293 TRACE("(%p)->(%p)\n", This, p);
1294 return node_get_text(&This->node, p);
1298 static HRESULT WINAPI domdoc_put_text(
1299 IXMLDOMDocument3 *iface,
1302 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1303 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1308 static HRESULT WINAPI domdoc_get_specified(
1309 IXMLDOMDocument3 *iface,
1310 VARIANT_BOOL* isSpecified )
1312 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1313 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1314 *isSpecified = VARIANT_TRUE;
1319 static HRESULT WINAPI domdoc_get_definition(
1320 IXMLDOMDocument3 *iface,
1321 IXMLDOMNode** definitionNode )
1323 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1324 FIXME("(%p)->(%p)\n", This, definitionNode);
1329 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1330 IXMLDOMDocument3 *iface,
1331 VARIANT* typedValue )
1333 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1334 FIXME("(%p)->(%p)\n", This, typedValue);
1335 return return_null_var(typedValue);
1338 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1339 IXMLDOMDocument3 *iface,
1340 VARIANT typedValue )
1342 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1343 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1348 static HRESULT WINAPI domdoc_get_dataType(
1349 IXMLDOMDocument3 *iface,
1352 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1353 TRACE("(%p)->(%p)\n", This, typename);
1354 return return_null_var( typename );
1358 static HRESULT WINAPI domdoc_put_dataType(
1359 IXMLDOMDocument3 *iface,
1362 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1364 FIXME("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
1367 return E_INVALIDARG;
1372 static int XMLCALL domdoc_get_xml_writecallback(void *ctx, const char *data, int len)
1374 return xmlBufferAdd((xmlBufferPtr)ctx, (xmlChar*)data, len) == 0 ? len : 0;
1377 static HRESULT WINAPI domdoc_get_xml(
1378 IXMLDOMDocument3 *iface,
1381 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1382 xmlSaveCtxtPtr ctxt;
1387 TRACE("(%p)->(%p)\n", This, p);
1390 return E_INVALIDARG;
1394 buf = xmlBufferCreate();
1396 return E_OUTOFMEMORY;
1398 options = xmldoc_has_decl(get_doc(This)) ? XML_SAVE_NO_DECL : 0;
1399 options |= XML_SAVE_FORMAT;
1400 ctxt = xmlSaveToIO(domdoc_get_xml_writecallback, NULL, buf, "UTF-8", options);
1405 return E_OUTOFMEMORY;
1408 ret = xmlSaveDoc(ctxt, get_doc(This));
1409 /* flushes on close */
1412 TRACE("%ld, len=%d\n", ret, xmlBufferLength(buf));
1413 if(ret != -1 && xmlBufferLength(buf) > 0)
1417 content = bstr_from_xmlChar(xmlBufferContent(buf));
1418 content = EnsureCorrectEOL(content);
1424 *p = SysAllocStringLen(NULL, 0);
1429 return *p ? S_OK : E_OUTOFMEMORY;
1433 static HRESULT WINAPI domdoc_transformNode(
1434 IXMLDOMDocument3 *iface,
1438 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1439 TRACE("(%p)->(%p %p)\n", This, node, p);
1440 return node_transform_node(&This->node, node, p);
1444 static HRESULT WINAPI domdoc_selectNodes(
1445 IXMLDOMDocument3 *iface,
1447 IXMLDOMNodeList **outList)
1449 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1450 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList);
1451 return node_select_nodes(&This->node, p, outList);
1455 static HRESULT WINAPI domdoc_selectSingleNode(
1456 IXMLDOMDocument3 *iface,
1458 IXMLDOMNode **outNode)
1460 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1461 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode);
1462 return node_select_singlenode(&This->node, p, outNode);
1466 static HRESULT WINAPI domdoc_get_parsed(
1467 IXMLDOMDocument3 *iface,
1468 VARIANT_BOOL* isParsed )
1470 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1471 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1472 *isParsed = VARIANT_TRUE;
1477 static HRESULT WINAPI domdoc_get_namespaceURI(
1478 IXMLDOMDocument3 *iface,
1479 BSTR* namespaceURI )
1481 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1482 TRACE("(%p)->(%p)\n", This, namespaceURI);
1483 return node_get_namespaceURI(&This->node, namespaceURI);
1487 static HRESULT WINAPI domdoc_get_prefix(
1488 IXMLDOMDocument3 *iface,
1491 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1492 TRACE("(%p)->(%p)\n", This, prefix);
1493 return return_null_bstr( prefix );
1497 static HRESULT WINAPI domdoc_get_baseName(
1498 IXMLDOMDocument3 *iface,
1501 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1502 TRACE("(%p)->(%p)\n", This, name);
1503 return return_null_bstr( name );
1507 static HRESULT WINAPI domdoc_transformNodeToObject(
1508 IXMLDOMDocument3 *iface,
1509 IXMLDOMNode* stylesheet,
1510 VARIANT outputObject)
1512 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1513 FIXME("(%p)->(%p %s)\n", This, stylesheet, debugstr_variant(&outputObject));
1518 static HRESULT WINAPI domdoc_get_doctype(
1519 IXMLDOMDocument3 *iface,
1520 IXMLDOMDocumentType** documentType )
1522 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1523 FIXME("(%p)\n", This);
1528 static HRESULT WINAPI domdoc_get_implementation(
1529 IXMLDOMDocument3 *iface,
1530 IXMLDOMImplementation** impl )
1532 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1534 TRACE("(%p)->(%p)\n", This, impl);
1537 return E_INVALIDARG;
1539 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1544 static HRESULT WINAPI domdoc_get_documentElement(
1545 IXMLDOMDocument3 *iface,
1546 IXMLDOMElement** DOMElement )
1548 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1549 IXMLDOMNode *element_node;
1553 TRACE("(%p)->(%p)\n", This, DOMElement);
1556 return E_INVALIDARG;
1560 root = xmlDocGetRootElement( get_doc(This) );
1564 element_node = create_node( root );
1565 if(!element_node) return S_FALSE;
1567 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1568 IXMLDOMNode_Release(element_node);
1574 static HRESULT WINAPI domdoc_put_documentElement(
1575 IXMLDOMDocument3 *iface,
1576 IXMLDOMElement* DOMElement )
1578 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1579 IXMLDOMNode *elementNode;
1584 TRACE("(%p)->(%p)\n", This, DOMElement);
1586 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1590 xmlNode = get_node_obj( elementNode );
1592 FIXME("elementNode is not our object\n");
1596 if(!xmlNode->node->parent)
1597 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1598 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1600 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1601 IXMLDOMNode_Release( elementNode );
1604 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1610 static HRESULT WINAPI domdoc_createElement(
1611 IXMLDOMDocument3 *iface,
1613 IXMLDOMElement** element )
1615 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1620 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1622 if (!element || !tagname) return E_INVALIDARG;
1624 V_VT(&type) = VT_I1;
1625 V_I1(&type) = NODE_ELEMENT;
1627 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1630 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1631 IXMLDOMNode_Release(node);
1638 static HRESULT WINAPI domdoc_createDocumentFragment(
1639 IXMLDOMDocument3 *iface,
1640 IXMLDOMDocumentFragment** frag )
1642 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1647 TRACE("(%p)->(%p)\n", This, frag);
1649 if (!frag) return E_INVALIDARG;
1653 V_VT(&type) = VT_I1;
1654 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1656 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1659 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1660 IXMLDOMNode_Release(node);
1667 static HRESULT WINAPI domdoc_createTextNode(
1668 IXMLDOMDocument3 *iface,
1670 IXMLDOMText** text )
1672 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1677 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1679 if (!text) return E_INVALIDARG;
1683 V_VT(&type) = VT_I1;
1684 V_I1(&type) = NODE_TEXT;
1686 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1689 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1690 IXMLDOMNode_Release(node);
1691 hr = IXMLDOMText_put_data(*text, data);
1698 static HRESULT WINAPI domdoc_createComment(
1699 IXMLDOMDocument3 *iface,
1701 IXMLDOMComment** comment )
1703 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1708 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1710 if (!comment) return E_INVALIDARG;
1714 V_VT(&type) = VT_I1;
1715 V_I1(&type) = NODE_COMMENT;
1717 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1720 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1721 IXMLDOMNode_Release(node);
1722 hr = IXMLDOMComment_put_data(*comment, data);
1729 static HRESULT WINAPI domdoc_createCDATASection(
1730 IXMLDOMDocument3 *iface,
1732 IXMLDOMCDATASection** cdata )
1734 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1739 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1741 if (!cdata) return E_INVALIDARG;
1745 V_VT(&type) = VT_I1;
1746 V_I1(&type) = NODE_CDATA_SECTION;
1748 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1751 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1752 IXMLDOMNode_Release(node);
1753 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1760 static HRESULT WINAPI domdoc_createProcessingInstruction(
1761 IXMLDOMDocument3 *iface,
1764 IXMLDOMProcessingInstruction** pi )
1766 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1771 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1773 if (!pi) return E_INVALIDARG;
1777 V_VT(&type) = VT_I1;
1778 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1780 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1785 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1786 node_obj = get_node_obj(node);
1787 hr = node_set_content(node_obj, data);
1789 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1790 IXMLDOMNode_Release(node);
1797 static HRESULT WINAPI domdoc_createAttribute(
1798 IXMLDOMDocument3 *iface,
1800 IXMLDOMAttribute** attribute )
1802 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1807 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1809 if (!attribute || !name) return E_INVALIDARG;
1811 V_VT(&type) = VT_I1;
1812 V_I1(&type) = NODE_ATTRIBUTE;
1814 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1817 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1818 IXMLDOMNode_Release(node);
1825 static HRESULT WINAPI domdoc_createEntityReference(
1826 IXMLDOMDocument3 *iface,
1828 IXMLDOMEntityReference** entityref )
1830 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1835 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1837 if (!entityref) return E_INVALIDARG;
1841 V_VT(&type) = VT_I1;
1842 V_I1(&type) = NODE_ENTITY_REFERENCE;
1844 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1847 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1848 IXMLDOMNode_Release(node);
1854 xmlChar* tagName_to_XPath(const BSTR tagName)
1856 xmlChar *query, *tmp;
1857 static const xmlChar mod_pre[] = "*[local-name()='";
1858 static const xmlChar mod_post[] = "']";
1859 static const xmlChar prefix[] = "descendant::";
1860 const WCHAR *tokBegin, *tokEnd;
1863 query = xmlStrdup(prefix);
1866 while (tokBegin && *tokBegin)
1871 query = xmlStrcat(query, BAD_CAST "/");
1875 query = xmlStrcat(query, BAD_CAST "*");
1879 query = xmlStrcat(query, mod_pre);
1881 while (*tokEnd && *tokEnd != '/')
1883 len = WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, NULL, 0, NULL, NULL);
1884 tmp = xmlMalloc(len);
1885 WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, (char*)tmp, len, NULL, NULL);
1886 query = xmlStrncat(query, tmp, len);
1889 query = xmlStrcat(query, mod_post);
1896 static HRESULT WINAPI domdoc_getElementsByTagName(
1897 IXMLDOMDocument3 *iface,
1899 IXMLDOMNodeList** resultList )
1901 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1906 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1908 if (!tagName || !resultList) return E_INVALIDARG;
1910 XPath = This->properties->XPath;
1911 This->properties->XPath = TRUE;
1912 query = tagName_to_XPath(tagName);
1913 hr = queryresult_create((xmlNodePtr)get_doc(This), query, resultList);
1915 This->properties->XPath = XPath;
1920 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1926 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1928 return E_INVALIDARG;
1935 static HRESULT WINAPI domdoc_createNode(
1936 IXMLDOMDocument3 *iface,
1940 IXMLDOMNode** node )
1942 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1943 DOMNodeType node_type;
1945 xmlChar *xml_name, *href;
1948 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1950 if(!node) return E_INVALIDARG;
1952 hr = get_node_type(Type, &node_type);
1953 if(FAILED(hr)) return hr;
1955 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1956 FIXME("nodes with namespaces currently not supported.\n");
1958 TRACE("node_type %d\n", node_type);
1960 /* exit earlier for types that need name */
1964 case NODE_ATTRIBUTE:
1965 case NODE_ENTITY_REFERENCE:
1966 case NODE_PROCESSING_INSTRUCTION:
1967 if (!name || *name == 0) return E_FAIL;
1972 xml_name = xmlChar_from_wchar(name);
1973 /* prevent empty href to be allocated */
1974 href = namespaceURI ? xmlChar_from_wchar(namespaceURI) : NULL;
1980 xmlChar *local, *prefix;
1982 local = xmlSplitQName2(xml_name, &prefix);
1984 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
1986 /* allow to create default namespace xmlns= */
1987 if (local || (href && *href))
1989 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
1990 xmlSetNs(xmlnode, ns);
1998 case NODE_ATTRIBUTE:
1999 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
2002 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
2004 case NODE_CDATA_SECTION:
2005 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
2007 case NODE_ENTITY_REFERENCE:
2008 xmlnode = xmlNewReference(get_doc(This), xml_name);
2010 case NODE_PROCESSING_INSTRUCTION:
2011 #ifdef HAVE_XMLNEWDOCPI
2012 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
2014 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2019 xmlnode = xmlNewDocComment(get_doc(This), NULL);
2021 case NODE_DOCUMENT_FRAGMENT:
2022 xmlnode = xmlNewDocFragment(get_doc(This));
2024 /* unsupported types */
2026 case NODE_DOCUMENT_TYPE:
2029 heap_free(xml_name);
2030 return E_INVALIDARG;
2032 FIXME("unhandled node type %d\n", node_type);
2037 *node = create_node(xmlnode);
2038 heap_free(xml_name);
2043 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
2044 xmldoc_add_orphan(xmlnode->doc, xmlnode);
2051 static HRESULT WINAPI domdoc_nodeFromID(
2052 IXMLDOMDocument3 *iface,
2054 IXMLDOMNode** node )
2056 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2057 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
2061 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
2066 xmldoc = doparse(This, ptr, len, NULL);
2068 xmldoc->_private = create_priv();
2069 return attach_xmldoc(This, xmldoc);
2075 static HRESULT doread( domdoc *This, LPWSTR filename )
2080 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
2085 detach_bsc(This->bsc);
2091 static HRESULT WINAPI domdoc_load(
2092 IXMLDOMDocument3 *iface,
2094 VARIANT_BOOL* isSuccessful )
2096 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2097 LPWSTR filename = NULL;
2098 HRESULT hr = S_FALSE;
2099 IXMLDOMDocument3 *pNewDoc = NULL;
2100 IStream *pStream = NULL;
2103 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
2105 *isSuccessful = VARIANT_FALSE;
2107 assert( &This->node );
2109 switch( V_VT(&xmlSource) )
2112 filename = V_BSTR(&xmlSource);
2115 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
2120 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
2121 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
2122 hr = attach_xmldoc(This, xmldoc);
2125 *isSuccessful = VARIANT_TRUE;
2130 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
2133 IPersistStream *pDocStream;
2134 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
2137 hr = IPersistStream_Load(pDocStream, pStream);
2138 IStream_Release(pStream);
2141 *isSuccessful = VARIANT_TRUE;
2143 TRACE("Using IStream to load Document\n");
2148 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
2153 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
2158 /* ISequentialStream */
2159 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
2163 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
2166 TRACE("filename (%s)\n", debugstr_w(filename));
2170 hr = doread( This, filename );
2173 This->error = E_FAIL;
2176 hr = This->error = S_OK;
2177 *isSuccessful = VARIANT_TRUE;
2181 if(!filename || FAILED(hr)) {
2182 xmldoc = xmlNewDoc(NULL);
2183 xmldoc->_private = create_priv();
2184 hr = attach_xmldoc(This, xmldoc);
2189 TRACE("ret (%d)\n", hr);
2195 static HRESULT WINAPI domdoc_get_readyState(
2196 IXMLDOMDocument3 *iface,
2199 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2200 FIXME("stub! (%p)->(%p)\n", This, value);
2203 return E_INVALIDARG;
2205 *value = READYSTATE_COMPLETE;
2210 static HRESULT WINAPI domdoc_get_parseError(
2211 IXMLDOMDocument3 *iface,
2212 IXMLDOMParseError** errorObj )
2214 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2215 static const WCHAR err[] = {'e','r','r','o','r',0};
2216 BSTR error_string = NULL;
2218 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2221 error_string = SysAllocString(err);
2223 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2224 if(!*errorObj) return E_OUTOFMEMORY;
2229 static HRESULT WINAPI domdoc_get_url(
2230 IXMLDOMDocument3 *iface,
2233 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2234 FIXME("(%p)->(%p)\n", This, urlString);
2239 static HRESULT WINAPI domdoc_get_async(
2240 IXMLDOMDocument3 *iface,
2241 VARIANT_BOOL* isAsync )
2243 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2245 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2246 *isAsync = This->async;
2251 static HRESULT WINAPI domdoc_put_async(
2252 IXMLDOMDocument3 *iface,
2253 VARIANT_BOOL isAsync )
2255 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2257 TRACE("(%p)->(%d)\n", This, isAsync);
2258 This->async = isAsync;
2263 static HRESULT WINAPI domdoc_abort(
2264 IXMLDOMDocument3 *iface )
2266 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2267 FIXME("%p\n", This);
2272 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
2277 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
2278 str = heap_alloc( len );
2281 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
2287 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2288 static HRESULT WINAPI domdoc_loadXML(
2289 IXMLDOMDocument3 *iface,
2291 VARIANT_BOOL* isSuccessful )
2293 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2294 static const xmlChar encoding[] = "UTF-8";
2295 xmlDocPtr xmldoc = NULL;
2296 HRESULT hr = S_FALSE, hr2;
2300 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2302 assert ( &This->node );
2306 *isSuccessful = VARIANT_FALSE;
2308 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
2310 xmldoc = doparse(This, str, len, encoding);
2314 This->error = E_FAIL;
2315 TRACE("failed to parse document\n");
2319 hr = This->error = S_OK;
2320 *isSuccessful = VARIANT_TRUE;
2321 TRACE("parsed document %p\n", xmldoc);
2326 xmldoc = xmlNewDoc(NULL);
2328 xmldoc->_private = create_priv();
2330 hr2 = attach_xmldoc(This, xmldoc);
2337 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2341 if(!WriteFile(ctx, buffer, len, &written, NULL))
2343 WARN("write error\n");
2350 static int XMLCALL domdoc_save_closecallback(void *ctx)
2352 return CloseHandle(ctx) ? 0 : -1;
2355 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2360 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2363 WARN("stream write error: 0x%08x\n", hr);
2370 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2372 IStream_Release((IStream*)ctx);
2376 static HRESULT WINAPI domdoc_save(
2377 IXMLDOMDocument3 *iface,
2378 VARIANT destination )
2380 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2381 xmlSaveCtxtPtr ctx = NULL;
2385 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
2386 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
2388 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
2390 FIXME("Unhandled vt %d\n", V_VT(&destination));
2394 if(V_VT(&destination) == VT_UNKNOWN)
2396 IUnknown *pUnk = V_UNKNOWN(&destination);
2397 IXMLDOMDocument2 *document;
2400 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2403 VARIANT_BOOL success;
2406 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2409 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2413 IXMLDOMDocument3_Release(document);
2417 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2420 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2421 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2425 IStream_Release(stream);
2432 /* save with file path */
2433 HANDLE handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
2434 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2435 if( handle == INVALID_HANDLE_VALUE )
2437 WARN("failed to create file\n");
2441 /* disable top XML declaration */
2442 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2443 handle, NULL, XML_SAVE_NO_DECL);
2446 CloseHandle(handle);
2451 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2452 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2453 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2455 /* will release resources through close callback */
2461 static HRESULT WINAPI domdoc_get_validateOnParse(
2462 IXMLDOMDocument3 *iface,
2463 VARIANT_BOOL* isValidating )
2465 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2466 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2467 *isValidating = This->validating;
2472 static HRESULT WINAPI domdoc_put_validateOnParse(
2473 IXMLDOMDocument3 *iface,
2474 VARIANT_BOOL isValidating )
2476 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2477 TRACE("(%p)->(%d)\n", This, isValidating);
2478 This->validating = isValidating;
2483 static HRESULT WINAPI domdoc_get_resolveExternals(
2484 IXMLDOMDocument3 *iface,
2485 VARIANT_BOOL* isResolving )
2487 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2488 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2489 *isResolving = This->resolving;
2494 static HRESULT WINAPI domdoc_put_resolveExternals(
2495 IXMLDOMDocument3 *iface,
2496 VARIANT_BOOL isResolving )
2498 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2499 TRACE("(%p)->(%d)\n", This, isResolving);
2500 This->resolving = isResolving;
2505 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2506 IXMLDOMDocument3 *iface,
2507 VARIANT_BOOL* isPreserving )
2509 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2510 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->properties->preserving);
2511 *isPreserving = This->properties->preserving;
2516 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2517 IXMLDOMDocument3 *iface,
2518 VARIANT_BOOL isPreserving )
2520 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2521 TRACE("(%p)->(%d)\n", This, isPreserving);
2522 This->properties->preserving = isPreserving;
2527 static HRESULT WINAPI domdoc_put_onreadystatechange(
2528 IXMLDOMDocument3 *iface,
2531 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2533 TRACE("(%p)->(%s)\n", This, debugstr_variant(&event));
2534 return set_doc_event(This, EVENTID_READYSTATECHANGE, &event);
2538 static HRESULT WINAPI domdoc_put_onDataAvailable(
2539 IXMLDOMDocument3 *iface,
2540 VARIANT onDataAvailableSink )
2542 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2543 FIXME("%p\n", This);
2547 static HRESULT WINAPI domdoc_put_onTransformNode(
2548 IXMLDOMDocument3 *iface,
2549 VARIANT onTransformNodeSink )
2551 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2552 FIXME("%p\n", This);
2556 static HRESULT WINAPI domdoc_get_namespaces(
2557 IXMLDOMDocument3* iface,
2558 IXMLDOMSchemaCollection** schemaCollection )
2560 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2561 FIXME("(%p)->(%p)\n", This, schemaCollection);
2565 static HRESULT WINAPI domdoc_get_schemas(
2566 IXMLDOMDocument3* iface,
2569 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2570 HRESULT hr = S_FALSE;
2571 IXMLDOMSchemaCollection2* cur_schema = This->properties->schemaCache;
2573 TRACE("(%p)->(%p)\n", This, var1);
2575 VariantInit(var1); /* Test shows we don't call VariantClear here */
2576 V_VT(var1) = VT_NULL;
2580 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2582 V_VT(var1) = VT_DISPATCH;
2587 static HRESULT WINAPI domdoc_putref_schemas(
2588 IXMLDOMDocument3* iface,
2591 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2592 HRESULT hr = E_FAIL;
2593 IXMLDOMSchemaCollection2* new_schema = NULL;
2595 FIXME("(%p): semi-stub\n", This);
2599 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2603 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2612 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2617 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->properties->schemaCache, new_schema);
2618 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2624 static inline BOOL is_wellformed(xmlDocPtr doc)
2626 #ifdef HAVE_XMLDOC_PROPERTIES
2627 return doc->properties & XML_DOC_WELLFORMED;
2629 /* Not a full check, but catches the worst violations */
2633 for (child = doc->children; child != NULL; child = child->next)
2635 switch (child->type)
2637 case XML_ELEMENT_NODE:
2642 case XML_CDATA_SECTION_NODE:
2654 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2658 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2662 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2666 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2670 static HRESULT WINAPI domdoc_validateNode(
2671 IXMLDOMDocument3* iface,
2673 IXMLDOMParseError** err)
2675 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2676 LONG state, err_code = 0;
2680 TRACE("(%p)->(%p, %p)\n", This, node, err);
2681 domdoc_get_readyState(iface, &state);
2682 if (state != READYSTATE_COMPLETE)
2685 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2692 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2696 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2699 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2703 if (!is_wellformed(get_doc(This)))
2705 ERR("doc not well-formed\n");
2707 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2711 /* DTD validation */
2712 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2714 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2715 vctx->error = validate_error;
2716 vctx->warning = validate_warning;
2719 if (!((node == (IXMLDOMNode*)iface)?
2720 xmlValidateDocument(vctx, get_doc(This)) :
2721 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2723 /* TODO: get a real error code here */
2724 TRACE("DTD validation failed\n");
2725 err_code = E_XML_INVALID;
2728 xmlFreeValidCtxt(vctx);
2731 /* Schema validation */
2732 if (hr == S_OK && This->properties->schemaCache != NULL)
2735 hr = SchemaCache_validate_tree(This->properties->schemaCache, get_node_obj(node)->node);
2739 /* TODO: get a real error code here */
2742 TRACE("schema validation succeeded\n");
2746 ERR("schema validation failed\n");
2747 err_code = E_XML_INVALID;
2752 /* not really OK, just didn't find a schema for the ns */
2759 ERR("no DTD or schema found\n");
2760 err_code = E_XML_NODTD;
2765 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2770 static HRESULT WINAPI domdoc_validate(
2771 IXMLDOMDocument3* iface,
2772 IXMLDOMParseError** err)
2774 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2775 TRACE("(%p)->(%p)\n", This, err);
2776 return domdoc_validateNode(iface, (IXMLDOMNode*)iface, err);
2779 static HRESULT WINAPI domdoc_setProperty(
2780 IXMLDOMDocument3* iface,
2784 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2786 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2788 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2794 V_VT(&varStr) = VT_EMPTY;
2795 if (V_VT(&var) != VT_BSTR)
2797 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2799 bstr = V_BSTR(&varStr);
2802 bstr = V_BSTR(&var);
2805 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2806 This->properties->XPath = TRUE;
2807 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2808 This->properties->XPath = FALSE;
2812 VariantClear(&varStr);
2815 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2820 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2821 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2822 xmlXPathContextPtr ctx;
2823 struct list *pNsList;
2824 select_ns_entry* pNsEntry = NULL;
2826 V_VT(&varStr) = VT_EMPTY;
2827 if (V_VT(&var) != VT_BSTR)
2829 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2831 bstr = V_BSTR(&varStr);
2834 bstr = V_BSTR(&var);
2838 pNsList = &(This->properties->selectNsList);
2839 clear_selectNsList(pNsList);
2841 nsStr = xmlChar_from_wchar(bstr);
2844 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2846 This->properties->selectNsStr = nsStr;
2847 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2850 ctx = xmlXPathNewContext(This->node.node->doc);
2853 for (; *pTokBegin; pTokBegin = pTokEnd)
2855 if (pNsEntry != NULL)
2856 memset(pNsEntry, 0, sizeof(select_ns_entry));
2858 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2860 while (*pTokBegin == ' ')
2862 pTokEnd = pTokBegin;
2863 while (*pTokEnd != ' ' && *pTokEnd != 0)
2866 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2869 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2870 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2875 if (*pTokBegin == '=')
2877 /*valid for XSLPattern?*/
2878 FIXME("Setting default xmlns not supported - skipping.\n");
2879 pTokBegin = pTokEnd;
2882 else if (*pTokBegin == ':')
2884 pNsEntry->prefix = ++pTokBegin;
2885 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2888 if (pTokInner == pTokEnd)
2891 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2892 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2896 pNsEntry->prefix_end = *pTokInner;
2900 if (pTokEnd-pTokInner > 1 &&
2901 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2902 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2904 pNsEntry->href = ++pTokInner;
2905 pNsEntry->href_end = *(pTokEnd-1);
2907 list_add_tail(pNsList, &pNsEntry->entry);
2908 /*let libxml figure out if they're valid from here ;)*/
2909 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2918 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2919 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2920 list_add_tail(pNsList, &pNsEntry->entry);
2933 heap_free(pNsEntry);
2934 xmlXPathFreeContext(ctx);
2937 VariantClear(&varStr);
2940 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2941 lstrcmpiW(p, PropertyNewParserW) == 0)
2944 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2948 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2952 static HRESULT WINAPI domdoc_getProperty(
2953 IXMLDOMDocument3* iface,
2957 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2959 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2962 return E_INVALIDARG;
2964 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2966 V_VT(var) = VT_BSTR;
2967 V_BSTR(var) = This->properties->XPath ?
2968 SysAllocString(PropValueXPathW) :
2969 SysAllocString(PropValueXSLPatternW);
2970 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2972 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2975 BSTR rebuiltStr, cur;
2976 const xmlChar *nsStr;
2977 struct list *pNsList;
2978 select_ns_entry* pNsEntry;
2980 V_VT(var) = VT_BSTR;
2981 nsStr = This->properties->selectNsStr;
2982 pNsList = &This->properties->selectNsList;
2983 lenA = This->properties->selectNsStr_len;
2984 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
2985 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
2986 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
2988 /* this is fine because all of the chars that end tokens are ASCII*/
2989 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
2991 while (*cur != 0) ++cur;
2992 if (pNsEntry->prefix_end)
2994 *cur = pNsEntry->prefix_end;
2995 while (*cur != 0) ++cur;
2998 if (pNsEntry->href_end)
3000 *cur = pNsEntry->href_end;
3003 V_BSTR(var) = SysAllocString(rebuiltStr);
3004 heap_free(rebuiltStr);
3008 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
3012 static HRESULT WINAPI domdoc_importNode(
3013 IXMLDOMDocument3* iface,
3016 IXMLDOMNode** clone)
3018 domdoc *This = impl_from_IXMLDOMDocument3( iface );
3019 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
3023 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
3025 domdoc_QueryInterface,
3028 domdoc_GetTypeInfoCount,
3030 domdoc_GetIDsOfNames,
3032 domdoc_get_nodeName,
3033 domdoc_get_nodeValue,
3034 domdoc_put_nodeValue,
3035 domdoc_get_nodeType,
3036 domdoc_get_parentNode,
3037 domdoc_get_childNodes,
3038 domdoc_get_firstChild,
3039 domdoc_get_lastChild,
3040 domdoc_get_previousSibling,
3041 domdoc_get_nextSibling,
3042 domdoc_get_attributes,
3043 domdoc_insertBefore,
3044 domdoc_replaceChild,
3047 domdoc_hasChildNodes,
3048 domdoc_get_ownerDocument,
3050 domdoc_get_nodeTypeString,
3053 domdoc_get_specified,
3054 domdoc_get_definition,
3055 domdoc_get_nodeTypedValue,
3056 domdoc_put_nodeTypedValue,
3057 domdoc_get_dataType,
3058 domdoc_put_dataType,
3060 domdoc_transformNode,
3062 domdoc_selectSingleNode,
3064 domdoc_get_namespaceURI,
3066 domdoc_get_baseName,
3067 domdoc_transformNodeToObject,
3069 domdoc_get_implementation,
3070 domdoc_get_documentElement,
3071 domdoc_put_documentElement,
3072 domdoc_createElement,
3073 domdoc_createDocumentFragment,
3074 domdoc_createTextNode,
3075 domdoc_createComment,
3076 domdoc_createCDATASection,
3077 domdoc_createProcessingInstruction,
3078 domdoc_createAttribute,
3079 domdoc_createEntityReference,
3080 domdoc_getElementsByTagName,
3084 domdoc_get_readyState,
3085 domdoc_get_parseError,
3092 domdoc_get_validateOnParse,
3093 domdoc_put_validateOnParse,
3094 domdoc_get_resolveExternals,
3095 domdoc_put_resolveExternals,
3096 domdoc_get_preserveWhiteSpace,
3097 domdoc_put_preserveWhiteSpace,
3098 domdoc_put_onreadystatechange,
3099 domdoc_put_onDataAvailable,
3100 domdoc_put_onTransformNode,
3101 domdoc_get_namespaces,
3103 domdoc_putref_schemas,
3107 domdoc_validateNode,
3111 /* IConnectionPointContainer */
3112 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
3113 REFIID riid, void **ppv)
3115 domdoc *This = impl_from_IConnectionPointContainer(iface);
3116 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)This, riid, ppv);
3119 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
3121 domdoc *This = impl_from_IConnectionPointContainer(iface);
3122 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)This);
3125 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
3127 domdoc *This = impl_from_IConnectionPointContainer(iface);
3128 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)This);
3131 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
3132 IEnumConnectionPoints **ppEnum)
3134 domdoc *This = impl_from_IConnectionPointContainer(iface);
3135 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3139 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
3140 REFIID riid, IConnectionPoint **cp)
3142 domdoc *This = impl_from_IConnectionPointContainer(iface);
3143 ConnectionPoint *iter;
3145 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
3149 for(iter = This->cp_list; iter; iter = iter->next)
3151 if (IsEqualGUID(iter->iid, riid))
3152 *cp = (IConnectionPoint*)&iter->lpVtblConnectionPoint;
3157 IConnectionPoint_AddRef(*cp);
3161 FIXME("unsupported riid %s\n", debugstr_guid(riid));
3162 return CONNECT_E_NOCONNECTION;
3166 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
3168 ConnectionPointContainer_QueryInterface,
3169 ConnectionPointContainer_AddRef,
3170 ConnectionPointContainer_Release,
3171 ConnectionPointContainer_EnumConnectionPoints,
3172 ConnectionPointContainer_FindConnectionPoint
3175 /* IConnectionPoint */
3176 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
3177 REFIID riid, void **ppv)
3179 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3181 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3185 if (IsEqualGUID(&IID_IUnknown, riid) ||
3186 IsEqualGUID(&IID_IConnectionPoint, riid))
3193 IConnectionPoint_AddRef(iface);
3197 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3198 return E_NOINTERFACE;
3201 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3203 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3204 return IConnectionPointContainer_AddRef(This->container);
3207 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3209 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3210 return IConnectionPointContainer_Release(This->container);
3213 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3215 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3217 TRACE("(%p)->(%p)\n", This, iid);
3219 if (!iid) return E_POINTER;
3225 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3226 IConnectionPointContainer **container)
3228 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3230 TRACE("(%p)->(%p)\n", This, container);
3232 if (!container) return E_POINTER;
3234 *container = This->container;
3235 IConnectionPointContainer_AddRef(*container);
3239 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
3242 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3243 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
3247 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3249 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3251 TRACE("(%p)->(%d)\n", This, cookie);
3253 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3254 return CONNECT_E_NOCONNECTION;
3256 IUnknown_Release(This->sinks[cookie-1].unk);
3257 This->sinks[cookie-1].unk = NULL;
3262 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3263 IEnumConnections **ppEnum)
3265 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3266 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3270 static const IConnectionPointVtbl ConnectionPointVtbl =
3272 ConnectionPoint_QueryInterface,
3273 ConnectionPoint_AddRef,
3274 ConnectionPoint_Release,
3275 ConnectionPoint_GetConnectionInterface,
3276 ConnectionPoint_GetConnectionPointContainer,
3277 ConnectionPoint_Advise,
3278 ConnectionPoint_Unadvise,
3279 ConnectionPoint_EnumConnections
3282 void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3284 cp->lpVtblConnectionPoint = &ConnectionPointVtbl;
3290 cp->next = doc->cp_list;
3293 cp->container = (IConnectionPointContainer*)&doc->lpVtblConnectionPointContainer;
3296 /* domdoc implementation of IObjectWithSite */
3297 static HRESULT WINAPI
3298 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3300 domdoc *This = impl_from_IObjectWithSite(iface);
3301 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppvObject );
3304 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3306 domdoc *This = impl_from_IObjectWithSite(iface);
3307 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3310 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3312 domdoc *This = impl_from_IObjectWithSite(iface);
3313 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3316 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3318 domdoc *This = impl_from_IObjectWithSite(iface);
3320 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3325 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3328 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3330 domdoc *This = impl_from_IObjectWithSite(iface);
3332 TRACE("(%p)->(%p)\n", iface, punk);
3338 IUnknown_Release( This->site );
3345 IUnknown_AddRef( punk );
3348 IUnknown_Release( This->site );
3355 static const IObjectWithSiteVtbl domdocObjectSite =
3357 domdoc_ObjectWithSite_QueryInterface,
3358 domdoc_ObjectWithSite_AddRef,
3359 domdoc_ObjectWithSite_Release,
3360 domdoc_ObjectWithSite_SetSite,
3361 domdoc_ObjectWithSite_GetSite
3364 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3366 domdoc *This = impl_from_IObjectSafety(iface);
3367 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppv );
3370 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3372 domdoc *This = impl_from_IObjectSafety(iface);
3373 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3376 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3378 domdoc *This = impl_from_IObjectSafety(iface);
3379 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3382 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3384 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3385 DWORD *supported, DWORD *enabled)
3387 domdoc *This = impl_from_IObjectSafety(iface);
3389 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3391 if(!supported || !enabled) return E_POINTER;
3393 *supported = SAFETY_SUPPORTED_OPTIONS;
3394 *enabled = This->safeopt;
3399 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3400 DWORD mask, DWORD enabled)
3402 domdoc *This = impl_from_IObjectSafety(iface);
3403 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3405 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3408 This->safeopt = enabled & mask & SAFETY_SUPPORTED_OPTIONS;
3412 #undef SAFETY_SUPPORTED_OPTIONS
3414 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3415 domdoc_Safety_QueryInterface,
3416 domdoc_Safety_AddRef,
3417 domdoc_Safety_Release,
3418 domdoc_Safety_GetInterfaceSafetyOptions,
3419 domdoc_Safety_SetInterfaceSafetyOptions
3422 static const tid_t domdoc_iface_tids[] = {
3424 IXMLDOMDocument_tid,
3425 IXMLDOMDocument2_tid,
3428 static dispex_static_data_t domdoc_dispex = {
3430 IXMLDOMDocument2_tid,
3435 HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3439 doc = heap_alloc( sizeof (*doc) );
3441 return E_OUTOFMEMORY;
3443 doc->lpVtbl = &domdoc_vtbl;
3444 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
3445 doc->lpvtblIObjectWithSite = &domdocObjectSite;
3446 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
3447 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
3448 doc->lpVtblConnectionPointContainer = &ConnectionPointContainerVtbl;
3450 doc->async = VARIANT_TRUE;
3451 doc->validating = 0;
3453 doc->properties = properties_from_xmlDocPtr(xmldoc);
3459 doc->cp_list = NULL;
3460 memset(doc->events, 0, sizeof(doc->events));
3462 /* events connection points */
3463 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3464 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3465 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3467 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->lpVtbl, &domdoc_dispex);
3469 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
3471 TRACE("returning iface %p\n", *document);
3475 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3480 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
3482 xmldoc = xmlNewDoc(NULL);
3484 return E_OUTOFMEMORY;
3486 xmldoc->_private = create_priv();
3487 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
3489 hr = get_domdoc_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3492 free_properties(properties_from_xmlDocPtr(xmldoc));
3493 heap_free(xmldoc->_private);
3501 IUnknown* create_domdoc( xmlNodePtr document )
3506 TRACE("(%p)\n", document);
3508 hr = get_domdoc_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3517 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3519 MESSAGE("This program tried to use a DOMDocument object, but\n"
3520 "libxml2 support was not present at compile time.\n");