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};
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 const IConnectionPointVtbl *lpVtblConnectionPoint;
100 ConnectionPoint *next;
101 IConnectionPointContainer *container;
108 IPropertyNotifySink *propnotif;
114 EVENTID_READYSTATECHANGE = 0,
115 EVENTID_DATAAVAILABLE,
116 EVENTID_TRANSFORMNODE,
123 const struct IXMLDOMDocument3Vtbl *lpVtbl;
124 const struct IPersistStreamInitVtbl *lpvtblIPersistStreamInit;
125 const struct IObjectWithSiteVtbl *lpvtblIObjectWithSite;
126 const struct IObjectSafetyVtbl *lpvtblIObjectSafety;
127 const struct ISupportErrorInfoVtbl *lpvtblISupportErrorInfo;
128 const struct IConnectionPointContainerVtbl *lpVtblConnectionPointContainer;
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 (ConnectionPoint *)((char*)iface - FIELD_OFFSET(ConnectionPoint, lpVtblConnectionPoint));
188 In native windows, the whole lifetime management of XMLDOMNodes is
189 managed automatically using reference counts. Wine emulates that by
190 maintaining a reference count to the document that is increased for
191 each IXMLDOMNode pointer passed out for this document. If all these
192 pointers are gone, the document is unreachable and gets freed, that
193 is, all nodes in the tree of the document get freed.
195 You are able to create nodes that are associated to a document (in
196 fact, in msxml's XMLDOM model, all nodes are associated to a document),
197 but not in the tree of that document, for example using the createFoo
198 functions from IXMLDOMDocument. These nodes do not get cleaned up
199 by libxml, so we have to do it ourselves.
201 To catch these nodes, a list of "orphan nodes" is introduced.
202 It contains pointers to all roots of node trees that are
203 associated with the document without being part of the document
204 tree. All nodes with parent==NULL (except for the document root nodes)
205 should be in the orphan node list of their document. All orphan nodes
206 get freed together with the document itself.
209 typedef struct _xmldoc_priv {
212 domdoc_properties* properties;
215 typedef struct _orphan_entry {
220 typedef struct _select_ns_entry {
222 xmlChar const* prefix;
228 static inline xmldoc_priv * priv_from_xmlDocPtr(const xmlDocPtr doc)
230 return doc->_private;
233 static inline domdoc_properties * properties_from_xmlDocPtr(xmlDocPtr doc)
235 return priv_from_xmlDocPtr(doc)->properties;
238 BOOL is_xpathmode(const xmlDocPtr doc)
240 return properties_from_xmlDocPtr(doc)->XPath;
243 void set_xpathmode(xmlDocPtr doc, BOOL xpath)
245 properties_from_xmlDocPtr(doc)->XPath = xpath;
248 int registerNamespaces(xmlXPathContextPtr ctxt)
251 const select_ns_entry* ns = NULL;
252 const struct list* pNsList = &properties_from_xmlDocPtr(ctxt->doc)->selectNsList;
254 TRACE("(%p)\n", ctxt);
256 LIST_FOR_EACH_ENTRY( ns, pNsList, select_ns_entry, entry )
258 xmlXPathRegisterNs(ctxt, ns->prefix, ns->href);
265 static inline void clear_selectNsList(struct list* pNsList)
267 select_ns_entry *ns, *ns2;
268 LIST_FOR_EACH_ENTRY_SAFE( ns, ns2, pNsList, select_ns_entry, entry )
275 static xmldoc_priv * create_priv(void)
278 priv = heap_alloc( sizeof (*priv) );
283 list_init( &priv->orphans );
284 priv->properties = NULL;
290 static domdoc_properties * create_properties(const GUID *clsid)
292 domdoc_properties *properties = heap_alloc(sizeof(domdoc_properties));
294 list_init(&properties->selectNsList);
295 properties->preserving = VARIANT_FALSE;
296 properties->schemaCache = NULL;
297 properties->selectNsStr = heap_alloc_zero(sizeof(xmlChar));
298 properties->selectNsStr_len = 0;
300 /* properties that are dependent on object versions */
301 if (IsEqualCLSID(clsid, &CLSID_DOMDocument30))
303 properties->version = MSXML3;
304 properties->XPath = FALSE;
306 else if (IsEqualCLSID(clsid, &CLSID_DOMDocument40))
308 properties->version = MSXML4;
309 properties->XPath = TRUE;
311 else if (IsEqualCLSID(clsid, &CLSID_DOMDocument60))
313 properties->version = MSXML6;
314 properties->XPath = TRUE;
318 properties->version = MSXML_DEFAULT;
319 properties->XPath = FALSE;
325 static domdoc_properties* copy_properties(domdoc_properties const* properties)
327 domdoc_properties* pcopy = heap_alloc(sizeof(domdoc_properties));
328 select_ns_entry const* ns = NULL;
329 select_ns_entry* new_ns = NULL;
330 int len = (properties->selectNsStr_len+1)*sizeof(xmlChar);
335 pcopy->version = properties->version;
336 pcopy->preserving = properties->preserving;
337 pcopy->schemaCache = properties->schemaCache;
338 if (pcopy->schemaCache)
339 IXMLDOMSchemaCollection2_AddRef(pcopy->schemaCache);
340 pcopy->XPath = properties->XPath;
341 pcopy->selectNsStr_len = properties->selectNsStr_len;
342 list_init( &pcopy->selectNsList );
343 pcopy->selectNsStr = heap_alloc(len);
344 memcpy((xmlChar*)pcopy->selectNsStr, properties->selectNsStr, len);
345 offset = pcopy->selectNsStr - properties->selectNsStr;
347 LIST_FOR_EACH_ENTRY( ns, (&properties->selectNsList), select_ns_entry, entry )
349 new_ns = heap_alloc(sizeof(select_ns_entry));
350 memcpy(new_ns, ns, sizeof(select_ns_entry));
351 new_ns->href += offset;
352 new_ns->prefix += offset;
353 list_add_tail(&pcopy->selectNsList, &new_ns->entry);
361 static void free_properties(domdoc_properties* properties)
365 if (properties->schemaCache)
366 IXMLDOMSchemaCollection2_Release(properties->schemaCache);
367 clear_selectNsList(&properties->selectNsList);
368 heap_free((xmlChar*)properties->selectNsStr);
369 heap_free(properties);
373 static BOOL xmldoc_has_decl(xmlDocPtr doc)
375 return doc->children && (xmlStrEqual(doc->children->name, (xmlChar*)"xml") == 1);
378 /* links a "<?xml" node as a first child */
379 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
382 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
385 /* unlinks a first "<?xml" child if it was created */
386 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
392 if (doc->standalone != -1)
394 node = doc->children;
395 xmlUnlinkNode( node );
403 BOOL is_preserving_whitespace(xmlNodePtr node)
405 domdoc_properties* properties = NULL;
406 /* during parsing the xmlDoc._private stuff is not there */
407 if (priv_from_xmlDocPtr(node->doc))
408 properties = properties_from_xmlDocPtr(node->doc);
409 return ((properties && properties->preserving == VARIANT_TRUE) ||
410 xmlNodeGetSpacePreserve(node) == 1);
413 static inline BOOL strn_isspace(xmlChar const* str, int len)
415 for (; str && len > 0 && *str; ++str, --len)
422 static void sax_characters(void *ctx, const xmlChar *ch, int len)
424 xmlParserCtxtPtr ctxt;
427 ctxt = (xmlParserCtxtPtr) ctx;
428 This = (const domdoc*) ctxt->_private;
432 /* during domdoc_loadXML() the xmlDocPtr->_private data is not available */
433 if (!This->properties->preserving &&
434 !is_preserving_whitespace(ctxt->node) &&
435 strn_isspace(ch, len))
439 xmlSAX2Characters(ctxt, ch, len);
442 static void LIBXML2_LOG_CALLBACK sax_error(void* ctx, char const* msg, ...)
446 LIBXML2_CALLBACK_ERR(doparse, msg, ap);
450 static void LIBXML2_LOG_CALLBACK sax_warning(void* ctx, char const* msg, ...)
454 LIBXML2_CALLBACK_WARN(doparse, msg, ap);
458 static void sax_serror(void* ctx, xmlErrorPtr err)
460 LIBXML2_CALLBACK_SERROR(doparse, err);
463 static xmlDocPtr doparse(domdoc* This, char *ptr, int len, xmlChar const* encoding)
465 xmlDocPtr doc = NULL;
466 xmlParserCtxtPtr pctx;
467 static xmlSAXHandler sax_handler = {
468 xmlSAX2InternalSubset, /* internalSubset */
469 xmlSAX2IsStandalone, /* isStandalone */
470 xmlSAX2HasInternalSubset, /* hasInternalSubset */
471 xmlSAX2HasExternalSubset, /* hasExternalSubset */
472 xmlSAX2ResolveEntity, /* resolveEntity */
473 xmlSAX2GetEntity, /* getEntity */
474 xmlSAX2EntityDecl, /* entityDecl */
475 xmlSAX2NotationDecl, /* notationDecl */
476 xmlSAX2AttributeDecl, /* attributeDecl */
477 xmlSAX2ElementDecl, /* elementDecl */
478 xmlSAX2UnparsedEntityDecl, /* unparsedEntityDecl */
479 xmlSAX2SetDocumentLocator, /* setDocumentLocator */
480 xmlSAX2StartDocument, /* startDocument */
481 xmlSAX2EndDocument, /* endDocument */
482 xmlSAX2StartElement, /* startElement */
483 xmlSAX2EndElement, /* endElement */
484 xmlSAX2Reference, /* reference */
485 sax_characters, /* characters */
486 sax_characters, /* ignorableWhitespace */
487 xmlSAX2ProcessingInstruction, /* processingInstruction */
488 xmlSAX2Comment, /* comment */
489 sax_warning, /* warning */
490 sax_error, /* error */
491 sax_error, /* fatalError */
492 xmlSAX2GetParameterEntity, /* getParameterEntity */
493 xmlSAX2CDataBlock, /* cdataBlock */
494 xmlSAX2ExternalSubset, /* externalSubset */
497 xmlSAX2StartElementNs, /* startElementNs */
498 xmlSAX2EndElementNs, /* endElementNs */
499 sax_serror /* serror */
503 pctx = xmlCreateMemoryParserCtxt(ptr, len);
506 ERR("Failed to create parser context\n");
510 if (pctx->sax) xmlFree(pctx->sax);
511 pctx->sax = &sax_handler;
512 pctx->_private = This;
514 pctx->encoding = xmlStrdup(encoding);
515 xmlParseDocument(pctx);
517 if (pctx->wellFormed)
523 xmlFreeDoc(pctx->myDoc);
527 xmlFreeParserCtxt(pctx);
529 /* TODO: put this in one of the SAX callbacks */
530 /* create first child as a <?xml...?> */
531 if (doc && doc->standalone != -1)
535 xmlChar *xmlbuff = (xmlChar*)buff;
537 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
539 /* version attribute can't be omitted */
540 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
541 xmlNodeAddContent( node, xmlbuff );
545 sprintf(buff, " encoding=\"%s\"", doc->encoding);
546 xmlNodeAddContent( node, xmlbuff );
549 if (doc->standalone != -2)
551 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
552 xmlNodeAddContent( node, xmlbuff );
555 xmldoc_link_xmldecl( doc, node );
561 void xmldoc_init(xmlDocPtr doc, const GUID *clsid)
563 doc->_private = create_priv();
564 priv_from_xmlDocPtr(doc)->properties = create_properties(clsid);
567 LONG xmldoc_add_ref(xmlDocPtr doc)
569 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
570 TRACE("(%p)->(%d)\n", doc, ref);
574 LONG xmldoc_release(xmlDocPtr doc)
576 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
577 LONG ref = InterlockedDecrement(&priv->refs);
578 TRACE("(%p)->(%d)\n", doc, ref);
581 orphan_entry *orphan, *orphan2;
582 TRACE("freeing docptr %p\n", doc);
584 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
586 xmlFreeNode( orphan->node );
589 free_properties(priv->properties);
590 heap_free(doc->_private);
598 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
600 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
603 entry = heap_alloc( sizeof (*entry) );
605 return E_OUTOFMEMORY;
608 list_add_head( &priv->orphans, &entry->entry );
612 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
614 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
615 orphan_entry *entry, *entry2;
617 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
619 if( entry->node == node )
621 list_remove( &entry->entry );
630 static inline xmlDocPtr get_doc( domdoc *This )
632 return (xmlDocPtr)This->node.node;
635 static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
639 priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
640 if (xmldoc_release(get_doc(This)) != 0)
641 priv_from_xmlDocPtr(get_doc(This))->properties =
642 copy_properties(This->properties);
645 This->node.node = (xmlNodePtr) xml;
649 xmldoc_add_ref(get_doc(This));
650 priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
656 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
658 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
661 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
663 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStreamInit));
666 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
668 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
671 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
673 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
676 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
678 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblISupportErrorInfo));
681 static inline domdoc *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
683 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtblConnectionPointContainer));
686 /************************************************************************
687 * domdoc implementation of IPersistStream.
689 static HRESULT WINAPI domdoc_IPersistStreamInit_QueryInterface(
690 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
692 domdoc* This = impl_from_IPersistStreamInit(iface);
693 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)&This->lpVtbl, riid, ppvObj);
696 static ULONG WINAPI domdoc_IPersistStreamInit_AddRef(
697 IPersistStreamInit *iface)
699 domdoc* This = impl_from_IPersistStreamInit(iface);
700 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)&This->lpVtbl);
703 static ULONG WINAPI domdoc_IPersistStreamInit_Release(
704 IPersistStreamInit *iface)
706 domdoc* This = impl_from_IPersistStreamInit(iface);
707 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)&This->lpVtbl);
710 static HRESULT WINAPI domdoc_IPersistStreamInit_GetClassID(
711 IPersistStreamInit *iface, CLSID *classid)
713 domdoc* This = impl_from_IPersistStreamInit(iface);
714 TRACE("(%p)->(%p)\n", This, classid);
719 *classid = *DOMDocument_version(This->properties->version);
724 static HRESULT WINAPI domdoc_IPersistStreamInit_IsDirty(
725 IPersistStreamInit *iface)
727 domdoc *This = impl_from_IPersistStreamInit(iface);
728 FIXME("(%p): stub!\n", This);
732 static HRESULT WINAPI domdoc_IPersistStreamInit_Load(
733 IPersistStreamInit *iface, LPSTREAM pStm)
735 domdoc *This = impl_from_IPersistStreamInit(iface);
738 DWORD read, written, len;
741 xmlDocPtr xmldoc = NULL;
743 TRACE("(%p)->(%p)\n", This, pStm);
748 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
754 IStream_Read(pStm, buf, sizeof(buf), &read);
755 hr = IStream_Write(This->stream, buf, read, &written);
756 } while(SUCCEEDED(hr) && written != 0 && read != 0);
760 ERR("Failed to copy stream\n");
764 hr = GetHGlobalFromStream(This->stream, &hglobal);
768 len = GlobalSize(hglobal);
769 ptr = GlobalLock(hglobal);
771 xmldoc = doparse(This, ptr, len, NULL);
772 GlobalUnlock(hglobal);
776 ERR("Failed to parse xml\n");
780 xmldoc->_private = create_priv();
782 return attach_xmldoc(This, xmldoc);
785 static HRESULT WINAPI domdoc_IPersistStreamInit_Save(
786 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
788 domdoc *This = impl_from_IPersistStreamInit(iface);
792 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
794 hr = IXMLDOMDocument3_get_xml( (IXMLDOMDocument3*)&This->lpVtbl, &xmlString );
797 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
799 hr = IStream_Write( stream, xmlString, len, NULL );
800 SysFreeString(xmlString);
803 TRACE("ret 0x%08x\n", hr);
808 static HRESULT WINAPI domdoc_IPersistStreamInit_GetSizeMax(
809 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
811 domdoc *This = impl_from_IPersistStreamInit(iface);
812 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
816 static HRESULT WINAPI domdoc_IPersistStreamInit_InitNew(
817 IPersistStreamInit *iface)
819 domdoc *This = impl_from_IPersistStreamInit(iface);
820 TRACE("(%p)\n", This);
824 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
826 domdoc_IPersistStreamInit_QueryInterface,
827 domdoc_IPersistStreamInit_AddRef,
828 domdoc_IPersistStreamInit_Release,
829 domdoc_IPersistStreamInit_GetClassID,
830 domdoc_IPersistStreamInit_IsDirty,
831 domdoc_IPersistStreamInit_Load,
832 domdoc_IPersistStreamInit_Save,
833 domdoc_IPersistStreamInit_GetSizeMax,
834 domdoc_IPersistStreamInit_InitNew
837 /* ISupportErrorInfo interface */
838 static HRESULT WINAPI support_error_QueryInterface(
839 ISupportErrorInfo *iface,
840 REFIID riid, void** ppvObj )
842 domdoc *This = impl_from_ISupportErrorInfo(iface);
843 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3 *)This, riid, ppvObj);
846 static ULONG WINAPI support_error_AddRef(
847 ISupportErrorInfo *iface )
849 domdoc *This = impl_from_ISupportErrorInfo(iface);
850 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
853 static ULONG WINAPI support_error_Release(
854 ISupportErrorInfo *iface )
856 domdoc *This = impl_from_ISupportErrorInfo(iface);
857 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
860 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
861 ISupportErrorInfo *iface,
864 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
868 static const struct ISupportErrorInfoVtbl support_error_vtbl =
870 support_error_QueryInterface,
871 support_error_AddRef,
872 support_error_Release,
873 support_error_InterfaceSupportsErrorInfo
876 /* IXMLDOMDocument2 interface */
877 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
879 domdoc *This = impl_from_IXMLDOMDocument3( iface );
881 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
885 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
886 IsEqualGUID( riid, &IID_IDispatch ) ||
887 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
888 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
889 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
890 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
894 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
895 IsEqualGUID(&IID_IPersistStreamInit, riid))
897 *ppvObject = &(This->lpvtblIPersistStreamInit);
899 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
901 *ppvObject = &(This->lpvtblIObjectWithSite);
903 else if (IsEqualGUID(&IID_IObjectSafety, riid))
905 *ppvObject = &(This->lpvtblIObjectSafety);
907 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
909 *ppvObject = &This->lpvtblISupportErrorInfo;
911 else if(node_query_interface(&This->node, riid, ppvObject))
913 return *ppvObject ? S_OK : E_NOINTERFACE;
915 else if (IsEqualGUID( riid, &IID_IConnectionPointContainer ))
917 *ppvObject = &This->lpVtblConnectionPointContainer;
919 else if(IsEqualGUID(&IID_IRunnableObject, riid))
921 TRACE("IID_IRunnableObject not supported returning NULL\n");
922 return E_NOINTERFACE;
926 FIXME("interface %s not implemented\n", debugstr_guid(riid));
927 return E_NOINTERFACE;
930 IUnknown_AddRef((IUnknown*)*ppvObject);
936 static ULONG WINAPI domdoc_AddRef(
937 IXMLDOMDocument3 *iface )
939 domdoc *This = impl_from_IXMLDOMDocument3( iface );
940 ULONG ref = InterlockedIncrement( &This->ref );
941 TRACE("(%p)->(%d)\n", This, ref );
946 static ULONG WINAPI domdoc_Release(
947 IXMLDOMDocument3 *iface )
949 domdoc *This = impl_from_IXMLDOMDocument3( iface );
950 LONG ref = InterlockedDecrement( &This->ref );
952 TRACE("(%p)->(%d)\n", This, ref );
959 detach_bsc(This->bsc);
962 IUnknown_Release( This->site );
963 destroy_xmlnode(&This->node);
965 IStream_Release(This->stream);
967 for (eid = 0; eid < EVENTID_LAST; eid++)
968 if (This->events[eid]) IDispatch_Release(This->events[eid]);
976 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
978 domdoc *This = impl_from_IXMLDOMDocument3( iface );
980 TRACE("(%p)->(%p)\n", This, pctinfo);
987 static HRESULT WINAPI domdoc_GetTypeInfo(
988 IXMLDOMDocument3 *iface,
989 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
991 domdoc *This = impl_from_IXMLDOMDocument3( iface );
994 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
996 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
1001 static HRESULT WINAPI domdoc_GetIDsOfNames(
1002 IXMLDOMDocument3 *iface,
1004 LPOLESTR* rgszNames,
1009 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1010 ITypeInfo *typeinfo;
1013 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1016 if(!rgszNames || cNames == 0 || !rgDispId)
1017 return E_INVALIDARG;
1019 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
1022 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1023 ITypeInfo_Release(typeinfo);
1030 static HRESULT WINAPI domdoc_Invoke(
1031 IXMLDOMDocument3 *iface,
1032 DISPID dispIdMember,
1036 DISPPARAMS* pDispParams,
1037 VARIANT* pVarResult,
1038 EXCEPINFO* pExcepInfo,
1041 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1042 ITypeInfo *typeinfo;
1045 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1046 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1048 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
1051 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
1052 pVarResult, pExcepInfo, puArgErr);
1053 ITypeInfo_Release(typeinfo);
1060 static HRESULT WINAPI domdoc_get_nodeName(
1061 IXMLDOMDocument3 *iface,
1064 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1066 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
1068 TRACE("(%p)->(%p)\n", This, name);
1070 return return_bstr(documentW, name);
1074 static HRESULT WINAPI domdoc_get_nodeValue(
1075 IXMLDOMDocument3 *iface,
1078 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1080 TRACE("(%p)->(%p)\n", This, value);
1083 return E_INVALIDARG;
1085 V_VT(value) = VT_NULL;
1086 V_BSTR(value) = NULL; /* tests show that we should do this */
1091 static HRESULT WINAPI domdoc_put_nodeValue(
1092 IXMLDOMDocument3 *iface,
1095 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1096 TRACE("(%p)->(v%d)\n", This, V_VT(&value));
1101 static HRESULT WINAPI domdoc_get_nodeType(
1102 IXMLDOMDocument3 *iface,
1105 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1107 TRACE("(%p)->(%p)\n", This, type);
1109 *type = NODE_DOCUMENT;
1114 static HRESULT WINAPI domdoc_get_parentNode(
1115 IXMLDOMDocument3 *iface,
1116 IXMLDOMNode** parent )
1118 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1120 TRACE("(%p)->(%p)\n", This, parent);
1122 return node_get_parent(&This->node, parent);
1126 static HRESULT WINAPI domdoc_get_childNodes(
1127 IXMLDOMDocument3 *iface,
1128 IXMLDOMNodeList** childList )
1130 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1132 TRACE("(%p)->(%p)\n", This, childList);
1134 return node_get_child_nodes(&This->node, childList);
1138 static HRESULT WINAPI domdoc_get_firstChild(
1139 IXMLDOMDocument3 *iface,
1140 IXMLDOMNode** firstChild )
1142 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1144 TRACE("(%p)->(%p)\n", This, firstChild);
1146 return node_get_first_child(&This->node, firstChild);
1150 static HRESULT WINAPI domdoc_get_lastChild(
1151 IXMLDOMDocument3 *iface,
1152 IXMLDOMNode** lastChild )
1154 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1156 TRACE("(%p)->(%p)\n", This, lastChild);
1158 return node_get_last_child(&This->node, lastChild);
1162 static HRESULT WINAPI domdoc_get_previousSibling(
1163 IXMLDOMDocument3 *iface,
1164 IXMLDOMNode** previousSibling )
1166 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1168 TRACE("(%p)->(%p)\n", This, previousSibling);
1170 return return_null_node(previousSibling);
1174 static HRESULT WINAPI domdoc_get_nextSibling(
1175 IXMLDOMDocument3 *iface,
1176 IXMLDOMNode** nextSibling )
1178 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1180 TRACE("(%p)->(%p)\n", This, nextSibling);
1182 return return_null_node(nextSibling);
1186 static HRESULT WINAPI domdoc_get_attributes(
1187 IXMLDOMDocument3 *iface,
1188 IXMLDOMNamedNodeMap** attributeMap )
1190 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1192 TRACE("(%p)->(%p)\n", This, attributeMap);
1194 return return_null_ptr((void**)attributeMap);
1198 static HRESULT WINAPI domdoc_insertBefore(
1199 IXMLDOMDocument3 *iface,
1200 IXMLDOMNode* newChild,
1202 IXMLDOMNode** outNewChild )
1204 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1206 TRACE("(%p)->(%p x%d %p)\n", This, newChild, V_VT(&refChild), outNewChild);
1208 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1212 static HRESULT WINAPI domdoc_replaceChild(
1213 IXMLDOMDocument3 *iface,
1214 IXMLDOMNode* newChild,
1215 IXMLDOMNode* oldChild,
1216 IXMLDOMNode** outOldChild)
1218 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1220 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1222 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1226 static HRESULT WINAPI domdoc_removeChild(
1227 IXMLDOMDocument3 *iface,
1229 IXMLDOMNode **oldChild)
1231 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1232 TRACE("(%p)->(%p %p)\n", This, child, oldChild);
1233 return node_remove_child(&This->node, child, oldChild);
1237 static HRESULT WINAPI domdoc_appendChild(
1238 IXMLDOMDocument3 *iface,
1240 IXMLDOMNode **outChild)
1242 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1243 TRACE("(%p)->(%p %p)\n", This, child, outChild);
1244 return node_append_child(&This->node, child, outChild);
1248 static HRESULT WINAPI domdoc_hasChildNodes(
1249 IXMLDOMDocument3 *iface,
1252 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1253 TRACE("(%p)->(%p)\n", This, ret);
1254 return node_has_childnodes(&This->node, ret);
1258 static HRESULT WINAPI domdoc_get_ownerDocument(
1259 IXMLDOMDocument3 *iface,
1260 IXMLDOMDocument **doc)
1262 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1263 TRACE("(%p)->(%p)\n", This, doc);
1264 return node_get_owner_doc(&This->node, doc);
1268 static HRESULT WINAPI domdoc_cloneNode(
1269 IXMLDOMDocument3 *iface,
1271 IXMLDOMNode** outNode)
1273 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1274 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
1275 return node_clone( &This->node, deep, outNode );
1279 static HRESULT WINAPI domdoc_get_nodeTypeString(
1280 IXMLDOMDocument3 *iface,
1283 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1284 static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
1286 TRACE("(%p)->(%p)\n", This, p);
1288 return return_bstr(documentW, p);
1292 static HRESULT WINAPI domdoc_get_text(
1293 IXMLDOMDocument3 *iface,
1296 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1297 TRACE("(%p)->(%p)\n", This, p);
1298 return node_get_text(&This->node, p);
1302 static HRESULT WINAPI domdoc_put_text(
1303 IXMLDOMDocument3 *iface,
1306 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1307 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1312 static HRESULT WINAPI domdoc_get_specified(
1313 IXMLDOMDocument3 *iface,
1314 VARIANT_BOOL* isSpecified )
1316 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1317 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1318 *isSpecified = VARIANT_TRUE;
1323 static HRESULT WINAPI domdoc_get_definition(
1324 IXMLDOMDocument3 *iface,
1325 IXMLDOMNode** definitionNode )
1327 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1328 FIXME("(%p)->(%p)\n", This, definitionNode);
1333 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1334 IXMLDOMDocument3 *iface,
1337 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1338 TRACE("(%p)->(%p)\n", This, v);
1339 return return_null_var(v);
1342 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1343 IXMLDOMDocument3 *iface,
1344 VARIANT typedValue )
1346 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1347 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1352 static HRESULT WINAPI domdoc_get_dataType(
1353 IXMLDOMDocument3 *iface,
1356 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1357 TRACE("(%p)->(%p)\n", This, typename);
1358 return return_null_var( typename );
1362 static HRESULT WINAPI domdoc_put_dataType(
1363 IXMLDOMDocument3 *iface,
1366 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1368 FIXME("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
1371 return E_INVALIDARG;
1376 static int XMLCALL domdoc_get_xml_writecallback(void *ctx, const char *data, int len)
1378 return xmlBufferAdd((xmlBufferPtr)ctx, (xmlChar*)data, len) == 0 ? len : 0;
1381 static HRESULT WINAPI domdoc_get_xml(
1382 IXMLDOMDocument3 *iface,
1385 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1386 xmlSaveCtxtPtr ctxt;
1391 TRACE("(%p)->(%p)\n", This, p);
1394 return E_INVALIDARG;
1398 buf = xmlBufferCreate();
1400 return E_OUTOFMEMORY;
1402 options = xmldoc_has_decl(get_doc(This)) ? XML_SAVE_NO_DECL : 0;
1403 options |= XML_SAVE_FORMAT;
1404 ctxt = xmlSaveToIO(domdoc_get_xml_writecallback, NULL, buf, "UTF-8", options);
1409 return E_OUTOFMEMORY;
1412 ret = xmlSaveDoc(ctxt, get_doc(This));
1413 /* flushes on close */
1416 TRACE("%ld, len=%d\n", ret, xmlBufferLength(buf));
1417 if(ret != -1 && xmlBufferLength(buf) > 0)
1421 content = bstr_from_xmlChar(xmlBufferContent(buf));
1422 content = EnsureCorrectEOL(content);
1428 *p = SysAllocStringLen(NULL, 0);
1433 return *p ? S_OK : E_OUTOFMEMORY;
1437 static HRESULT WINAPI domdoc_transformNode(
1438 IXMLDOMDocument3 *iface,
1442 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1443 TRACE("(%p)->(%p %p)\n", This, node, p);
1444 return node_transform_node(&This->node, node, p);
1448 static HRESULT WINAPI domdoc_selectNodes(
1449 IXMLDOMDocument3 *iface,
1451 IXMLDOMNodeList **outList)
1453 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1454 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList);
1455 return node_select_nodes(&This->node, p, outList);
1459 static HRESULT WINAPI domdoc_selectSingleNode(
1460 IXMLDOMDocument3 *iface,
1462 IXMLDOMNode **outNode)
1464 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1465 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode);
1466 return node_select_singlenode(&This->node, p, outNode);
1470 static HRESULT WINAPI domdoc_get_parsed(
1471 IXMLDOMDocument3 *iface,
1472 VARIANT_BOOL* isParsed )
1474 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1475 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1476 *isParsed = VARIANT_TRUE;
1481 static HRESULT WINAPI domdoc_get_namespaceURI(
1482 IXMLDOMDocument3 *iface,
1483 BSTR* namespaceURI )
1485 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1486 TRACE("(%p)->(%p)\n", This, namespaceURI);
1487 return node_get_namespaceURI(&This->node, namespaceURI);
1491 static HRESULT WINAPI domdoc_get_prefix(
1492 IXMLDOMDocument3 *iface,
1495 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1496 TRACE("(%p)->(%p)\n", This, prefix);
1497 return return_null_bstr( prefix );
1501 static HRESULT WINAPI domdoc_get_baseName(
1502 IXMLDOMDocument3 *iface,
1505 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1506 TRACE("(%p)->(%p)\n", This, name);
1507 return return_null_bstr( name );
1511 static HRESULT WINAPI domdoc_transformNodeToObject(
1512 IXMLDOMDocument3 *iface,
1513 IXMLDOMNode* stylesheet,
1514 VARIANT outputObject)
1516 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1517 FIXME("(%p)->(%p %s)\n", This, stylesheet, debugstr_variant(&outputObject));
1522 static HRESULT WINAPI domdoc_get_doctype(
1523 IXMLDOMDocument3 *iface,
1524 IXMLDOMDocumentType** doctype )
1526 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1531 TRACE("(%p)->(%p)\n", This, doctype);
1533 if (!doctype) return E_INVALIDARG;
1537 dtd = xmlGetIntSubset(get_doc(This));
1538 if (!dtd) return S_FALSE;
1540 node = create_node((xmlNodePtr)dtd);
1541 if (!node) return S_FALSE;
1543 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentType, (void**)doctype);
1544 IXMLDOMNode_Release(node);
1550 static HRESULT WINAPI domdoc_get_implementation(
1551 IXMLDOMDocument3 *iface,
1552 IXMLDOMImplementation** impl )
1554 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1556 TRACE("(%p)->(%p)\n", This, impl);
1559 return E_INVALIDARG;
1561 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1566 static HRESULT WINAPI domdoc_get_documentElement(
1567 IXMLDOMDocument3 *iface,
1568 IXMLDOMElement** DOMElement )
1570 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1571 IXMLDOMNode *element_node;
1575 TRACE("(%p)->(%p)\n", This, DOMElement);
1578 return E_INVALIDARG;
1582 root = xmlDocGetRootElement( get_doc(This) );
1586 element_node = create_node( root );
1587 if(!element_node) return S_FALSE;
1589 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1590 IXMLDOMNode_Release(element_node);
1596 static HRESULT WINAPI domdoc_put_documentElement(
1597 IXMLDOMDocument3 *iface,
1598 IXMLDOMElement* DOMElement )
1600 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1601 IXMLDOMNode *elementNode;
1606 TRACE("(%p)->(%p)\n", This, DOMElement);
1608 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1612 xmlNode = get_node_obj( elementNode );
1613 if(!xmlNode) return E_FAIL;
1615 if(!xmlNode->node->parent)
1616 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1617 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1619 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1620 IXMLDOMNode_Release( elementNode );
1623 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1629 static HRESULT WINAPI domdoc_createElement(
1630 IXMLDOMDocument3 *iface,
1632 IXMLDOMElement** element )
1634 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1639 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1641 if (!element || !tagname) return E_INVALIDARG;
1643 V_VT(&type) = VT_I1;
1644 V_I1(&type) = NODE_ELEMENT;
1646 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1649 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1650 IXMLDOMNode_Release(node);
1657 static HRESULT WINAPI domdoc_createDocumentFragment(
1658 IXMLDOMDocument3 *iface,
1659 IXMLDOMDocumentFragment** frag )
1661 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1666 TRACE("(%p)->(%p)\n", This, frag);
1668 if (!frag) return E_INVALIDARG;
1672 V_VT(&type) = VT_I1;
1673 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1675 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1678 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1679 IXMLDOMNode_Release(node);
1686 static HRESULT WINAPI domdoc_createTextNode(
1687 IXMLDOMDocument3 *iface,
1689 IXMLDOMText** text )
1691 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1696 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1698 if (!text) return E_INVALIDARG;
1702 V_VT(&type) = VT_I1;
1703 V_I1(&type) = NODE_TEXT;
1705 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1708 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1709 IXMLDOMNode_Release(node);
1710 hr = IXMLDOMText_put_data(*text, data);
1717 static HRESULT WINAPI domdoc_createComment(
1718 IXMLDOMDocument3 *iface,
1720 IXMLDOMComment** comment )
1722 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1727 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1729 if (!comment) return E_INVALIDARG;
1733 V_VT(&type) = VT_I1;
1734 V_I1(&type) = NODE_COMMENT;
1736 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1739 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1740 IXMLDOMNode_Release(node);
1741 hr = IXMLDOMComment_put_data(*comment, data);
1748 static HRESULT WINAPI domdoc_createCDATASection(
1749 IXMLDOMDocument3 *iface,
1751 IXMLDOMCDATASection** cdata )
1753 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1758 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1760 if (!cdata) return E_INVALIDARG;
1764 V_VT(&type) = VT_I1;
1765 V_I1(&type) = NODE_CDATA_SECTION;
1767 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1770 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1771 IXMLDOMNode_Release(node);
1772 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1779 static HRESULT WINAPI domdoc_createProcessingInstruction(
1780 IXMLDOMDocument3 *iface,
1783 IXMLDOMProcessingInstruction** pi )
1785 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1790 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1792 if (!pi) return E_INVALIDARG;
1796 V_VT(&type) = VT_I1;
1797 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1799 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1804 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1805 node_obj = get_node_obj(node);
1806 hr = node_set_content(node_obj, data);
1808 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1809 IXMLDOMNode_Release(node);
1816 static HRESULT WINAPI domdoc_createAttribute(
1817 IXMLDOMDocument3 *iface,
1819 IXMLDOMAttribute** attribute )
1821 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1826 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1828 if (!attribute || !name) return E_INVALIDARG;
1830 V_VT(&type) = VT_I1;
1831 V_I1(&type) = NODE_ATTRIBUTE;
1833 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1836 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1837 IXMLDOMNode_Release(node);
1844 static HRESULT WINAPI domdoc_createEntityReference(
1845 IXMLDOMDocument3 *iface,
1847 IXMLDOMEntityReference** entityref )
1849 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1854 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1856 if (!entityref) return E_INVALIDARG;
1860 V_VT(&type) = VT_I1;
1861 V_I1(&type) = NODE_ENTITY_REFERENCE;
1863 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1866 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1867 IXMLDOMNode_Release(node);
1873 xmlChar* tagName_to_XPath(const BSTR tagName)
1875 xmlChar *query, *tmp;
1876 static const xmlChar mod_pre[] = "*[local-name()='";
1877 static const xmlChar mod_post[] = "']";
1878 static const xmlChar prefix[] = "descendant::";
1879 const WCHAR *tokBegin, *tokEnd;
1882 query = xmlStrdup(prefix);
1885 while (tokBegin && *tokBegin)
1890 query = xmlStrcat(query, BAD_CAST "/");
1894 query = xmlStrcat(query, BAD_CAST "*");
1898 query = xmlStrcat(query, mod_pre);
1900 while (*tokEnd && *tokEnd != '/')
1902 len = WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, NULL, 0, NULL, NULL);
1903 tmp = xmlMalloc(len);
1904 WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, (char*)tmp, len, NULL, NULL);
1905 query = xmlStrncat(query, tmp, len);
1908 query = xmlStrcat(query, mod_post);
1915 static HRESULT WINAPI domdoc_getElementsByTagName(
1916 IXMLDOMDocument3 *iface,
1918 IXMLDOMNodeList** resultList )
1920 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1925 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1927 if (!tagName || !resultList) return E_INVALIDARG;
1929 XPath = This->properties->XPath;
1930 This->properties->XPath = TRUE;
1931 query = tagName_to_XPath(tagName);
1932 hr = create_selection((xmlNodePtr)get_doc(This), query, resultList);
1934 This->properties->XPath = XPath;
1939 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1945 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1947 return E_INVALIDARG;
1954 static HRESULT WINAPI domdoc_createNode(
1955 IXMLDOMDocument3 *iface,
1959 IXMLDOMNode** node )
1961 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1962 DOMNodeType node_type;
1964 xmlChar *xml_name, *href;
1967 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1969 if(!node) return E_INVALIDARG;
1971 hr = get_node_type(Type, &node_type);
1972 if(FAILED(hr)) return hr;
1974 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1975 FIXME("nodes with namespaces currently not supported.\n");
1977 TRACE("node_type %d\n", node_type);
1979 /* exit earlier for types that need name */
1983 case NODE_ATTRIBUTE:
1984 case NODE_ENTITY_REFERENCE:
1985 case NODE_PROCESSING_INSTRUCTION:
1986 if (!name || *name == 0) return E_FAIL;
1991 xml_name = xmlchar_from_wchar(name);
1992 /* prevent empty href to be allocated */
1993 href = namespaceURI ? xmlchar_from_wchar(namespaceURI) : NULL;
1999 xmlChar *local, *prefix;
2001 local = xmlSplitQName2(xml_name, &prefix);
2003 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
2005 /* allow to create default namespace xmlns= */
2006 if (local || (href && *href))
2008 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
2009 xmlSetNs(xmlnode, ns);
2017 case NODE_ATTRIBUTE:
2018 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
2021 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
2023 case NODE_CDATA_SECTION:
2024 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
2026 case NODE_ENTITY_REFERENCE:
2027 xmlnode = xmlNewReference(get_doc(This), xml_name);
2029 case NODE_PROCESSING_INSTRUCTION:
2030 #ifdef HAVE_XMLNEWDOCPI
2031 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
2033 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2038 xmlnode = xmlNewDocComment(get_doc(This), NULL);
2040 case NODE_DOCUMENT_FRAGMENT:
2041 xmlnode = xmlNewDocFragment(get_doc(This));
2043 /* unsupported types */
2045 case NODE_DOCUMENT_TYPE:
2048 heap_free(xml_name);
2049 return E_INVALIDARG;
2051 FIXME("unhandled node type %d\n", node_type);
2056 *node = create_node(xmlnode);
2057 heap_free(xml_name);
2062 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
2063 xmldoc_add_orphan(xmlnode->doc, xmlnode);
2070 static HRESULT WINAPI domdoc_nodeFromID(
2071 IXMLDOMDocument3 *iface,
2073 IXMLDOMNode** node )
2075 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2076 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
2080 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
2085 xmldoc = doparse(This, ptr, len, NULL);
2087 xmldoc->_private = create_priv();
2088 return attach_xmldoc(This, xmldoc);
2094 static HRESULT doread( domdoc *This, LPWSTR filename )
2099 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
2104 detach_bsc(This->bsc);
2110 static HRESULT WINAPI domdoc_load(
2111 IXMLDOMDocument3 *iface,
2113 VARIANT_BOOL* isSuccessful )
2115 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2116 LPWSTR filename = NULL;
2117 HRESULT hr = S_FALSE;
2118 IXMLDOMDocument3 *pNewDoc = NULL;
2119 IStream *pStream = NULL;
2122 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
2124 *isSuccessful = VARIANT_FALSE;
2126 assert( &This->node );
2128 switch( V_VT(&xmlSource) )
2131 filename = V_BSTR(&xmlSource);
2134 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
2139 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
2140 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
2141 hr = attach_xmldoc(This, xmldoc);
2144 *isSuccessful = VARIANT_TRUE;
2149 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
2152 IPersistStream *pDocStream;
2153 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
2156 hr = IPersistStream_Load(pDocStream, pStream);
2157 IStream_Release(pStream);
2160 *isSuccessful = VARIANT_TRUE;
2162 TRACE("Using IStream to load Document\n");
2167 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
2172 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
2177 /* ISequentialStream */
2178 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
2182 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
2185 TRACE("filename (%s)\n", debugstr_w(filename));
2189 hr = doread( This, filename );
2192 This->error = E_FAIL;
2195 hr = This->error = S_OK;
2196 *isSuccessful = VARIANT_TRUE;
2200 if(!filename || FAILED(hr)) {
2201 xmldoc = xmlNewDoc(NULL);
2202 xmldoc->_private = create_priv();
2203 hr = attach_xmldoc(This, xmldoc);
2208 TRACE("ret (%d)\n", hr);
2214 static HRESULT WINAPI domdoc_get_readyState(
2215 IXMLDOMDocument3 *iface,
2218 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2219 FIXME("stub! (%p)->(%p)\n", This, value);
2222 return E_INVALIDARG;
2224 *value = READYSTATE_COMPLETE;
2229 static HRESULT WINAPI domdoc_get_parseError(
2230 IXMLDOMDocument3 *iface,
2231 IXMLDOMParseError** errorObj )
2233 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2234 static const WCHAR err[] = {'e','r','r','o','r',0};
2235 BSTR error_string = NULL;
2237 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2240 error_string = SysAllocString(err);
2242 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2243 if(!*errorObj) return E_OUTOFMEMORY;
2248 static HRESULT WINAPI domdoc_get_url(
2249 IXMLDOMDocument3 *iface,
2252 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2253 FIXME("(%p)->(%p)\n", This, urlString);
2258 static HRESULT WINAPI domdoc_get_async(
2259 IXMLDOMDocument3 *iface,
2260 VARIANT_BOOL* isAsync )
2262 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2264 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2265 *isAsync = This->async;
2270 static HRESULT WINAPI domdoc_put_async(
2271 IXMLDOMDocument3 *iface,
2272 VARIANT_BOOL isAsync )
2274 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2276 TRACE("(%p)->(%d)\n", This, isAsync);
2277 This->async = isAsync;
2282 static HRESULT WINAPI domdoc_abort(
2283 IXMLDOMDocument3 *iface )
2285 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2286 FIXME("%p\n", This);
2291 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
2296 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
2297 str = heap_alloc( len );
2300 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
2306 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2307 static HRESULT WINAPI domdoc_loadXML(
2308 IXMLDOMDocument3 *iface,
2310 VARIANT_BOOL* isSuccessful )
2312 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2313 static const xmlChar encoding[] = "UTF-8";
2314 xmlDocPtr xmldoc = NULL;
2315 HRESULT hr = S_FALSE, hr2;
2319 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2321 assert ( &This->node );
2325 *isSuccessful = VARIANT_FALSE;
2327 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
2329 xmldoc = doparse(This, str, len, encoding);
2333 This->error = E_FAIL;
2334 TRACE("failed to parse document\n");
2338 hr = This->error = S_OK;
2339 *isSuccessful = VARIANT_TRUE;
2340 TRACE("parsed document %p\n", xmldoc);
2345 xmldoc = xmlNewDoc(NULL);
2347 xmldoc->_private = create_priv();
2349 hr2 = attach_xmldoc(This, xmldoc);
2356 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2360 if(!WriteFile(ctx, buffer, len, &written, NULL))
2362 WARN("write error\n");
2369 static int XMLCALL domdoc_save_closecallback(void *ctx)
2371 return CloseHandle(ctx) ? 0 : -1;
2374 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2379 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2382 WARN("stream write error: 0x%08x\n", hr);
2389 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2391 IStream_Release((IStream*)ctx);
2395 static HRESULT WINAPI domdoc_save(
2396 IXMLDOMDocument3 *iface,
2397 VARIANT destination )
2399 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2400 xmlSaveCtxtPtr ctx = NULL;
2404 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
2405 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
2407 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
2409 FIXME("Unhandled vt %d\n", V_VT(&destination));
2413 if(V_VT(&destination) == VT_UNKNOWN)
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);
2451 /* save with file path */
2452 HANDLE handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
2453 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2454 if( handle == INVALID_HANDLE_VALUE )
2456 WARN("failed to create file\n");
2460 /* disable top XML declaration */
2461 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2462 handle, NULL, XML_SAVE_NO_DECL);
2465 CloseHandle(handle);
2470 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2471 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2472 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2474 /* will release resources through close callback */
2480 static HRESULT WINAPI domdoc_get_validateOnParse(
2481 IXMLDOMDocument3 *iface,
2482 VARIANT_BOOL* isValidating )
2484 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2485 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2486 *isValidating = This->validating;
2491 static HRESULT WINAPI domdoc_put_validateOnParse(
2492 IXMLDOMDocument3 *iface,
2493 VARIANT_BOOL isValidating )
2495 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2496 TRACE("(%p)->(%d)\n", This, isValidating);
2497 This->validating = isValidating;
2502 static HRESULT WINAPI domdoc_get_resolveExternals(
2503 IXMLDOMDocument3 *iface,
2504 VARIANT_BOOL* isResolving )
2506 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2507 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2508 *isResolving = This->resolving;
2513 static HRESULT WINAPI domdoc_put_resolveExternals(
2514 IXMLDOMDocument3 *iface,
2515 VARIANT_BOOL isResolving )
2517 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2518 TRACE("(%p)->(%d)\n", This, isResolving);
2519 This->resolving = isResolving;
2524 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2525 IXMLDOMDocument3 *iface,
2526 VARIANT_BOOL* isPreserving )
2528 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2529 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->properties->preserving);
2530 *isPreserving = This->properties->preserving;
2535 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2536 IXMLDOMDocument3 *iface,
2537 VARIANT_BOOL isPreserving )
2539 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2540 TRACE("(%p)->(%d)\n", This, isPreserving);
2541 This->properties->preserving = isPreserving;
2546 static HRESULT WINAPI domdoc_put_onreadystatechange(
2547 IXMLDOMDocument3 *iface,
2550 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2552 TRACE("(%p)->(%s)\n", This, debugstr_variant(&event));
2553 return set_doc_event(This, EVENTID_READYSTATECHANGE, &event);
2557 static HRESULT WINAPI domdoc_put_onDataAvailable(
2558 IXMLDOMDocument3 *iface,
2559 VARIANT onDataAvailableSink )
2561 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2562 FIXME("%p\n", This);
2566 static HRESULT WINAPI domdoc_put_onTransformNode(
2567 IXMLDOMDocument3 *iface,
2568 VARIANT onTransformNodeSink )
2570 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2571 FIXME("%p\n", This);
2575 static HRESULT WINAPI domdoc_get_namespaces(
2576 IXMLDOMDocument3* iface,
2577 IXMLDOMSchemaCollection** schemaCollection )
2579 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2580 FIXME("(%p)->(%p)\n", This, schemaCollection);
2584 static HRESULT WINAPI domdoc_get_schemas(
2585 IXMLDOMDocument3* iface,
2588 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2589 HRESULT hr = S_FALSE;
2590 IXMLDOMSchemaCollection2* cur_schema = This->properties->schemaCache;
2592 TRACE("(%p)->(%p)\n", This, var1);
2594 VariantInit(var1); /* Test shows we don't call VariantClear here */
2595 V_VT(var1) = VT_NULL;
2599 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2601 V_VT(var1) = VT_DISPATCH;
2606 static HRESULT WINAPI domdoc_putref_schemas(
2607 IXMLDOMDocument3* iface,
2610 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2611 HRESULT hr = E_FAIL;
2612 IXMLDOMSchemaCollection2* new_schema = NULL;
2614 FIXME("(%p): semi-stub\n", This);
2618 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2622 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2631 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2636 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->properties->schemaCache, new_schema);
2637 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2643 static inline BOOL is_wellformed(xmlDocPtr doc)
2645 #ifdef HAVE_XMLDOC_PROPERTIES
2646 return doc->properties & XML_DOC_WELLFORMED;
2648 /* Not a full check, but catches the worst violations */
2652 for (child = doc->children; child != NULL; child = child->next)
2654 switch (child->type)
2656 case XML_ELEMENT_NODE:
2661 case XML_CDATA_SECTION_NODE:
2673 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2677 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2681 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2685 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2689 static HRESULT WINAPI domdoc_validateNode(
2690 IXMLDOMDocument3* iface,
2692 IXMLDOMParseError** err)
2694 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2695 LONG state, err_code = 0;
2699 TRACE("(%p)->(%p, %p)\n", This, node, err);
2700 domdoc_get_readyState(iface, &state);
2701 if (state != READYSTATE_COMPLETE)
2704 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2711 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2715 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2718 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2722 if (!is_wellformed(get_doc(This)))
2724 ERR("doc not well-formed\n");
2726 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2730 /* DTD validation */
2731 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2733 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2734 vctx->error = validate_error;
2735 vctx->warning = validate_warning;
2738 if (!((node == (IXMLDOMNode*)iface)?
2739 xmlValidateDocument(vctx, get_doc(This)) :
2740 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2742 /* TODO: get a real error code here */
2743 TRACE("DTD validation failed\n");
2744 err_code = E_XML_INVALID;
2747 xmlFreeValidCtxt(vctx);
2750 /* Schema validation */
2751 if (hr == S_OK && This->properties->schemaCache != NULL)
2754 hr = SchemaCache_validate_tree(This->properties->schemaCache, get_node_obj(node)->node);
2758 /* TODO: get a real error code here */
2761 TRACE("schema validation succeeded\n");
2765 ERR("schema validation failed\n");
2766 err_code = E_XML_INVALID;
2771 /* not really OK, just didn't find a schema for the ns */
2778 ERR("no DTD or schema found\n");
2779 err_code = E_XML_NODTD;
2784 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2789 static HRESULT WINAPI domdoc_validate(
2790 IXMLDOMDocument3* iface,
2791 IXMLDOMParseError** err)
2793 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2794 TRACE("(%p)->(%p)\n", This, err);
2795 return domdoc_validateNode(iface, (IXMLDOMNode*)iface, err);
2798 static HRESULT WINAPI domdoc_setProperty(
2799 IXMLDOMDocument3* iface,
2803 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2805 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2807 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2813 V_VT(&varStr) = VT_EMPTY;
2814 if (V_VT(&var) != VT_BSTR)
2816 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2818 bstr = V_BSTR(&varStr);
2821 bstr = V_BSTR(&var);
2824 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2825 This->properties->XPath = TRUE;
2826 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2827 This->properties->XPath = FALSE;
2831 VariantClear(&varStr);
2834 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2839 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2840 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2841 xmlXPathContextPtr ctx;
2842 struct list *pNsList;
2843 select_ns_entry* pNsEntry = NULL;
2845 V_VT(&varStr) = VT_EMPTY;
2846 if (V_VT(&var) != VT_BSTR)
2848 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2850 bstr = V_BSTR(&varStr);
2853 bstr = V_BSTR(&var);
2857 pNsList = &(This->properties->selectNsList);
2858 clear_selectNsList(pNsList);
2860 nsStr = xmlchar_from_wchar(bstr);
2862 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2864 This->properties->selectNsStr = nsStr;
2865 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2868 ctx = xmlXPathNewContext(This->node.node->doc);
2871 for (; *pTokBegin; pTokBegin = pTokEnd)
2873 if (pNsEntry != NULL)
2874 memset(pNsEntry, 0, sizeof(select_ns_entry));
2876 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2878 while (*pTokBegin == ' ')
2880 pTokEnd = pTokBegin;
2881 while (*pTokEnd != ' ' && *pTokEnd != 0)
2884 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2887 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2888 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2893 if (*pTokBegin == '=')
2895 /*valid for XSLPattern?*/
2896 FIXME("Setting default xmlns not supported - skipping.\n");
2897 pTokBegin = pTokEnd;
2900 else if (*pTokBegin == ':')
2902 pNsEntry->prefix = ++pTokBegin;
2903 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2906 if (pTokInner == pTokEnd)
2909 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2910 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2914 pNsEntry->prefix_end = *pTokInner;
2918 if (pTokEnd-pTokInner > 1 &&
2919 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2920 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2922 pNsEntry->href = ++pTokInner;
2923 pNsEntry->href_end = *(pTokEnd-1);
2925 list_add_tail(pNsList, &pNsEntry->entry);
2926 /*let libxml figure out if they're valid from here ;)*/
2927 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2936 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2937 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2938 list_add_tail(pNsList, &pNsEntry->entry);
2951 heap_free(pNsEntry);
2952 xmlXPathFreeContext(ctx);
2955 VariantClear(&varStr);
2958 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2959 lstrcmpiW(p, PropertyNewParserW) == 0 ||
2960 lstrcmpiW(p, PropertyResolveExternalsW) == 0)
2963 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2967 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2971 static HRESULT WINAPI domdoc_getProperty(
2972 IXMLDOMDocument3* iface,
2976 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2978 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2981 return E_INVALIDARG;
2983 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2985 V_VT(var) = VT_BSTR;
2986 V_BSTR(var) = This->properties->XPath ?
2987 SysAllocString(PropValueXPathW) :
2988 SysAllocString(PropValueXSLPatternW);
2989 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2991 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2994 BSTR rebuiltStr, cur;
2995 const xmlChar *nsStr;
2996 struct list *pNsList;
2997 select_ns_entry* pNsEntry;
2999 V_VT(var) = VT_BSTR;
3000 nsStr = This->properties->selectNsStr;
3001 pNsList = &This->properties->selectNsList;
3002 lenA = This->properties->selectNsStr_len;
3003 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
3004 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
3005 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
3007 /* this is fine because all of the chars that end tokens are ASCII*/
3008 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
3010 while (*cur != 0) ++cur;
3011 if (pNsEntry->prefix_end)
3013 *cur = pNsEntry->prefix_end;
3014 while (*cur != 0) ++cur;
3017 if (pNsEntry->href_end)
3019 *cur = pNsEntry->href_end;
3022 V_BSTR(var) = SysAllocString(rebuiltStr);
3023 heap_free(rebuiltStr);
3027 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
3031 static HRESULT WINAPI domdoc_importNode(
3032 IXMLDOMDocument3* iface,
3035 IXMLDOMNode** clone)
3037 domdoc *This = impl_from_IXMLDOMDocument3( iface );
3038 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
3042 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
3044 domdoc_QueryInterface,
3047 domdoc_GetTypeInfoCount,
3049 domdoc_GetIDsOfNames,
3051 domdoc_get_nodeName,
3052 domdoc_get_nodeValue,
3053 domdoc_put_nodeValue,
3054 domdoc_get_nodeType,
3055 domdoc_get_parentNode,
3056 domdoc_get_childNodes,
3057 domdoc_get_firstChild,
3058 domdoc_get_lastChild,
3059 domdoc_get_previousSibling,
3060 domdoc_get_nextSibling,
3061 domdoc_get_attributes,
3062 domdoc_insertBefore,
3063 domdoc_replaceChild,
3066 domdoc_hasChildNodes,
3067 domdoc_get_ownerDocument,
3069 domdoc_get_nodeTypeString,
3072 domdoc_get_specified,
3073 domdoc_get_definition,
3074 domdoc_get_nodeTypedValue,
3075 domdoc_put_nodeTypedValue,
3076 domdoc_get_dataType,
3077 domdoc_put_dataType,
3079 domdoc_transformNode,
3081 domdoc_selectSingleNode,
3083 domdoc_get_namespaceURI,
3085 domdoc_get_baseName,
3086 domdoc_transformNodeToObject,
3088 domdoc_get_implementation,
3089 domdoc_get_documentElement,
3090 domdoc_put_documentElement,
3091 domdoc_createElement,
3092 domdoc_createDocumentFragment,
3093 domdoc_createTextNode,
3094 domdoc_createComment,
3095 domdoc_createCDATASection,
3096 domdoc_createProcessingInstruction,
3097 domdoc_createAttribute,
3098 domdoc_createEntityReference,
3099 domdoc_getElementsByTagName,
3103 domdoc_get_readyState,
3104 domdoc_get_parseError,
3111 domdoc_get_validateOnParse,
3112 domdoc_put_validateOnParse,
3113 domdoc_get_resolveExternals,
3114 domdoc_put_resolveExternals,
3115 domdoc_get_preserveWhiteSpace,
3116 domdoc_put_preserveWhiteSpace,
3117 domdoc_put_onreadystatechange,
3118 domdoc_put_onDataAvailable,
3119 domdoc_put_onTransformNode,
3120 domdoc_get_namespaces,
3122 domdoc_putref_schemas,
3126 domdoc_validateNode,
3130 /* IConnectionPointContainer */
3131 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
3132 REFIID riid, void **ppv)
3134 domdoc *This = impl_from_IConnectionPointContainer(iface);
3135 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)This, riid, ppv);
3138 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
3140 domdoc *This = impl_from_IConnectionPointContainer(iface);
3141 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)This);
3144 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
3146 domdoc *This = impl_from_IConnectionPointContainer(iface);
3147 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)This);
3150 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
3151 IEnumConnectionPoints **ppEnum)
3153 domdoc *This = impl_from_IConnectionPointContainer(iface);
3154 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3158 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
3159 REFIID riid, IConnectionPoint **cp)
3161 domdoc *This = impl_from_IConnectionPointContainer(iface);
3162 ConnectionPoint *iter;
3164 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
3168 for(iter = This->cp_list; iter; iter = iter->next)
3170 if (IsEqualGUID(iter->iid, riid))
3171 *cp = (IConnectionPoint*)&iter->lpVtblConnectionPoint;
3176 IConnectionPoint_AddRef(*cp);
3180 FIXME("unsupported riid %s\n", debugstr_guid(riid));
3181 return CONNECT_E_NOCONNECTION;
3185 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
3187 ConnectionPointContainer_QueryInterface,
3188 ConnectionPointContainer_AddRef,
3189 ConnectionPointContainer_Release,
3190 ConnectionPointContainer_EnumConnectionPoints,
3191 ConnectionPointContainer_FindConnectionPoint
3194 /* IConnectionPoint */
3195 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
3196 REFIID riid, void **ppv)
3198 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3200 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3204 if (IsEqualGUID(&IID_IUnknown, riid) ||
3205 IsEqualGUID(&IID_IConnectionPoint, riid))
3212 IConnectionPoint_AddRef(iface);
3216 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3217 return E_NOINTERFACE;
3220 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3222 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3223 return IConnectionPointContainer_AddRef(This->container);
3226 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3228 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3229 return IConnectionPointContainer_Release(This->container);
3232 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3234 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3236 TRACE("(%p)->(%p)\n", This, iid);
3238 if (!iid) return E_POINTER;
3244 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3245 IConnectionPointContainer **container)
3247 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3249 TRACE("(%p)->(%p)\n", This, container);
3251 if (!container) return E_POINTER;
3253 *container = This->container;
3254 IConnectionPointContainer_AddRef(*container);
3258 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
3261 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3262 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
3266 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3268 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3270 TRACE("(%p)->(%d)\n", This, cookie);
3272 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3273 return CONNECT_E_NOCONNECTION;
3275 IUnknown_Release(This->sinks[cookie-1].unk);
3276 This->sinks[cookie-1].unk = NULL;
3281 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3282 IEnumConnections **ppEnum)
3284 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3285 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3289 static const IConnectionPointVtbl ConnectionPointVtbl =
3291 ConnectionPoint_QueryInterface,
3292 ConnectionPoint_AddRef,
3293 ConnectionPoint_Release,
3294 ConnectionPoint_GetConnectionInterface,
3295 ConnectionPoint_GetConnectionPointContainer,
3296 ConnectionPoint_Advise,
3297 ConnectionPoint_Unadvise,
3298 ConnectionPoint_EnumConnections
3301 void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3303 cp->lpVtblConnectionPoint = &ConnectionPointVtbl;
3309 cp->next = doc->cp_list;
3312 cp->container = (IConnectionPointContainer*)&doc->lpVtblConnectionPointContainer;
3315 /* domdoc implementation of IObjectWithSite */
3316 static HRESULT WINAPI
3317 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3319 domdoc *This = impl_from_IObjectWithSite(iface);
3320 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppvObject );
3323 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3325 domdoc *This = impl_from_IObjectWithSite(iface);
3326 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3329 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3331 domdoc *This = impl_from_IObjectWithSite(iface);
3332 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3335 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3337 domdoc *This = impl_from_IObjectWithSite(iface);
3339 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3344 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3347 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3349 domdoc *This = impl_from_IObjectWithSite(iface);
3351 TRACE("(%p)->(%p)\n", iface, punk);
3357 IUnknown_Release( This->site );
3364 IUnknown_AddRef( punk );
3367 IUnknown_Release( This->site );
3374 static const IObjectWithSiteVtbl domdocObjectSite =
3376 domdoc_ObjectWithSite_QueryInterface,
3377 domdoc_ObjectWithSite_AddRef,
3378 domdoc_ObjectWithSite_Release,
3379 domdoc_ObjectWithSite_SetSite,
3380 domdoc_ObjectWithSite_GetSite
3383 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3385 domdoc *This = impl_from_IObjectSafety(iface);
3386 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppv );
3389 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3391 domdoc *This = impl_from_IObjectSafety(iface);
3392 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3395 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3397 domdoc *This = impl_from_IObjectSafety(iface);
3398 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3401 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3403 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3404 DWORD *supported, DWORD *enabled)
3406 domdoc *This = impl_from_IObjectSafety(iface);
3408 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3410 if(!supported || !enabled) return E_POINTER;
3412 *supported = SAFETY_SUPPORTED_OPTIONS;
3413 *enabled = This->safeopt;
3418 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3419 DWORD mask, DWORD enabled)
3421 domdoc *This = impl_from_IObjectSafety(iface);
3422 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3424 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3427 This->safeopt = enabled & mask & SAFETY_SUPPORTED_OPTIONS;
3431 #undef SAFETY_SUPPORTED_OPTIONS
3433 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3434 domdoc_Safety_QueryInterface,
3435 domdoc_Safety_AddRef,
3436 domdoc_Safety_Release,
3437 domdoc_Safety_GetInterfaceSafetyOptions,
3438 domdoc_Safety_SetInterfaceSafetyOptions
3441 static const tid_t domdoc_iface_tids[] = {
3443 IXMLDOMDocument_tid,
3444 IXMLDOMDocument2_tid,
3447 static dispex_static_data_t domdoc_dispex = {
3449 IXMLDOMDocument2_tid,
3454 HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3458 doc = heap_alloc( sizeof (*doc) );
3460 return E_OUTOFMEMORY;
3462 doc->lpVtbl = &domdoc_vtbl;
3463 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
3464 doc->lpvtblIObjectWithSite = &domdocObjectSite;
3465 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
3466 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
3467 doc->lpVtblConnectionPointContainer = &ConnectionPointContainerVtbl;
3469 doc->async = VARIANT_TRUE;
3470 doc->validating = 0;
3472 doc->properties = properties_from_xmlDocPtr(xmldoc);
3478 doc->cp_list = NULL;
3479 memset(doc->events, 0, sizeof(doc->events));
3481 /* events connection points */
3482 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3483 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3484 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3486 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->lpVtbl, &domdoc_dispex);
3488 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
3490 TRACE("returning iface %p\n", *document);
3494 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3499 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
3501 xmldoc = xmlNewDoc(NULL);
3503 return E_OUTOFMEMORY;
3505 xmldoc->_private = create_priv();
3506 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
3508 hr = get_domdoc_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3511 free_properties(properties_from_xmlDocPtr(xmldoc));
3512 heap_free(xmldoc->_private);
3520 IUnknown* create_domdoc( xmlNodePtr document )
3525 TRACE("(%p)\n", document);
3527 hr = get_domdoc_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3536 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3538 MESSAGE("This program tried to use a DOMDocument object, but\n"
3539 "libxml2 support was not present at compile time.\n");