2 * DOM Document implementation
4 * Copyright 2005 Mike McCormack
5 * Copyright 2010 Adam Martinson for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define NONAMELESSUNION
30 # include <libxml/parser.h>
31 # include <libxml/xmlerror.h>
32 # include <libxml/xpathInternals.h>
33 # include <libxml/xmlsave.h>
34 # include <libxml/SAX2.h>
35 # include <libxml/parserInternals.h>
52 #include "wine/debug.h"
53 #include "wine/list.h"
55 #include "msxml_private.h"
57 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
61 /* not defined in older versions */
62 #define XML_SAVE_FORMAT 1
63 #define XML_SAVE_NO_DECL 2
64 #define XML_SAVE_NO_EMPTY 4
65 #define XML_SAVE_NO_XHTML 8
66 #define XML_SAVE_XHTML 16
67 #define XML_SAVE_AS_XML 32
68 #define XML_SAVE_AS_HTML 64
70 static const WCHAR PropertySelectionLanguageW[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
71 static const WCHAR PropertySelectionNamespacesW[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
72 static const WCHAR PropertyProhibitDTDW[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
73 static const WCHAR PropertyNewParserW[] = {'N','e','w','P','a','r','s','e','r',0};
74 static const WCHAR PropValueXPathW[] = {'X','P','a','t','h',0};
75 static const WCHAR PropValueXSLPatternW[] = {'X','S','L','P','a','t','t','e','r','n',0};
77 /* Anything that passes the test_get_ownerDocument()
78 * tests can go here (data shared between all instances).
79 * We need to preserve this when reloading a document,
80 * and also need access to it from the libxml backend. */
81 typedef struct _domdoc_properties {
82 MSXML_VERSION version;
83 VARIANT_BOOL preserving;
84 IXMLDOMSchemaCollection2* schemaCache;
85 struct list selectNsList;
86 xmlChar const* selectNsStr;
91 typedef struct ConnectionPoint ConnectionPoint;
92 typedef struct domdoc domdoc;
94 struct ConnectionPoint
96 const IConnectionPointVtbl *lpVtblConnectionPoint;
99 ConnectionPoint *next;
100 IConnectionPointContainer *container;
107 IPropertyNotifySink *propnotif;
113 EVENTID_READYSTATECHANGE = 0,
114 EVENTID_DATAAVAILABLE,
115 EVENTID_TRANSFORMNODE,
122 const struct IXMLDOMDocument3Vtbl *lpVtbl;
123 const struct IPersistStreamInitVtbl *lpvtblIPersistStreamInit;
124 const struct IObjectWithSiteVtbl *lpvtblIObjectWithSite;
125 const struct IObjectSafetyVtbl *lpvtblIObjectSafety;
126 const struct ISupportErrorInfoVtbl *lpvtblISupportErrorInfo;
127 const struct IConnectionPointContainerVtbl *lpVtblConnectionPointContainer;
130 VARIANT_BOOL validating;
131 VARIANT_BOOL resolving;
132 domdoc_properties* properties;
145 /* connection list */
146 ConnectionPoint *cp_list;
147 ConnectionPoint cp_domdocevents;
148 ConnectionPoint cp_propnotif;
149 ConnectionPoint cp_dispatch;
152 IDispatch *events[EVENTID_LAST];
155 static HRESULT set_doc_event(domdoc *doc, eventid_t eid, const VARIANT *v)
163 IUnknown_QueryInterface(V_UNKNOWN(v), &IID_IDispatch, (void**)&disp);
168 disp = V_DISPATCH(v);
169 if (disp) IDispatch_AddRef(disp);
172 return DISP_E_TYPEMISMATCH;
175 if (doc->events[eid]) IDispatch_Release(doc->events[eid]);
176 doc->events[eid] = disp;
181 static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface)
183 return (ConnectionPoint *)((char*)iface - FIELD_OFFSET(ConnectionPoint, lpVtblConnectionPoint));
187 In native windows, the whole lifetime management of XMLDOMNodes is
188 managed automatically using reference counts. Wine emulates that by
189 maintaining a reference count to the document that is increased for
190 each IXMLDOMNode pointer passed out for this document. If all these
191 pointers are gone, the document is unreachable and gets freed, that
192 is, all nodes in the tree of the document get freed.
194 You are able to create nodes that are associated to a document (in
195 fact, in msxml's XMLDOM model, all nodes are associated to a document),
196 but not in the tree of that document, for example using the createFoo
197 functions from IXMLDOMDocument. These nodes do not get cleaned up
198 by libxml, so we have to do it ourselves.
200 To catch these nodes, a list of "orphan nodes" is introduced.
201 It contains pointers to all roots of node trees that are
202 associated with the document without being part of the document
203 tree. All nodes with parent==NULL (except for the document root nodes)
204 should be in the orphan node list of their document. All orphan nodes
205 get freed together with the document itself.
208 typedef struct _xmldoc_priv {
211 domdoc_properties* properties;
214 typedef struct _orphan_entry {
219 typedef struct _select_ns_entry {
221 xmlChar const* prefix;
227 static inline xmldoc_priv * priv_from_xmlDocPtr(const xmlDocPtr doc)
229 return doc->_private;
232 static inline domdoc_properties * properties_from_xmlDocPtr(xmlDocPtr doc)
234 return priv_from_xmlDocPtr(doc)->properties;
237 BOOL is_xpathmode(const xmlDocPtr doc)
239 return properties_from_xmlDocPtr(doc)->XPath;
242 void set_xpathmode(xmlDocPtr doc, BOOL xpath)
244 properties_from_xmlDocPtr(doc)->XPath = xpath;
247 int registerNamespaces(xmlXPathContextPtr ctxt)
250 const select_ns_entry* ns = NULL;
251 const struct list* pNsList = &properties_from_xmlDocPtr(ctxt->doc)->selectNsList;
253 TRACE("(%p)\n", ctxt);
255 LIST_FOR_EACH_ENTRY( ns, pNsList, select_ns_entry, entry )
257 xmlXPathRegisterNs(ctxt, ns->prefix, ns->href);
264 static inline void clear_selectNsList(struct list* pNsList)
266 select_ns_entry *ns, *ns2;
267 LIST_FOR_EACH_ENTRY_SAFE( ns, ns2, pNsList, select_ns_entry, entry )
274 static xmldoc_priv * create_priv(void)
277 priv = heap_alloc( sizeof (*priv) );
282 list_init( &priv->orphans );
283 priv->properties = NULL;
289 static domdoc_properties * create_properties(const GUID *clsid)
291 domdoc_properties *properties = heap_alloc(sizeof(domdoc_properties));
293 list_init(&properties->selectNsList);
294 properties->preserving = VARIANT_FALSE;
295 properties->schemaCache = NULL;
296 properties->selectNsStr = heap_alloc_zero(sizeof(xmlChar));
297 properties->selectNsStr_len = 0;
299 /* properties that are dependent on object versions */
300 if (IsEqualCLSID(clsid, &CLSID_DOMDocument30))
302 properties->version = MSXML3;
303 properties->XPath = FALSE;
305 else if (IsEqualCLSID(clsid, &CLSID_DOMDocument40))
307 properties->version = MSXML4;
308 properties->XPath = TRUE;
310 else if (IsEqualCLSID(clsid, &CLSID_DOMDocument60))
312 properties->version = MSXML6;
313 properties->XPath = TRUE;
317 properties->version = MSXML_DEFAULT;
318 properties->XPath = FALSE;
324 static domdoc_properties* copy_properties(domdoc_properties const* properties)
326 domdoc_properties* pcopy = heap_alloc(sizeof(domdoc_properties));
327 select_ns_entry const* ns = NULL;
328 select_ns_entry* new_ns = NULL;
329 int len = (properties->selectNsStr_len+1)*sizeof(xmlChar);
334 pcopy->version = properties->version;
335 pcopy->preserving = properties->preserving;
336 pcopy->schemaCache = properties->schemaCache;
337 if (pcopy->schemaCache)
338 IXMLDOMSchemaCollection2_AddRef(pcopy->schemaCache);
339 pcopy->XPath = properties->XPath;
340 pcopy->selectNsStr_len = properties->selectNsStr_len;
341 list_init( &pcopy->selectNsList );
342 pcopy->selectNsStr = heap_alloc(len);
343 memcpy((xmlChar*)pcopy->selectNsStr, properties->selectNsStr, len);
344 offset = pcopy->selectNsStr - properties->selectNsStr;
346 LIST_FOR_EACH_ENTRY( ns, (&properties->selectNsList), select_ns_entry, entry )
348 new_ns = heap_alloc(sizeof(select_ns_entry));
349 memcpy(new_ns, ns, sizeof(select_ns_entry));
350 new_ns->href += offset;
351 new_ns->prefix += offset;
352 list_add_tail(&pcopy->selectNsList, &new_ns->entry);
360 static void free_properties(domdoc_properties* properties)
364 if (properties->schemaCache)
365 IXMLDOMSchemaCollection2_Release(properties->schemaCache);
366 clear_selectNsList(&properties->selectNsList);
367 heap_free((xmlChar*)properties->selectNsStr);
368 heap_free(properties);
372 static BOOL xmldoc_has_decl(xmlDocPtr doc)
374 return doc->children && (xmlStrEqual(doc->children->name, (xmlChar*)"xml") == 1);
377 /* links a "<?xml" node as a first child */
378 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
381 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
384 /* unlinks a first "<?xml" child if it was created */
385 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
391 if (doc->standalone != -1)
393 node = doc->children;
394 xmlUnlinkNode( node );
402 BOOL is_preserving_whitespace(xmlNodePtr node)
404 domdoc_properties* properties = NULL;
405 /* during parsing the xmlDoc._private stuff is not there */
406 if (priv_from_xmlDocPtr(node->doc))
407 properties = properties_from_xmlDocPtr(node->doc);
408 return ((properties && properties->preserving == VARIANT_TRUE) ||
409 xmlNodeGetSpacePreserve(node) == 1);
412 static inline BOOL strn_isspace(xmlChar const* str, int len)
414 for (; str && len > 0 && *str; ++str, --len)
421 static void sax_characters(void *ctx, const xmlChar *ch, int len)
423 xmlParserCtxtPtr pctx;
426 pctx = (xmlParserCtxtPtr) ctx;
427 This = (domdoc const*) pctx->_private;
429 /* during domdoc_loadXML() the xmlDocPtr->_private data is not available */
430 if (!This->properties->preserving &&
431 !is_preserving_whitespace(pctx->node) &&
432 strn_isspace(ch, len))
435 xmlSAX2Characters(ctx, ch, len);
438 static void LIBXML2_LOG_CALLBACK sax_error(void* ctx, char const* msg, ...)
442 LIBXML2_CALLBACK_ERR(doparse, msg, ap);
446 static void LIBXML2_LOG_CALLBACK sax_warning(void* ctx, char const* msg, ...)
450 LIBXML2_CALLBACK_WARN(doparse, msg, ap);
454 static void sax_serror(void* ctx, xmlErrorPtr err)
456 LIBXML2_CALLBACK_SERROR(doparse, err);
459 static xmlDocPtr doparse(domdoc* This, char *ptr, int len, xmlChar const* encoding)
461 xmlDocPtr doc = NULL;
462 xmlParserCtxtPtr pctx;
463 static xmlSAXHandler sax_handler = {
464 xmlSAX2InternalSubset, /* internalSubset */
465 xmlSAX2IsStandalone, /* isStandalone */
466 xmlSAX2HasInternalSubset, /* hasInternalSubset */
467 xmlSAX2HasExternalSubset, /* hasExternalSubset */
468 xmlSAX2ResolveEntity, /* resolveEntity */
469 xmlSAX2GetEntity, /* getEntity */
470 xmlSAX2EntityDecl, /* entityDecl */
471 xmlSAX2NotationDecl, /* notationDecl */
472 xmlSAX2AttributeDecl, /* attributeDecl */
473 xmlSAX2ElementDecl, /* elementDecl */
474 xmlSAX2UnparsedEntityDecl, /* unparsedEntityDecl */
475 xmlSAX2SetDocumentLocator, /* setDocumentLocator */
476 xmlSAX2StartDocument, /* startDocument */
477 xmlSAX2EndDocument, /* endDocument */
478 xmlSAX2StartElement, /* startElement */
479 xmlSAX2EndElement, /* endElement */
480 xmlSAX2Reference, /* reference */
481 sax_characters, /* characters */
482 sax_characters, /* ignorableWhitespace */
483 xmlSAX2ProcessingInstruction, /* processingInstruction */
484 xmlSAX2Comment, /* comment */
485 sax_warning, /* warning */
486 sax_error, /* error */
487 sax_error, /* fatalError */
488 xmlSAX2GetParameterEntity, /* getParameterEntity */
489 xmlSAX2CDataBlock, /* cdataBlock */
490 xmlSAX2ExternalSubset, /* externalSubset */
493 xmlSAX2StartElementNs, /* startElementNs */
494 xmlSAX2EndElementNs, /* endElementNs */
495 sax_serror /* serror */
499 pctx = xmlCreateMemoryParserCtxt(ptr, len);
502 ERR("Failed to create parser context\n");
506 if (pctx->sax) xmlFree(pctx->sax);
507 pctx->sax = &sax_handler;
508 pctx->_private = This;
510 pctx->encoding = xmlStrdup(encoding);
511 xmlParseDocument(pctx);
513 if (pctx->wellFormed)
519 xmlFreeDoc(pctx->myDoc);
523 xmlFreeParserCtxt(pctx);
525 /* TODO: put this in one of the SAX callbacks */
526 /* create first child as a <?xml...?> */
527 if (doc && doc->standalone != -1)
531 xmlChar *xmlbuff = (xmlChar*)buff;
533 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
535 /* version attribute can't be omitted */
536 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
537 xmlNodeAddContent( node, xmlbuff );
541 sprintf(buff, " encoding=\"%s\"", doc->encoding);
542 xmlNodeAddContent( node, xmlbuff );
545 if (doc->standalone != -2)
547 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
548 xmlNodeAddContent( node, xmlbuff );
551 xmldoc_link_xmldecl( doc, node );
557 void xmldoc_init(xmlDocPtr doc, const GUID *clsid)
559 doc->_private = create_priv();
560 priv_from_xmlDocPtr(doc)->properties = create_properties(clsid);
563 LONG xmldoc_add_ref(xmlDocPtr doc)
565 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
566 TRACE("(%p)->(%d)\n", doc, ref);
570 LONG xmldoc_release(xmlDocPtr doc)
572 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
573 LONG ref = InterlockedDecrement(&priv->refs);
574 TRACE("(%p)->(%d)\n", doc, ref);
577 orphan_entry *orphan, *orphan2;
578 TRACE("freeing docptr %p\n", doc);
580 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
582 xmlFreeNode( orphan->node );
585 free_properties(priv->properties);
586 heap_free(doc->_private);
594 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
596 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
599 entry = heap_alloc( sizeof (*entry) );
601 return E_OUTOFMEMORY;
604 list_add_head( &priv->orphans, &entry->entry );
608 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
610 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
611 orphan_entry *entry, *entry2;
613 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
615 if( entry->node == node )
617 list_remove( &entry->entry );
626 static inline xmlDocPtr get_doc( domdoc *This )
628 return (xmlDocPtr)This->node.node;
631 static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
635 priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
636 if (xmldoc_release(get_doc(This)) != 0)
637 priv_from_xmlDocPtr(get_doc(This))->properties =
638 copy_properties(This->properties);
641 This->node.node = (xmlNodePtr) xml;
645 xmldoc_add_ref(get_doc(This));
646 priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
652 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
654 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
657 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
659 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStreamInit));
662 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
664 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
667 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
669 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
672 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
674 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblISupportErrorInfo));
677 static inline domdoc *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
679 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtblConnectionPointContainer));
682 /************************************************************************
683 * domdoc implementation of IPersistStream.
685 static HRESULT WINAPI domdoc_IPersistStreamInit_QueryInterface(
686 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
688 domdoc* This = impl_from_IPersistStreamInit(iface);
689 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)&This->lpVtbl, riid, ppvObj);
692 static ULONG WINAPI domdoc_IPersistStreamInit_AddRef(
693 IPersistStreamInit *iface)
695 domdoc* This = impl_from_IPersistStreamInit(iface);
696 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)&This->lpVtbl);
699 static ULONG WINAPI domdoc_IPersistStreamInit_Release(
700 IPersistStreamInit *iface)
702 domdoc* This = impl_from_IPersistStreamInit(iface);
703 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)&This->lpVtbl);
706 static HRESULT WINAPI domdoc_IPersistStreamInit_GetClassID(
707 IPersistStreamInit *iface, CLSID *classid)
709 domdoc* This = impl_from_IPersistStreamInit(iface);
710 TRACE("(%p)->(%p)\n", This, classid);
715 *classid = *DOMDocument_version(This->properties->version);
720 static HRESULT WINAPI domdoc_IPersistStreamInit_IsDirty(
721 IPersistStreamInit *iface)
723 domdoc *This = impl_from_IPersistStreamInit(iface);
724 FIXME("(%p): stub!\n", This);
728 static HRESULT WINAPI domdoc_IPersistStreamInit_Load(
729 IPersistStreamInit *iface, LPSTREAM pStm)
731 domdoc *This = impl_from_IPersistStreamInit(iface);
734 DWORD read, written, len;
737 xmlDocPtr xmldoc = NULL;
739 TRACE("(%p)->(%p)\n", This, pStm);
744 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
750 IStream_Read(pStm, buf, sizeof(buf), &read);
751 hr = IStream_Write(This->stream, buf, read, &written);
752 } while(SUCCEEDED(hr) && written != 0 && read != 0);
756 ERR("Failed to copy stream\n");
760 hr = GetHGlobalFromStream(This->stream, &hglobal);
764 len = GlobalSize(hglobal);
765 ptr = GlobalLock(hglobal);
767 xmldoc = doparse(This, ptr, len, NULL);
768 GlobalUnlock(hglobal);
772 ERR("Failed to parse xml\n");
776 xmldoc->_private = create_priv();
778 return attach_xmldoc(This, xmldoc);
781 static HRESULT WINAPI domdoc_IPersistStreamInit_Save(
782 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
784 domdoc *This = impl_from_IPersistStreamInit(iface);
788 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
790 hr = IXMLDOMDocument3_get_xml( (IXMLDOMDocument3*)&This->lpVtbl, &xmlString );
793 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
795 hr = IStream_Write( stream, xmlString, len, NULL );
796 SysFreeString(xmlString);
799 TRACE("ret 0x%08x\n", hr);
804 static HRESULT WINAPI domdoc_IPersistStreamInit_GetSizeMax(
805 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
807 domdoc *This = impl_from_IPersistStreamInit(iface);
808 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
812 static HRESULT WINAPI domdoc_IPersistStreamInit_InitNew(
813 IPersistStreamInit *iface)
815 domdoc *This = impl_from_IPersistStreamInit(iface);
816 TRACE("(%p)\n", This);
820 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
822 domdoc_IPersistStreamInit_QueryInterface,
823 domdoc_IPersistStreamInit_AddRef,
824 domdoc_IPersistStreamInit_Release,
825 domdoc_IPersistStreamInit_GetClassID,
826 domdoc_IPersistStreamInit_IsDirty,
827 domdoc_IPersistStreamInit_Load,
828 domdoc_IPersistStreamInit_Save,
829 domdoc_IPersistStreamInit_GetSizeMax,
830 domdoc_IPersistStreamInit_InitNew
833 /* ISupportErrorInfo interface */
834 static HRESULT WINAPI support_error_QueryInterface(
835 ISupportErrorInfo *iface,
836 REFIID riid, void** ppvObj )
838 domdoc *This = impl_from_ISupportErrorInfo(iface);
839 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3 *)This, riid, ppvObj);
842 static ULONG WINAPI support_error_AddRef(
843 ISupportErrorInfo *iface )
845 domdoc *This = impl_from_ISupportErrorInfo(iface);
846 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
849 static ULONG WINAPI support_error_Release(
850 ISupportErrorInfo *iface )
852 domdoc *This = impl_from_ISupportErrorInfo(iface);
853 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
856 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
857 ISupportErrorInfo *iface,
860 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
864 static const struct ISupportErrorInfoVtbl support_error_vtbl =
866 support_error_QueryInterface,
867 support_error_AddRef,
868 support_error_Release,
869 support_error_InterfaceSupportsErrorInfo
872 /* IXMLDOMDocument2 interface */
873 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
875 domdoc *This = impl_from_IXMLDOMDocument3( iface );
877 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
881 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
882 IsEqualGUID( riid, &IID_IDispatch ) ||
883 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
884 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
885 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
886 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
890 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
891 IsEqualGUID(&IID_IPersistStreamInit, riid))
893 *ppvObject = &(This->lpvtblIPersistStreamInit);
895 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
897 *ppvObject = &(This->lpvtblIObjectWithSite);
899 else if (IsEqualGUID(&IID_IObjectSafety, riid))
901 *ppvObject = &(This->lpvtblIObjectSafety);
903 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
905 *ppvObject = &This->lpvtblISupportErrorInfo;
907 else if(node_query_interface(&This->node, riid, ppvObject))
909 return *ppvObject ? S_OK : E_NOINTERFACE;
911 else if (IsEqualGUID( riid, &IID_IConnectionPointContainer ))
913 *ppvObject = &This->lpVtblConnectionPointContainer;
915 else if(IsEqualGUID(&IID_IRunnableObject, riid))
917 TRACE("IID_IRunnableObject not supported returning NULL\n");
918 return E_NOINTERFACE;
922 FIXME("interface %s not implemented\n", debugstr_guid(riid));
923 return E_NOINTERFACE;
926 IUnknown_AddRef((IUnknown*)*ppvObject);
932 static ULONG WINAPI domdoc_AddRef(
933 IXMLDOMDocument3 *iface )
935 domdoc *This = impl_from_IXMLDOMDocument3( iface );
936 ULONG ref = InterlockedIncrement( &This->ref );
937 TRACE("(%p)->(%d)\n", This, ref );
942 static ULONG WINAPI domdoc_Release(
943 IXMLDOMDocument3 *iface )
945 domdoc *This = impl_from_IXMLDOMDocument3( iface );
946 LONG ref = InterlockedDecrement( &This->ref );
948 TRACE("(%p)->(%d)\n", This, ref );
955 detach_bsc(This->bsc);
958 IUnknown_Release( This->site );
959 destroy_xmlnode(&This->node);
961 IStream_Release(This->stream);
963 for (eid = 0; eid < EVENTID_LAST; eid++)
964 if (This->events[eid]) IDispatch_Release(This->events[eid]);
972 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
974 domdoc *This = impl_from_IXMLDOMDocument3( iface );
976 TRACE("(%p)->(%p)\n", This, pctinfo);
983 static HRESULT WINAPI domdoc_GetTypeInfo(
984 IXMLDOMDocument3 *iface,
985 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
987 domdoc *This = impl_from_IXMLDOMDocument3( iface );
990 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
992 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
997 static HRESULT WINAPI domdoc_GetIDsOfNames(
998 IXMLDOMDocument3 *iface,
1000 LPOLESTR* rgszNames,
1005 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1006 ITypeInfo *typeinfo;
1009 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1012 if(!rgszNames || cNames == 0 || !rgDispId)
1013 return E_INVALIDARG;
1015 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
1018 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1019 ITypeInfo_Release(typeinfo);
1026 static HRESULT WINAPI domdoc_Invoke(
1027 IXMLDOMDocument3 *iface,
1028 DISPID dispIdMember,
1032 DISPPARAMS* pDispParams,
1033 VARIANT* pVarResult,
1034 EXCEPINFO* pExcepInfo,
1037 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1038 ITypeInfo *typeinfo;
1041 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1042 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1044 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
1047 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
1048 pVarResult, pExcepInfo, puArgErr);
1049 ITypeInfo_Release(typeinfo);
1056 static HRESULT WINAPI domdoc_get_nodeName(
1057 IXMLDOMDocument3 *iface,
1060 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1062 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
1064 TRACE("(%p)->(%p)\n", This, name);
1066 return return_bstr(documentW, name);
1070 static HRESULT WINAPI domdoc_get_nodeValue(
1071 IXMLDOMDocument3 *iface,
1074 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1076 TRACE("(%p)->(%p)\n", This, value);
1079 return E_INVALIDARG;
1081 V_VT(value) = VT_NULL;
1082 V_BSTR(value) = NULL; /* tests show that we should do this */
1087 static HRESULT WINAPI domdoc_put_nodeValue(
1088 IXMLDOMDocument3 *iface,
1091 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1092 TRACE("(%p)->(v%d)\n", This, V_VT(&value));
1097 static HRESULT WINAPI domdoc_get_nodeType(
1098 IXMLDOMDocument3 *iface,
1101 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1103 TRACE("(%p)->(%p)\n", This, type);
1105 *type = NODE_DOCUMENT;
1110 static HRESULT WINAPI domdoc_get_parentNode(
1111 IXMLDOMDocument3 *iface,
1112 IXMLDOMNode** parent )
1114 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1116 TRACE("(%p)->(%p)\n", This, parent);
1118 return node_get_parent(&This->node, parent);
1122 static HRESULT WINAPI domdoc_get_childNodes(
1123 IXMLDOMDocument3 *iface,
1124 IXMLDOMNodeList** childList )
1126 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1128 TRACE("(%p)->(%p)\n", This, childList);
1130 return node_get_child_nodes(&This->node, childList);
1134 static HRESULT WINAPI domdoc_get_firstChild(
1135 IXMLDOMDocument3 *iface,
1136 IXMLDOMNode** firstChild )
1138 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1140 TRACE("(%p)->(%p)\n", This, firstChild);
1142 return node_get_first_child(&This->node, firstChild);
1146 static HRESULT WINAPI domdoc_get_lastChild(
1147 IXMLDOMDocument3 *iface,
1148 IXMLDOMNode** lastChild )
1150 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1152 TRACE("(%p)->(%p)\n", This, lastChild);
1154 return node_get_last_child(&This->node, lastChild);
1158 static HRESULT WINAPI domdoc_get_previousSibling(
1159 IXMLDOMDocument3 *iface,
1160 IXMLDOMNode** previousSibling )
1162 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1164 TRACE("(%p)->(%p)\n", This, previousSibling);
1166 return return_null_node(previousSibling);
1170 static HRESULT WINAPI domdoc_get_nextSibling(
1171 IXMLDOMDocument3 *iface,
1172 IXMLDOMNode** nextSibling )
1174 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1176 TRACE("(%p)->(%p)\n", This, nextSibling);
1178 return return_null_node(nextSibling);
1182 static HRESULT WINAPI domdoc_get_attributes(
1183 IXMLDOMDocument3 *iface,
1184 IXMLDOMNamedNodeMap** attributeMap )
1186 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1188 TRACE("(%p)->(%p)\n", This, attributeMap);
1190 return return_null_ptr((void**)attributeMap);
1194 static HRESULT WINAPI domdoc_insertBefore(
1195 IXMLDOMDocument3 *iface,
1196 IXMLDOMNode* newChild,
1198 IXMLDOMNode** outNewChild )
1200 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1202 TRACE("(%p)->(%p x%d %p)\n", This, newChild, V_VT(&refChild), outNewChild);
1204 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1208 static HRESULT WINAPI domdoc_replaceChild(
1209 IXMLDOMDocument3 *iface,
1210 IXMLDOMNode* newChild,
1211 IXMLDOMNode* oldChild,
1212 IXMLDOMNode** outOldChild)
1214 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1216 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1218 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1222 static HRESULT WINAPI domdoc_removeChild(
1223 IXMLDOMDocument3 *iface,
1225 IXMLDOMNode **oldChild)
1227 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1228 TRACE("(%p)->(%p %p)\n", This, child, oldChild);
1229 return node_remove_child(&This->node, child, oldChild);
1233 static HRESULT WINAPI domdoc_appendChild(
1234 IXMLDOMDocument3 *iface,
1236 IXMLDOMNode **outChild)
1238 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1239 TRACE("(%p)->(%p %p)\n", This, child, outChild);
1240 return node_append_child(&This->node, child, outChild);
1244 static HRESULT WINAPI domdoc_hasChildNodes(
1245 IXMLDOMDocument3 *iface,
1248 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1249 TRACE("(%p)->(%p)\n", This, ret);
1250 return node_has_childnodes(&This->node, ret);
1254 static HRESULT WINAPI domdoc_get_ownerDocument(
1255 IXMLDOMDocument3 *iface,
1256 IXMLDOMDocument **doc)
1258 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1259 TRACE("(%p)->(%p)\n", This, doc);
1260 return node_get_owner_doc(&This->node, doc);
1264 static HRESULT WINAPI domdoc_cloneNode(
1265 IXMLDOMDocument3 *iface,
1267 IXMLDOMNode** outNode)
1269 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1270 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
1271 return node_clone( &This->node, deep, outNode );
1275 static HRESULT WINAPI domdoc_get_nodeTypeString(
1276 IXMLDOMDocument3 *iface,
1279 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1280 static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
1282 TRACE("(%p)->(%p)\n", This, p);
1284 return return_bstr(documentW, p);
1288 static HRESULT WINAPI domdoc_get_text(
1289 IXMLDOMDocument3 *iface,
1292 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1293 TRACE("(%p)->(%p)\n", This, p);
1294 return node_get_text(&This->node, p);
1298 static HRESULT WINAPI domdoc_put_text(
1299 IXMLDOMDocument3 *iface,
1302 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1303 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1308 static HRESULT WINAPI domdoc_get_specified(
1309 IXMLDOMDocument3 *iface,
1310 VARIANT_BOOL* isSpecified )
1312 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1313 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1314 *isSpecified = VARIANT_TRUE;
1319 static HRESULT WINAPI domdoc_get_definition(
1320 IXMLDOMDocument3 *iface,
1321 IXMLDOMNode** definitionNode )
1323 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1324 FIXME("(%p)->(%p)\n", This, definitionNode);
1329 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1330 IXMLDOMDocument3 *iface,
1333 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1334 TRACE("(%p)->(%p)\n", This, v);
1335 return return_null_var(v);
1338 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1339 IXMLDOMDocument3 *iface,
1340 VARIANT typedValue )
1342 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1343 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1348 static HRESULT WINAPI domdoc_get_dataType(
1349 IXMLDOMDocument3 *iface,
1352 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1353 TRACE("(%p)->(%p)\n", This, typename);
1354 return return_null_var( typename );
1358 static HRESULT WINAPI domdoc_put_dataType(
1359 IXMLDOMDocument3 *iface,
1362 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1364 FIXME("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
1367 return E_INVALIDARG;
1372 static int XMLCALL domdoc_get_xml_writecallback(void *ctx, const char *data, int len)
1374 return xmlBufferAdd((xmlBufferPtr)ctx, (xmlChar*)data, len) == 0 ? len : 0;
1377 static HRESULT WINAPI domdoc_get_xml(
1378 IXMLDOMDocument3 *iface,
1381 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1382 xmlSaveCtxtPtr ctxt;
1387 TRACE("(%p)->(%p)\n", This, p);
1390 return E_INVALIDARG;
1394 buf = xmlBufferCreate();
1396 return E_OUTOFMEMORY;
1398 options = xmldoc_has_decl(get_doc(This)) ? XML_SAVE_NO_DECL : 0;
1399 options |= XML_SAVE_FORMAT;
1400 ctxt = xmlSaveToIO(domdoc_get_xml_writecallback, NULL, buf, "UTF-8", options);
1405 return E_OUTOFMEMORY;
1408 ret = xmlSaveDoc(ctxt, get_doc(This));
1409 /* flushes on close */
1412 TRACE("%ld, len=%d\n", ret, xmlBufferLength(buf));
1413 if(ret != -1 && xmlBufferLength(buf) > 0)
1417 content = bstr_from_xmlChar(xmlBufferContent(buf));
1418 content = EnsureCorrectEOL(content);
1424 *p = SysAllocStringLen(NULL, 0);
1429 return *p ? S_OK : E_OUTOFMEMORY;
1433 static HRESULT WINAPI domdoc_transformNode(
1434 IXMLDOMDocument3 *iface,
1438 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1439 TRACE("(%p)->(%p %p)\n", This, node, p);
1440 return node_transform_node(&This->node, node, p);
1444 static HRESULT WINAPI domdoc_selectNodes(
1445 IXMLDOMDocument3 *iface,
1447 IXMLDOMNodeList **outList)
1449 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1450 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList);
1451 return node_select_nodes(&This->node, p, outList);
1455 static HRESULT WINAPI domdoc_selectSingleNode(
1456 IXMLDOMDocument3 *iface,
1458 IXMLDOMNode **outNode)
1460 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1461 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode);
1462 return node_select_singlenode(&This->node, p, outNode);
1466 static HRESULT WINAPI domdoc_get_parsed(
1467 IXMLDOMDocument3 *iface,
1468 VARIANT_BOOL* isParsed )
1470 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1471 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1472 *isParsed = VARIANT_TRUE;
1477 static HRESULT WINAPI domdoc_get_namespaceURI(
1478 IXMLDOMDocument3 *iface,
1479 BSTR* namespaceURI )
1481 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1482 TRACE("(%p)->(%p)\n", This, namespaceURI);
1483 return node_get_namespaceURI(&This->node, namespaceURI);
1487 static HRESULT WINAPI domdoc_get_prefix(
1488 IXMLDOMDocument3 *iface,
1491 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1492 TRACE("(%p)->(%p)\n", This, prefix);
1493 return return_null_bstr( prefix );
1497 static HRESULT WINAPI domdoc_get_baseName(
1498 IXMLDOMDocument3 *iface,
1501 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1502 TRACE("(%p)->(%p)\n", This, name);
1503 return return_null_bstr( name );
1507 static HRESULT WINAPI domdoc_transformNodeToObject(
1508 IXMLDOMDocument3 *iface,
1509 IXMLDOMNode* stylesheet,
1510 VARIANT outputObject)
1512 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1513 FIXME("(%p)->(%p %s)\n", This, stylesheet, debugstr_variant(&outputObject));
1518 static HRESULT WINAPI domdoc_get_doctype(
1519 IXMLDOMDocument3 *iface,
1520 IXMLDOMDocumentType** doctype )
1522 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1527 TRACE("(%p)->(%p)\n", This, doctype);
1529 if (!doctype) return E_INVALIDARG;
1533 dtd = xmlGetIntSubset(get_doc(This));
1534 if (!dtd) return S_FALSE;
1536 node = create_node((xmlNodePtr)dtd);
1537 if (!node) return S_FALSE;
1539 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentType, (void**)doctype);
1540 IXMLDOMNode_Release(node);
1546 static HRESULT WINAPI domdoc_get_implementation(
1547 IXMLDOMDocument3 *iface,
1548 IXMLDOMImplementation** impl )
1550 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1552 TRACE("(%p)->(%p)\n", This, impl);
1555 return E_INVALIDARG;
1557 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1562 static HRESULT WINAPI domdoc_get_documentElement(
1563 IXMLDOMDocument3 *iface,
1564 IXMLDOMElement** DOMElement )
1566 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1567 IXMLDOMNode *element_node;
1571 TRACE("(%p)->(%p)\n", This, DOMElement);
1574 return E_INVALIDARG;
1578 root = xmlDocGetRootElement( get_doc(This) );
1582 element_node = create_node( root );
1583 if(!element_node) return S_FALSE;
1585 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1586 IXMLDOMNode_Release(element_node);
1592 static HRESULT WINAPI domdoc_put_documentElement(
1593 IXMLDOMDocument3 *iface,
1594 IXMLDOMElement* DOMElement )
1596 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1597 IXMLDOMNode *elementNode;
1602 TRACE("(%p)->(%p)\n", This, DOMElement);
1604 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1608 xmlNode = get_node_obj( elementNode );
1609 if(!xmlNode) return E_FAIL;
1611 if(!xmlNode->node->parent)
1612 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1613 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1615 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1616 IXMLDOMNode_Release( elementNode );
1619 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1625 static HRESULT WINAPI domdoc_createElement(
1626 IXMLDOMDocument3 *iface,
1628 IXMLDOMElement** element )
1630 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1635 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1637 if (!element || !tagname) return E_INVALIDARG;
1639 V_VT(&type) = VT_I1;
1640 V_I1(&type) = NODE_ELEMENT;
1642 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1645 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1646 IXMLDOMNode_Release(node);
1653 static HRESULT WINAPI domdoc_createDocumentFragment(
1654 IXMLDOMDocument3 *iface,
1655 IXMLDOMDocumentFragment** frag )
1657 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1662 TRACE("(%p)->(%p)\n", This, frag);
1664 if (!frag) return E_INVALIDARG;
1668 V_VT(&type) = VT_I1;
1669 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1671 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1674 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1675 IXMLDOMNode_Release(node);
1682 static HRESULT WINAPI domdoc_createTextNode(
1683 IXMLDOMDocument3 *iface,
1685 IXMLDOMText** text )
1687 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1692 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1694 if (!text) return E_INVALIDARG;
1698 V_VT(&type) = VT_I1;
1699 V_I1(&type) = NODE_TEXT;
1701 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1704 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1705 IXMLDOMNode_Release(node);
1706 hr = IXMLDOMText_put_data(*text, data);
1713 static HRESULT WINAPI domdoc_createComment(
1714 IXMLDOMDocument3 *iface,
1716 IXMLDOMComment** comment )
1718 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1723 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1725 if (!comment) return E_INVALIDARG;
1729 V_VT(&type) = VT_I1;
1730 V_I1(&type) = NODE_COMMENT;
1732 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1735 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1736 IXMLDOMNode_Release(node);
1737 hr = IXMLDOMComment_put_data(*comment, data);
1744 static HRESULT WINAPI domdoc_createCDATASection(
1745 IXMLDOMDocument3 *iface,
1747 IXMLDOMCDATASection** cdata )
1749 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1754 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1756 if (!cdata) return E_INVALIDARG;
1760 V_VT(&type) = VT_I1;
1761 V_I1(&type) = NODE_CDATA_SECTION;
1763 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1766 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1767 IXMLDOMNode_Release(node);
1768 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1775 static HRESULT WINAPI domdoc_createProcessingInstruction(
1776 IXMLDOMDocument3 *iface,
1779 IXMLDOMProcessingInstruction** pi )
1781 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1786 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1788 if (!pi) return E_INVALIDARG;
1792 V_VT(&type) = VT_I1;
1793 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1795 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1800 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1801 node_obj = get_node_obj(node);
1802 hr = node_set_content(node_obj, data);
1804 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1805 IXMLDOMNode_Release(node);
1812 static HRESULT WINAPI domdoc_createAttribute(
1813 IXMLDOMDocument3 *iface,
1815 IXMLDOMAttribute** attribute )
1817 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1822 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1824 if (!attribute || !name) return E_INVALIDARG;
1826 V_VT(&type) = VT_I1;
1827 V_I1(&type) = NODE_ATTRIBUTE;
1829 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1832 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1833 IXMLDOMNode_Release(node);
1840 static HRESULT WINAPI domdoc_createEntityReference(
1841 IXMLDOMDocument3 *iface,
1843 IXMLDOMEntityReference** entityref )
1845 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1850 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1852 if (!entityref) return E_INVALIDARG;
1856 V_VT(&type) = VT_I1;
1857 V_I1(&type) = NODE_ENTITY_REFERENCE;
1859 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1862 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1863 IXMLDOMNode_Release(node);
1869 xmlChar* tagName_to_XPath(const BSTR tagName)
1871 xmlChar *query, *tmp;
1872 static const xmlChar mod_pre[] = "*[local-name()='";
1873 static const xmlChar mod_post[] = "']";
1874 static const xmlChar prefix[] = "descendant::";
1875 const WCHAR *tokBegin, *tokEnd;
1878 query = xmlStrdup(prefix);
1881 while (tokBegin && *tokBegin)
1886 query = xmlStrcat(query, BAD_CAST "/");
1890 query = xmlStrcat(query, BAD_CAST "*");
1894 query = xmlStrcat(query, mod_pre);
1896 while (*tokEnd && *tokEnd != '/')
1898 len = WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, NULL, 0, NULL, NULL);
1899 tmp = xmlMalloc(len);
1900 WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, (char*)tmp, len, NULL, NULL);
1901 query = xmlStrncat(query, tmp, len);
1904 query = xmlStrcat(query, mod_post);
1911 static HRESULT WINAPI domdoc_getElementsByTagName(
1912 IXMLDOMDocument3 *iface,
1914 IXMLDOMNodeList** resultList )
1916 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1921 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1923 if (!tagName || !resultList) return E_INVALIDARG;
1925 XPath = This->properties->XPath;
1926 This->properties->XPath = TRUE;
1927 query = tagName_to_XPath(tagName);
1928 hr = queryresult_create((xmlNodePtr)get_doc(This), query, resultList);
1930 This->properties->XPath = XPath;
1935 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1941 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1943 return E_INVALIDARG;
1950 static HRESULT WINAPI domdoc_createNode(
1951 IXMLDOMDocument3 *iface,
1955 IXMLDOMNode** node )
1957 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1958 DOMNodeType node_type;
1960 xmlChar *xml_name, *href;
1963 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1965 if(!node) return E_INVALIDARG;
1967 hr = get_node_type(Type, &node_type);
1968 if(FAILED(hr)) return hr;
1970 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1971 FIXME("nodes with namespaces currently not supported.\n");
1973 TRACE("node_type %d\n", node_type);
1975 /* exit earlier for types that need name */
1979 case NODE_ATTRIBUTE:
1980 case NODE_ENTITY_REFERENCE:
1981 case NODE_PROCESSING_INSTRUCTION:
1982 if (!name || *name == 0) return E_FAIL;
1987 xml_name = xmlchar_from_wchar(name);
1988 /* prevent empty href to be allocated */
1989 href = namespaceURI ? xmlchar_from_wchar(namespaceURI) : NULL;
1995 xmlChar *local, *prefix;
1997 local = xmlSplitQName2(xml_name, &prefix);
1999 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
2001 /* allow to create default namespace xmlns= */
2002 if (local || (href && *href))
2004 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
2005 xmlSetNs(xmlnode, ns);
2013 case NODE_ATTRIBUTE:
2014 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
2017 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
2019 case NODE_CDATA_SECTION:
2020 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
2022 case NODE_ENTITY_REFERENCE:
2023 xmlnode = xmlNewReference(get_doc(This), xml_name);
2025 case NODE_PROCESSING_INSTRUCTION:
2026 #ifdef HAVE_XMLNEWDOCPI
2027 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
2029 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2034 xmlnode = xmlNewDocComment(get_doc(This), NULL);
2036 case NODE_DOCUMENT_FRAGMENT:
2037 xmlnode = xmlNewDocFragment(get_doc(This));
2039 /* unsupported types */
2041 case NODE_DOCUMENT_TYPE:
2044 heap_free(xml_name);
2045 return E_INVALIDARG;
2047 FIXME("unhandled node type %d\n", node_type);
2052 *node = create_node(xmlnode);
2053 heap_free(xml_name);
2058 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
2059 xmldoc_add_orphan(xmlnode->doc, xmlnode);
2066 static HRESULT WINAPI domdoc_nodeFromID(
2067 IXMLDOMDocument3 *iface,
2069 IXMLDOMNode** node )
2071 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2072 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
2076 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
2081 xmldoc = doparse(This, ptr, len, NULL);
2083 xmldoc->_private = create_priv();
2084 return attach_xmldoc(This, xmldoc);
2090 static HRESULT doread( domdoc *This, LPWSTR filename )
2095 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
2100 detach_bsc(This->bsc);
2106 static HRESULT WINAPI domdoc_load(
2107 IXMLDOMDocument3 *iface,
2109 VARIANT_BOOL* isSuccessful )
2111 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2112 LPWSTR filename = NULL;
2113 HRESULT hr = S_FALSE;
2114 IXMLDOMDocument3 *pNewDoc = NULL;
2115 IStream *pStream = NULL;
2118 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
2120 *isSuccessful = VARIANT_FALSE;
2122 assert( &This->node );
2124 switch( V_VT(&xmlSource) )
2127 filename = V_BSTR(&xmlSource);
2130 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
2135 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
2136 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
2137 hr = attach_xmldoc(This, xmldoc);
2140 *isSuccessful = VARIANT_TRUE;
2145 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
2148 IPersistStream *pDocStream;
2149 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
2152 hr = IPersistStream_Load(pDocStream, pStream);
2153 IStream_Release(pStream);
2156 *isSuccessful = VARIANT_TRUE;
2158 TRACE("Using IStream to load Document\n");
2163 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
2168 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
2173 /* ISequentialStream */
2174 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
2178 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
2181 TRACE("filename (%s)\n", debugstr_w(filename));
2185 hr = doread( This, filename );
2188 This->error = E_FAIL;
2191 hr = This->error = S_OK;
2192 *isSuccessful = VARIANT_TRUE;
2196 if(!filename || FAILED(hr)) {
2197 xmldoc = xmlNewDoc(NULL);
2198 xmldoc->_private = create_priv();
2199 hr = attach_xmldoc(This, xmldoc);
2204 TRACE("ret (%d)\n", hr);
2210 static HRESULT WINAPI domdoc_get_readyState(
2211 IXMLDOMDocument3 *iface,
2214 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2215 FIXME("stub! (%p)->(%p)\n", This, value);
2218 return E_INVALIDARG;
2220 *value = READYSTATE_COMPLETE;
2225 static HRESULT WINAPI domdoc_get_parseError(
2226 IXMLDOMDocument3 *iface,
2227 IXMLDOMParseError** errorObj )
2229 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2230 static const WCHAR err[] = {'e','r','r','o','r',0};
2231 BSTR error_string = NULL;
2233 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2236 error_string = SysAllocString(err);
2238 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2239 if(!*errorObj) return E_OUTOFMEMORY;
2244 static HRESULT WINAPI domdoc_get_url(
2245 IXMLDOMDocument3 *iface,
2248 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2249 FIXME("(%p)->(%p)\n", This, urlString);
2254 static HRESULT WINAPI domdoc_get_async(
2255 IXMLDOMDocument3 *iface,
2256 VARIANT_BOOL* isAsync )
2258 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2260 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2261 *isAsync = This->async;
2266 static HRESULT WINAPI domdoc_put_async(
2267 IXMLDOMDocument3 *iface,
2268 VARIANT_BOOL isAsync )
2270 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2272 TRACE("(%p)->(%d)\n", This, isAsync);
2273 This->async = isAsync;
2278 static HRESULT WINAPI domdoc_abort(
2279 IXMLDOMDocument3 *iface )
2281 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2282 FIXME("%p\n", This);
2287 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
2292 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
2293 str = heap_alloc( len );
2296 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
2302 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2303 static HRESULT WINAPI domdoc_loadXML(
2304 IXMLDOMDocument3 *iface,
2306 VARIANT_BOOL* isSuccessful )
2308 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2309 static const xmlChar encoding[] = "UTF-8";
2310 xmlDocPtr xmldoc = NULL;
2311 HRESULT hr = S_FALSE, hr2;
2315 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2317 assert ( &This->node );
2321 *isSuccessful = VARIANT_FALSE;
2323 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
2325 xmldoc = doparse(This, str, len, encoding);
2329 This->error = E_FAIL;
2330 TRACE("failed to parse document\n");
2334 hr = This->error = S_OK;
2335 *isSuccessful = VARIANT_TRUE;
2336 TRACE("parsed document %p\n", xmldoc);
2341 xmldoc = xmlNewDoc(NULL);
2343 xmldoc->_private = create_priv();
2345 hr2 = attach_xmldoc(This, xmldoc);
2352 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2356 if(!WriteFile(ctx, buffer, len, &written, NULL))
2358 WARN("write error\n");
2365 static int XMLCALL domdoc_save_closecallback(void *ctx)
2367 return CloseHandle(ctx) ? 0 : -1;
2370 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2375 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2378 WARN("stream write error: 0x%08x\n", hr);
2385 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2387 IStream_Release((IStream*)ctx);
2391 static HRESULT WINAPI domdoc_save(
2392 IXMLDOMDocument3 *iface,
2393 VARIANT destination )
2395 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2396 xmlSaveCtxtPtr ctx = NULL;
2400 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
2401 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
2403 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
2405 FIXME("Unhandled vt %d\n", V_VT(&destination));
2409 if(V_VT(&destination) == VT_UNKNOWN)
2411 IUnknown *pUnk = V_UNKNOWN(&destination);
2412 IXMLDOMDocument2 *document;
2415 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2418 VARIANT_BOOL success;
2421 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2424 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2428 IXMLDOMDocument3_Release(document);
2432 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2435 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2436 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2440 IStream_Release(stream);
2447 /* save with file path */
2448 HANDLE handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
2449 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2450 if( handle == INVALID_HANDLE_VALUE )
2452 WARN("failed to create file\n");
2456 /* disable top XML declaration */
2457 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2458 handle, NULL, XML_SAVE_NO_DECL);
2461 CloseHandle(handle);
2466 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2467 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2468 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2470 /* will release resources through close callback */
2476 static HRESULT WINAPI domdoc_get_validateOnParse(
2477 IXMLDOMDocument3 *iface,
2478 VARIANT_BOOL* isValidating )
2480 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2481 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2482 *isValidating = This->validating;
2487 static HRESULT WINAPI domdoc_put_validateOnParse(
2488 IXMLDOMDocument3 *iface,
2489 VARIANT_BOOL isValidating )
2491 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2492 TRACE("(%p)->(%d)\n", This, isValidating);
2493 This->validating = isValidating;
2498 static HRESULT WINAPI domdoc_get_resolveExternals(
2499 IXMLDOMDocument3 *iface,
2500 VARIANT_BOOL* isResolving )
2502 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2503 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2504 *isResolving = This->resolving;
2509 static HRESULT WINAPI domdoc_put_resolveExternals(
2510 IXMLDOMDocument3 *iface,
2511 VARIANT_BOOL isResolving )
2513 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2514 TRACE("(%p)->(%d)\n", This, isResolving);
2515 This->resolving = isResolving;
2520 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2521 IXMLDOMDocument3 *iface,
2522 VARIANT_BOOL* isPreserving )
2524 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2525 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->properties->preserving);
2526 *isPreserving = This->properties->preserving;
2531 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2532 IXMLDOMDocument3 *iface,
2533 VARIANT_BOOL isPreserving )
2535 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2536 TRACE("(%p)->(%d)\n", This, isPreserving);
2537 This->properties->preserving = isPreserving;
2542 static HRESULT WINAPI domdoc_put_onreadystatechange(
2543 IXMLDOMDocument3 *iface,
2546 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2548 TRACE("(%p)->(%s)\n", This, debugstr_variant(&event));
2549 return set_doc_event(This, EVENTID_READYSTATECHANGE, &event);
2553 static HRESULT WINAPI domdoc_put_onDataAvailable(
2554 IXMLDOMDocument3 *iface,
2555 VARIANT onDataAvailableSink )
2557 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2558 FIXME("%p\n", This);
2562 static HRESULT WINAPI domdoc_put_onTransformNode(
2563 IXMLDOMDocument3 *iface,
2564 VARIANT onTransformNodeSink )
2566 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2567 FIXME("%p\n", This);
2571 static HRESULT WINAPI domdoc_get_namespaces(
2572 IXMLDOMDocument3* iface,
2573 IXMLDOMSchemaCollection** schemaCollection )
2575 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2576 FIXME("(%p)->(%p)\n", This, schemaCollection);
2580 static HRESULT WINAPI domdoc_get_schemas(
2581 IXMLDOMDocument3* iface,
2584 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2585 HRESULT hr = S_FALSE;
2586 IXMLDOMSchemaCollection2* cur_schema = This->properties->schemaCache;
2588 TRACE("(%p)->(%p)\n", This, var1);
2590 VariantInit(var1); /* Test shows we don't call VariantClear here */
2591 V_VT(var1) = VT_NULL;
2595 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2597 V_VT(var1) = VT_DISPATCH;
2602 static HRESULT WINAPI domdoc_putref_schemas(
2603 IXMLDOMDocument3* iface,
2606 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2607 HRESULT hr = E_FAIL;
2608 IXMLDOMSchemaCollection2* new_schema = NULL;
2610 FIXME("(%p): semi-stub\n", This);
2614 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2618 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2627 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2632 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->properties->schemaCache, new_schema);
2633 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2639 static inline BOOL is_wellformed(xmlDocPtr doc)
2641 #ifdef HAVE_XMLDOC_PROPERTIES
2642 return doc->properties & XML_DOC_WELLFORMED;
2644 /* Not a full check, but catches the worst violations */
2648 for (child = doc->children; child != NULL; child = child->next)
2650 switch (child->type)
2652 case XML_ELEMENT_NODE:
2657 case XML_CDATA_SECTION_NODE:
2669 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2673 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2677 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2681 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2685 static HRESULT WINAPI domdoc_validateNode(
2686 IXMLDOMDocument3* iface,
2688 IXMLDOMParseError** err)
2690 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2691 LONG state, err_code = 0;
2695 TRACE("(%p)->(%p, %p)\n", This, node, err);
2696 domdoc_get_readyState(iface, &state);
2697 if (state != READYSTATE_COMPLETE)
2700 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2707 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2711 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2714 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2718 if (!is_wellformed(get_doc(This)))
2720 ERR("doc not well-formed\n");
2722 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2726 /* DTD validation */
2727 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2729 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2730 vctx->error = validate_error;
2731 vctx->warning = validate_warning;
2734 if (!((node == (IXMLDOMNode*)iface)?
2735 xmlValidateDocument(vctx, get_doc(This)) :
2736 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2738 /* TODO: get a real error code here */
2739 TRACE("DTD validation failed\n");
2740 err_code = E_XML_INVALID;
2743 xmlFreeValidCtxt(vctx);
2746 /* Schema validation */
2747 if (hr == S_OK && This->properties->schemaCache != NULL)
2750 hr = SchemaCache_validate_tree(This->properties->schemaCache, get_node_obj(node)->node);
2754 /* TODO: get a real error code here */
2757 TRACE("schema validation succeeded\n");
2761 ERR("schema validation failed\n");
2762 err_code = E_XML_INVALID;
2767 /* not really OK, just didn't find a schema for the ns */
2774 ERR("no DTD or schema found\n");
2775 err_code = E_XML_NODTD;
2780 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2785 static HRESULT WINAPI domdoc_validate(
2786 IXMLDOMDocument3* iface,
2787 IXMLDOMParseError** err)
2789 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2790 TRACE("(%p)->(%p)\n", This, err);
2791 return domdoc_validateNode(iface, (IXMLDOMNode*)iface, err);
2794 static HRESULT WINAPI domdoc_setProperty(
2795 IXMLDOMDocument3* iface,
2799 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2801 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2803 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2809 V_VT(&varStr) = VT_EMPTY;
2810 if (V_VT(&var) != VT_BSTR)
2812 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2814 bstr = V_BSTR(&varStr);
2817 bstr = V_BSTR(&var);
2820 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2821 This->properties->XPath = TRUE;
2822 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2823 This->properties->XPath = FALSE;
2827 VariantClear(&varStr);
2830 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2835 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2836 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2837 xmlXPathContextPtr ctx;
2838 struct list *pNsList;
2839 select_ns_entry* pNsEntry = NULL;
2841 V_VT(&varStr) = VT_EMPTY;
2842 if (V_VT(&var) != VT_BSTR)
2844 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2846 bstr = V_BSTR(&varStr);
2849 bstr = V_BSTR(&var);
2853 pNsList = &(This->properties->selectNsList);
2854 clear_selectNsList(pNsList);
2856 nsStr = xmlchar_from_wchar(bstr);
2858 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2860 This->properties->selectNsStr = nsStr;
2861 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2864 ctx = xmlXPathNewContext(This->node.node->doc);
2867 for (; *pTokBegin; pTokBegin = pTokEnd)
2869 if (pNsEntry != NULL)
2870 memset(pNsEntry, 0, sizeof(select_ns_entry));
2872 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2874 while (*pTokBegin == ' ')
2876 pTokEnd = pTokBegin;
2877 while (*pTokEnd != ' ' && *pTokEnd != 0)
2880 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2883 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2884 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2889 if (*pTokBegin == '=')
2891 /*valid for XSLPattern?*/
2892 FIXME("Setting default xmlns not supported - skipping.\n");
2893 pTokBegin = pTokEnd;
2896 else if (*pTokBegin == ':')
2898 pNsEntry->prefix = ++pTokBegin;
2899 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2902 if (pTokInner == pTokEnd)
2905 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2906 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2910 pNsEntry->prefix_end = *pTokInner;
2914 if (pTokEnd-pTokInner > 1 &&
2915 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2916 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2918 pNsEntry->href = ++pTokInner;
2919 pNsEntry->href_end = *(pTokEnd-1);
2921 list_add_tail(pNsList, &pNsEntry->entry);
2922 /*let libxml figure out if they're valid from here ;)*/
2923 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2932 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2933 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2934 list_add_tail(pNsList, &pNsEntry->entry);
2947 heap_free(pNsEntry);
2948 xmlXPathFreeContext(ctx);
2951 VariantClear(&varStr);
2954 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2955 lstrcmpiW(p, PropertyNewParserW) == 0)
2958 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2962 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2966 static HRESULT WINAPI domdoc_getProperty(
2967 IXMLDOMDocument3* iface,
2971 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2973 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2976 return E_INVALIDARG;
2978 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2980 V_VT(var) = VT_BSTR;
2981 V_BSTR(var) = This->properties->XPath ?
2982 SysAllocString(PropValueXPathW) :
2983 SysAllocString(PropValueXSLPatternW);
2984 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2986 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2989 BSTR rebuiltStr, cur;
2990 const xmlChar *nsStr;
2991 struct list *pNsList;
2992 select_ns_entry* pNsEntry;
2994 V_VT(var) = VT_BSTR;
2995 nsStr = This->properties->selectNsStr;
2996 pNsList = &This->properties->selectNsList;
2997 lenA = This->properties->selectNsStr_len;
2998 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
2999 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
3000 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
3002 /* this is fine because all of the chars that end tokens are ASCII*/
3003 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
3005 while (*cur != 0) ++cur;
3006 if (pNsEntry->prefix_end)
3008 *cur = pNsEntry->prefix_end;
3009 while (*cur != 0) ++cur;
3012 if (pNsEntry->href_end)
3014 *cur = pNsEntry->href_end;
3017 V_BSTR(var) = SysAllocString(rebuiltStr);
3018 heap_free(rebuiltStr);
3022 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
3026 static HRESULT WINAPI domdoc_importNode(
3027 IXMLDOMDocument3* iface,
3030 IXMLDOMNode** clone)
3032 domdoc *This = impl_from_IXMLDOMDocument3( iface );
3033 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
3037 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
3039 domdoc_QueryInterface,
3042 domdoc_GetTypeInfoCount,
3044 domdoc_GetIDsOfNames,
3046 domdoc_get_nodeName,
3047 domdoc_get_nodeValue,
3048 domdoc_put_nodeValue,
3049 domdoc_get_nodeType,
3050 domdoc_get_parentNode,
3051 domdoc_get_childNodes,
3052 domdoc_get_firstChild,
3053 domdoc_get_lastChild,
3054 domdoc_get_previousSibling,
3055 domdoc_get_nextSibling,
3056 domdoc_get_attributes,
3057 domdoc_insertBefore,
3058 domdoc_replaceChild,
3061 domdoc_hasChildNodes,
3062 domdoc_get_ownerDocument,
3064 domdoc_get_nodeTypeString,
3067 domdoc_get_specified,
3068 domdoc_get_definition,
3069 domdoc_get_nodeTypedValue,
3070 domdoc_put_nodeTypedValue,
3071 domdoc_get_dataType,
3072 domdoc_put_dataType,
3074 domdoc_transformNode,
3076 domdoc_selectSingleNode,
3078 domdoc_get_namespaceURI,
3080 domdoc_get_baseName,
3081 domdoc_transformNodeToObject,
3083 domdoc_get_implementation,
3084 domdoc_get_documentElement,
3085 domdoc_put_documentElement,
3086 domdoc_createElement,
3087 domdoc_createDocumentFragment,
3088 domdoc_createTextNode,
3089 domdoc_createComment,
3090 domdoc_createCDATASection,
3091 domdoc_createProcessingInstruction,
3092 domdoc_createAttribute,
3093 domdoc_createEntityReference,
3094 domdoc_getElementsByTagName,
3098 domdoc_get_readyState,
3099 domdoc_get_parseError,
3106 domdoc_get_validateOnParse,
3107 domdoc_put_validateOnParse,
3108 domdoc_get_resolveExternals,
3109 domdoc_put_resolveExternals,
3110 domdoc_get_preserveWhiteSpace,
3111 domdoc_put_preserveWhiteSpace,
3112 domdoc_put_onreadystatechange,
3113 domdoc_put_onDataAvailable,
3114 domdoc_put_onTransformNode,
3115 domdoc_get_namespaces,
3117 domdoc_putref_schemas,
3121 domdoc_validateNode,
3125 /* IConnectionPointContainer */
3126 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
3127 REFIID riid, void **ppv)
3129 domdoc *This = impl_from_IConnectionPointContainer(iface);
3130 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)This, riid, ppv);
3133 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
3135 domdoc *This = impl_from_IConnectionPointContainer(iface);
3136 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)This);
3139 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
3141 domdoc *This = impl_from_IConnectionPointContainer(iface);
3142 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)This);
3145 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
3146 IEnumConnectionPoints **ppEnum)
3148 domdoc *This = impl_from_IConnectionPointContainer(iface);
3149 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3153 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
3154 REFIID riid, IConnectionPoint **cp)
3156 domdoc *This = impl_from_IConnectionPointContainer(iface);
3157 ConnectionPoint *iter;
3159 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
3163 for(iter = This->cp_list; iter; iter = iter->next)
3165 if (IsEqualGUID(iter->iid, riid))
3166 *cp = (IConnectionPoint*)&iter->lpVtblConnectionPoint;
3171 IConnectionPoint_AddRef(*cp);
3175 FIXME("unsupported riid %s\n", debugstr_guid(riid));
3176 return CONNECT_E_NOCONNECTION;
3180 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
3182 ConnectionPointContainer_QueryInterface,
3183 ConnectionPointContainer_AddRef,
3184 ConnectionPointContainer_Release,
3185 ConnectionPointContainer_EnumConnectionPoints,
3186 ConnectionPointContainer_FindConnectionPoint
3189 /* IConnectionPoint */
3190 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
3191 REFIID riid, void **ppv)
3193 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3195 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3199 if (IsEqualGUID(&IID_IUnknown, riid) ||
3200 IsEqualGUID(&IID_IConnectionPoint, riid))
3207 IConnectionPoint_AddRef(iface);
3211 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3212 return E_NOINTERFACE;
3215 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3217 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3218 return IConnectionPointContainer_AddRef(This->container);
3221 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3223 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3224 return IConnectionPointContainer_Release(This->container);
3227 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3229 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3231 TRACE("(%p)->(%p)\n", This, iid);
3233 if (!iid) return E_POINTER;
3239 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3240 IConnectionPointContainer **container)
3242 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3244 TRACE("(%p)->(%p)\n", This, container);
3246 if (!container) return E_POINTER;
3248 *container = This->container;
3249 IConnectionPointContainer_AddRef(*container);
3253 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
3256 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3257 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
3261 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3263 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3265 TRACE("(%p)->(%d)\n", This, cookie);
3267 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3268 return CONNECT_E_NOCONNECTION;
3270 IUnknown_Release(This->sinks[cookie-1].unk);
3271 This->sinks[cookie-1].unk = NULL;
3276 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3277 IEnumConnections **ppEnum)
3279 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3280 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3284 static const IConnectionPointVtbl ConnectionPointVtbl =
3286 ConnectionPoint_QueryInterface,
3287 ConnectionPoint_AddRef,
3288 ConnectionPoint_Release,
3289 ConnectionPoint_GetConnectionInterface,
3290 ConnectionPoint_GetConnectionPointContainer,
3291 ConnectionPoint_Advise,
3292 ConnectionPoint_Unadvise,
3293 ConnectionPoint_EnumConnections
3296 void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3298 cp->lpVtblConnectionPoint = &ConnectionPointVtbl;
3304 cp->next = doc->cp_list;
3307 cp->container = (IConnectionPointContainer*)&doc->lpVtblConnectionPointContainer;
3310 /* domdoc implementation of IObjectWithSite */
3311 static HRESULT WINAPI
3312 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3314 domdoc *This = impl_from_IObjectWithSite(iface);
3315 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppvObject );
3318 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3320 domdoc *This = impl_from_IObjectWithSite(iface);
3321 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3324 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3326 domdoc *This = impl_from_IObjectWithSite(iface);
3327 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3330 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3332 domdoc *This = impl_from_IObjectWithSite(iface);
3334 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3339 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3342 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3344 domdoc *This = impl_from_IObjectWithSite(iface);
3346 TRACE("(%p)->(%p)\n", iface, punk);
3352 IUnknown_Release( This->site );
3359 IUnknown_AddRef( punk );
3362 IUnknown_Release( This->site );
3369 static const IObjectWithSiteVtbl domdocObjectSite =
3371 domdoc_ObjectWithSite_QueryInterface,
3372 domdoc_ObjectWithSite_AddRef,
3373 domdoc_ObjectWithSite_Release,
3374 domdoc_ObjectWithSite_SetSite,
3375 domdoc_ObjectWithSite_GetSite
3378 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3380 domdoc *This = impl_from_IObjectSafety(iface);
3381 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppv );
3384 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3386 domdoc *This = impl_from_IObjectSafety(iface);
3387 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3390 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3392 domdoc *This = impl_from_IObjectSafety(iface);
3393 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3396 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3398 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3399 DWORD *supported, DWORD *enabled)
3401 domdoc *This = impl_from_IObjectSafety(iface);
3403 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3405 if(!supported || !enabled) return E_POINTER;
3407 *supported = SAFETY_SUPPORTED_OPTIONS;
3408 *enabled = This->safeopt;
3413 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3414 DWORD mask, DWORD enabled)
3416 domdoc *This = impl_from_IObjectSafety(iface);
3417 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3419 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3422 This->safeopt = enabled & mask & SAFETY_SUPPORTED_OPTIONS;
3426 #undef SAFETY_SUPPORTED_OPTIONS
3428 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3429 domdoc_Safety_QueryInterface,
3430 domdoc_Safety_AddRef,
3431 domdoc_Safety_Release,
3432 domdoc_Safety_GetInterfaceSafetyOptions,
3433 domdoc_Safety_SetInterfaceSafetyOptions
3436 static const tid_t domdoc_iface_tids[] = {
3438 IXMLDOMDocument_tid,
3439 IXMLDOMDocument2_tid,
3442 static dispex_static_data_t domdoc_dispex = {
3444 IXMLDOMDocument2_tid,
3449 HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3453 doc = heap_alloc( sizeof (*doc) );
3455 return E_OUTOFMEMORY;
3457 doc->lpVtbl = &domdoc_vtbl;
3458 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
3459 doc->lpvtblIObjectWithSite = &domdocObjectSite;
3460 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
3461 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
3462 doc->lpVtblConnectionPointContainer = &ConnectionPointContainerVtbl;
3464 doc->async = VARIANT_TRUE;
3465 doc->validating = 0;
3467 doc->properties = properties_from_xmlDocPtr(xmldoc);
3473 doc->cp_list = NULL;
3474 memset(doc->events, 0, sizeof(doc->events));
3476 /* events connection points */
3477 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3478 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3479 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3481 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->lpVtbl, &domdoc_dispex);
3483 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
3485 TRACE("returning iface %p\n", *document);
3489 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3494 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
3496 xmldoc = xmlNewDoc(NULL);
3498 return E_OUTOFMEMORY;
3500 xmldoc->_private = create_priv();
3501 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
3503 hr = get_domdoc_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3506 free_properties(properties_from_xmlDocPtr(xmldoc));
3507 heap_free(xmldoc->_private);
3515 IUnknown* create_domdoc( xmlNodePtr document )
3520 TRACE("(%p)\n", document);
3522 hr = get_domdoc_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3531 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3533 MESSAGE("This program tried to use a DOMDocument object, but\n"
3534 "libxml2 support was not present at compile time.\n");