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 pctx;
427 pctx = (xmlParserCtxtPtr) ctx;
428 This = (domdoc const*) pctx->_private;
430 /* during domdoc_loadXML() the xmlDocPtr->_private data is not available */
431 if (!This->properties->preserving &&
432 !is_preserving_whitespace(pctx->node) &&
433 strn_isspace(ch, len))
436 xmlSAX2Characters(ctx, ch, len);
439 static void LIBXML2_LOG_CALLBACK sax_error(void* ctx, char const* msg, ...)
443 LIBXML2_CALLBACK_ERR(doparse, msg, ap);
447 static void LIBXML2_LOG_CALLBACK sax_warning(void* ctx, char const* msg, ...)
451 LIBXML2_CALLBACK_WARN(doparse, msg, ap);
455 static void sax_serror(void* ctx, xmlErrorPtr err)
457 LIBXML2_CALLBACK_SERROR(doparse, err);
460 static xmlDocPtr doparse(domdoc* This, char *ptr, int len, xmlChar const* encoding)
462 xmlDocPtr doc = NULL;
463 xmlParserCtxtPtr pctx;
464 static xmlSAXHandler sax_handler = {
465 xmlSAX2InternalSubset, /* internalSubset */
466 xmlSAX2IsStandalone, /* isStandalone */
467 xmlSAX2HasInternalSubset, /* hasInternalSubset */
468 xmlSAX2HasExternalSubset, /* hasExternalSubset */
469 xmlSAX2ResolveEntity, /* resolveEntity */
470 xmlSAX2GetEntity, /* getEntity */
471 xmlSAX2EntityDecl, /* entityDecl */
472 xmlSAX2NotationDecl, /* notationDecl */
473 xmlSAX2AttributeDecl, /* attributeDecl */
474 xmlSAX2ElementDecl, /* elementDecl */
475 xmlSAX2UnparsedEntityDecl, /* unparsedEntityDecl */
476 xmlSAX2SetDocumentLocator, /* setDocumentLocator */
477 xmlSAX2StartDocument, /* startDocument */
478 xmlSAX2EndDocument, /* endDocument */
479 xmlSAX2StartElement, /* startElement */
480 xmlSAX2EndElement, /* endElement */
481 xmlSAX2Reference, /* reference */
482 sax_characters, /* characters */
483 sax_characters, /* ignorableWhitespace */
484 xmlSAX2ProcessingInstruction, /* processingInstruction */
485 xmlSAX2Comment, /* comment */
486 sax_warning, /* warning */
487 sax_error, /* error */
488 sax_error, /* fatalError */
489 xmlSAX2GetParameterEntity, /* getParameterEntity */
490 xmlSAX2CDataBlock, /* cdataBlock */
491 xmlSAX2ExternalSubset, /* externalSubset */
494 xmlSAX2StartElementNs, /* startElementNs */
495 xmlSAX2EndElementNs, /* endElementNs */
496 sax_serror /* serror */
500 pctx = xmlCreateMemoryParserCtxt(ptr, len);
503 ERR("Failed to create parser context\n");
507 if (pctx->sax) xmlFree(pctx->sax);
508 pctx->sax = &sax_handler;
509 pctx->_private = This;
511 pctx->encoding = xmlStrdup(encoding);
512 xmlParseDocument(pctx);
514 if (pctx->wellFormed)
520 xmlFreeDoc(pctx->myDoc);
524 xmlFreeParserCtxt(pctx);
526 /* TODO: put this in one of the SAX callbacks */
527 /* create first child as a <?xml...?> */
528 if (doc && doc->standalone != -1)
532 xmlChar *xmlbuff = (xmlChar*)buff;
534 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
536 /* version attribute can't be omitted */
537 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
538 xmlNodeAddContent( node, xmlbuff );
542 sprintf(buff, " encoding=\"%s\"", doc->encoding);
543 xmlNodeAddContent( node, xmlbuff );
546 if (doc->standalone != -2)
548 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
549 xmlNodeAddContent( node, xmlbuff );
552 xmldoc_link_xmldecl( doc, node );
558 void xmldoc_init(xmlDocPtr doc, const GUID *clsid)
560 doc->_private = create_priv();
561 priv_from_xmlDocPtr(doc)->properties = create_properties(clsid);
564 LONG xmldoc_add_ref(xmlDocPtr doc)
566 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
567 TRACE("(%p)->(%d)\n", doc, ref);
571 LONG xmldoc_release(xmlDocPtr doc)
573 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
574 LONG ref = InterlockedDecrement(&priv->refs);
575 TRACE("(%p)->(%d)\n", doc, ref);
578 orphan_entry *orphan, *orphan2;
579 TRACE("freeing docptr %p\n", doc);
581 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
583 xmlFreeNode( orphan->node );
586 free_properties(priv->properties);
587 heap_free(doc->_private);
595 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
597 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
600 entry = heap_alloc( sizeof (*entry) );
602 return E_OUTOFMEMORY;
605 list_add_head( &priv->orphans, &entry->entry );
609 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
611 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
612 orphan_entry *entry, *entry2;
614 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
616 if( entry->node == node )
618 list_remove( &entry->entry );
627 static inline xmlDocPtr get_doc( domdoc *This )
629 return (xmlDocPtr)This->node.node;
632 static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
636 priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
637 if (xmldoc_release(get_doc(This)) != 0)
638 priv_from_xmlDocPtr(get_doc(This))->properties =
639 copy_properties(This->properties);
642 This->node.node = (xmlNodePtr) xml;
646 xmldoc_add_ref(get_doc(This));
647 priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
653 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
655 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
658 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
660 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStreamInit));
663 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
665 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
668 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
670 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
673 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
675 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblISupportErrorInfo));
678 static inline domdoc *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
680 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtblConnectionPointContainer));
683 /************************************************************************
684 * domdoc implementation of IPersistStream.
686 static HRESULT WINAPI domdoc_IPersistStreamInit_QueryInterface(
687 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
689 domdoc* This = impl_from_IPersistStreamInit(iface);
690 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)&This->lpVtbl, riid, ppvObj);
693 static ULONG WINAPI domdoc_IPersistStreamInit_AddRef(
694 IPersistStreamInit *iface)
696 domdoc* This = impl_from_IPersistStreamInit(iface);
697 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)&This->lpVtbl);
700 static ULONG WINAPI domdoc_IPersistStreamInit_Release(
701 IPersistStreamInit *iface)
703 domdoc* This = impl_from_IPersistStreamInit(iface);
704 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)&This->lpVtbl);
707 static HRESULT WINAPI domdoc_IPersistStreamInit_GetClassID(
708 IPersistStreamInit *iface, CLSID *classid)
710 domdoc* This = impl_from_IPersistStreamInit(iface);
711 TRACE("(%p)->(%p)\n", This, classid);
716 *classid = *DOMDocument_version(This->properties->version);
721 static HRESULT WINAPI domdoc_IPersistStreamInit_IsDirty(
722 IPersistStreamInit *iface)
724 domdoc *This = impl_from_IPersistStreamInit(iface);
725 FIXME("(%p): stub!\n", This);
729 static HRESULT WINAPI domdoc_IPersistStreamInit_Load(
730 IPersistStreamInit *iface, LPSTREAM pStm)
732 domdoc *This = impl_from_IPersistStreamInit(iface);
735 DWORD read, written, len;
738 xmlDocPtr xmldoc = NULL;
740 TRACE("(%p)->(%p)\n", This, pStm);
745 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
751 IStream_Read(pStm, buf, sizeof(buf), &read);
752 hr = IStream_Write(This->stream, buf, read, &written);
753 } while(SUCCEEDED(hr) && written != 0 && read != 0);
757 ERR("Failed to copy stream\n");
761 hr = GetHGlobalFromStream(This->stream, &hglobal);
765 len = GlobalSize(hglobal);
766 ptr = GlobalLock(hglobal);
768 xmldoc = doparse(This, ptr, len, NULL);
769 GlobalUnlock(hglobal);
773 ERR("Failed to parse xml\n");
777 xmldoc->_private = create_priv();
779 return attach_xmldoc(This, xmldoc);
782 static HRESULT WINAPI domdoc_IPersistStreamInit_Save(
783 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
785 domdoc *This = impl_from_IPersistStreamInit(iface);
789 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
791 hr = IXMLDOMDocument3_get_xml( (IXMLDOMDocument3*)&This->lpVtbl, &xmlString );
794 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
796 hr = IStream_Write( stream, xmlString, len, NULL );
797 SysFreeString(xmlString);
800 TRACE("ret 0x%08x\n", hr);
805 static HRESULT WINAPI domdoc_IPersistStreamInit_GetSizeMax(
806 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
808 domdoc *This = impl_from_IPersistStreamInit(iface);
809 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
813 static HRESULT WINAPI domdoc_IPersistStreamInit_InitNew(
814 IPersistStreamInit *iface)
816 domdoc *This = impl_from_IPersistStreamInit(iface);
817 TRACE("(%p)\n", This);
821 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
823 domdoc_IPersistStreamInit_QueryInterface,
824 domdoc_IPersistStreamInit_AddRef,
825 domdoc_IPersistStreamInit_Release,
826 domdoc_IPersistStreamInit_GetClassID,
827 domdoc_IPersistStreamInit_IsDirty,
828 domdoc_IPersistStreamInit_Load,
829 domdoc_IPersistStreamInit_Save,
830 domdoc_IPersistStreamInit_GetSizeMax,
831 domdoc_IPersistStreamInit_InitNew
834 /* ISupportErrorInfo interface */
835 static HRESULT WINAPI support_error_QueryInterface(
836 ISupportErrorInfo *iface,
837 REFIID riid, void** ppvObj )
839 domdoc *This = impl_from_ISupportErrorInfo(iface);
840 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3 *)This, riid, ppvObj);
843 static ULONG WINAPI support_error_AddRef(
844 ISupportErrorInfo *iface )
846 domdoc *This = impl_from_ISupportErrorInfo(iface);
847 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
850 static ULONG WINAPI support_error_Release(
851 ISupportErrorInfo *iface )
853 domdoc *This = impl_from_ISupportErrorInfo(iface);
854 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
857 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
858 ISupportErrorInfo *iface,
861 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
865 static const struct ISupportErrorInfoVtbl support_error_vtbl =
867 support_error_QueryInterface,
868 support_error_AddRef,
869 support_error_Release,
870 support_error_InterfaceSupportsErrorInfo
873 /* IXMLDOMDocument2 interface */
874 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
876 domdoc *This = impl_from_IXMLDOMDocument3( iface );
878 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
882 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
883 IsEqualGUID( riid, &IID_IDispatch ) ||
884 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
885 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
886 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
887 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
891 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
892 IsEqualGUID(&IID_IPersistStreamInit, riid))
894 *ppvObject = &(This->lpvtblIPersistStreamInit);
896 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
898 *ppvObject = &(This->lpvtblIObjectWithSite);
900 else if (IsEqualGUID(&IID_IObjectSafety, riid))
902 *ppvObject = &(This->lpvtblIObjectSafety);
904 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
906 *ppvObject = &This->lpvtblISupportErrorInfo;
908 else if(node_query_interface(&This->node, riid, ppvObject))
910 return *ppvObject ? S_OK : E_NOINTERFACE;
912 else if (IsEqualGUID( riid, &IID_IConnectionPointContainer ))
914 *ppvObject = &This->lpVtblConnectionPointContainer;
916 else if(IsEqualGUID(&IID_IRunnableObject, riid))
918 TRACE("IID_IRunnableObject not supported returning NULL\n");
919 return E_NOINTERFACE;
923 FIXME("interface %s not implemented\n", debugstr_guid(riid));
924 return E_NOINTERFACE;
927 IUnknown_AddRef((IUnknown*)*ppvObject);
933 static ULONG WINAPI domdoc_AddRef(
934 IXMLDOMDocument3 *iface )
936 domdoc *This = impl_from_IXMLDOMDocument3( iface );
937 ULONG ref = InterlockedIncrement( &This->ref );
938 TRACE("(%p)->(%d)\n", This, ref );
943 static ULONG WINAPI domdoc_Release(
944 IXMLDOMDocument3 *iface )
946 domdoc *This = impl_from_IXMLDOMDocument3( iface );
947 LONG ref = InterlockedDecrement( &This->ref );
949 TRACE("(%p)->(%d)\n", This, ref );
956 detach_bsc(This->bsc);
959 IUnknown_Release( This->site );
960 destroy_xmlnode(&This->node);
962 IStream_Release(This->stream);
964 for (eid = 0; eid < EVENTID_LAST; eid++)
965 if (This->events[eid]) IDispatch_Release(This->events[eid]);
973 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
975 domdoc *This = impl_from_IXMLDOMDocument3( iface );
977 TRACE("(%p)->(%p)\n", This, pctinfo);
984 static HRESULT WINAPI domdoc_GetTypeInfo(
985 IXMLDOMDocument3 *iface,
986 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
988 domdoc *This = impl_from_IXMLDOMDocument3( iface );
991 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
993 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
998 static HRESULT WINAPI domdoc_GetIDsOfNames(
999 IXMLDOMDocument3 *iface,
1001 LPOLESTR* rgszNames,
1006 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1007 ITypeInfo *typeinfo;
1010 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1013 if(!rgszNames || cNames == 0 || !rgDispId)
1014 return E_INVALIDARG;
1016 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
1019 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1020 ITypeInfo_Release(typeinfo);
1027 static HRESULT WINAPI domdoc_Invoke(
1028 IXMLDOMDocument3 *iface,
1029 DISPID dispIdMember,
1033 DISPPARAMS* pDispParams,
1034 VARIANT* pVarResult,
1035 EXCEPINFO* pExcepInfo,
1038 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1039 ITypeInfo *typeinfo;
1042 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1043 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1045 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
1048 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
1049 pVarResult, pExcepInfo, puArgErr);
1050 ITypeInfo_Release(typeinfo);
1057 static HRESULT WINAPI domdoc_get_nodeName(
1058 IXMLDOMDocument3 *iface,
1061 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1063 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
1065 TRACE("(%p)->(%p)\n", This, name);
1067 return return_bstr(documentW, name);
1071 static HRESULT WINAPI domdoc_get_nodeValue(
1072 IXMLDOMDocument3 *iface,
1075 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1077 TRACE("(%p)->(%p)\n", This, value);
1080 return E_INVALIDARG;
1082 V_VT(value) = VT_NULL;
1083 V_BSTR(value) = NULL; /* tests show that we should do this */
1088 static HRESULT WINAPI domdoc_put_nodeValue(
1089 IXMLDOMDocument3 *iface,
1092 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1093 TRACE("(%p)->(v%d)\n", This, V_VT(&value));
1098 static HRESULT WINAPI domdoc_get_nodeType(
1099 IXMLDOMDocument3 *iface,
1102 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1104 TRACE("(%p)->(%p)\n", This, type);
1106 *type = NODE_DOCUMENT;
1111 static HRESULT WINAPI domdoc_get_parentNode(
1112 IXMLDOMDocument3 *iface,
1113 IXMLDOMNode** parent )
1115 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1117 TRACE("(%p)->(%p)\n", This, parent);
1119 return node_get_parent(&This->node, parent);
1123 static HRESULT WINAPI domdoc_get_childNodes(
1124 IXMLDOMDocument3 *iface,
1125 IXMLDOMNodeList** childList )
1127 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1129 TRACE("(%p)->(%p)\n", This, childList);
1131 return node_get_child_nodes(&This->node, childList);
1135 static HRESULT WINAPI domdoc_get_firstChild(
1136 IXMLDOMDocument3 *iface,
1137 IXMLDOMNode** firstChild )
1139 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1141 TRACE("(%p)->(%p)\n", This, firstChild);
1143 return node_get_first_child(&This->node, firstChild);
1147 static HRESULT WINAPI domdoc_get_lastChild(
1148 IXMLDOMDocument3 *iface,
1149 IXMLDOMNode** lastChild )
1151 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1153 TRACE("(%p)->(%p)\n", This, lastChild);
1155 return node_get_last_child(&This->node, lastChild);
1159 static HRESULT WINAPI domdoc_get_previousSibling(
1160 IXMLDOMDocument3 *iface,
1161 IXMLDOMNode** previousSibling )
1163 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1165 TRACE("(%p)->(%p)\n", This, previousSibling);
1167 return return_null_node(previousSibling);
1171 static HRESULT WINAPI domdoc_get_nextSibling(
1172 IXMLDOMDocument3 *iface,
1173 IXMLDOMNode** nextSibling )
1175 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1177 TRACE("(%p)->(%p)\n", This, nextSibling);
1179 return return_null_node(nextSibling);
1183 static HRESULT WINAPI domdoc_get_attributes(
1184 IXMLDOMDocument3 *iface,
1185 IXMLDOMNamedNodeMap** attributeMap )
1187 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1189 TRACE("(%p)->(%p)\n", This, attributeMap);
1191 return return_null_ptr((void**)attributeMap);
1195 static HRESULT WINAPI domdoc_insertBefore(
1196 IXMLDOMDocument3 *iface,
1197 IXMLDOMNode* newChild,
1199 IXMLDOMNode** outNewChild )
1201 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1203 TRACE("(%p)->(%p x%d %p)\n", This, newChild, V_VT(&refChild), outNewChild);
1205 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1209 static HRESULT WINAPI domdoc_replaceChild(
1210 IXMLDOMDocument3 *iface,
1211 IXMLDOMNode* newChild,
1212 IXMLDOMNode* oldChild,
1213 IXMLDOMNode** outOldChild)
1215 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1217 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1219 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1223 static HRESULT WINAPI domdoc_removeChild(
1224 IXMLDOMDocument3 *iface,
1226 IXMLDOMNode **oldChild)
1228 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1229 TRACE("(%p)->(%p %p)\n", This, child, oldChild);
1230 return node_remove_child(&This->node, child, oldChild);
1234 static HRESULT WINAPI domdoc_appendChild(
1235 IXMLDOMDocument3 *iface,
1237 IXMLDOMNode **outChild)
1239 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1240 TRACE("(%p)->(%p %p)\n", This, child, outChild);
1241 return node_append_child(&This->node, child, outChild);
1245 static HRESULT WINAPI domdoc_hasChildNodes(
1246 IXMLDOMDocument3 *iface,
1249 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1250 TRACE("(%p)->(%p)\n", This, ret);
1251 return node_has_childnodes(&This->node, ret);
1255 static HRESULT WINAPI domdoc_get_ownerDocument(
1256 IXMLDOMDocument3 *iface,
1257 IXMLDOMDocument **doc)
1259 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1260 TRACE("(%p)->(%p)\n", This, doc);
1261 return node_get_owner_doc(&This->node, doc);
1265 static HRESULT WINAPI domdoc_cloneNode(
1266 IXMLDOMDocument3 *iface,
1268 IXMLDOMNode** outNode)
1270 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1271 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
1272 return node_clone( &This->node, deep, outNode );
1276 static HRESULT WINAPI domdoc_get_nodeTypeString(
1277 IXMLDOMDocument3 *iface,
1280 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1281 static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
1283 TRACE("(%p)->(%p)\n", This, p);
1285 return return_bstr(documentW, p);
1289 static HRESULT WINAPI domdoc_get_text(
1290 IXMLDOMDocument3 *iface,
1293 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1294 TRACE("(%p)->(%p)\n", This, p);
1295 return node_get_text(&This->node, p);
1299 static HRESULT WINAPI domdoc_put_text(
1300 IXMLDOMDocument3 *iface,
1303 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1304 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1309 static HRESULT WINAPI domdoc_get_specified(
1310 IXMLDOMDocument3 *iface,
1311 VARIANT_BOOL* isSpecified )
1313 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1314 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1315 *isSpecified = VARIANT_TRUE;
1320 static HRESULT WINAPI domdoc_get_definition(
1321 IXMLDOMDocument3 *iface,
1322 IXMLDOMNode** definitionNode )
1324 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1325 FIXME("(%p)->(%p)\n", This, definitionNode);
1330 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1331 IXMLDOMDocument3 *iface,
1334 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1335 TRACE("(%p)->(%p)\n", This, v);
1336 return return_null_var(v);
1339 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1340 IXMLDOMDocument3 *iface,
1341 VARIANT typedValue )
1343 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1344 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1349 static HRESULT WINAPI domdoc_get_dataType(
1350 IXMLDOMDocument3 *iface,
1353 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1354 TRACE("(%p)->(%p)\n", This, typename);
1355 return return_null_var( typename );
1359 static HRESULT WINAPI domdoc_put_dataType(
1360 IXMLDOMDocument3 *iface,
1363 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1365 FIXME("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
1368 return E_INVALIDARG;
1373 static int XMLCALL domdoc_get_xml_writecallback(void *ctx, const char *data, int len)
1375 return xmlBufferAdd((xmlBufferPtr)ctx, (xmlChar*)data, len) == 0 ? len : 0;
1378 static HRESULT WINAPI domdoc_get_xml(
1379 IXMLDOMDocument3 *iface,
1382 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1383 xmlSaveCtxtPtr ctxt;
1388 TRACE("(%p)->(%p)\n", This, p);
1391 return E_INVALIDARG;
1395 buf = xmlBufferCreate();
1397 return E_OUTOFMEMORY;
1399 options = xmldoc_has_decl(get_doc(This)) ? XML_SAVE_NO_DECL : 0;
1400 options |= XML_SAVE_FORMAT;
1401 ctxt = xmlSaveToIO(domdoc_get_xml_writecallback, NULL, buf, "UTF-8", options);
1406 return E_OUTOFMEMORY;
1409 ret = xmlSaveDoc(ctxt, get_doc(This));
1410 /* flushes on close */
1413 TRACE("%ld, len=%d\n", ret, xmlBufferLength(buf));
1414 if(ret != -1 && xmlBufferLength(buf) > 0)
1418 content = bstr_from_xmlChar(xmlBufferContent(buf));
1419 content = EnsureCorrectEOL(content);
1425 *p = SysAllocStringLen(NULL, 0);
1430 return *p ? S_OK : E_OUTOFMEMORY;
1434 static HRESULT WINAPI domdoc_transformNode(
1435 IXMLDOMDocument3 *iface,
1439 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1440 TRACE("(%p)->(%p %p)\n", This, node, p);
1441 return node_transform_node(&This->node, node, p);
1445 static HRESULT WINAPI domdoc_selectNodes(
1446 IXMLDOMDocument3 *iface,
1448 IXMLDOMNodeList **outList)
1450 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1451 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList);
1452 return node_select_nodes(&This->node, p, outList);
1456 static HRESULT WINAPI domdoc_selectSingleNode(
1457 IXMLDOMDocument3 *iface,
1459 IXMLDOMNode **outNode)
1461 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1462 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode);
1463 return node_select_singlenode(&This->node, p, outNode);
1467 static HRESULT WINAPI domdoc_get_parsed(
1468 IXMLDOMDocument3 *iface,
1469 VARIANT_BOOL* isParsed )
1471 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1472 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1473 *isParsed = VARIANT_TRUE;
1478 static HRESULT WINAPI domdoc_get_namespaceURI(
1479 IXMLDOMDocument3 *iface,
1480 BSTR* namespaceURI )
1482 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1483 TRACE("(%p)->(%p)\n", This, namespaceURI);
1484 return node_get_namespaceURI(&This->node, namespaceURI);
1488 static HRESULT WINAPI domdoc_get_prefix(
1489 IXMLDOMDocument3 *iface,
1492 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1493 TRACE("(%p)->(%p)\n", This, prefix);
1494 return return_null_bstr( prefix );
1498 static HRESULT WINAPI domdoc_get_baseName(
1499 IXMLDOMDocument3 *iface,
1502 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1503 TRACE("(%p)->(%p)\n", This, name);
1504 return return_null_bstr( name );
1508 static HRESULT WINAPI domdoc_transformNodeToObject(
1509 IXMLDOMDocument3 *iface,
1510 IXMLDOMNode* stylesheet,
1511 VARIANT outputObject)
1513 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1514 FIXME("(%p)->(%p %s)\n", This, stylesheet, debugstr_variant(&outputObject));
1519 static HRESULT WINAPI domdoc_get_doctype(
1520 IXMLDOMDocument3 *iface,
1521 IXMLDOMDocumentType** doctype )
1523 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1528 TRACE("(%p)->(%p)\n", This, doctype);
1530 if (!doctype) return E_INVALIDARG;
1534 dtd = xmlGetIntSubset(get_doc(This));
1535 if (!dtd) return S_FALSE;
1537 node = create_node((xmlNodePtr)dtd);
1538 if (!node) return S_FALSE;
1540 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentType, (void**)doctype);
1541 IXMLDOMNode_Release(node);
1547 static HRESULT WINAPI domdoc_get_implementation(
1548 IXMLDOMDocument3 *iface,
1549 IXMLDOMImplementation** impl )
1551 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1553 TRACE("(%p)->(%p)\n", This, impl);
1556 return E_INVALIDARG;
1558 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1563 static HRESULT WINAPI domdoc_get_documentElement(
1564 IXMLDOMDocument3 *iface,
1565 IXMLDOMElement** DOMElement )
1567 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1568 IXMLDOMNode *element_node;
1572 TRACE("(%p)->(%p)\n", This, DOMElement);
1575 return E_INVALIDARG;
1579 root = xmlDocGetRootElement( get_doc(This) );
1583 element_node = create_node( root );
1584 if(!element_node) return S_FALSE;
1586 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1587 IXMLDOMNode_Release(element_node);
1593 static HRESULT WINAPI domdoc_put_documentElement(
1594 IXMLDOMDocument3 *iface,
1595 IXMLDOMElement* DOMElement )
1597 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1598 IXMLDOMNode *elementNode;
1603 TRACE("(%p)->(%p)\n", This, DOMElement);
1605 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1609 xmlNode = get_node_obj( elementNode );
1610 if(!xmlNode) return E_FAIL;
1612 if(!xmlNode->node->parent)
1613 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1614 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1616 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1617 IXMLDOMNode_Release( elementNode );
1620 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1626 static HRESULT WINAPI domdoc_createElement(
1627 IXMLDOMDocument3 *iface,
1629 IXMLDOMElement** element )
1631 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1636 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1638 if (!element || !tagname) return E_INVALIDARG;
1640 V_VT(&type) = VT_I1;
1641 V_I1(&type) = NODE_ELEMENT;
1643 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1646 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1647 IXMLDOMNode_Release(node);
1654 static HRESULT WINAPI domdoc_createDocumentFragment(
1655 IXMLDOMDocument3 *iface,
1656 IXMLDOMDocumentFragment** frag )
1658 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1663 TRACE("(%p)->(%p)\n", This, frag);
1665 if (!frag) return E_INVALIDARG;
1669 V_VT(&type) = VT_I1;
1670 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1672 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1675 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1676 IXMLDOMNode_Release(node);
1683 static HRESULT WINAPI domdoc_createTextNode(
1684 IXMLDOMDocument3 *iface,
1686 IXMLDOMText** text )
1688 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1693 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1695 if (!text) return E_INVALIDARG;
1699 V_VT(&type) = VT_I1;
1700 V_I1(&type) = NODE_TEXT;
1702 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1705 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1706 IXMLDOMNode_Release(node);
1707 hr = IXMLDOMText_put_data(*text, data);
1714 static HRESULT WINAPI domdoc_createComment(
1715 IXMLDOMDocument3 *iface,
1717 IXMLDOMComment** comment )
1719 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1724 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1726 if (!comment) return E_INVALIDARG;
1730 V_VT(&type) = VT_I1;
1731 V_I1(&type) = NODE_COMMENT;
1733 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1736 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1737 IXMLDOMNode_Release(node);
1738 hr = IXMLDOMComment_put_data(*comment, data);
1745 static HRESULT WINAPI domdoc_createCDATASection(
1746 IXMLDOMDocument3 *iface,
1748 IXMLDOMCDATASection** cdata )
1750 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1755 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1757 if (!cdata) return E_INVALIDARG;
1761 V_VT(&type) = VT_I1;
1762 V_I1(&type) = NODE_CDATA_SECTION;
1764 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1767 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1768 IXMLDOMNode_Release(node);
1769 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1776 static HRESULT WINAPI domdoc_createProcessingInstruction(
1777 IXMLDOMDocument3 *iface,
1780 IXMLDOMProcessingInstruction** pi )
1782 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1787 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1789 if (!pi) return E_INVALIDARG;
1793 V_VT(&type) = VT_I1;
1794 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1796 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1801 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1802 node_obj = get_node_obj(node);
1803 hr = node_set_content(node_obj, data);
1805 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1806 IXMLDOMNode_Release(node);
1813 static HRESULT WINAPI domdoc_createAttribute(
1814 IXMLDOMDocument3 *iface,
1816 IXMLDOMAttribute** attribute )
1818 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1823 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1825 if (!attribute || !name) return E_INVALIDARG;
1827 V_VT(&type) = VT_I1;
1828 V_I1(&type) = NODE_ATTRIBUTE;
1830 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1833 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1834 IXMLDOMNode_Release(node);
1841 static HRESULT WINAPI domdoc_createEntityReference(
1842 IXMLDOMDocument3 *iface,
1844 IXMLDOMEntityReference** entityref )
1846 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1851 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1853 if (!entityref) return E_INVALIDARG;
1857 V_VT(&type) = VT_I1;
1858 V_I1(&type) = NODE_ENTITY_REFERENCE;
1860 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1863 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1864 IXMLDOMNode_Release(node);
1870 xmlChar* tagName_to_XPath(const BSTR tagName)
1872 xmlChar *query, *tmp;
1873 static const xmlChar mod_pre[] = "*[local-name()='";
1874 static const xmlChar mod_post[] = "']";
1875 static const xmlChar prefix[] = "descendant::";
1876 const WCHAR *tokBegin, *tokEnd;
1879 query = xmlStrdup(prefix);
1882 while (tokBegin && *tokBegin)
1887 query = xmlStrcat(query, BAD_CAST "/");
1891 query = xmlStrcat(query, BAD_CAST "*");
1895 query = xmlStrcat(query, mod_pre);
1897 while (*tokEnd && *tokEnd != '/')
1899 len = WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, NULL, 0, NULL, NULL);
1900 tmp = xmlMalloc(len);
1901 WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, (char*)tmp, len, NULL, NULL);
1902 query = xmlStrncat(query, tmp, len);
1905 query = xmlStrcat(query, mod_post);
1912 static HRESULT WINAPI domdoc_getElementsByTagName(
1913 IXMLDOMDocument3 *iface,
1915 IXMLDOMNodeList** resultList )
1917 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1922 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1924 if (!tagName || !resultList) return E_INVALIDARG;
1926 XPath = This->properties->XPath;
1927 This->properties->XPath = TRUE;
1928 query = tagName_to_XPath(tagName);
1929 hr = queryresult_create((xmlNodePtr)get_doc(This), query, resultList);
1931 This->properties->XPath = XPath;
1936 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1942 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1944 return E_INVALIDARG;
1951 static HRESULT WINAPI domdoc_createNode(
1952 IXMLDOMDocument3 *iface,
1956 IXMLDOMNode** node )
1958 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1959 DOMNodeType node_type;
1961 xmlChar *xml_name, *href;
1964 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1966 if(!node) return E_INVALIDARG;
1968 hr = get_node_type(Type, &node_type);
1969 if(FAILED(hr)) return hr;
1971 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1972 FIXME("nodes with namespaces currently not supported.\n");
1974 TRACE("node_type %d\n", node_type);
1976 /* exit earlier for types that need name */
1980 case NODE_ATTRIBUTE:
1981 case NODE_ENTITY_REFERENCE:
1982 case NODE_PROCESSING_INSTRUCTION:
1983 if (!name || *name == 0) return E_FAIL;
1988 xml_name = xmlchar_from_wchar(name);
1989 /* prevent empty href to be allocated */
1990 href = namespaceURI ? xmlchar_from_wchar(namespaceURI) : NULL;
1996 xmlChar *local, *prefix;
1998 local = xmlSplitQName2(xml_name, &prefix);
2000 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
2002 /* allow to create default namespace xmlns= */
2003 if (local || (href && *href))
2005 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
2006 xmlSetNs(xmlnode, ns);
2014 case NODE_ATTRIBUTE:
2015 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
2018 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
2020 case NODE_CDATA_SECTION:
2021 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
2023 case NODE_ENTITY_REFERENCE:
2024 xmlnode = xmlNewReference(get_doc(This), xml_name);
2026 case NODE_PROCESSING_INSTRUCTION:
2027 #ifdef HAVE_XMLNEWDOCPI
2028 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
2030 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2035 xmlnode = xmlNewDocComment(get_doc(This), NULL);
2037 case NODE_DOCUMENT_FRAGMENT:
2038 xmlnode = xmlNewDocFragment(get_doc(This));
2040 /* unsupported types */
2042 case NODE_DOCUMENT_TYPE:
2045 heap_free(xml_name);
2046 return E_INVALIDARG;
2048 FIXME("unhandled node type %d\n", node_type);
2053 *node = create_node(xmlnode);
2054 heap_free(xml_name);
2059 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
2060 xmldoc_add_orphan(xmlnode->doc, xmlnode);
2067 static HRESULT WINAPI domdoc_nodeFromID(
2068 IXMLDOMDocument3 *iface,
2070 IXMLDOMNode** node )
2072 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2073 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
2077 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
2082 xmldoc = doparse(This, ptr, len, NULL);
2084 xmldoc->_private = create_priv();
2085 return attach_xmldoc(This, xmldoc);
2091 static HRESULT doread( domdoc *This, LPWSTR filename )
2096 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
2101 detach_bsc(This->bsc);
2107 static HRESULT WINAPI domdoc_load(
2108 IXMLDOMDocument3 *iface,
2110 VARIANT_BOOL* isSuccessful )
2112 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2113 LPWSTR filename = NULL;
2114 HRESULT hr = S_FALSE;
2115 IXMLDOMDocument3 *pNewDoc = NULL;
2116 IStream *pStream = NULL;
2119 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
2121 *isSuccessful = VARIANT_FALSE;
2123 assert( &This->node );
2125 switch( V_VT(&xmlSource) )
2128 filename = V_BSTR(&xmlSource);
2131 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
2136 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
2137 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
2138 hr = attach_xmldoc(This, xmldoc);
2141 *isSuccessful = VARIANT_TRUE;
2146 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
2149 IPersistStream *pDocStream;
2150 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
2153 hr = IPersistStream_Load(pDocStream, pStream);
2154 IStream_Release(pStream);
2157 *isSuccessful = VARIANT_TRUE;
2159 TRACE("Using IStream to load Document\n");
2164 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
2169 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
2174 /* ISequentialStream */
2175 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
2179 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
2182 TRACE("filename (%s)\n", debugstr_w(filename));
2186 hr = doread( This, filename );
2189 This->error = E_FAIL;
2192 hr = This->error = S_OK;
2193 *isSuccessful = VARIANT_TRUE;
2197 if(!filename || FAILED(hr)) {
2198 xmldoc = xmlNewDoc(NULL);
2199 xmldoc->_private = create_priv();
2200 hr = attach_xmldoc(This, xmldoc);
2205 TRACE("ret (%d)\n", hr);
2211 static HRESULT WINAPI domdoc_get_readyState(
2212 IXMLDOMDocument3 *iface,
2215 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2216 FIXME("stub! (%p)->(%p)\n", This, value);
2219 return E_INVALIDARG;
2221 *value = READYSTATE_COMPLETE;
2226 static HRESULT WINAPI domdoc_get_parseError(
2227 IXMLDOMDocument3 *iface,
2228 IXMLDOMParseError** errorObj )
2230 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2231 static const WCHAR err[] = {'e','r','r','o','r',0};
2232 BSTR error_string = NULL;
2234 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2237 error_string = SysAllocString(err);
2239 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2240 if(!*errorObj) return E_OUTOFMEMORY;
2245 static HRESULT WINAPI domdoc_get_url(
2246 IXMLDOMDocument3 *iface,
2249 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2250 FIXME("(%p)->(%p)\n", This, urlString);
2255 static HRESULT WINAPI domdoc_get_async(
2256 IXMLDOMDocument3 *iface,
2257 VARIANT_BOOL* isAsync )
2259 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2261 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2262 *isAsync = This->async;
2267 static HRESULT WINAPI domdoc_put_async(
2268 IXMLDOMDocument3 *iface,
2269 VARIANT_BOOL isAsync )
2271 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2273 TRACE("(%p)->(%d)\n", This, isAsync);
2274 This->async = isAsync;
2279 static HRESULT WINAPI domdoc_abort(
2280 IXMLDOMDocument3 *iface )
2282 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2283 FIXME("%p\n", This);
2288 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
2293 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
2294 str = heap_alloc( len );
2297 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
2303 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2304 static HRESULT WINAPI domdoc_loadXML(
2305 IXMLDOMDocument3 *iface,
2307 VARIANT_BOOL* isSuccessful )
2309 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2310 static const xmlChar encoding[] = "UTF-8";
2311 xmlDocPtr xmldoc = NULL;
2312 HRESULT hr = S_FALSE, hr2;
2316 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2318 assert ( &This->node );
2322 *isSuccessful = VARIANT_FALSE;
2324 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
2326 xmldoc = doparse(This, str, len, encoding);
2330 This->error = E_FAIL;
2331 TRACE("failed to parse document\n");
2335 hr = This->error = S_OK;
2336 *isSuccessful = VARIANT_TRUE;
2337 TRACE("parsed document %p\n", xmldoc);
2342 xmldoc = xmlNewDoc(NULL);
2344 xmldoc->_private = create_priv();
2346 hr2 = attach_xmldoc(This, xmldoc);
2353 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2357 if(!WriteFile(ctx, buffer, len, &written, NULL))
2359 WARN("write error\n");
2366 static int XMLCALL domdoc_save_closecallback(void *ctx)
2368 return CloseHandle(ctx) ? 0 : -1;
2371 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2376 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2379 WARN("stream write error: 0x%08x\n", hr);
2386 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2388 IStream_Release((IStream*)ctx);
2392 static HRESULT WINAPI domdoc_save(
2393 IXMLDOMDocument3 *iface,
2394 VARIANT destination )
2396 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2397 xmlSaveCtxtPtr ctx = NULL;
2401 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
2402 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
2404 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
2406 FIXME("Unhandled vt %d\n", V_VT(&destination));
2410 if(V_VT(&destination) == VT_UNKNOWN)
2412 IUnknown *pUnk = V_UNKNOWN(&destination);
2413 IXMLDOMDocument2 *document;
2416 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2419 VARIANT_BOOL success;
2422 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2425 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2429 IXMLDOMDocument3_Release(document);
2433 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2436 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2437 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2441 IStream_Release(stream);
2448 /* save with file path */
2449 HANDLE handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
2450 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2451 if( handle == INVALID_HANDLE_VALUE )
2453 WARN("failed to create file\n");
2457 /* disable top XML declaration */
2458 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2459 handle, NULL, XML_SAVE_NO_DECL);
2462 CloseHandle(handle);
2467 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2468 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2469 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2471 /* will release resources through close callback */
2477 static HRESULT WINAPI domdoc_get_validateOnParse(
2478 IXMLDOMDocument3 *iface,
2479 VARIANT_BOOL* isValidating )
2481 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2482 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2483 *isValidating = This->validating;
2488 static HRESULT WINAPI domdoc_put_validateOnParse(
2489 IXMLDOMDocument3 *iface,
2490 VARIANT_BOOL isValidating )
2492 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2493 TRACE("(%p)->(%d)\n", This, isValidating);
2494 This->validating = isValidating;
2499 static HRESULT WINAPI domdoc_get_resolveExternals(
2500 IXMLDOMDocument3 *iface,
2501 VARIANT_BOOL* isResolving )
2503 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2504 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2505 *isResolving = This->resolving;
2510 static HRESULT WINAPI domdoc_put_resolveExternals(
2511 IXMLDOMDocument3 *iface,
2512 VARIANT_BOOL isResolving )
2514 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2515 TRACE("(%p)->(%d)\n", This, isResolving);
2516 This->resolving = isResolving;
2521 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2522 IXMLDOMDocument3 *iface,
2523 VARIANT_BOOL* isPreserving )
2525 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2526 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->properties->preserving);
2527 *isPreserving = This->properties->preserving;
2532 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2533 IXMLDOMDocument3 *iface,
2534 VARIANT_BOOL isPreserving )
2536 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2537 TRACE("(%p)->(%d)\n", This, isPreserving);
2538 This->properties->preserving = isPreserving;
2543 static HRESULT WINAPI domdoc_put_onreadystatechange(
2544 IXMLDOMDocument3 *iface,
2547 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2549 TRACE("(%p)->(%s)\n", This, debugstr_variant(&event));
2550 return set_doc_event(This, EVENTID_READYSTATECHANGE, &event);
2554 static HRESULT WINAPI domdoc_put_onDataAvailable(
2555 IXMLDOMDocument3 *iface,
2556 VARIANT onDataAvailableSink )
2558 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2559 FIXME("%p\n", This);
2563 static HRESULT WINAPI domdoc_put_onTransformNode(
2564 IXMLDOMDocument3 *iface,
2565 VARIANT onTransformNodeSink )
2567 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2568 FIXME("%p\n", This);
2572 static HRESULT WINAPI domdoc_get_namespaces(
2573 IXMLDOMDocument3* iface,
2574 IXMLDOMSchemaCollection** schemaCollection )
2576 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2577 FIXME("(%p)->(%p)\n", This, schemaCollection);
2581 static HRESULT WINAPI domdoc_get_schemas(
2582 IXMLDOMDocument3* iface,
2585 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2586 HRESULT hr = S_FALSE;
2587 IXMLDOMSchemaCollection2* cur_schema = This->properties->schemaCache;
2589 TRACE("(%p)->(%p)\n", This, var1);
2591 VariantInit(var1); /* Test shows we don't call VariantClear here */
2592 V_VT(var1) = VT_NULL;
2596 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2598 V_VT(var1) = VT_DISPATCH;
2603 static HRESULT WINAPI domdoc_putref_schemas(
2604 IXMLDOMDocument3* iface,
2607 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2608 HRESULT hr = E_FAIL;
2609 IXMLDOMSchemaCollection2* new_schema = NULL;
2611 FIXME("(%p): semi-stub\n", This);
2615 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2619 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2628 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2633 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->properties->schemaCache, new_schema);
2634 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2640 static inline BOOL is_wellformed(xmlDocPtr doc)
2642 #ifdef HAVE_XMLDOC_PROPERTIES
2643 return doc->properties & XML_DOC_WELLFORMED;
2645 /* Not a full check, but catches the worst violations */
2649 for (child = doc->children; child != NULL; child = child->next)
2651 switch (child->type)
2653 case XML_ELEMENT_NODE:
2658 case XML_CDATA_SECTION_NODE:
2670 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2674 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2678 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2682 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2686 static HRESULT WINAPI domdoc_validateNode(
2687 IXMLDOMDocument3* iface,
2689 IXMLDOMParseError** err)
2691 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2692 LONG state, err_code = 0;
2696 TRACE("(%p)->(%p, %p)\n", This, node, err);
2697 domdoc_get_readyState(iface, &state);
2698 if (state != READYSTATE_COMPLETE)
2701 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2708 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2712 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2715 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2719 if (!is_wellformed(get_doc(This)))
2721 ERR("doc not well-formed\n");
2723 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2727 /* DTD validation */
2728 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2730 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2731 vctx->error = validate_error;
2732 vctx->warning = validate_warning;
2735 if (!((node == (IXMLDOMNode*)iface)?
2736 xmlValidateDocument(vctx, get_doc(This)) :
2737 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2739 /* TODO: get a real error code here */
2740 TRACE("DTD validation failed\n");
2741 err_code = E_XML_INVALID;
2744 xmlFreeValidCtxt(vctx);
2747 /* Schema validation */
2748 if (hr == S_OK && This->properties->schemaCache != NULL)
2751 hr = SchemaCache_validate_tree(This->properties->schemaCache, get_node_obj(node)->node);
2755 /* TODO: get a real error code here */
2758 TRACE("schema validation succeeded\n");
2762 ERR("schema validation failed\n");
2763 err_code = E_XML_INVALID;
2768 /* not really OK, just didn't find a schema for the ns */
2775 ERR("no DTD or schema found\n");
2776 err_code = E_XML_NODTD;
2781 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2786 static HRESULT WINAPI domdoc_validate(
2787 IXMLDOMDocument3* iface,
2788 IXMLDOMParseError** err)
2790 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2791 TRACE("(%p)->(%p)\n", This, err);
2792 return domdoc_validateNode(iface, (IXMLDOMNode*)iface, err);
2795 static HRESULT WINAPI domdoc_setProperty(
2796 IXMLDOMDocument3* iface,
2800 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2802 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2804 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2810 V_VT(&varStr) = VT_EMPTY;
2811 if (V_VT(&var) != VT_BSTR)
2813 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2815 bstr = V_BSTR(&varStr);
2818 bstr = V_BSTR(&var);
2821 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2822 This->properties->XPath = TRUE;
2823 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2824 This->properties->XPath = FALSE;
2828 VariantClear(&varStr);
2831 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2836 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2837 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2838 xmlXPathContextPtr ctx;
2839 struct list *pNsList;
2840 select_ns_entry* pNsEntry = NULL;
2842 V_VT(&varStr) = VT_EMPTY;
2843 if (V_VT(&var) != VT_BSTR)
2845 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2847 bstr = V_BSTR(&varStr);
2850 bstr = V_BSTR(&var);
2854 pNsList = &(This->properties->selectNsList);
2855 clear_selectNsList(pNsList);
2857 nsStr = xmlchar_from_wchar(bstr);
2859 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2861 This->properties->selectNsStr = nsStr;
2862 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2865 ctx = xmlXPathNewContext(This->node.node->doc);
2868 for (; *pTokBegin; pTokBegin = pTokEnd)
2870 if (pNsEntry != NULL)
2871 memset(pNsEntry, 0, sizeof(select_ns_entry));
2873 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2875 while (*pTokBegin == ' ')
2877 pTokEnd = pTokBegin;
2878 while (*pTokEnd != ' ' && *pTokEnd != 0)
2881 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2884 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2885 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2890 if (*pTokBegin == '=')
2892 /*valid for XSLPattern?*/
2893 FIXME("Setting default xmlns not supported - skipping.\n");
2894 pTokBegin = pTokEnd;
2897 else if (*pTokBegin == ':')
2899 pNsEntry->prefix = ++pTokBegin;
2900 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2903 if (pTokInner == pTokEnd)
2906 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2907 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2911 pNsEntry->prefix_end = *pTokInner;
2915 if (pTokEnd-pTokInner > 1 &&
2916 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2917 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2919 pNsEntry->href = ++pTokInner;
2920 pNsEntry->href_end = *(pTokEnd-1);
2922 list_add_tail(pNsList, &pNsEntry->entry);
2923 /*let libxml figure out if they're valid from here ;)*/
2924 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2933 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2934 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2935 list_add_tail(pNsList, &pNsEntry->entry);
2948 heap_free(pNsEntry);
2949 xmlXPathFreeContext(ctx);
2952 VariantClear(&varStr);
2955 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2956 lstrcmpiW(p, PropertyNewParserW) == 0 ||
2957 lstrcmpiW(p, PropertyResolveExternalsW) == 0)
2960 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2964 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2968 static HRESULT WINAPI domdoc_getProperty(
2969 IXMLDOMDocument3* iface,
2973 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2975 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2978 return E_INVALIDARG;
2980 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2982 V_VT(var) = VT_BSTR;
2983 V_BSTR(var) = This->properties->XPath ?
2984 SysAllocString(PropValueXPathW) :
2985 SysAllocString(PropValueXSLPatternW);
2986 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2988 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2991 BSTR rebuiltStr, cur;
2992 const xmlChar *nsStr;
2993 struct list *pNsList;
2994 select_ns_entry* pNsEntry;
2996 V_VT(var) = VT_BSTR;
2997 nsStr = This->properties->selectNsStr;
2998 pNsList = &This->properties->selectNsList;
2999 lenA = This->properties->selectNsStr_len;
3000 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
3001 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
3002 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
3004 /* this is fine because all of the chars that end tokens are ASCII*/
3005 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
3007 while (*cur != 0) ++cur;
3008 if (pNsEntry->prefix_end)
3010 *cur = pNsEntry->prefix_end;
3011 while (*cur != 0) ++cur;
3014 if (pNsEntry->href_end)
3016 *cur = pNsEntry->href_end;
3019 V_BSTR(var) = SysAllocString(rebuiltStr);
3020 heap_free(rebuiltStr);
3024 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
3028 static HRESULT WINAPI domdoc_importNode(
3029 IXMLDOMDocument3* iface,
3032 IXMLDOMNode** clone)
3034 domdoc *This = impl_from_IXMLDOMDocument3( iface );
3035 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
3039 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
3041 domdoc_QueryInterface,
3044 domdoc_GetTypeInfoCount,
3046 domdoc_GetIDsOfNames,
3048 domdoc_get_nodeName,
3049 domdoc_get_nodeValue,
3050 domdoc_put_nodeValue,
3051 domdoc_get_nodeType,
3052 domdoc_get_parentNode,
3053 domdoc_get_childNodes,
3054 domdoc_get_firstChild,
3055 domdoc_get_lastChild,
3056 domdoc_get_previousSibling,
3057 domdoc_get_nextSibling,
3058 domdoc_get_attributes,
3059 domdoc_insertBefore,
3060 domdoc_replaceChild,
3063 domdoc_hasChildNodes,
3064 domdoc_get_ownerDocument,
3066 domdoc_get_nodeTypeString,
3069 domdoc_get_specified,
3070 domdoc_get_definition,
3071 domdoc_get_nodeTypedValue,
3072 domdoc_put_nodeTypedValue,
3073 domdoc_get_dataType,
3074 domdoc_put_dataType,
3076 domdoc_transformNode,
3078 domdoc_selectSingleNode,
3080 domdoc_get_namespaceURI,
3082 domdoc_get_baseName,
3083 domdoc_transformNodeToObject,
3085 domdoc_get_implementation,
3086 domdoc_get_documentElement,
3087 domdoc_put_documentElement,
3088 domdoc_createElement,
3089 domdoc_createDocumentFragment,
3090 domdoc_createTextNode,
3091 domdoc_createComment,
3092 domdoc_createCDATASection,
3093 domdoc_createProcessingInstruction,
3094 domdoc_createAttribute,
3095 domdoc_createEntityReference,
3096 domdoc_getElementsByTagName,
3100 domdoc_get_readyState,
3101 domdoc_get_parseError,
3108 domdoc_get_validateOnParse,
3109 domdoc_put_validateOnParse,
3110 domdoc_get_resolveExternals,
3111 domdoc_put_resolveExternals,
3112 domdoc_get_preserveWhiteSpace,
3113 domdoc_put_preserveWhiteSpace,
3114 domdoc_put_onreadystatechange,
3115 domdoc_put_onDataAvailable,
3116 domdoc_put_onTransformNode,
3117 domdoc_get_namespaces,
3119 domdoc_putref_schemas,
3123 domdoc_validateNode,
3127 /* IConnectionPointContainer */
3128 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
3129 REFIID riid, void **ppv)
3131 domdoc *This = impl_from_IConnectionPointContainer(iface);
3132 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)This, riid, ppv);
3135 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
3137 domdoc *This = impl_from_IConnectionPointContainer(iface);
3138 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)This);
3141 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
3143 domdoc *This = impl_from_IConnectionPointContainer(iface);
3144 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)This);
3147 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
3148 IEnumConnectionPoints **ppEnum)
3150 domdoc *This = impl_from_IConnectionPointContainer(iface);
3151 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3155 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
3156 REFIID riid, IConnectionPoint **cp)
3158 domdoc *This = impl_from_IConnectionPointContainer(iface);
3159 ConnectionPoint *iter;
3161 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
3165 for(iter = This->cp_list; iter; iter = iter->next)
3167 if (IsEqualGUID(iter->iid, riid))
3168 *cp = (IConnectionPoint*)&iter->lpVtblConnectionPoint;
3173 IConnectionPoint_AddRef(*cp);
3177 FIXME("unsupported riid %s\n", debugstr_guid(riid));
3178 return CONNECT_E_NOCONNECTION;
3182 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
3184 ConnectionPointContainer_QueryInterface,
3185 ConnectionPointContainer_AddRef,
3186 ConnectionPointContainer_Release,
3187 ConnectionPointContainer_EnumConnectionPoints,
3188 ConnectionPointContainer_FindConnectionPoint
3191 /* IConnectionPoint */
3192 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
3193 REFIID riid, void **ppv)
3195 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3197 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3201 if (IsEqualGUID(&IID_IUnknown, riid) ||
3202 IsEqualGUID(&IID_IConnectionPoint, riid))
3209 IConnectionPoint_AddRef(iface);
3213 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3214 return E_NOINTERFACE;
3217 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3219 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3220 return IConnectionPointContainer_AddRef(This->container);
3223 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3225 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3226 return IConnectionPointContainer_Release(This->container);
3229 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3231 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3233 TRACE("(%p)->(%p)\n", This, iid);
3235 if (!iid) return E_POINTER;
3241 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3242 IConnectionPointContainer **container)
3244 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3246 TRACE("(%p)->(%p)\n", This, container);
3248 if (!container) return E_POINTER;
3250 *container = This->container;
3251 IConnectionPointContainer_AddRef(*container);
3255 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
3258 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3259 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
3263 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3265 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3267 TRACE("(%p)->(%d)\n", This, cookie);
3269 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3270 return CONNECT_E_NOCONNECTION;
3272 IUnknown_Release(This->sinks[cookie-1].unk);
3273 This->sinks[cookie-1].unk = NULL;
3278 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3279 IEnumConnections **ppEnum)
3281 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3282 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3286 static const IConnectionPointVtbl ConnectionPointVtbl =
3288 ConnectionPoint_QueryInterface,
3289 ConnectionPoint_AddRef,
3290 ConnectionPoint_Release,
3291 ConnectionPoint_GetConnectionInterface,
3292 ConnectionPoint_GetConnectionPointContainer,
3293 ConnectionPoint_Advise,
3294 ConnectionPoint_Unadvise,
3295 ConnectionPoint_EnumConnections
3298 void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3300 cp->lpVtblConnectionPoint = &ConnectionPointVtbl;
3306 cp->next = doc->cp_list;
3309 cp->container = (IConnectionPointContainer*)&doc->lpVtblConnectionPointContainer;
3312 /* domdoc implementation of IObjectWithSite */
3313 static HRESULT WINAPI
3314 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3316 domdoc *This = impl_from_IObjectWithSite(iface);
3317 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppvObject );
3320 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3322 domdoc *This = impl_from_IObjectWithSite(iface);
3323 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3326 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3328 domdoc *This = impl_from_IObjectWithSite(iface);
3329 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3332 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3334 domdoc *This = impl_from_IObjectWithSite(iface);
3336 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3341 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3344 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3346 domdoc *This = impl_from_IObjectWithSite(iface);
3348 TRACE("(%p)->(%p)\n", iface, punk);
3354 IUnknown_Release( This->site );
3361 IUnknown_AddRef( punk );
3364 IUnknown_Release( This->site );
3371 static const IObjectWithSiteVtbl domdocObjectSite =
3373 domdoc_ObjectWithSite_QueryInterface,
3374 domdoc_ObjectWithSite_AddRef,
3375 domdoc_ObjectWithSite_Release,
3376 domdoc_ObjectWithSite_SetSite,
3377 domdoc_ObjectWithSite_GetSite
3380 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3382 domdoc *This = impl_from_IObjectSafety(iface);
3383 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppv );
3386 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3388 domdoc *This = impl_from_IObjectSafety(iface);
3389 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3392 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3394 domdoc *This = impl_from_IObjectSafety(iface);
3395 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3398 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3400 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3401 DWORD *supported, DWORD *enabled)
3403 domdoc *This = impl_from_IObjectSafety(iface);
3405 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3407 if(!supported || !enabled) return E_POINTER;
3409 *supported = SAFETY_SUPPORTED_OPTIONS;
3410 *enabled = This->safeopt;
3415 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3416 DWORD mask, DWORD enabled)
3418 domdoc *This = impl_from_IObjectSafety(iface);
3419 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3421 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3424 This->safeopt = enabled & mask & SAFETY_SUPPORTED_OPTIONS;
3428 #undef SAFETY_SUPPORTED_OPTIONS
3430 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3431 domdoc_Safety_QueryInterface,
3432 domdoc_Safety_AddRef,
3433 domdoc_Safety_Release,
3434 domdoc_Safety_GetInterfaceSafetyOptions,
3435 domdoc_Safety_SetInterfaceSafetyOptions
3438 static const tid_t domdoc_iface_tids[] = {
3440 IXMLDOMDocument_tid,
3441 IXMLDOMDocument2_tid,
3444 static dispex_static_data_t domdoc_dispex = {
3446 IXMLDOMDocument2_tid,
3451 HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3455 doc = heap_alloc( sizeof (*doc) );
3457 return E_OUTOFMEMORY;
3459 doc->lpVtbl = &domdoc_vtbl;
3460 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
3461 doc->lpvtblIObjectWithSite = &domdocObjectSite;
3462 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
3463 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
3464 doc->lpVtblConnectionPointContainer = &ConnectionPointContainerVtbl;
3466 doc->async = VARIANT_TRUE;
3467 doc->validating = 0;
3469 doc->properties = properties_from_xmlDocPtr(xmldoc);
3475 doc->cp_list = NULL;
3476 memset(doc->events, 0, sizeof(doc->events));
3478 /* events connection points */
3479 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3480 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3481 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3483 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->lpVtbl, &domdoc_dispex);
3485 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
3487 TRACE("returning iface %p\n", *document);
3491 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3496 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
3498 xmldoc = xmlNewDoc(NULL);
3500 return E_OUTOFMEMORY;
3502 xmldoc->_private = create_priv();
3503 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
3505 hr = get_domdoc_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3508 free_properties(properties_from_xmlDocPtr(xmldoc));
3509 heap_free(xmldoc->_private);
3517 IUnknown* create_domdoc( xmlNodePtr document )
3522 TRACE("(%p)\n", document);
3524 hr = get_domdoc_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3533 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3535 MESSAGE("This program tried to use a DOMDocument object, but\n"
3536 "libxml2 support was not present at compile time.\n");