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** documentType )
1522 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1523 FIXME("(%p)\n", This);
1528 static HRESULT WINAPI domdoc_get_implementation(
1529 IXMLDOMDocument3 *iface,
1530 IXMLDOMImplementation** impl )
1532 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1534 TRACE("(%p)->(%p)\n", This, impl);
1537 return E_INVALIDARG;
1539 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1544 static HRESULT WINAPI domdoc_get_documentElement(
1545 IXMLDOMDocument3 *iface,
1546 IXMLDOMElement** DOMElement )
1548 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1549 IXMLDOMNode *element_node;
1553 TRACE("(%p)->(%p)\n", This, DOMElement);
1556 return E_INVALIDARG;
1560 root = xmlDocGetRootElement( get_doc(This) );
1564 element_node = create_node( root );
1565 if(!element_node) return S_FALSE;
1567 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1568 IXMLDOMNode_Release(element_node);
1574 static HRESULT WINAPI domdoc_put_documentElement(
1575 IXMLDOMDocument3 *iface,
1576 IXMLDOMElement* DOMElement )
1578 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1579 IXMLDOMNode *elementNode;
1584 TRACE("(%p)->(%p)\n", This, DOMElement);
1586 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1590 xmlNode = get_node_obj( elementNode );
1591 if(!xmlNode) return E_FAIL;
1593 if(!xmlNode->node->parent)
1594 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1595 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1597 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1598 IXMLDOMNode_Release( elementNode );
1601 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1607 static HRESULT WINAPI domdoc_createElement(
1608 IXMLDOMDocument3 *iface,
1610 IXMLDOMElement** element )
1612 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1617 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1619 if (!element || !tagname) return E_INVALIDARG;
1621 V_VT(&type) = VT_I1;
1622 V_I1(&type) = NODE_ELEMENT;
1624 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1627 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1628 IXMLDOMNode_Release(node);
1635 static HRESULT WINAPI domdoc_createDocumentFragment(
1636 IXMLDOMDocument3 *iface,
1637 IXMLDOMDocumentFragment** frag )
1639 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1644 TRACE("(%p)->(%p)\n", This, frag);
1646 if (!frag) return E_INVALIDARG;
1650 V_VT(&type) = VT_I1;
1651 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1653 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1656 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1657 IXMLDOMNode_Release(node);
1664 static HRESULT WINAPI domdoc_createTextNode(
1665 IXMLDOMDocument3 *iface,
1667 IXMLDOMText** text )
1669 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1674 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1676 if (!text) return E_INVALIDARG;
1680 V_VT(&type) = VT_I1;
1681 V_I1(&type) = NODE_TEXT;
1683 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1686 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1687 IXMLDOMNode_Release(node);
1688 hr = IXMLDOMText_put_data(*text, data);
1695 static HRESULT WINAPI domdoc_createComment(
1696 IXMLDOMDocument3 *iface,
1698 IXMLDOMComment** comment )
1700 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1705 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1707 if (!comment) return E_INVALIDARG;
1711 V_VT(&type) = VT_I1;
1712 V_I1(&type) = NODE_COMMENT;
1714 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1717 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1718 IXMLDOMNode_Release(node);
1719 hr = IXMLDOMComment_put_data(*comment, data);
1726 static HRESULT WINAPI domdoc_createCDATASection(
1727 IXMLDOMDocument3 *iface,
1729 IXMLDOMCDATASection** cdata )
1731 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1736 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1738 if (!cdata) return E_INVALIDARG;
1742 V_VT(&type) = VT_I1;
1743 V_I1(&type) = NODE_CDATA_SECTION;
1745 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1748 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1749 IXMLDOMNode_Release(node);
1750 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1757 static HRESULT WINAPI domdoc_createProcessingInstruction(
1758 IXMLDOMDocument3 *iface,
1761 IXMLDOMProcessingInstruction** pi )
1763 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1768 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1770 if (!pi) return E_INVALIDARG;
1774 V_VT(&type) = VT_I1;
1775 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1777 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1782 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1783 node_obj = get_node_obj(node);
1784 hr = node_set_content(node_obj, data);
1786 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1787 IXMLDOMNode_Release(node);
1794 static HRESULT WINAPI domdoc_createAttribute(
1795 IXMLDOMDocument3 *iface,
1797 IXMLDOMAttribute** attribute )
1799 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1804 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1806 if (!attribute || !name) return E_INVALIDARG;
1808 V_VT(&type) = VT_I1;
1809 V_I1(&type) = NODE_ATTRIBUTE;
1811 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1814 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1815 IXMLDOMNode_Release(node);
1822 static HRESULT WINAPI domdoc_createEntityReference(
1823 IXMLDOMDocument3 *iface,
1825 IXMLDOMEntityReference** entityref )
1827 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1832 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1834 if (!entityref) return E_INVALIDARG;
1838 V_VT(&type) = VT_I1;
1839 V_I1(&type) = NODE_ENTITY_REFERENCE;
1841 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1844 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1845 IXMLDOMNode_Release(node);
1851 xmlChar* tagName_to_XPath(const BSTR tagName)
1853 xmlChar *query, *tmp;
1854 static const xmlChar mod_pre[] = "*[local-name()='";
1855 static const xmlChar mod_post[] = "']";
1856 static const xmlChar prefix[] = "descendant::";
1857 const WCHAR *tokBegin, *tokEnd;
1860 query = xmlStrdup(prefix);
1863 while (tokBegin && *tokBegin)
1868 query = xmlStrcat(query, BAD_CAST "/");
1872 query = xmlStrcat(query, BAD_CAST "*");
1876 query = xmlStrcat(query, mod_pre);
1878 while (*tokEnd && *tokEnd != '/')
1880 len = WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, NULL, 0, NULL, NULL);
1881 tmp = xmlMalloc(len);
1882 WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, (char*)tmp, len, NULL, NULL);
1883 query = xmlStrncat(query, tmp, len);
1886 query = xmlStrcat(query, mod_post);
1893 static HRESULT WINAPI domdoc_getElementsByTagName(
1894 IXMLDOMDocument3 *iface,
1896 IXMLDOMNodeList** resultList )
1898 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1903 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1905 if (!tagName || !resultList) return E_INVALIDARG;
1907 XPath = This->properties->XPath;
1908 This->properties->XPath = TRUE;
1909 query = tagName_to_XPath(tagName);
1910 hr = queryresult_create((xmlNodePtr)get_doc(This), query, resultList);
1912 This->properties->XPath = XPath;
1917 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1923 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1925 return E_INVALIDARG;
1932 static HRESULT WINAPI domdoc_createNode(
1933 IXMLDOMDocument3 *iface,
1937 IXMLDOMNode** node )
1939 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1940 DOMNodeType node_type;
1942 xmlChar *xml_name, *href;
1945 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1947 if(!node) return E_INVALIDARG;
1949 hr = get_node_type(Type, &node_type);
1950 if(FAILED(hr)) return hr;
1952 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1953 FIXME("nodes with namespaces currently not supported.\n");
1955 TRACE("node_type %d\n", node_type);
1957 /* exit earlier for types that need name */
1961 case NODE_ATTRIBUTE:
1962 case NODE_ENTITY_REFERENCE:
1963 case NODE_PROCESSING_INSTRUCTION:
1964 if (!name || *name == 0) return E_FAIL;
1969 xml_name = xmlChar_from_wchar(name);
1970 /* prevent empty href to be allocated */
1971 href = namespaceURI ? xmlChar_from_wchar(namespaceURI) : NULL;
1977 xmlChar *local, *prefix;
1979 local = xmlSplitQName2(xml_name, &prefix);
1981 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
1983 /* allow to create default namespace xmlns= */
1984 if (local || (href && *href))
1986 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
1987 xmlSetNs(xmlnode, ns);
1995 case NODE_ATTRIBUTE:
1996 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1999 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
2001 case NODE_CDATA_SECTION:
2002 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
2004 case NODE_ENTITY_REFERENCE:
2005 xmlnode = xmlNewReference(get_doc(This), xml_name);
2007 case NODE_PROCESSING_INSTRUCTION:
2008 #ifdef HAVE_XMLNEWDOCPI
2009 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
2011 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2016 xmlnode = xmlNewDocComment(get_doc(This), NULL);
2018 case NODE_DOCUMENT_FRAGMENT:
2019 xmlnode = xmlNewDocFragment(get_doc(This));
2021 /* unsupported types */
2023 case NODE_DOCUMENT_TYPE:
2026 heap_free(xml_name);
2027 return E_INVALIDARG;
2029 FIXME("unhandled node type %d\n", node_type);
2034 *node = create_node(xmlnode);
2035 heap_free(xml_name);
2040 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
2041 xmldoc_add_orphan(xmlnode->doc, xmlnode);
2048 static HRESULT WINAPI domdoc_nodeFromID(
2049 IXMLDOMDocument3 *iface,
2051 IXMLDOMNode** node )
2053 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2054 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
2058 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
2063 xmldoc = doparse(This, ptr, len, NULL);
2065 xmldoc->_private = create_priv();
2066 return attach_xmldoc(This, xmldoc);
2072 static HRESULT doread( domdoc *This, LPWSTR filename )
2077 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
2082 detach_bsc(This->bsc);
2088 static HRESULT WINAPI domdoc_load(
2089 IXMLDOMDocument3 *iface,
2091 VARIANT_BOOL* isSuccessful )
2093 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2094 LPWSTR filename = NULL;
2095 HRESULT hr = S_FALSE;
2096 IXMLDOMDocument3 *pNewDoc = NULL;
2097 IStream *pStream = NULL;
2100 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
2102 *isSuccessful = VARIANT_FALSE;
2104 assert( &This->node );
2106 switch( V_VT(&xmlSource) )
2109 filename = V_BSTR(&xmlSource);
2112 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
2117 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
2118 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
2119 hr = attach_xmldoc(This, xmldoc);
2122 *isSuccessful = VARIANT_TRUE;
2127 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
2130 IPersistStream *pDocStream;
2131 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
2134 hr = IPersistStream_Load(pDocStream, pStream);
2135 IStream_Release(pStream);
2138 *isSuccessful = VARIANT_TRUE;
2140 TRACE("Using IStream to load Document\n");
2145 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
2150 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
2155 /* ISequentialStream */
2156 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
2160 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
2163 TRACE("filename (%s)\n", debugstr_w(filename));
2167 hr = doread( This, filename );
2170 This->error = E_FAIL;
2173 hr = This->error = S_OK;
2174 *isSuccessful = VARIANT_TRUE;
2178 if(!filename || FAILED(hr)) {
2179 xmldoc = xmlNewDoc(NULL);
2180 xmldoc->_private = create_priv();
2181 hr = attach_xmldoc(This, xmldoc);
2186 TRACE("ret (%d)\n", hr);
2192 static HRESULT WINAPI domdoc_get_readyState(
2193 IXMLDOMDocument3 *iface,
2196 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2197 FIXME("stub! (%p)->(%p)\n", This, value);
2200 return E_INVALIDARG;
2202 *value = READYSTATE_COMPLETE;
2207 static HRESULT WINAPI domdoc_get_parseError(
2208 IXMLDOMDocument3 *iface,
2209 IXMLDOMParseError** errorObj )
2211 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2212 static const WCHAR err[] = {'e','r','r','o','r',0};
2213 BSTR error_string = NULL;
2215 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2218 error_string = SysAllocString(err);
2220 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2221 if(!*errorObj) return E_OUTOFMEMORY;
2226 static HRESULT WINAPI domdoc_get_url(
2227 IXMLDOMDocument3 *iface,
2230 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2231 FIXME("(%p)->(%p)\n", This, urlString);
2236 static HRESULT WINAPI domdoc_get_async(
2237 IXMLDOMDocument3 *iface,
2238 VARIANT_BOOL* isAsync )
2240 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2242 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2243 *isAsync = This->async;
2248 static HRESULT WINAPI domdoc_put_async(
2249 IXMLDOMDocument3 *iface,
2250 VARIANT_BOOL isAsync )
2252 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2254 TRACE("(%p)->(%d)\n", This, isAsync);
2255 This->async = isAsync;
2260 static HRESULT WINAPI domdoc_abort(
2261 IXMLDOMDocument3 *iface )
2263 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2264 FIXME("%p\n", This);
2269 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
2274 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
2275 str = heap_alloc( len );
2278 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
2284 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2285 static HRESULT WINAPI domdoc_loadXML(
2286 IXMLDOMDocument3 *iface,
2288 VARIANT_BOOL* isSuccessful )
2290 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2291 static const xmlChar encoding[] = "UTF-8";
2292 xmlDocPtr xmldoc = NULL;
2293 HRESULT hr = S_FALSE, hr2;
2297 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2299 assert ( &This->node );
2303 *isSuccessful = VARIANT_FALSE;
2305 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
2307 xmldoc = doparse(This, str, len, encoding);
2311 This->error = E_FAIL;
2312 TRACE("failed to parse document\n");
2316 hr = This->error = S_OK;
2317 *isSuccessful = VARIANT_TRUE;
2318 TRACE("parsed document %p\n", xmldoc);
2323 xmldoc = xmlNewDoc(NULL);
2325 xmldoc->_private = create_priv();
2327 hr2 = attach_xmldoc(This, xmldoc);
2334 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2338 if(!WriteFile(ctx, buffer, len, &written, NULL))
2340 WARN("write error\n");
2347 static int XMLCALL domdoc_save_closecallback(void *ctx)
2349 return CloseHandle(ctx) ? 0 : -1;
2352 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2357 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2360 WARN("stream write error: 0x%08x\n", hr);
2367 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2369 IStream_Release((IStream*)ctx);
2373 static HRESULT WINAPI domdoc_save(
2374 IXMLDOMDocument3 *iface,
2375 VARIANT destination )
2377 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2378 xmlSaveCtxtPtr ctx = NULL;
2382 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
2383 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
2385 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
2387 FIXME("Unhandled vt %d\n", V_VT(&destination));
2391 if(V_VT(&destination) == VT_UNKNOWN)
2393 IUnknown *pUnk = V_UNKNOWN(&destination);
2394 IXMLDOMDocument2 *document;
2397 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2400 VARIANT_BOOL success;
2403 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2406 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2410 IXMLDOMDocument3_Release(document);
2414 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2417 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2418 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2422 IStream_Release(stream);
2429 /* save with file path */
2430 HANDLE handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
2431 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2432 if( handle == INVALID_HANDLE_VALUE )
2434 WARN("failed to create file\n");
2438 /* disable top XML declaration */
2439 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2440 handle, NULL, XML_SAVE_NO_DECL);
2443 CloseHandle(handle);
2448 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2449 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2450 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2452 /* will release resources through close callback */
2458 static HRESULT WINAPI domdoc_get_validateOnParse(
2459 IXMLDOMDocument3 *iface,
2460 VARIANT_BOOL* isValidating )
2462 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2463 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2464 *isValidating = This->validating;
2469 static HRESULT WINAPI domdoc_put_validateOnParse(
2470 IXMLDOMDocument3 *iface,
2471 VARIANT_BOOL isValidating )
2473 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2474 TRACE("(%p)->(%d)\n", This, isValidating);
2475 This->validating = isValidating;
2480 static HRESULT WINAPI domdoc_get_resolveExternals(
2481 IXMLDOMDocument3 *iface,
2482 VARIANT_BOOL* isResolving )
2484 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2485 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2486 *isResolving = This->resolving;
2491 static HRESULT WINAPI domdoc_put_resolveExternals(
2492 IXMLDOMDocument3 *iface,
2493 VARIANT_BOOL isResolving )
2495 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2496 TRACE("(%p)->(%d)\n", This, isResolving);
2497 This->resolving = isResolving;
2502 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2503 IXMLDOMDocument3 *iface,
2504 VARIANT_BOOL* isPreserving )
2506 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2507 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->properties->preserving);
2508 *isPreserving = This->properties->preserving;
2513 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2514 IXMLDOMDocument3 *iface,
2515 VARIANT_BOOL isPreserving )
2517 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2518 TRACE("(%p)->(%d)\n", This, isPreserving);
2519 This->properties->preserving = isPreserving;
2524 static HRESULT WINAPI domdoc_put_onreadystatechange(
2525 IXMLDOMDocument3 *iface,
2528 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2530 TRACE("(%p)->(%s)\n", This, debugstr_variant(&event));
2531 return set_doc_event(This, EVENTID_READYSTATECHANGE, &event);
2535 static HRESULT WINAPI domdoc_put_onDataAvailable(
2536 IXMLDOMDocument3 *iface,
2537 VARIANT onDataAvailableSink )
2539 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2540 FIXME("%p\n", This);
2544 static HRESULT WINAPI domdoc_put_onTransformNode(
2545 IXMLDOMDocument3 *iface,
2546 VARIANT onTransformNodeSink )
2548 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2549 FIXME("%p\n", This);
2553 static HRESULT WINAPI domdoc_get_namespaces(
2554 IXMLDOMDocument3* iface,
2555 IXMLDOMSchemaCollection** schemaCollection )
2557 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2558 FIXME("(%p)->(%p)\n", This, schemaCollection);
2562 static HRESULT WINAPI domdoc_get_schemas(
2563 IXMLDOMDocument3* iface,
2566 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2567 HRESULT hr = S_FALSE;
2568 IXMLDOMSchemaCollection2* cur_schema = This->properties->schemaCache;
2570 TRACE("(%p)->(%p)\n", This, var1);
2572 VariantInit(var1); /* Test shows we don't call VariantClear here */
2573 V_VT(var1) = VT_NULL;
2577 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2579 V_VT(var1) = VT_DISPATCH;
2584 static HRESULT WINAPI domdoc_putref_schemas(
2585 IXMLDOMDocument3* iface,
2588 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2589 HRESULT hr = E_FAIL;
2590 IXMLDOMSchemaCollection2* new_schema = NULL;
2592 FIXME("(%p): semi-stub\n", This);
2596 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2600 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2609 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2614 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->properties->schemaCache, new_schema);
2615 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2621 static inline BOOL is_wellformed(xmlDocPtr doc)
2623 #ifdef HAVE_XMLDOC_PROPERTIES
2624 return doc->properties & XML_DOC_WELLFORMED;
2626 /* Not a full check, but catches the worst violations */
2630 for (child = doc->children; child != NULL; child = child->next)
2632 switch (child->type)
2634 case XML_ELEMENT_NODE:
2639 case XML_CDATA_SECTION_NODE:
2651 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2655 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2659 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2663 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2667 static HRESULT WINAPI domdoc_validateNode(
2668 IXMLDOMDocument3* iface,
2670 IXMLDOMParseError** err)
2672 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2673 LONG state, err_code = 0;
2677 TRACE("(%p)->(%p, %p)\n", This, node, err);
2678 domdoc_get_readyState(iface, &state);
2679 if (state != READYSTATE_COMPLETE)
2682 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2689 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2693 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2696 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2700 if (!is_wellformed(get_doc(This)))
2702 ERR("doc not well-formed\n");
2704 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2708 /* DTD validation */
2709 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2711 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2712 vctx->error = validate_error;
2713 vctx->warning = validate_warning;
2716 if (!((node == (IXMLDOMNode*)iface)?
2717 xmlValidateDocument(vctx, get_doc(This)) :
2718 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2720 /* TODO: get a real error code here */
2721 TRACE("DTD validation failed\n");
2722 err_code = E_XML_INVALID;
2725 xmlFreeValidCtxt(vctx);
2728 /* Schema validation */
2729 if (hr == S_OK && This->properties->schemaCache != NULL)
2732 hr = SchemaCache_validate_tree(This->properties->schemaCache, get_node_obj(node)->node);
2736 /* TODO: get a real error code here */
2739 TRACE("schema validation succeeded\n");
2743 ERR("schema validation failed\n");
2744 err_code = E_XML_INVALID;
2749 /* not really OK, just didn't find a schema for the ns */
2756 ERR("no DTD or schema found\n");
2757 err_code = E_XML_NODTD;
2762 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2767 static HRESULT WINAPI domdoc_validate(
2768 IXMLDOMDocument3* iface,
2769 IXMLDOMParseError** err)
2771 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2772 TRACE("(%p)->(%p)\n", This, err);
2773 return domdoc_validateNode(iface, (IXMLDOMNode*)iface, err);
2776 static HRESULT WINAPI domdoc_setProperty(
2777 IXMLDOMDocument3* iface,
2781 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2783 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2785 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2791 V_VT(&varStr) = VT_EMPTY;
2792 if (V_VT(&var) != VT_BSTR)
2794 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2796 bstr = V_BSTR(&varStr);
2799 bstr = V_BSTR(&var);
2802 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2803 This->properties->XPath = TRUE;
2804 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2805 This->properties->XPath = FALSE;
2809 VariantClear(&varStr);
2812 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2817 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2818 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2819 xmlXPathContextPtr ctx;
2820 struct list *pNsList;
2821 select_ns_entry* pNsEntry = NULL;
2823 V_VT(&varStr) = VT_EMPTY;
2824 if (V_VT(&var) != VT_BSTR)
2826 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2828 bstr = V_BSTR(&varStr);
2831 bstr = V_BSTR(&var);
2835 pNsList = &(This->properties->selectNsList);
2836 clear_selectNsList(pNsList);
2838 nsStr = xmlChar_from_wchar(bstr);
2841 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2843 This->properties->selectNsStr = nsStr;
2844 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2847 ctx = xmlXPathNewContext(This->node.node->doc);
2850 for (; *pTokBegin; pTokBegin = pTokEnd)
2852 if (pNsEntry != NULL)
2853 memset(pNsEntry, 0, sizeof(select_ns_entry));
2855 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2857 while (*pTokBegin == ' ')
2859 pTokEnd = pTokBegin;
2860 while (*pTokEnd != ' ' && *pTokEnd != 0)
2863 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2866 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2867 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2872 if (*pTokBegin == '=')
2874 /*valid for XSLPattern?*/
2875 FIXME("Setting default xmlns not supported - skipping.\n");
2876 pTokBegin = pTokEnd;
2879 else if (*pTokBegin == ':')
2881 pNsEntry->prefix = ++pTokBegin;
2882 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2885 if (pTokInner == pTokEnd)
2888 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2889 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2893 pNsEntry->prefix_end = *pTokInner;
2897 if (pTokEnd-pTokInner > 1 &&
2898 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2899 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2901 pNsEntry->href = ++pTokInner;
2902 pNsEntry->href_end = *(pTokEnd-1);
2904 list_add_tail(pNsList, &pNsEntry->entry);
2905 /*let libxml figure out if they're valid from here ;)*/
2906 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2915 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2916 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2917 list_add_tail(pNsList, &pNsEntry->entry);
2930 heap_free(pNsEntry);
2931 xmlXPathFreeContext(ctx);
2934 VariantClear(&varStr);
2937 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2938 lstrcmpiW(p, PropertyNewParserW) == 0)
2941 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2945 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2949 static HRESULT WINAPI domdoc_getProperty(
2950 IXMLDOMDocument3* iface,
2954 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2956 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2959 return E_INVALIDARG;
2961 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2963 V_VT(var) = VT_BSTR;
2964 V_BSTR(var) = This->properties->XPath ?
2965 SysAllocString(PropValueXPathW) :
2966 SysAllocString(PropValueXSLPatternW);
2967 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2969 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2972 BSTR rebuiltStr, cur;
2973 const xmlChar *nsStr;
2974 struct list *pNsList;
2975 select_ns_entry* pNsEntry;
2977 V_VT(var) = VT_BSTR;
2978 nsStr = This->properties->selectNsStr;
2979 pNsList = &This->properties->selectNsList;
2980 lenA = This->properties->selectNsStr_len;
2981 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
2982 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
2983 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
2985 /* this is fine because all of the chars that end tokens are ASCII*/
2986 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
2988 while (*cur != 0) ++cur;
2989 if (pNsEntry->prefix_end)
2991 *cur = pNsEntry->prefix_end;
2992 while (*cur != 0) ++cur;
2995 if (pNsEntry->href_end)
2997 *cur = pNsEntry->href_end;
3000 V_BSTR(var) = SysAllocString(rebuiltStr);
3001 heap_free(rebuiltStr);
3005 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
3009 static HRESULT WINAPI domdoc_importNode(
3010 IXMLDOMDocument3* iface,
3013 IXMLDOMNode** clone)
3015 domdoc *This = impl_from_IXMLDOMDocument3( iface );
3016 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
3020 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
3022 domdoc_QueryInterface,
3025 domdoc_GetTypeInfoCount,
3027 domdoc_GetIDsOfNames,
3029 domdoc_get_nodeName,
3030 domdoc_get_nodeValue,
3031 domdoc_put_nodeValue,
3032 domdoc_get_nodeType,
3033 domdoc_get_parentNode,
3034 domdoc_get_childNodes,
3035 domdoc_get_firstChild,
3036 domdoc_get_lastChild,
3037 domdoc_get_previousSibling,
3038 domdoc_get_nextSibling,
3039 domdoc_get_attributes,
3040 domdoc_insertBefore,
3041 domdoc_replaceChild,
3044 domdoc_hasChildNodes,
3045 domdoc_get_ownerDocument,
3047 domdoc_get_nodeTypeString,
3050 domdoc_get_specified,
3051 domdoc_get_definition,
3052 domdoc_get_nodeTypedValue,
3053 domdoc_put_nodeTypedValue,
3054 domdoc_get_dataType,
3055 domdoc_put_dataType,
3057 domdoc_transformNode,
3059 domdoc_selectSingleNode,
3061 domdoc_get_namespaceURI,
3063 domdoc_get_baseName,
3064 domdoc_transformNodeToObject,
3066 domdoc_get_implementation,
3067 domdoc_get_documentElement,
3068 domdoc_put_documentElement,
3069 domdoc_createElement,
3070 domdoc_createDocumentFragment,
3071 domdoc_createTextNode,
3072 domdoc_createComment,
3073 domdoc_createCDATASection,
3074 domdoc_createProcessingInstruction,
3075 domdoc_createAttribute,
3076 domdoc_createEntityReference,
3077 domdoc_getElementsByTagName,
3081 domdoc_get_readyState,
3082 domdoc_get_parseError,
3089 domdoc_get_validateOnParse,
3090 domdoc_put_validateOnParse,
3091 domdoc_get_resolveExternals,
3092 domdoc_put_resolveExternals,
3093 domdoc_get_preserveWhiteSpace,
3094 domdoc_put_preserveWhiteSpace,
3095 domdoc_put_onreadystatechange,
3096 domdoc_put_onDataAvailable,
3097 domdoc_put_onTransformNode,
3098 domdoc_get_namespaces,
3100 domdoc_putref_schemas,
3104 domdoc_validateNode,
3108 /* IConnectionPointContainer */
3109 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
3110 REFIID riid, void **ppv)
3112 domdoc *This = impl_from_IConnectionPointContainer(iface);
3113 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)This, riid, ppv);
3116 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
3118 domdoc *This = impl_from_IConnectionPointContainer(iface);
3119 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)This);
3122 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
3124 domdoc *This = impl_from_IConnectionPointContainer(iface);
3125 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)This);
3128 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
3129 IEnumConnectionPoints **ppEnum)
3131 domdoc *This = impl_from_IConnectionPointContainer(iface);
3132 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3136 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
3137 REFIID riid, IConnectionPoint **cp)
3139 domdoc *This = impl_from_IConnectionPointContainer(iface);
3140 ConnectionPoint *iter;
3142 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
3146 for(iter = This->cp_list; iter; iter = iter->next)
3148 if (IsEqualGUID(iter->iid, riid))
3149 *cp = (IConnectionPoint*)&iter->lpVtblConnectionPoint;
3154 IConnectionPoint_AddRef(*cp);
3158 FIXME("unsupported riid %s\n", debugstr_guid(riid));
3159 return CONNECT_E_NOCONNECTION;
3163 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
3165 ConnectionPointContainer_QueryInterface,
3166 ConnectionPointContainer_AddRef,
3167 ConnectionPointContainer_Release,
3168 ConnectionPointContainer_EnumConnectionPoints,
3169 ConnectionPointContainer_FindConnectionPoint
3172 /* IConnectionPoint */
3173 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
3174 REFIID riid, void **ppv)
3176 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3178 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3182 if (IsEqualGUID(&IID_IUnknown, riid) ||
3183 IsEqualGUID(&IID_IConnectionPoint, riid))
3190 IConnectionPoint_AddRef(iface);
3194 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3195 return E_NOINTERFACE;
3198 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3200 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3201 return IConnectionPointContainer_AddRef(This->container);
3204 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3206 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3207 return IConnectionPointContainer_Release(This->container);
3210 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3212 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3214 TRACE("(%p)->(%p)\n", This, iid);
3216 if (!iid) return E_POINTER;
3222 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3223 IConnectionPointContainer **container)
3225 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3227 TRACE("(%p)->(%p)\n", This, container);
3229 if (!container) return E_POINTER;
3231 *container = This->container;
3232 IConnectionPointContainer_AddRef(*container);
3236 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
3239 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3240 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
3244 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3246 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3248 TRACE("(%p)->(%d)\n", This, cookie);
3250 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3251 return CONNECT_E_NOCONNECTION;
3253 IUnknown_Release(This->sinks[cookie-1].unk);
3254 This->sinks[cookie-1].unk = NULL;
3259 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3260 IEnumConnections **ppEnum)
3262 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3263 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3267 static const IConnectionPointVtbl ConnectionPointVtbl =
3269 ConnectionPoint_QueryInterface,
3270 ConnectionPoint_AddRef,
3271 ConnectionPoint_Release,
3272 ConnectionPoint_GetConnectionInterface,
3273 ConnectionPoint_GetConnectionPointContainer,
3274 ConnectionPoint_Advise,
3275 ConnectionPoint_Unadvise,
3276 ConnectionPoint_EnumConnections
3279 void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3281 cp->lpVtblConnectionPoint = &ConnectionPointVtbl;
3287 cp->next = doc->cp_list;
3290 cp->container = (IConnectionPointContainer*)&doc->lpVtblConnectionPointContainer;
3293 /* domdoc implementation of IObjectWithSite */
3294 static HRESULT WINAPI
3295 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3297 domdoc *This = impl_from_IObjectWithSite(iface);
3298 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppvObject );
3301 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3303 domdoc *This = impl_from_IObjectWithSite(iface);
3304 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3307 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3309 domdoc *This = impl_from_IObjectWithSite(iface);
3310 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3313 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3315 domdoc *This = impl_from_IObjectWithSite(iface);
3317 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3322 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3325 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3327 domdoc *This = impl_from_IObjectWithSite(iface);
3329 TRACE("(%p)->(%p)\n", iface, punk);
3335 IUnknown_Release( This->site );
3342 IUnknown_AddRef( punk );
3345 IUnknown_Release( This->site );
3352 static const IObjectWithSiteVtbl domdocObjectSite =
3354 domdoc_ObjectWithSite_QueryInterface,
3355 domdoc_ObjectWithSite_AddRef,
3356 domdoc_ObjectWithSite_Release,
3357 domdoc_ObjectWithSite_SetSite,
3358 domdoc_ObjectWithSite_GetSite
3361 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3363 domdoc *This = impl_from_IObjectSafety(iface);
3364 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppv );
3367 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3369 domdoc *This = impl_from_IObjectSafety(iface);
3370 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3373 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3375 domdoc *This = impl_from_IObjectSafety(iface);
3376 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3379 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3381 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3382 DWORD *supported, DWORD *enabled)
3384 domdoc *This = impl_from_IObjectSafety(iface);
3386 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3388 if(!supported || !enabled) return E_POINTER;
3390 *supported = SAFETY_SUPPORTED_OPTIONS;
3391 *enabled = This->safeopt;
3396 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3397 DWORD mask, DWORD enabled)
3399 domdoc *This = impl_from_IObjectSafety(iface);
3400 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3402 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3405 This->safeopt = enabled & mask & SAFETY_SUPPORTED_OPTIONS;
3409 #undef SAFETY_SUPPORTED_OPTIONS
3411 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3412 domdoc_Safety_QueryInterface,
3413 domdoc_Safety_AddRef,
3414 domdoc_Safety_Release,
3415 domdoc_Safety_GetInterfaceSafetyOptions,
3416 domdoc_Safety_SetInterfaceSafetyOptions
3419 static const tid_t domdoc_iface_tids[] = {
3421 IXMLDOMDocument_tid,
3422 IXMLDOMDocument2_tid,
3425 static dispex_static_data_t domdoc_dispex = {
3427 IXMLDOMDocument2_tid,
3432 HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3436 doc = heap_alloc( sizeof (*doc) );
3438 return E_OUTOFMEMORY;
3440 doc->lpVtbl = &domdoc_vtbl;
3441 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
3442 doc->lpvtblIObjectWithSite = &domdocObjectSite;
3443 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
3444 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
3445 doc->lpVtblConnectionPointContainer = &ConnectionPointContainerVtbl;
3447 doc->async = VARIANT_TRUE;
3448 doc->validating = 0;
3450 doc->properties = properties_from_xmlDocPtr(xmldoc);
3456 doc->cp_list = NULL;
3457 memset(doc->events, 0, sizeof(doc->events));
3459 /* events connection points */
3460 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3461 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3462 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3464 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->lpVtbl, &domdoc_dispex);
3466 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
3468 TRACE("returning iface %p\n", *document);
3472 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3477 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
3479 xmldoc = xmlNewDoc(NULL);
3481 return E_OUTOFMEMORY;
3483 xmldoc->_private = create_priv();
3484 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
3486 hr = get_domdoc_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3489 free_properties(properties_from_xmlDocPtr(xmldoc));
3490 heap_free(xmldoc->_private);
3498 IUnknown* create_domdoc( xmlNodePtr document )
3503 TRACE("(%p)\n", document);
3505 hr = get_domdoc_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3514 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3516 MESSAGE("This program tried to use a DOMDocument object, but\n"
3517 "libxml2 support was not present at compile time.\n");