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;
921 TRACE("interface %s not implemented\n", debugstr_guid(riid));
922 return E_NOINTERFACE;
925 IUnknown_AddRef((IUnknown*)*ppvObject);
931 static ULONG WINAPI domdoc_AddRef(
932 IXMLDOMDocument3 *iface )
934 domdoc *This = impl_from_IXMLDOMDocument3( iface );
935 ULONG ref = InterlockedIncrement( &This->ref );
936 TRACE("(%p)->(%d)\n", This, ref );
941 static ULONG WINAPI domdoc_Release(
942 IXMLDOMDocument3 *iface )
944 domdoc *This = impl_from_IXMLDOMDocument3( iface );
945 LONG ref = InterlockedDecrement( &This->ref );
947 TRACE("(%p)->(%d)\n", This, ref );
954 detach_bsc(This->bsc);
957 IUnknown_Release( This->site );
958 destroy_xmlnode(&This->node);
960 IStream_Release(This->stream);
962 for (eid = 0; eid < EVENTID_LAST; eid++)
963 if (This->events[eid]) IDispatch_Release(This->events[eid]);
971 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
973 domdoc *This = impl_from_IXMLDOMDocument3( iface );
975 TRACE("(%p)->(%p)\n", This, pctinfo);
982 static HRESULT WINAPI domdoc_GetTypeInfo(
983 IXMLDOMDocument3 *iface,
984 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
986 domdoc *This = impl_from_IXMLDOMDocument3( iface );
989 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
991 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
996 static HRESULT WINAPI domdoc_GetIDsOfNames(
997 IXMLDOMDocument3 *iface,
1004 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1005 ITypeInfo *typeinfo;
1008 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1011 if(!rgszNames || cNames == 0 || !rgDispId)
1012 return E_INVALIDARG;
1014 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
1017 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1018 ITypeInfo_Release(typeinfo);
1025 static HRESULT WINAPI domdoc_Invoke(
1026 IXMLDOMDocument3 *iface,
1027 DISPID dispIdMember,
1031 DISPPARAMS* pDispParams,
1032 VARIANT* pVarResult,
1033 EXCEPINFO* pExcepInfo,
1036 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1037 ITypeInfo *typeinfo;
1040 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1041 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1043 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
1046 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
1047 pVarResult, pExcepInfo, puArgErr);
1048 ITypeInfo_Release(typeinfo);
1055 static HRESULT WINAPI domdoc_get_nodeName(
1056 IXMLDOMDocument3 *iface,
1059 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1061 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
1063 TRACE("(%p)->(%p)\n", This, name);
1065 return return_bstr(documentW, name);
1069 static HRESULT WINAPI domdoc_get_nodeValue(
1070 IXMLDOMDocument3 *iface,
1073 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1075 TRACE("(%p)->(%p)\n", This, value);
1078 return E_INVALIDARG;
1080 V_VT(value) = VT_NULL;
1081 V_BSTR(value) = NULL; /* tests show that we should do this */
1086 static HRESULT WINAPI domdoc_put_nodeValue(
1087 IXMLDOMDocument3 *iface,
1090 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1091 TRACE("(%p)->(v%d)\n", This, V_VT(&value));
1096 static HRESULT WINAPI domdoc_get_nodeType(
1097 IXMLDOMDocument3 *iface,
1100 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1102 TRACE("(%p)->(%p)\n", This, type);
1104 *type = NODE_DOCUMENT;
1109 static HRESULT WINAPI domdoc_get_parentNode(
1110 IXMLDOMDocument3 *iface,
1111 IXMLDOMNode** parent )
1113 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1115 TRACE("(%p)->(%p)\n", This, parent);
1117 return node_get_parent(&This->node, parent);
1121 static HRESULT WINAPI domdoc_get_childNodes(
1122 IXMLDOMDocument3 *iface,
1123 IXMLDOMNodeList** childList )
1125 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1127 TRACE("(%p)->(%p)\n", This, childList);
1129 return node_get_child_nodes(&This->node, childList);
1133 static HRESULT WINAPI domdoc_get_firstChild(
1134 IXMLDOMDocument3 *iface,
1135 IXMLDOMNode** firstChild )
1137 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1139 TRACE("(%p)->(%p)\n", This, firstChild);
1141 return node_get_first_child(&This->node, firstChild);
1145 static HRESULT WINAPI domdoc_get_lastChild(
1146 IXMLDOMDocument3 *iface,
1147 IXMLDOMNode** lastChild )
1149 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1151 TRACE("(%p)->(%p)\n", This, lastChild);
1153 return node_get_last_child(&This->node, lastChild);
1157 static HRESULT WINAPI domdoc_get_previousSibling(
1158 IXMLDOMDocument3 *iface,
1159 IXMLDOMNode** previousSibling )
1161 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1163 TRACE("(%p)->(%p)\n", This, previousSibling);
1165 return return_null_node(previousSibling);
1169 static HRESULT WINAPI domdoc_get_nextSibling(
1170 IXMLDOMDocument3 *iface,
1171 IXMLDOMNode** nextSibling )
1173 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1175 TRACE("(%p)->(%p)\n", This, nextSibling);
1177 return return_null_node(nextSibling);
1181 static HRESULT WINAPI domdoc_get_attributes(
1182 IXMLDOMDocument3 *iface,
1183 IXMLDOMNamedNodeMap** attributeMap )
1185 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1187 TRACE("(%p)->(%p)\n", This, attributeMap);
1189 return return_null_ptr((void**)attributeMap);
1193 static HRESULT WINAPI domdoc_insertBefore(
1194 IXMLDOMDocument3 *iface,
1195 IXMLDOMNode* newChild,
1197 IXMLDOMNode** outNewChild )
1199 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1201 TRACE("(%p)->(%p x%d %p)\n", This, newChild, V_VT(&refChild), outNewChild);
1203 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1207 static HRESULT WINAPI domdoc_replaceChild(
1208 IXMLDOMDocument3 *iface,
1209 IXMLDOMNode* newChild,
1210 IXMLDOMNode* oldChild,
1211 IXMLDOMNode** outOldChild)
1213 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1215 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1217 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1221 static HRESULT WINAPI domdoc_removeChild(
1222 IXMLDOMDocument3 *iface,
1224 IXMLDOMNode **oldChild)
1226 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1227 TRACE("(%p)->(%p %p)\n", This, child, oldChild);
1228 return node_remove_child(&This->node, child, oldChild);
1232 static HRESULT WINAPI domdoc_appendChild(
1233 IXMLDOMDocument3 *iface,
1235 IXMLDOMNode **outChild)
1237 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1238 TRACE("(%p)->(%p %p)\n", This, child, outChild);
1239 return node_append_child(&This->node, child, outChild);
1243 static HRESULT WINAPI domdoc_hasChildNodes(
1244 IXMLDOMDocument3 *iface,
1247 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1248 TRACE("(%p)->(%p)\n", This, ret);
1249 return node_has_childnodes(&This->node, ret);
1253 static HRESULT WINAPI domdoc_get_ownerDocument(
1254 IXMLDOMDocument3 *iface,
1255 IXMLDOMDocument **doc)
1257 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1258 TRACE("(%p)->(%p)\n", This, doc);
1259 return node_get_owner_doc(&This->node, doc);
1263 static HRESULT WINAPI domdoc_cloneNode(
1264 IXMLDOMDocument3 *iface,
1266 IXMLDOMNode** outNode)
1268 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1269 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
1270 return node_clone( &This->node, deep, outNode );
1274 static HRESULT WINAPI domdoc_get_nodeTypeString(
1275 IXMLDOMDocument3 *iface,
1278 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1279 static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
1281 TRACE("(%p)->(%p)\n", This, p);
1283 return return_bstr(documentW, p);
1287 static HRESULT WINAPI domdoc_get_text(
1288 IXMLDOMDocument3 *iface,
1291 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1292 TRACE("(%p)->(%p)\n", This, p);
1293 return node_get_text(&This->node, p);
1297 static HRESULT WINAPI domdoc_put_text(
1298 IXMLDOMDocument3 *iface,
1301 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1302 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1307 static HRESULT WINAPI domdoc_get_specified(
1308 IXMLDOMDocument3 *iface,
1309 VARIANT_BOOL* isSpecified )
1311 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1312 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1313 *isSpecified = VARIANT_TRUE;
1318 static HRESULT WINAPI domdoc_get_definition(
1319 IXMLDOMDocument3 *iface,
1320 IXMLDOMNode** definitionNode )
1322 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1323 FIXME("(%p)->(%p)\n", This, definitionNode);
1328 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1329 IXMLDOMDocument3 *iface,
1332 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1333 TRACE("(%p)->(%p)\n", This, v);
1334 return return_null_var(v);
1337 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1338 IXMLDOMDocument3 *iface,
1339 VARIANT typedValue )
1341 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1342 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1347 static HRESULT WINAPI domdoc_get_dataType(
1348 IXMLDOMDocument3 *iface,
1351 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1352 TRACE("(%p)->(%p)\n", This, typename);
1353 return return_null_var( typename );
1357 static HRESULT WINAPI domdoc_put_dataType(
1358 IXMLDOMDocument3 *iface,
1361 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1363 FIXME("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
1366 return E_INVALIDARG;
1371 static int XMLCALL domdoc_get_xml_writecallback(void *ctx, const char *data, int len)
1373 return xmlBufferAdd((xmlBufferPtr)ctx, (xmlChar*)data, len) == 0 ? len : 0;
1376 static HRESULT WINAPI domdoc_get_xml(
1377 IXMLDOMDocument3 *iface,
1380 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1381 xmlSaveCtxtPtr ctxt;
1386 TRACE("(%p)->(%p)\n", This, p);
1389 return E_INVALIDARG;
1393 buf = xmlBufferCreate();
1395 return E_OUTOFMEMORY;
1397 options = xmldoc_has_decl(get_doc(This)) ? XML_SAVE_NO_DECL : 0;
1398 options |= XML_SAVE_FORMAT;
1399 ctxt = xmlSaveToIO(domdoc_get_xml_writecallback, NULL, buf, "UTF-8", options);
1404 return E_OUTOFMEMORY;
1407 ret = xmlSaveDoc(ctxt, get_doc(This));
1408 /* flushes on close */
1411 TRACE("%ld, len=%d\n", ret, xmlBufferLength(buf));
1412 if(ret != -1 && xmlBufferLength(buf) > 0)
1416 content = bstr_from_xmlChar(xmlBufferContent(buf));
1417 content = EnsureCorrectEOL(content);
1423 *p = SysAllocStringLen(NULL, 0);
1428 return *p ? S_OK : E_OUTOFMEMORY;
1432 static HRESULT WINAPI domdoc_transformNode(
1433 IXMLDOMDocument3 *iface,
1437 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1438 TRACE("(%p)->(%p %p)\n", This, node, p);
1439 return node_transform_node(&This->node, node, p);
1443 static HRESULT WINAPI domdoc_selectNodes(
1444 IXMLDOMDocument3 *iface,
1446 IXMLDOMNodeList **outList)
1448 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1449 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList);
1450 return node_select_nodes(&This->node, p, outList);
1454 static HRESULT WINAPI domdoc_selectSingleNode(
1455 IXMLDOMDocument3 *iface,
1457 IXMLDOMNode **outNode)
1459 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1460 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode);
1461 return node_select_singlenode(&This->node, p, outNode);
1465 static HRESULT WINAPI domdoc_get_parsed(
1466 IXMLDOMDocument3 *iface,
1467 VARIANT_BOOL* isParsed )
1469 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1470 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1471 *isParsed = VARIANT_TRUE;
1476 static HRESULT WINAPI domdoc_get_namespaceURI(
1477 IXMLDOMDocument3 *iface,
1478 BSTR* namespaceURI )
1480 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1481 TRACE("(%p)->(%p)\n", This, namespaceURI);
1482 return node_get_namespaceURI(&This->node, namespaceURI);
1486 static HRESULT WINAPI domdoc_get_prefix(
1487 IXMLDOMDocument3 *iface,
1490 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1491 TRACE("(%p)->(%p)\n", This, prefix);
1492 return return_null_bstr( prefix );
1496 static HRESULT WINAPI domdoc_get_baseName(
1497 IXMLDOMDocument3 *iface,
1500 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1501 TRACE("(%p)->(%p)\n", This, name);
1502 return return_null_bstr( name );
1506 static HRESULT WINAPI domdoc_transformNodeToObject(
1507 IXMLDOMDocument3 *iface,
1508 IXMLDOMNode* stylesheet,
1509 VARIANT outputObject)
1511 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1512 FIXME("(%p)->(%p %s)\n", This, stylesheet, debugstr_variant(&outputObject));
1517 static HRESULT WINAPI domdoc_get_doctype(
1518 IXMLDOMDocument3 *iface,
1519 IXMLDOMDocumentType** doctype )
1521 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1526 TRACE("(%p)->(%p)\n", This, doctype);
1528 if (!doctype) return E_INVALIDARG;
1532 dtd = xmlGetIntSubset(get_doc(This));
1533 if (!dtd) return S_FALSE;
1535 node = create_node((xmlNodePtr)dtd);
1536 if (!node) return S_FALSE;
1538 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentType, (void**)doctype);
1539 IXMLDOMNode_Release(node);
1545 static HRESULT WINAPI domdoc_get_implementation(
1546 IXMLDOMDocument3 *iface,
1547 IXMLDOMImplementation** impl )
1549 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1551 TRACE("(%p)->(%p)\n", This, impl);
1554 return E_INVALIDARG;
1556 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1561 static HRESULT WINAPI domdoc_get_documentElement(
1562 IXMLDOMDocument3 *iface,
1563 IXMLDOMElement** DOMElement )
1565 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1566 IXMLDOMNode *element_node;
1570 TRACE("(%p)->(%p)\n", This, DOMElement);
1573 return E_INVALIDARG;
1577 root = xmlDocGetRootElement( get_doc(This) );
1581 element_node = create_node( root );
1582 if(!element_node) return S_FALSE;
1584 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1585 IXMLDOMNode_Release(element_node);
1591 static HRESULT WINAPI domdoc_put_documentElement(
1592 IXMLDOMDocument3 *iface,
1593 IXMLDOMElement* DOMElement )
1595 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1596 IXMLDOMNode *elementNode;
1601 TRACE("(%p)->(%p)\n", This, DOMElement);
1603 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1607 xmlNode = get_node_obj( elementNode );
1608 if(!xmlNode) return E_FAIL;
1610 if(!xmlNode->node->parent)
1611 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1612 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1614 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1615 IXMLDOMNode_Release( elementNode );
1618 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1624 static HRESULT WINAPI domdoc_createElement(
1625 IXMLDOMDocument3 *iface,
1627 IXMLDOMElement** element )
1629 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1634 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1636 if (!element || !tagname) return E_INVALIDARG;
1638 V_VT(&type) = VT_I1;
1639 V_I1(&type) = NODE_ELEMENT;
1641 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1644 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1645 IXMLDOMNode_Release(node);
1652 static HRESULT WINAPI domdoc_createDocumentFragment(
1653 IXMLDOMDocument3 *iface,
1654 IXMLDOMDocumentFragment** frag )
1656 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1661 TRACE("(%p)->(%p)\n", This, frag);
1663 if (!frag) return E_INVALIDARG;
1667 V_VT(&type) = VT_I1;
1668 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1670 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1673 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1674 IXMLDOMNode_Release(node);
1681 static HRESULT WINAPI domdoc_createTextNode(
1682 IXMLDOMDocument3 *iface,
1684 IXMLDOMText** text )
1686 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1691 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1693 if (!text) return E_INVALIDARG;
1697 V_VT(&type) = VT_I1;
1698 V_I1(&type) = NODE_TEXT;
1700 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1703 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1704 IXMLDOMNode_Release(node);
1705 hr = IXMLDOMText_put_data(*text, data);
1712 static HRESULT WINAPI domdoc_createComment(
1713 IXMLDOMDocument3 *iface,
1715 IXMLDOMComment** comment )
1717 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1722 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1724 if (!comment) return E_INVALIDARG;
1728 V_VT(&type) = VT_I1;
1729 V_I1(&type) = NODE_COMMENT;
1731 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1734 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1735 IXMLDOMNode_Release(node);
1736 hr = IXMLDOMComment_put_data(*comment, data);
1743 static HRESULT WINAPI domdoc_createCDATASection(
1744 IXMLDOMDocument3 *iface,
1746 IXMLDOMCDATASection** cdata )
1748 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1753 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1755 if (!cdata) return E_INVALIDARG;
1759 V_VT(&type) = VT_I1;
1760 V_I1(&type) = NODE_CDATA_SECTION;
1762 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1765 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1766 IXMLDOMNode_Release(node);
1767 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1774 static HRESULT WINAPI domdoc_createProcessingInstruction(
1775 IXMLDOMDocument3 *iface,
1778 IXMLDOMProcessingInstruction** pi )
1780 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1785 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1787 if (!pi) return E_INVALIDARG;
1791 V_VT(&type) = VT_I1;
1792 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1794 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1799 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1800 node_obj = get_node_obj(node);
1801 hr = node_set_content(node_obj, data);
1803 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1804 IXMLDOMNode_Release(node);
1811 static HRESULT WINAPI domdoc_createAttribute(
1812 IXMLDOMDocument3 *iface,
1814 IXMLDOMAttribute** attribute )
1816 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1821 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1823 if (!attribute || !name) return E_INVALIDARG;
1825 V_VT(&type) = VT_I1;
1826 V_I1(&type) = NODE_ATTRIBUTE;
1828 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1831 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1832 IXMLDOMNode_Release(node);
1839 static HRESULT WINAPI domdoc_createEntityReference(
1840 IXMLDOMDocument3 *iface,
1842 IXMLDOMEntityReference** entityref )
1844 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1849 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1851 if (!entityref) return E_INVALIDARG;
1855 V_VT(&type) = VT_I1;
1856 V_I1(&type) = NODE_ENTITY_REFERENCE;
1858 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1861 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1862 IXMLDOMNode_Release(node);
1868 xmlChar* tagName_to_XPath(const BSTR tagName)
1870 xmlChar *query, *tmp;
1871 static const xmlChar mod_pre[] = "*[local-name()='";
1872 static const xmlChar mod_post[] = "']";
1873 static const xmlChar prefix[] = "descendant::";
1874 const WCHAR *tokBegin, *tokEnd;
1877 query = xmlStrdup(prefix);
1880 while (tokBegin && *tokBegin)
1885 query = xmlStrcat(query, BAD_CAST "/");
1889 query = xmlStrcat(query, BAD_CAST "*");
1893 query = xmlStrcat(query, mod_pre);
1895 while (*tokEnd && *tokEnd != '/')
1897 len = WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, NULL, 0, NULL, NULL);
1898 tmp = xmlMalloc(len);
1899 WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, (char*)tmp, len, NULL, NULL);
1900 query = xmlStrncat(query, tmp, len);
1903 query = xmlStrcat(query, mod_post);
1910 static HRESULT WINAPI domdoc_getElementsByTagName(
1911 IXMLDOMDocument3 *iface,
1913 IXMLDOMNodeList** resultList )
1915 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1920 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1922 if (!tagName || !resultList) return E_INVALIDARG;
1924 XPath = This->properties->XPath;
1925 This->properties->XPath = TRUE;
1926 query = tagName_to_XPath(tagName);
1927 hr = create_selection((xmlNodePtr)get_doc(This), query, resultList);
1929 This->properties->XPath = XPath;
1934 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1940 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1942 return E_INVALIDARG;
1949 static HRESULT WINAPI domdoc_createNode(
1950 IXMLDOMDocument3 *iface,
1954 IXMLDOMNode** node )
1956 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1957 DOMNodeType node_type;
1959 xmlChar *xml_name, *href;
1962 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1964 if(!node) return E_INVALIDARG;
1966 hr = get_node_type(Type, &node_type);
1967 if(FAILED(hr)) return hr;
1969 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1970 FIXME("nodes with namespaces currently not supported.\n");
1972 TRACE("node_type %d\n", node_type);
1974 /* exit earlier for types that need name */
1978 case NODE_ATTRIBUTE:
1979 case NODE_ENTITY_REFERENCE:
1980 case NODE_PROCESSING_INSTRUCTION:
1981 if (!name || *name == 0) return E_FAIL;
1986 xml_name = xmlchar_from_wchar(name);
1987 /* prevent empty href to be allocated */
1988 href = namespaceURI ? xmlchar_from_wchar(namespaceURI) : NULL;
1994 xmlChar *local, *prefix;
1996 local = xmlSplitQName2(xml_name, &prefix);
1998 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
2000 /* allow to create default namespace xmlns= */
2001 if (local || (href && *href))
2003 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
2004 xmlSetNs(xmlnode, ns);
2012 case NODE_ATTRIBUTE:
2013 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
2016 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
2018 case NODE_CDATA_SECTION:
2019 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
2021 case NODE_ENTITY_REFERENCE:
2022 xmlnode = xmlNewReference(get_doc(This), xml_name);
2024 case NODE_PROCESSING_INSTRUCTION:
2025 #ifdef HAVE_XMLNEWDOCPI
2026 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
2028 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2033 xmlnode = xmlNewDocComment(get_doc(This), NULL);
2035 case NODE_DOCUMENT_FRAGMENT:
2036 xmlnode = xmlNewDocFragment(get_doc(This));
2038 /* unsupported types */
2040 case NODE_DOCUMENT_TYPE:
2043 heap_free(xml_name);
2044 return E_INVALIDARG;
2046 FIXME("unhandled node type %d\n", node_type);
2051 *node = create_node(xmlnode);
2052 heap_free(xml_name);
2057 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
2058 xmldoc_add_orphan(xmlnode->doc, xmlnode);
2065 static HRESULT WINAPI domdoc_nodeFromID(
2066 IXMLDOMDocument3 *iface,
2068 IXMLDOMNode** node )
2070 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2071 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
2075 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
2080 xmldoc = doparse(This, ptr, len, NULL);
2082 xmldoc->_private = create_priv();
2083 return attach_xmldoc(This, xmldoc);
2089 static HRESULT doread( domdoc *This, LPWSTR filename )
2094 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
2099 detach_bsc(This->bsc);
2105 static HRESULT WINAPI domdoc_load(
2106 IXMLDOMDocument3 *iface,
2108 VARIANT_BOOL* isSuccessful )
2110 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2111 LPWSTR filename = NULL;
2112 HRESULT hr = S_FALSE;
2113 IXMLDOMDocument3 *pNewDoc = NULL;
2114 IStream *pStream = NULL;
2117 TRACE("(%p)->(%s)\n", This, debugstr_variant(&source));
2119 *isSuccessful = VARIANT_FALSE;
2121 assert( &This->node );
2123 switch( V_VT(&source) )
2126 filename = V_BSTR(&source);
2128 case VT_BSTR|VT_BYREF:
2129 if (!V_BSTRREF(&source)) return E_INVALIDARG;
2130 filename = *V_BSTRREF(&source);
2133 hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
2138 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
2139 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
2140 hr = attach_xmldoc(This, xmldoc);
2143 *isSuccessful = VARIANT_TRUE;
2148 hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IStream, (void**)&pStream);
2151 IPersistStream *pDocStream;
2152 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
2155 hr = IPersistStream_Load(pDocStream, pStream);
2156 IStream_Release(pStream);
2159 *isSuccessful = VARIANT_TRUE;
2161 TRACE("Using IStream to load Document\n");
2166 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
2171 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
2176 /* ISequentialStream */
2177 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&source)->lpVtbl);
2181 FIXME("VT type not supported (%d)\n", V_VT(&source));
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 static 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");