2 * DOM Document implementation
4 * Copyright 2005 Mike McCormack
5 * Copyright 2010-2011 Adam Martinson for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define NONAMELESSUNION
30 # include <libxml/parser.h>
31 # include <libxml/xmlerror.h>
32 # include <libxml/xpathInternals.h>
33 # include <libxml/xmlsave.h>
34 # include <libxml/SAX2.h>
35 # include <libxml/parserInternals.h>
52 #include "wine/debug.h"
53 #include "wine/list.h"
55 #include "msxml_private.h"
57 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
61 /* not defined in older versions */
62 #define XML_SAVE_FORMAT 1
63 #define XML_SAVE_NO_DECL 2
64 #define XML_SAVE_NO_EMPTY 4
65 #define XML_SAVE_NO_XHTML 8
66 #define XML_SAVE_XHTML 16
67 #define XML_SAVE_AS_XML 32
68 #define XML_SAVE_AS_HTML 64
70 static const WCHAR PropertySelectionLanguageW[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
71 static const WCHAR PropertySelectionNamespacesW[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
72 static const WCHAR PropertyProhibitDTDW[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
73 static const WCHAR PropertyNewParserW[] = {'N','e','w','P','a','r','s','e','r',0};
74 static const WCHAR PropValueXPathW[] = {'X','P','a','t','h',0};
75 static const WCHAR PropValueXSLPatternW[] = {'X','S','L','P','a','t','t','e','r','n',0};
76 static const WCHAR PropertyResolveExternalsW[] = {'R','e','s','o','l','v','e','E','x','t','e','r','n','a','l','s',0};
78 /* Anything that passes the test_get_ownerDocument()
79 * tests can go here (data shared between all instances).
80 * We need to preserve this when reloading a document,
81 * and also need access to it from the libxml backend. */
82 typedef struct _domdoc_properties {
83 MSXML_VERSION version;
84 VARIANT_BOOL preserving;
85 IXMLDOMSchemaCollection2* schemaCache;
86 struct list selectNsList;
87 xmlChar const* selectNsStr;
92 typedef struct ConnectionPoint ConnectionPoint;
93 typedef struct domdoc domdoc;
95 struct ConnectionPoint
97 IConnectionPoint IConnectionPoint_iface;
100 ConnectionPoint *next;
101 IConnectionPointContainer *container;
108 IPropertyNotifySink *propnotif;
114 EVENTID_READYSTATECHANGE = 0,
115 EVENTID_DATAAVAILABLE,
116 EVENTID_TRANSFORMNODE,
123 IXMLDOMDocument3 IXMLDOMDocument3_iface;
124 IPersistStreamInit IPersistStreamInit_iface;
125 IObjectWithSite IObjectWithSite_iface;
126 IObjectSafety IObjectSafety_iface;
127 ISupportErrorInfo ISupportErrorInfo_iface;
128 IConnectionPointContainer IConnectionPointContainer_iface;
131 VARIANT_BOOL validating;
132 VARIANT_BOOL resolving;
133 domdoc_properties* properties;
146 /* connection list */
147 ConnectionPoint *cp_list;
148 ConnectionPoint cp_domdocevents;
149 ConnectionPoint cp_propnotif;
150 ConnectionPoint cp_dispatch;
153 IDispatch *events[EVENTID_LAST];
156 static HRESULT set_doc_event(domdoc *doc, eventid_t eid, const VARIANT *v)
164 IUnknown_QueryInterface(V_UNKNOWN(v), &IID_IDispatch, (void**)&disp);
169 disp = V_DISPATCH(v);
170 if (disp) IDispatch_AddRef(disp);
173 return DISP_E_TYPEMISMATCH;
176 if (doc->events[eid]) IDispatch_Release(doc->events[eid]);
177 doc->events[eid] = disp;
182 static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface)
184 return CONTAINING_RECORD(iface, ConnectionPoint, IConnectionPoint_iface);
188 In native windows, the whole lifetime management of XMLDOMNodes is
189 managed automatically using reference counts. Wine emulates that by
190 maintaining a reference count to the document that is increased for
191 each IXMLDOMNode pointer passed out for this document. If all these
192 pointers are gone, the document is unreachable and gets freed, that
193 is, all nodes in the tree of the document get freed.
195 You are able to create nodes that are associated to a document (in
196 fact, in msxml's XMLDOM model, all nodes are associated to a document),
197 but not in the tree of that document, for example using the createFoo
198 functions from IXMLDOMDocument. These nodes do not get cleaned up
199 by libxml, so we have to do it ourselves.
201 To catch these nodes, a list of "orphan nodes" is introduced.
202 It contains pointers to all roots of node trees that are
203 associated with the document without being part of the document
204 tree. All nodes with parent==NULL (except for the document root nodes)
205 should be in the orphan node list of their document. All orphan nodes
206 get freed together with the document itself.
209 typedef struct _xmldoc_priv {
212 domdoc_properties* properties;
215 typedef struct _orphan_entry {
220 typedef struct _select_ns_entry {
222 xmlChar const* prefix;
228 static inline xmldoc_priv * priv_from_xmlDocPtr(const xmlDocPtr doc)
230 return doc->_private;
233 static inline domdoc_properties * properties_from_xmlDocPtr(xmlDocPtr doc)
235 return priv_from_xmlDocPtr(doc)->properties;
238 BOOL is_xpathmode(const xmlDocPtr doc)
240 return properties_from_xmlDocPtr(doc)->XPath;
243 void set_xpathmode(xmlDocPtr doc, BOOL xpath)
245 properties_from_xmlDocPtr(doc)->XPath = xpath;
248 int registerNamespaces(xmlXPathContextPtr ctxt)
251 const select_ns_entry* ns = NULL;
252 const struct list* pNsList = &properties_from_xmlDocPtr(ctxt->doc)->selectNsList;
254 TRACE("(%p)\n", ctxt);
256 LIST_FOR_EACH_ENTRY( ns, pNsList, select_ns_entry, entry )
258 xmlXPathRegisterNs(ctxt, ns->prefix, ns->href);
265 static inline void clear_selectNsList(struct list* pNsList)
267 select_ns_entry *ns, *ns2;
268 LIST_FOR_EACH_ENTRY_SAFE( ns, ns2, pNsList, select_ns_entry, entry )
275 static xmldoc_priv * create_priv(void)
278 priv = heap_alloc( sizeof (*priv) );
283 list_init( &priv->orphans );
284 priv->properties = NULL;
290 static domdoc_properties * create_properties(const GUID *clsid)
292 domdoc_properties *properties = heap_alloc(sizeof(domdoc_properties));
294 list_init(&properties->selectNsList);
295 properties->preserving = VARIANT_FALSE;
296 properties->schemaCache = NULL;
297 properties->selectNsStr = heap_alloc_zero(sizeof(xmlChar));
298 properties->selectNsStr_len = 0;
300 /* properties that are dependent on object versions */
301 if (IsEqualCLSID(clsid, &CLSID_DOMDocument30))
303 properties->version = MSXML3;
304 properties->XPath = FALSE;
306 else if (IsEqualCLSID(clsid, &CLSID_DOMDocument40))
308 properties->version = MSXML4;
309 properties->XPath = TRUE;
311 else if (IsEqualCLSID(clsid, &CLSID_DOMDocument60))
313 properties->version = MSXML6;
314 properties->XPath = TRUE;
318 properties->version = MSXML_DEFAULT;
319 properties->XPath = FALSE;
325 static domdoc_properties* copy_properties(domdoc_properties const* properties)
327 domdoc_properties* pcopy = heap_alloc(sizeof(domdoc_properties));
328 select_ns_entry const* ns = NULL;
329 select_ns_entry* new_ns = NULL;
330 int len = (properties->selectNsStr_len+1)*sizeof(xmlChar);
335 pcopy->version = properties->version;
336 pcopy->preserving = properties->preserving;
337 pcopy->schemaCache = properties->schemaCache;
338 if (pcopy->schemaCache)
339 IXMLDOMSchemaCollection2_AddRef(pcopy->schemaCache);
340 pcopy->XPath = properties->XPath;
341 pcopy->selectNsStr_len = properties->selectNsStr_len;
342 list_init( &pcopy->selectNsList );
343 pcopy->selectNsStr = heap_alloc(len);
344 memcpy((xmlChar*)pcopy->selectNsStr, properties->selectNsStr, len);
345 offset = pcopy->selectNsStr - properties->selectNsStr;
347 LIST_FOR_EACH_ENTRY( ns, (&properties->selectNsList), select_ns_entry, entry )
349 new_ns = heap_alloc(sizeof(select_ns_entry));
350 memcpy(new_ns, ns, sizeof(select_ns_entry));
351 new_ns->href += offset;
352 new_ns->prefix += offset;
353 list_add_tail(&pcopy->selectNsList, &new_ns->entry);
361 static void free_properties(domdoc_properties* properties)
365 if (properties->schemaCache)
366 IXMLDOMSchemaCollection2_Release(properties->schemaCache);
367 clear_selectNsList(&properties->selectNsList);
368 heap_free((xmlChar*)properties->selectNsStr);
369 heap_free(properties);
373 /* links a "<?xml" node as a first child */
374 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
377 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
380 /* unlinks a first "<?xml" child if it was created */
381 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
387 if (doc->standalone != -1)
389 node = doc->children;
390 xmlUnlinkNode( node );
398 BOOL is_preserving_whitespace(xmlNodePtr node)
400 domdoc_properties* properties = NULL;
401 /* during parsing the xmlDoc._private stuff is not there */
402 if (priv_from_xmlDocPtr(node->doc))
403 properties = properties_from_xmlDocPtr(node->doc);
404 return ((properties && properties->preserving == VARIANT_TRUE) ||
405 xmlNodeGetSpacePreserve(node) == 1);
408 static inline BOOL strn_isspace(xmlChar const* str, int len)
410 for (; str && len > 0 && *str; ++str, --len)
417 static void sax_characters(void *ctx, const xmlChar *ch, int len)
419 xmlParserCtxtPtr ctxt;
422 ctxt = (xmlParserCtxtPtr) ctx;
423 This = (const domdoc*) ctxt->_private;
427 /* during domdoc_loadXML() the xmlDocPtr->_private data is not available */
428 if (!This->properties->preserving &&
429 !is_preserving_whitespace(ctxt->node) &&
430 strn_isspace(ch, len))
434 xmlSAX2Characters(ctxt, ch, len);
437 static void LIBXML2_LOG_CALLBACK sax_error(void* ctx, char const* msg, ...)
441 LIBXML2_CALLBACK_ERR(doparse, msg, ap);
445 static void LIBXML2_LOG_CALLBACK sax_warning(void* ctx, char const* msg, ...)
449 LIBXML2_CALLBACK_WARN(doparse, msg, ap);
453 static void sax_serror(void* ctx, xmlErrorPtr err)
455 LIBXML2_CALLBACK_SERROR(doparse, err);
458 static xmlDocPtr doparse(domdoc* This, char *ptr, int len, xmlChar const* encoding)
460 xmlDocPtr doc = NULL;
461 xmlParserCtxtPtr pctx;
462 static xmlSAXHandler sax_handler = {
463 xmlSAX2InternalSubset, /* internalSubset */
464 xmlSAX2IsStandalone, /* isStandalone */
465 xmlSAX2HasInternalSubset, /* hasInternalSubset */
466 xmlSAX2HasExternalSubset, /* hasExternalSubset */
467 xmlSAX2ResolveEntity, /* resolveEntity */
468 xmlSAX2GetEntity, /* getEntity */
469 xmlSAX2EntityDecl, /* entityDecl */
470 xmlSAX2NotationDecl, /* notationDecl */
471 xmlSAX2AttributeDecl, /* attributeDecl */
472 xmlSAX2ElementDecl, /* elementDecl */
473 xmlSAX2UnparsedEntityDecl, /* unparsedEntityDecl */
474 xmlSAX2SetDocumentLocator, /* setDocumentLocator */
475 xmlSAX2StartDocument, /* startDocument */
476 xmlSAX2EndDocument, /* endDocument */
477 xmlSAX2StartElement, /* startElement */
478 xmlSAX2EndElement, /* endElement */
479 xmlSAX2Reference, /* reference */
480 sax_characters, /* characters */
481 sax_characters, /* ignorableWhitespace */
482 xmlSAX2ProcessingInstruction, /* processingInstruction */
483 xmlSAX2Comment, /* comment */
484 sax_warning, /* warning */
485 sax_error, /* error */
486 sax_error, /* fatalError */
487 xmlSAX2GetParameterEntity, /* getParameterEntity */
488 xmlSAX2CDataBlock, /* cdataBlock */
489 xmlSAX2ExternalSubset, /* externalSubset */
492 xmlSAX2StartElementNs, /* startElementNs */
493 xmlSAX2EndElementNs, /* endElementNs */
494 sax_serror /* serror */
498 pctx = xmlCreateMemoryParserCtxt(ptr, len);
501 ERR("Failed to create parser context\n");
505 if (pctx->sax) xmlFree(pctx->sax);
506 pctx->sax = &sax_handler;
507 pctx->_private = This;
509 pctx->encoding = xmlStrdup(encoding);
510 xmlParseDocument(pctx);
512 if (pctx->wellFormed)
518 xmlFreeDoc(pctx->myDoc);
522 xmlFreeParserCtxt(pctx);
524 /* TODO: put this in one of the SAX callbacks */
525 /* create first child as a <?xml...?> */
526 if (doc && doc->standalone != -1)
530 xmlChar *xmlbuff = (xmlChar*)buff;
532 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
534 /* version attribute can't be omitted */
535 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
536 xmlNodeAddContent( node, xmlbuff );
540 sprintf(buff, " encoding=\"%s\"", doc->encoding);
541 xmlNodeAddContent( node, xmlbuff );
544 if (doc->standalone != -2)
546 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
547 xmlNodeAddContent( node, xmlbuff );
550 xmldoc_link_xmldecl( doc, node );
556 void xmldoc_init(xmlDocPtr doc, const GUID *clsid)
558 doc->_private = create_priv();
559 priv_from_xmlDocPtr(doc)->properties = create_properties(clsid);
562 LONG xmldoc_add_ref(xmlDocPtr doc)
564 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
565 TRACE("(%p)->(%d)\n", doc, ref);
569 LONG xmldoc_release(xmlDocPtr doc)
571 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
572 LONG ref = InterlockedDecrement(&priv->refs);
573 TRACE("(%p)->(%d)\n", doc, ref);
576 orphan_entry *orphan, *orphan2;
577 TRACE("freeing docptr %p\n", doc);
579 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
581 xmlFreeNode( orphan->node );
584 free_properties(priv->properties);
585 heap_free(doc->_private);
593 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
595 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
598 entry = heap_alloc( sizeof (*entry) );
600 return E_OUTOFMEMORY;
603 list_add_head( &priv->orphans, &entry->entry );
607 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
609 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
610 orphan_entry *entry, *entry2;
612 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
614 if( entry->node == node )
616 list_remove( &entry->entry );
625 static inline xmlDocPtr get_doc( domdoc *This )
627 return (xmlDocPtr)This->node.node;
630 static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
634 priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
635 if (xmldoc_release(get_doc(This)) != 0)
636 priv_from_xmlDocPtr(get_doc(This))->properties =
637 copy_properties(This->properties);
640 This->node.node = (xmlNodePtr) xml;
644 xmldoc_add_ref(get_doc(This));
645 priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
651 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
653 return CONTAINING_RECORD(iface, domdoc, IXMLDOMDocument3_iface);
656 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
658 return CONTAINING_RECORD(iface, domdoc, IPersistStreamInit_iface);
661 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
663 return CONTAINING_RECORD(iface, domdoc, IObjectWithSite_iface);
666 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
668 return CONTAINING_RECORD(iface, domdoc, IObjectSafety_iface);
671 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
673 return CONTAINING_RECORD(iface, domdoc, ISupportErrorInfo_iface);
676 static inline domdoc *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
678 return CONTAINING_RECORD(iface, domdoc, IConnectionPointContainer_iface);
681 /************************************************************************
682 * domdoc implementation of IPersistStream.
684 static HRESULT WINAPI domdoc_IPersistStreamInit_QueryInterface(
685 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
687 domdoc* This = impl_from_IPersistStreamInit(iface);
688 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppvObj);
691 static ULONG WINAPI domdoc_IPersistStreamInit_AddRef(
692 IPersistStreamInit *iface)
694 domdoc* This = impl_from_IPersistStreamInit(iface);
695 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
698 static ULONG WINAPI domdoc_IPersistStreamInit_Release(
699 IPersistStreamInit *iface)
701 domdoc* This = impl_from_IPersistStreamInit(iface);
702 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
705 static HRESULT WINAPI domdoc_IPersistStreamInit_GetClassID(
706 IPersistStreamInit *iface, CLSID *classid)
708 domdoc* This = impl_from_IPersistStreamInit(iface);
709 TRACE("(%p)->(%p)\n", This, classid);
714 *classid = *DOMDocument_version(This->properties->version);
719 static HRESULT WINAPI domdoc_IPersistStreamInit_IsDirty(
720 IPersistStreamInit *iface)
722 domdoc *This = impl_from_IPersistStreamInit(iface);
723 FIXME("(%p): stub!\n", This);
727 static HRESULT WINAPI domdoc_IPersistStreamInit_Load(
728 IPersistStreamInit *iface, LPSTREAM pStm)
730 domdoc *This = impl_from_IPersistStreamInit(iface);
733 DWORD read, written, len;
736 xmlDocPtr xmldoc = NULL;
738 TRACE("(%p)->(%p)\n", This, pStm);
743 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
749 IStream_Read(pStm, buf, sizeof(buf), &read);
750 hr = IStream_Write(This->stream, buf, read, &written);
751 } while(SUCCEEDED(hr) && written != 0 && read != 0);
755 ERR("Failed to copy stream\n");
759 hr = GetHGlobalFromStream(This->stream, &hglobal);
763 len = GlobalSize(hglobal);
764 ptr = GlobalLock(hglobal);
766 xmldoc = doparse(This, ptr, len, NULL);
767 GlobalUnlock(hglobal);
771 ERR("Failed to parse xml\n");
775 xmldoc->_private = create_priv();
777 return attach_xmldoc(This, xmldoc);
780 static HRESULT WINAPI domdoc_IPersistStreamInit_Save(
781 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
783 domdoc *This = impl_from_IPersistStreamInit(iface);
787 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
789 hr = IXMLDOMDocument3_get_xml(&This->IXMLDOMDocument3_iface, &xmlString);
792 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
794 hr = IStream_Write( stream, xmlString, len, NULL );
795 SysFreeString(xmlString);
798 TRACE("ret 0x%08x\n", hr);
803 static HRESULT WINAPI domdoc_IPersistStreamInit_GetSizeMax(
804 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
806 domdoc *This = impl_from_IPersistStreamInit(iface);
807 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
811 static HRESULT WINAPI domdoc_IPersistStreamInit_InitNew(
812 IPersistStreamInit *iface)
814 domdoc *This = impl_from_IPersistStreamInit(iface);
815 TRACE("(%p)\n", This);
819 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
821 domdoc_IPersistStreamInit_QueryInterface,
822 domdoc_IPersistStreamInit_AddRef,
823 domdoc_IPersistStreamInit_Release,
824 domdoc_IPersistStreamInit_GetClassID,
825 domdoc_IPersistStreamInit_IsDirty,
826 domdoc_IPersistStreamInit_Load,
827 domdoc_IPersistStreamInit_Save,
828 domdoc_IPersistStreamInit_GetSizeMax,
829 domdoc_IPersistStreamInit_InitNew
832 /* ISupportErrorInfo interface */
833 static HRESULT WINAPI support_error_QueryInterface(
834 ISupportErrorInfo *iface,
835 REFIID riid, void** ppvObj )
837 domdoc *This = impl_from_ISupportErrorInfo(iface);
838 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppvObj);
841 static ULONG WINAPI support_error_AddRef(
842 ISupportErrorInfo *iface )
844 domdoc *This = impl_from_ISupportErrorInfo(iface);
845 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
848 static ULONG WINAPI support_error_Release(
849 ISupportErrorInfo *iface )
851 domdoc *This = impl_from_ISupportErrorInfo(iface);
852 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
855 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
856 ISupportErrorInfo *iface,
859 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
863 static const struct ISupportErrorInfoVtbl support_error_vtbl =
865 support_error_QueryInterface,
866 support_error_AddRef,
867 support_error_Release,
868 support_error_InterfaceSupportsErrorInfo
871 /* IXMLDOMDocument2 interface */
872 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
874 domdoc *This = impl_from_IXMLDOMDocument3( iface );
876 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
880 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
881 IsEqualGUID( riid, &IID_IDispatch ) ||
882 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
883 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
884 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
885 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
889 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
890 IsEqualGUID(&IID_IPersistStreamInit, riid))
892 *ppvObject = &This->IPersistStreamInit_iface;
894 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
896 *ppvObject = &This->IObjectWithSite_iface;
898 else if (IsEqualGUID(&IID_IObjectSafety, riid))
900 *ppvObject = &This->IObjectSafety_iface;
902 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
904 *ppvObject = &This->ISupportErrorInfo_iface;
906 else if(node_query_interface(&This->node, riid, ppvObject))
908 return *ppvObject ? S_OK : E_NOINTERFACE;
910 else if (IsEqualGUID( riid, &IID_IConnectionPointContainer ))
912 *ppvObject = &This->IConnectionPointContainer_iface;
916 TRACE("interface %s not implemented\n", debugstr_guid(riid));
917 return E_NOINTERFACE;
920 IUnknown_AddRef((IUnknown*)*ppvObject);
926 static ULONG WINAPI domdoc_AddRef(
927 IXMLDOMDocument3 *iface )
929 domdoc *This = impl_from_IXMLDOMDocument3( iface );
930 ULONG ref = InterlockedIncrement( &This->ref );
931 TRACE("(%p)->(%d)\n", This, ref );
936 static ULONG WINAPI domdoc_Release(
937 IXMLDOMDocument3 *iface )
939 domdoc *This = impl_from_IXMLDOMDocument3( iface );
940 LONG ref = InterlockedDecrement( &This->ref );
942 TRACE("(%p)->(%d)\n", This, ref );
949 detach_bsc(This->bsc);
952 IUnknown_Release( This->site );
953 destroy_xmlnode(&This->node);
955 IStream_Release(This->stream);
957 for (eid = 0; eid < EVENTID_LAST; eid++)
958 if (This->events[eid]) IDispatch_Release(This->events[eid]);
966 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
968 domdoc *This = impl_from_IXMLDOMDocument3( iface );
970 TRACE("(%p)->(%p)\n", This, pctinfo);
977 static HRESULT WINAPI domdoc_GetTypeInfo(
978 IXMLDOMDocument3 *iface,
979 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
981 domdoc *This = impl_from_IXMLDOMDocument3( iface );
984 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
986 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
991 static HRESULT WINAPI domdoc_GetIDsOfNames(
992 IXMLDOMDocument3 *iface,
999 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1000 ITypeInfo *typeinfo;
1003 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1006 if(!rgszNames || cNames == 0 || !rgDispId)
1007 return E_INVALIDARG;
1009 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
1012 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1013 ITypeInfo_Release(typeinfo);
1020 static HRESULT WINAPI domdoc_Invoke(
1021 IXMLDOMDocument3 *iface,
1022 DISPID dispIdMember,
1026 DISPPARAMS* pDispParams,
1027 VARIANT* pVarResult,
1028 EXCEPINFO* pExcepInfo,
1031 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1032 ITypeInfo *typeinfo;
1035 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1036 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1038 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
1041 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMDocument3_iface, dispIdMember, wFlags,
1042 pDispParams, pVarResult, pExcepInfo, puArgErr);
1043 ITypeInfo_Release(typeinfo);
1050 static HRESULT WINAPI domdoc_get_nodeName(
1051 IXMLDOMDocument3 *iface,
1054 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1056 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
1058 TRACE("(%p)->(%p)\n", This, name);
1060 return return_bstr(documentW, name);
1064 static HRESULT WINAPI domdoc_get_nodeValue(
1065 IXMLDOMDocument3 *iface,
1068 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1070 TRACE("(%p)->(%p)\n", This, value);
1073 return E_INVALIDARG;
1075 V_VT(value) = VT_NULL;
1076 V_BSTR(value) = NULL; /* tests show that we should do this */
1081 static HRESULT WINAPI domdoc_put_nodeValue(
1082 IXMLDOMDocument3 *iface,
1085 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1086 TRACE("(%p)->(v%d)\n", This, V_VT(&value));
1091 static HRESULT WINAPI domdoc_get_nodeType(
1092 IXMLDOMDocument3 *iface,
1095 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1097 TRACE("(%p)->(%p)\n", This, type);
1099 *type = NODE_DOCUMENT;
1104 static HRESULT WINAPI domdoc_get_parentNode(
1105 IXMLDOMDocument3 *iface,
1106 IXMLDOMNode** parent )
1108 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1110 TRACE("(%p)->(%p)\n", This, parent);
1112 return node_get_parent(&This->node, parent);
1116 static HRESULT WINAPI domdoc_get_childNodes(
1117 IXMLDOMDocument3 *iface,
1118 IXMLDOMNodeList** childList )
1120 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1122 TRACE("(%p)->(%p)\n", This, childList);
1124 return node_get_child_nodes(&This->node, childList);
1128 static HRESULT WINAPI domdoc_get_firstChild(
1129 IXMLDOMDocument3 *iface,
1130 IXMLDOMNode** firstChild )
1132 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1134 TRACE("(%p)->(%p)\n", This, firstChild);
1136 return node_get_first_child(&This->node, firstChild);
1140 static HRESULT WINAPI domdoc_get_lastChild(
1141 IXMLDOMDocument3 *iface,
1142 IXMLDOMNode** lastChild )
1144 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1146 TRACE("(%p)->(%p)\n", This, lastChild);
1148 return node_get_last_child(&This->node, lastChild);
1152 static HRESULT WINAPI domdoc_get_previousSibling(
1153 IXMLDOMDocument3 *iface,
1154 IXMLDOMNode** previousSibling )
1156 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1158 TRACE("(%p)->(%p)\n", This, previousSibling);
1160 return return_null_node(previousSibling);
1164 static HRESULT WINAPI domdoc_get_nextSibling(
1165 IXMLDOMDocument3 *iface,
1166 IXMLDOMNode** nextSibling )
1168 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1170 TRACE("(%p)->(%p)\n", This, nextSibling);
1172 return return_null_node(nextSibling);
1176 static HRESULT WINAPI domdoc_get_attributes(
1177 IXMLDOMDocument3 *iface,
1178 IXMLDOMNamedNodeMap** attributeMap )
1180 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1182 TRACE("(%p)->(%p)\n", This, attributeMap);
1184 return return_null_ptr((void**)attributeMap);
1188 static HRESULT WINAPI domdoc_insertBefore(
1189 IXMLDOMDocument3 *iface,
1190 IXMLDOMNode* newChild,
1192 IXMLDOMNode** outNewChild )
1194 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1196 TRACE("(%p)->(%p x%d %p)\n", This, newChild, V_VT(&refChild), outNewChild);
1198 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1202 static HRESULT WINAPI domdoc_replaceChild(
1203 IXMLDOMDocument3 *iface,
1204 IXMLDOMNode* newChild,
1205 IXMLDOMNode* oldChild,
1206 IXMLDOMNode** outOldChild)
1208 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1210 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1212 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1216 static HRESULT WINAPI domdoc_removeChild(
1217 IXMLDOMDocument3 *iface,
1219 IXMLDOMNode **oldChild)
1221 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1222 TRACE("(%p)->(%p %p)\n", This, child, oldChild);
1223 return node_remove_child(&This->node, child, oldChild);
1227 static HRESULT WINAPI domdoc_appendChild(
1228 IXMLDOMDocument3 *iface,
1230 IXMLDOMNode **outChild)
1232 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1233 TRACE("(%p)->(%p %p)\n", This, child, outChild);
1234 return node_append_child(&This->node, child, outChild);
1238 static HRESULT WINAPI domdoc_hasChildNodes(
1239 IXMLDOMDocument3 *iface,
1242 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1243 TRACE("(%p)->(%p)\n", This, ret);
1244 return node_has_childnodes(&This->node, ret);
1248 static HRESULT WINAPI domdoc_get_ownerDocument(
1249 IXMLDOMDocument3 *iface,
1250 IXMLDOMDocument **doc)
1252 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1253 TRACE("(%p)->(%p)\n", This, doc);
1254 return node_get_owner_doc(&This->node, doc);
1258 static HRESULT WINAPI domdoc_cloneNode(
1259 IXMLDOMDocument3 *iface,
1261 IXMLDOMNode** outNode)
1263 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1264 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
1265 return node_clone( &This->node, deep, outNode );
1269 static HRESULT WINAPI domdoc_get_nodeTypeString(
1270 IXMLDOMDocument3 *iface,
1273 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1274 static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
1276 TRACE("(%p)->(%p)\n", This, p);
1278 return return_bstr(documentW, p);
1282 static HRESULT WINAPI domdoc_get_text(
1283 IXMLDOMDocument3 *iface,
1286 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1287 TRACE("(%p)->(%p)\n", This, p);
1288 return node_get_text(&This->node, p);
1292 static HRESULT WINAPI domdoc_put_text(
1293 IXMLDOMDocument3 *iface,
1296 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1297 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1302 static HRESULT WINAPI domdoc_get_specified(
1303 IXMLDOMDocument3 *iface,
1304 VARIANT_BOOL* isSpecified )
1306 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1307 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1308 *isSpecified = VARIANT_TRUE;
1313 static HRESULT WINAPI domdoc_get_definition(
1314 IXMLDOMDocument3 *iface,
1315 IXMLDOMNode** definitionNode )
1317 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1318 FIXME("(%p)->(%p)\n", This, definitionNode);
1323 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1324 IXMLDOMDocument3 *iface,
1327 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1328 TRACE("(%p)->(%p)\n", This, v);
1329 return return_null_var(v);
1332 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1333 IXMLDOMDocument3 *iface,
1334 VARIANT typedValue )
1336 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1337 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1342 static HRESULT WINAPI domdoc_get_dataType(
1343 IXMLDOMDocument3 *iface,
1346 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1347 TRACE("(%p)->(%p)\n", This, typename);
1348 return return_null_var( typename );
1352 static HRESULT WINAPI domdoc_put_dataType(
1353 IXMLDOMDocument3 *iface,
1356 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1358 FIXME("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
1361 return E_INVALIDARG;
1366 static int XMLCALL domdoc_get_xml_writecallback(void *ctx, const char *data, int len)
1368 return xmlBufferAdd((xmlBufferPtr)ctx, (xmlChar*)data, len) == 0 ? len : 0;
1371 static HRESULT WINAPI domdoc_get_xml(
1372 IXMLDOMDocument3 *iface,
1375 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1376 xmlSaveCtxtPtr ctxt;
1381 TRACE("(%p)->(%p)\n", This, p);
1384 return E_INVALIDARG;
1388 buf = xmlBufferCreate();
1390 return E_OUTOFMEMORY;
1392 options = XML_SAVE_FORMAT | XML_SAVE_NO_DECL;
1393 ctxt = xmlSaveToIO(domdoc_get_xml_writecallback, NULL, buf, "UTF-8", options);
1398 return E_OUTOFMEMORY;
1401 ret = xmlSaveDoc(ctxt, get_doc(This));
1402 /* flushes on close */
1405 TRACE("%ld, len=%d\n", ret, xmlBufferLength(buf));
1406 if(ret != -1 && xmlBufferLength(buf) > 0)
1410 content = bstr_from_xmlChar(xmlBufferContent(buf));
1411 content = EnsureCorrectEOL(content);
1417 *p = SysAllocStringLen(NULL, 0);
1422 return *p ? S_OK : E_OUTOFMEMORY;
1426 static HRESULT WINAPI domdoc_transformNode(
1427 IXMLDOMDocument3 *iface,
1431 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1432 TRACE("(%p)->(%p %p)\n", This, node, p);
1433 return node_transform_node(&This->node, node, p);
1437 static HRESULT WINAPI domdoc_selectNodes(
1438 IXMLDOMDocument3 *iface,
1440 IXMLDOMNodeList **outList)
1442 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1443 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList);
1444 return node_select_nodes(&This->node, p, outList);
1448 static HRESULT WINAPI domdoc_selectSingleNode(
1449 IXMLDOMDocument3 *iface,
1451 IXMLDOMNode **outNode)
1453 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1454 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode);
1455 return node_select_singlenode(&This->node, p, outNode);
1459 static HRESULT WINAPI domdoc_get_parsed(
1460 IXMLDOMDocument3 *iface,
1461 VARIANT_BOOL* isParsed )
1463 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1464 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1465 *isParsed = VARIANT_TRUE;
1470 static HRESULT WINAPI domdoc_get_namespaceURI(
1471 IXMLDOMDocument3 *iface,
1472 BSTR* namespaceURI )
1474 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1475 TRACE("(%p)->(%p)\n", This, namespaceURI);
1476 return node_get_namespaceURI(&This->node, namespaceURI);
1480 static HRESULT WINAPI domdoc_get_prefix(
1481 IXMLDOMDocument3 *iface,
1484 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1485 TRACE("(%p)->(%p)\n", This, prefix);
1486 return return_null_bstr( prefix );
1490 static HRESULT WINAPI domdoc_get_baseName(
1491 IXMLDOMDocument3 *iface,
1494 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1495 TRACE("(%p)->(%p)\n", This, name);
1496 return return_null_bstr( name );
1500 static HRESULT WINAPI domdoc_transformNodeToObject(
1501 IXMLDOMDocument3 *iface,
1502 IXMLDOMNode* stylesheet,
1503 VARIANT outputObject)
1505 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1506 FIXME("(%p)->(%p %s)\n", This, stylesheet, debugstr_variant(&outputObject));
1511 static HRESULT WINAPI domdoc_get_doctype(
1512 IXMLDOMDocument3 *iface,
1513 IXMLDOMDocumentType** doctype )
1515 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1520 TRACE("(%p)->(%p)\n", This, doctype);
1522 if (!doctype) return E_INVALIDARG;
1526 dtd = xmlGetIntSubset(get_doc(This));
1527 if (!dtd) return S_FALSE;
1529 node = create_node((xmlNodePtr)dtd);
1530 if (!node) return S_FALSE;
1532 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentType, (void**)doctype);
1533 IXMLDOMNode_Release(node);
1539 static HRESULT WINAPI domdoc_get_implementation(
1540 IXMLDOMDocument3 *iface,
1541 IXMLDOMImplementation** impl )
1543 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1545 TRACE("(%p)->(%p)\n", This, impl);
1548 return E_INVALIDARG;
1550 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1555 static HRESULT WINAPI domdoc_get_documentElement(
1556 IXMLDOMDocument3 *iface,
1557 IXMLDOMElement** DOMElement )
1559 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1560 IXMLDOMNode *element_node;
1564 TRACE("(%p)->(%p)\n", This, DOMElement);
1567 return E_INVALIDARG;
1571 root = xmlDocGetRootElement( get_doc(This) );
1575 element_node = create_node( root );
1576 if(!element_node) return S_FALSE;
1578 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1579 IXMLDOMNode_Release(element_node);
1585 static HRESULT WINAPI domdoc_put_documentElement(
1586 IXMLDOMDocument3 *iface,
1587 IXMLDOMElement* DOMElement )
1589 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1590 IXMLDOMNode *elementNode;
1595 TRACE("(%p)->(%p)\n", This, DOMElement);
1597 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1601 xmlNode = get_node_obj( elementNode );
1602 if(!xmlNode) return E_FAIL;
1604 if(!xmlNode->node->parent)
1605 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1606 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1608 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1609 IXMLDOMNode_Release( elementNode );
1612 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1618 static HRESULT WINAPI domdoc_createElement(
1619 IXMLDOMDocument3 *iface,
1621 IXMLDOMElement** element )
1623 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1628 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1630 if (!element || !tagname) return E_INVALIDARG;
1632 V_VT(&type) = VT_I1;
1633 V_I1(&type) = NODE_ELEMENT;
1635 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1638 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1639 IXMLDOMNode_Release(node);
1646 static HRESULT WINAPI domdoc_createDocumentFragment(
1647 IXMLDOMDocument3 *iface,
1648 IXMLDOMDocumentFragment** frag )
1650 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1655 TRACE("(%p)->(%p)\n", This, frag);
1657 if (!frag) return E_INVALIDARG;
1661 V_VT(&type) = VT_I1;
1662 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1664 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1667 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1668 IXMLDOMNode_Release(node);
1675 static HRESULT WINAPI domdoc_createTextNode(
1676 IXMLDOMDocument3 *iface,
1678 IXMLDOMText** text )
1680 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1685 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1687 if (!text) return E_INVALIDARG;
1691 V_VT(&type) = VT_I1;
1692 V_I1(&type) = NODE_TEXT;
1694 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1697 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1698 IXMLDOMNode_Release(node);
1699 hr = IXMLDOMText_put_data(*text, data);
1706 static HRESULT WINAPI domdoc_createComment(
1707 IXMLDOMDocument3 *iface,
1709 IXMLDOMComment** comment )
1711 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1716 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1718 if (!comment) return E_INVALIDARG;
1722 V_VT(&type) = VT_I1;
1723 V_I1(&type) = NODE_COMMENT;
1725 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1728 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1729 IXMLDOMNode_Release(node);
1730 hr = IXMLDOMComment_put_data(*comment, data);
1737 static HRESULT WINAPI domdoc_createCDATASection(
1738 IXMLDOMDocument3 *iface,
1740 IXMLDOMCDATASection** cdata )
1742 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1747 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1749 if (!cdata) return E_INVALIDARG;
1753 V_VT(&type) = VT_I1;
1754 V_I1(&type) = NODE_CDATA_SECTION;
1756 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1759 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1760 IXMLDOMNode_Release(node);
1761 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1768 static HRESULT WINAPI domdoc_createProcessingInstruction(
1769 IXMLDOMDocument3 *iface,
1772 IXMLDOMProcessingInstruction** pi )
1774 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1779 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1781 if (!pi) return E_INVALIDARG;
1785 V_VT(&type) = VT_I1;
1786 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1788 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1793 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1794 node_obj = get_node_obj(node);
1795 hr = node_set_content(node_obj, data);
1797 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1798 IXMLDOMNode_Release(node);
1805 static HRESULT WINAPI domdoc_createAttribute(
1806 IXMLDOMDocument3 *iface,
1808 IXMLDOMAttribute** attribute )
1810 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1815 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1817 if (!attribute || !name) return E_INVALIDARG;
1819 V_VT(&type) = VT_I1;
1820 V_I1(&type) = NODE_ATTRIBUTE;
1822 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1825 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1826 IXMLDOMNode_Release(node);
1833 static HRESULT WINAPI domdoc_createEntityReference(
1834 IXMLDOMDocument3 *iface,
1836 IXMLDOMEntityReference** entityref )
1838 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1843 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1845 if (!entityref) return E_INVALIDARG;
1849 V_VT(&type) = VT_I1;
1850 V_I1(&type) = NODE_ENTITY_REFERENCE;
1852 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1855 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1856 IXMLDOMNode_Release(node);
1862 xmlChar* tagName_to_XPath(const BSTR tagName)
1864 xmlChar *query, *tmp;
1865 static const xmlChar mod_pre[] = "*[local-name()='";
1866 static const xmlChar mod_post[] = "']";
1867 static const xmlChar prefix[] = "descendant::";
1868 const WCHAR *tokBegin, *tokEnd;
1871 query = xmlStrdup(prefix);
1874 while (tokBegin && *tokBegin)
1879 query = xmlStrcat(query, BAD_CAST "/");
1883 query = xmlStrcat(query, BAD_CAST "*");
1887 query = xmlStrcat(query, mod_pre);
1889 while (*tokEnd && *tokEnd != '/')
1891 len = WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, NULL, 0, NULL, NULL);
1892 tmp = xmlMalloc(len);
1893 WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, (char*)tmp, len, NULL, NULL);
1894 query = xmlStrncat(query, tmp, len);
1897 query = xmlStrcat(query, mod_post);
1904 static HRESULT WINAPI domdoc_getElementsByTagName(
1905 IXMLDOMDocument3 *iface,
1907 IXMLDOMNodeList** resultList )
1909 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1914 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1916 if (!tagName || !resultList) return E_INVALIDARG;
1918 XPath = This->properties->XPath;
1919 This->properties->XPath = TRUE;
1920 query = tagName_to_XPath(tagName);
1921 hr = create_selection((xmlNodePtr)get_doc(This), query, resultList);
1923 This->properties->XPath = XPath;
1928 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1934 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1936 return E_INVALIDARG;
1943 static HRESULT WINAPI domdoc_createNode(
1944 IXMLDOMDocument3 *iface,
1948 IXMLDOMNode** node )
1950 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1951 DOMNodeType node_type;
1953 xmlChar *xml_name, *href;
1956 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1958 if(!node) return E_INVALIDARG;
1960 hr = get_node_type(Type, &node_type);
1961 if(FAILED(hr)) return hr;
1963 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1964 FIXME("nodes with namespaces currently not supported.\n");
1966 TRACE("node_type %d\n", node_type);
1968 /* exit earlier for types that need name */
1972 case NODE_ATTRIBUTE:
1973 case NODE_ENTITY_REFERENCE:
1974 case NODE_PROCESSING_INSTRUCTION:
1975 if (!name || *name == 0) return E_FAIL;
1980 xml_name = xmlchar_from_wchar(name);
1981 /* prevent empty href to be allocated */
1982 href = namespaceURI ? xmlchar_from_wchar(namespaceURI) : NULL;
1988 xmlChar *local, *prefix;
1990 local = xmlSplitQName2(xml_name, &prefix);
1992 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
1994 /* allow to create default namespace xmlns= */
1995 if (local || (href && *href))
1997 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
1998 xmlSetNs(xmlnode, ns);
2006 case NODE_ATTRIBUTE:
2007 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
2010 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
2012 case NODE_CDATA_SECTION:
2013 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
2015 case NODE_ENTITY_REFERENCE:
2016 xmlnode = xmlNewReference(get_doc(This), xml_name);
2018 case NODE_PROCESSING_INSTRUCTION:
2019 #ifdef HAVE_XMLNEWDOCPI
2020 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
2022 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2027 xmlnode = xmlNewDocComment(get_doc(This), NULL);
2029 case NODE_DOCUMENT_FRAGMENT:
2030 xmlnode = xmlNewDocFragment(get_doc(This));
2032 /* unsupported types */
2034 case NODE_DOCUMENT_TYPE:
2037 heap_free(xml_name);
2038 return E_INVALIDARG;
2040 FIXME("unhandled node type %d\n", node_type);
2045 *node = create_node(xmlnode);
2046 heap_free(xml_name);
2051 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
2052 xmldoc_add_orphan(xmlnode->doc, xmlnode);
2059 static HRESULT WINAPI domdoc_nodeFromID(
2060 IXMLDOMDocument3 *iface,
2062 IXMLDOMNode** node )
2064 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2065 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
2069 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
2074 xmldoc = doparse(This, ptr, len, NULL);
2076 xmldoc->_private = create_priv();
2077 return attach_xmldoc(This, xmldoc);
2083 static HRESULT doread( domdoc *This, LPWSTR filename )
2088 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
2093 detach_bsc(This->bsc);
2099 static HRESULT WINAPI domdoc_load(
2100 IXMLDOMDocument3 *iface,
2102 VARIANT_BOOL* isSuccessful )
2104 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2105 LPWSTR filename = NULL;
2106 HRESULT hr = S_FALSE;
2107 IXMLDOMDocument3 *pNewDoc = NULL;
2108 IStream *pStream = NULL;
2111 TRACE("(%p)->(%s)\n", This, debugstr_variant(&source));
2113 *isSuccessful = VARIANT_FALSE;
2115 assert( &This->node );
2117 switch( V_VT(&source) )
2120 filename = V_BSTR(&source);
2122 case VT_BSTR|VT_BYREF:
2123 if (!V_BSTRREF(&source)) return E_INVALIDARG;
2124 filename = *V_BSTRREF(&source);
2127 hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
2132 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
2133 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
2134 hr = attach_xmldoc(This, xmldoc);
2137 *isSuccessful = VARIANT_TRUE;
2142 hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IStream, (void**)&pStream);
2145 IPersistStream *pDocStream;
2146 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
2149 hr = IPersistStream_Load(pDocStream, pStream);
2150 IStream_Release(pStream);
2153 *isSuccessful = VARIANT_TRUE;
2155 TRACE("Using IStream to load Document\n");
2160 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
2165 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
2170 /* ISequentialStream */
2171 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&source)->lpVtbl);
2175 FIXME("VT type not supported (%d)\n", V_VT(&source));
2180 hr = doread( This, filename );
2183 This->error = E_FAIL;
2186 hr = This->error = S_OK;
2187 *isSuccessful = VARIANT_TRUE;
2191 if(!filename || FAILED(hr)) {
2192 xmldoc = xmlNewDoc(NULL);
2193 xmldoc->_private = create_priv();
2194 hr = attach_xmldoc(This, xmldoc);
2199 TRACE("ret (%d)\n", hr);
2205 static HRESULT WINAPI domdoc_get_readyState(
2206 IXMLDOMDocument3 *iface,
2209 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2210 FIXME("stub! (%p)->(%p)\n", This, value);
2213 return E_INVALIDARG;
2215 *value = READYSTATE_COMPLETE;
2220 static HRESULT WINAPI domdoc_get_parseError(
2221 IXMLDOMDocument3 *iface,
2222 IXMLDOMParseError** errorObj )
2224 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2225 static const WCHAR err[] = {'e','r','r','o','r',0};
2226 BSTR error_string = NULL;
2228 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2231 error_string = SysAllocString(err);
2233 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2234 if(!*errorObj) return E_OUTOFMEMORY;
2239 static HRESULT WINAPI domdoc_get_url(
2240 IXMLDOMDocument3 *iface,
2243 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2244 FIXME("(%p)->(%p)\n", This, urlString);
2249 static HRESULT WINAPI domdoc_get_async(
2250 IXMLDOMDocument3 *iface,
2251 VARIANT_BOOL* isAsync )
2253 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2255 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2256 *isAsync = This->async;
2261 static HRESULT WINAPI domdoc_put_async(
2262 IXMLDOMDocument3 *iface,
2263 VARIANT_BOOL isAsync )
2265 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2267 TRACE("(%p)->(%d)\n", This, isAsync);
2268 This->async = isAsync;
2273 static HRESULT WINAPI domdoc_abort(
2274 IXMLDOMDocument3 *iface )
2276 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2277 FIXME("%p\n", This);
2282 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
2287 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
2288 str = heap_alloc( len );
2291 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
2297 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2298 static HRESULT WINAPI domdoc_loadXML(
2299 IXMLDOMDocument3 *iface,
2301 VARIANT_BOOL* isSuccessful )
2303 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2304 static const xmlChar encoding[] = "UTF-8";
2305 xmlDocPtr xmldoc = NULL;
2306 HRESULT hr = S_FALSE, hr2;
2310 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2312 assert ( &This->node );
2316 *isSuccessful = VARIANT_FALSE;
2318 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
2320 xmldoc = doparse(This, str, len, encoding);
2324 This->error = E_FAIL;
2325 TRACE("failed to parse document\n");
2329 hr = This->error = S_OK;
2330 *isSuccessful = VARIANT_TRUE;
2331 TRACE("parsed document %p\n", xmldoc);
2336 xmldoc = xmlNewDoc(NULL);
2338 xmldoc->_private = create_priv();
2340 hr2 = attach_xmldoc(This, xmldoc);
2347 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2351 if(!WriteFile(ctx, buffer, len, &written, NULL))
2353 WARN("write error\n");
2360 static int XMLCALL domdoc_save_closecallback(void *ctx)
2362 return CloseHandle(ctx) ? 0 : -1;
2365 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2370 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2373 WARN("stream write error: 0x%08x\n", hr);
2380 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2382 IStream_Release((IStream*)ctx);
2386 static HRESULT WINAPI domdoc_save(
2387 IXMLDOMDocument3 *iface,
2388 VARIANT destination )
2390 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2391 xmlSaveCtxtPtr ctx = NULL;
2395 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
2396 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
2398 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
2400 FIXME("Unhandled vt %d\n", V_VT(&destination));
2404 if(V_VT(&destination) == VT_UNKNOWN)
2406 IUnknown *pUnk = V_UNKNOWN(&destination);
2407 IXMLDOMDocument2 *document;
2410 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2413 VARIANT_BOOL success;
2416 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2419 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2423 IXMLDOMDocument3_Release(document);
2427 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2430 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2431 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2435 IStream_Release(stream);
2442 /* save with file path */
2443 HANDLE handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
2444 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2445 if( handle == INVALID_HANDLE_VALUE )
2447 WARN("failed to create file\n");
2451 /* disable top XML declaration */
2452 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2453 handle, NULL, XML_SAVE_NO_DECL);
2456 CloseHandle(handle);
2461 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2462 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2463 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2465 /* will release resources through close callback */
2471 static HRESULT WINAPI domdoc_get_validateOnParse(
2472 IXMLDOMDocument3 *iface,
2473 VARIANT_BOOL* isValidating )
2475 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2476 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2477 *isValidating = This->validating;
2482 static HRESULT WINAPI domdoc_put_validateOnParse(
2483 IXMLDOMDocument3 *iface,
2484 VARIANT_BOOL isValidating )
2486 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2487 TRACE("(%p)->(%d)\n", This, isValidating);
2488 This->validating = isValidating;
2493 static HRESULT WINAPI domdoc_get_resolveExternals(
2494 IXMLDOMDocument3 *iface,
2495 VARIANT_BOOL* isResolving )
2497 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2498 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2499 *isResolving = This->resolving;
2504 static HRESULT WINAPI domdoc_put_resolveExternals(
2505 IXMLDOMDocument3 *iface,
2506 VARIANT_BOOL isResolving )
2508 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2509 TRACE("(%p)->(%d)\n", This, isResolving);
2510 This->resolving = isResolving;
2515 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2516 IXMLDOMDocument3 *iface,
2517 VARIANT_BOOL* isPreserving )
2519 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2520 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->properties->preserving);
2521 *isPreserving = This->properties->preserving;
2526 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2527 IXMLDOMDocument3 *iface,
2528 VARIANT_BOOL isPreserving )
2530 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2531 TRACE("(%p)->(%d)\n", This, isPreserving);
2532 This->properties->preserving = isPreserving;
2537 static HRESULT WINAPI domdoc_put_onreadystatechange(
2538 IXMLDOMDocument3 *iface,
2541 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2543 TRACE("(%p)->(%s)\n", This, debugstr_variant(&event));
2544 return set_doc_event(This, EVENTID_READYSTATECHANGE, &event);
2548 static HRESULT WINAPI domdoc_put_onDataAvailable(
2549 IXMLDOMDocument3 *iface,
2550 VARIANT onDataAvailableSink )
2552 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2553 FIXME("%p\n", This);
2557 static HRESULT WINAPI domdoc_put_onTransformNode(
2558 IXMLDOMDocument3 *iface,
2559 VARIANT onTransformNodeSink )
2561 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2562 FIXME("%p\n", This);
2566 static HRESULT WINAPI domdoc_get_namespaces(
2567 IXMLDOMDocument3* iface,
2568 IXMLDOMSchemaCollection** schemaCollection )
2570 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2571 FIXME("(%p)->(%p)\n", This, schemaCollection);
2575 static HRESULT WINAPI domdoc_get_schemas(
2576 IXMLDOMDocument3* iface,
2579 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2580 HRESULT hr = S_FALSE;
2581 IXMLDOMSchemaCollection2* cur_schema = This->properties->schemaCache;
2583 TRACE("(%p)->(%p)\n", This, var1);
2585 VariantInit(var1); /* Test shows we don't call VariantClear here */
2586 V_VT(var1) = VT_NULL;
2590 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2592 V_VT(var1) = VT_DISPATCH;
2597 static HRESULT WINAPI domdoc_putref_schemas(
2598 IXMLDOMDocument3* iface,
2601 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2602 HRESULT hr = E_FAIL;
2603 IXMLDOMSchemaCollection2* new_schema = NULL;
2605 FIXME("(%p): semi-stub\n", This);
2609 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2613 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2622 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2627 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->properties->schemaCache, new_schema);
2628 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2634 static inline BOOL is_wellformed(xmlDocPtr doc)
2636 #ifdef HAVE_XMLDOC_PROPERTIES
2637 return doc->properties & XML_DOC_WELLFORMED;
2639 /* Not a full check, but catches the worst violations */
2643 for (child = doc->children; child != NULL; child = child->next)
2645 switch (child->type)
2647 case XML_ELEMENT_NODE:
2652 case XML_CDATA_SECTION_NODE:
2664 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2668 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2672 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2676 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2680 static HRESULT WINAPI domdoc_validateNode(
2681 IXMLDOMDocument3* iface,
2683 IXMLDOMParseError** err)
2685 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2686 LONG state, err_code = 0;
2690 TRACE("(%p)->(%p, %p)\n", This, node, err);
2691 domdoc_get_readyState(iface, &state);
2692 if (state != READYSTATE_COMPLETE)
2695 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2702 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2706 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2709 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2713 if (!is_wellformed(get_doc(This)))
2715 ERR("doc not well-formed\n");
2717 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2721 /* DTD validation */
2722 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2724 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2725 vctx->error = validate_error;
2726 vctx->warning = validate_warning;
2729 if (!((node == (IXMLDOMNode*)iface)?
2730 xmlValidateDocument(vctx, get_doc(This)) :
2731 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2733 /* TODO: get a real error code here */
2734 TRACE("DTD validation failed\n");
2735 err_code = E_XML_INVALID;
2738 xmlFreeValidCtxt(vctx);
2741 /* Schema validation */
2742 if (hr == S_OK && This->properties->schemaCache != NULL)
2745 hr = SchemaCache_validate_tree(This->properties->schemaCache, get_node_obj(node)->node);
2749 /* TODO: get a real error code here */
2752 TRACE("schema validation succeeded\n");
2756 ERR("schema validation failed\n");
2757 err_code = E_XML_INVALID;
2762 /* not really OK, just didn't find a schema for the ns */
2769 ERR("no DTD or schema found\n");
2770 err_code = E_XML_NODTD;
2775 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2780 static HRESULT WINAPI domdoc_validate(
2781 IXMLDOMDocument3* iface,
2782 IXMLDOMParseError** err)
2784 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2785 TRACE("(%p)->(%p)\n", This, err);
2786 return domdoc_validateNode(iface, (IXMLDOMNode*)iface, err);
2789 static HRESULT WINAPI domdoc_setProperty(
2790 IXMLDOMDocument3* iface,
2794 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2796 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2798 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2804 V_VT(&varStr) = VT_EMPTY;
2805 if (V_VT(&var) != VT_BSTR)
2807 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2809 bstr = V_BSTR(&varStr);
2812 bstr = V_BSTR(&var);
2815 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2816 This->properties->XPath = TRUE;
2817 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2818 This->properties->XPath = FALSE;
2822 VariantClear(&varStr);
2825 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2830 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2831 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2832 xmlXPathContextPtr ctx;
2833 struct list *pNsList;
2834 select_ns_entry* pNsEntry = NULL;
2836 V_VT(&varStr) = VT_EMPTY;
2837 if (V_VT(&var) != VT_BSTR)
2839 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2841 bstr = V_BSTR(&varStr);
2844 bstr = V_BSTR(&var);
2848 pNsList = &(This->properties->selectNsList);
2849 clear_selectNsList(pNsList);
2851 nsStr = xmlchar_from_wchar(bstr);
2853 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2855 This->properties->selectNsStr = nsStr;
2856 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2859 ctx = xmlXPathNewContext(This->node.node->doc);
2862 for (; *pTokBegin; pTokBegin = pTokEnd)
2864 if (pNsEntry != NULL)
2865 memset(pNsEntry, 0, sizeof(select_ns_entry));
2867 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2869 while (*pTokBegin == ' ')
2871 pTokEnd = pTokBegin;
2872 while (*pTokEnd != ' ' && *pTokEnd != 0)
2875 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2878 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2879 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2884 if (*pTokBegin == '=')
2886 /*valid for XSLPattern?*/
2887 FIXME("Setting default xmlns not supported - skipping.\n");
2888 pTokBegin = pTokEnd;
2891 else if (*pTokBegin == ':')
2893 pNsEntry->prefix = ++pTokBegin;
2894 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2897 if (pTokInner == pTokEnd)
2900 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2901 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2905 pNsEntry->prefix_end = *pTokInner;
2909 if (pTokEnd-pTokInner > 1 &&
2910 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2911 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2913 pNsEntry->href = ++pTokInner;
2914 pNsEntry->href_end = *(pTokEnd-1);
2916 list_add_tail(pNsList, &pNsEntry->entry);
2917 /*let libxml figure out if they're valid from here ;)*/
2918 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2927 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2928 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2929 list_add_tail(pNsList, &pNsEntry->entry);
2942 heap_free(pNsEntry);
2943 xmlXPathFreeContext(ctx);
2946 VariantClear(&varStr);
2949 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2950 lstrcmpiW(p, PropertyNewParserW) == 0 ||
2951 lstrcmpiW(p, PropertyResolveExternalsW) == 0)
2954 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2958 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2962 static HRESULT WINAPI domdoc_getProperty(
2963 IXMLDOMDocument3* iface,
2967 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2969 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2972 return E_INVALIDARG;
2974 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2976 V_VT(var) = VT_BSTR;
2977 V_BSTR(var) = This->properties->XPath ?
2978 SysAllocString(PropValueXPathW) :
2979 SysAllocString(PropValueXSLPatternW);
2980 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2982 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2985 BSTR rebuiltStr, cur;
2986 const xmlChar *nsStr;
2987 struct list *pNsList;
2988 select_ns_entry* pNsEntry;
2990 V_VT(var) = VT_BSTR;
2991 nsStr = This->properties->selectNsStr;
2992 pNsList = &This->properties->selectNsList;
2993 lenA = This->properties->selectNsStr_len;
2994 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
2995 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
2996 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
2998 /* this is fine because all of the chars that end tokens are ASCII*/
2999 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
3001 while (*cur != 0) ++cur;
3002 if (pNsEntry->prefix_end)
3004 *cur = pNsEntry->prefix_end;
3005 while (*cur != 0) ++cur;
3008 if (pNsEntry->href_end)
3010 *cur = pNsEntry->href_end;
3013 V_BSTR(var) = SysAllocString(rebuiltStr);
3014 heap_free(rebuiltStr);
3018 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
3022 static HRESULT WINAPI domdoc_importNode(
3023 IXMLDOMDocument3* iface,
3026 IXMLDOMNode** clone)
3028 domdoc *This = impl_from_IXMLDOMDocument3( iface );
3029 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
3033 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
3035 domdoc_QueryInterface,
3038 domdoc_GetTypeInfoCount,
3040 domdoc_GetIDsOfNames,
3042 domdoc_get_nodeName,
3043 domdoc_get_nodeValue,
3044 domdoc_put_nodeValue,
3045 domdoc_get_nodeType,
3046 domdoc_get_parentNode,
3047 domdoc_get_childNodes,
3048 domdoc_get_firstChild,
3049 domdoc_get_lastChild,
3050 domdoc_get_previousSibling,
3051 domdoc_get_nextSibling,
3052 domdoc_get_attributes,
3053 domdoc_insertBefore,
3054 domdoc_replaceChild,
3057 domdoc_hasChildNodes,
3058 domdoc_get_ownerDocument,
3060 domdoc_get_nodeTypeString,
3063 domdoc_get_specified,
3064 domdoc_get_definition,
3065 domdoc_get_nodeTypedValue,
3066 domdoc_put_nodeTypedValue,
3067 domdoc_get_dataType,
3068 domdoc_put_dataType,
3070 domdoc_transformNode,
3072 domdoc_selectSingleNode,
3074 domdoc_get_namespaceURI,
3076 domdoc_get_baseName,
3077 domdoc_transformNodeToObject,
3079 domdoc_get_implementation,
3080 domdoc_get_documentElement,
3081 domdoc_put_documentElement,
3082 domdoc_createElement,
3083 domdoc_createDocumentFragment,
3084 domdoc_createTextNode,
3085 domdoc_createComment,
3086 domdoc_createCDATASection,
3087 domdoc_createProcessingInstruction,
3088 domdoc_createAttribute,
3089 domdoc_createEntityReference,
3090 domdoc_getElementsByTagName,
3094 domdoc_get_readyState,
3095 domdoc_get_parseError,
3102 domdoc_get_validateOnParse,
3103 domdoc_put_validateOnParse,
3104 domdoc_get_resolveExternals,
3105 domdoc_put_resolveExternals,
3106 domdoc_get_preserveWhiteSpace,
3107 domdoc_put_preserveWhiteSpace,
3108 domdoc_put_onreadystatechange,
3109 domdoc_put_onDataAvailable,
3110 domdoc_put_onTransformNode,
3111 domdoc_get_namespaces,
3113 domdoc_putref_schemas,
3117 domdoc_validateNode,
3121 /* IConnectionPointContainer */
3122 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
3123 REFIID riid, void **ppv)
3125 domdoc *This = impl_from_IConnectionPointContainer(iface);
3126 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppv);
3129 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
3131 domdoc *This = impl_from_IConnectionPointContainer(iface);
3132 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3135 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
3137 domdoc *This = impl_from_IConnectionPointContainer(iface);
3138 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3141 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
3142 IEnumConnectionPoints **ppEnum)
3144 domdoc *This = impl_from_IConnectionPointContainer(iface);
3145 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3149 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
3150 REFIID riid, IConnectionPoint **cp)
3152 domdoc *This = impl_from_IConnectionPointContainer(iface);
3153 ConnectionPoint *iter;
3155 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
3159 for(iter = This->cp_list; iter; iter = iter->next)
3161 if (IsEqualGUID(iter->iid, riid))
3162 *cp = &iter->IConnectionPoint_iface;
3167 IConnectionPoint_AddRef(*cp);
3171 FIXME("unsupported riid %s\n", debugstr_guid(riid));
3172 return CONNECT_E_NOCONNECTION;
3176 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
3178 ConnectionPointContainer_QueryInterface,
3179 ConnectionPointContainer_AddRef,
3180 ConnectionPointContainer_Release,
3181 ConnectionPointContainer_EnumConnectionPoints,
3182 ConnectionPointContainer_FindConnectionPoint
3185 /* IConnectionPoint */
3186 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
3187 REFIID riid, void **ppv)
3189 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3191 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3195 if (IsEqualGUID(&IID_IUnknown, riid) ||
3196 IsEqualGUID(&IID_IConnectionPoint, riid))
3203 IConnectionPoint_AddRef(iface);
3207 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3208 return E_NOINTERFACE;
3211 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3213 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3214 return IConnectionPointContainer_AddRef(This->container);
3217 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3219 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3220 return IConnectionPointContainer_Release(This->container);
3223 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3225 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3227 TRACE("(%p)->(%p)\n", This, iid);
3229 if (!iid) return E_POINTER;
3235 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3236 IConnectionPointContainer **container)
3238 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3240 TRACE("(%p)->(%p)\n", This, container);
3242 if (!container) return E_POINTER;
3244 *container = This->container;
3245 IConnectionPointContainer_AddRef(*container);
3249 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
3252 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3253 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
3257 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3259 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3261 TRACE("(%p)->(%d)\n", This, cookie);
3263 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3264 return CONNECT_E_NOCONNECTION;
3266 IUnknown_Release(This->sinks[cookie-1].unk);
3267 This->sinks[cookie-1].unk = NULL;
3272 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3273 IEnumConnections **ppEnum)
3275 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3276 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3280 static const IConnectionPointVtbl ConnectionPointVtbl =
3282 ConnectionPoint_QueryInterface,
3283 ConnectionPoint_AddRef,
3284 ConnectionPoint_Release,
3285 ConnectionPoint_GetConnectionInterface,
3286 ConnectionPoint_GetConnectionPointContainer,
3287 ConnectionPoint_Advise,
3288 ConnectionPoint_Unadvise,
3289 ConnectionPoint_EnumConnections
3292 static void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3294 cp->IConnectionPoint_iface.lpVtbl = &ConnectionPointVtbl;
3300 cp->next = doc->cp_list;
3303 cp->container = &doc->IConnectionPointContainer_iface;
3306 /* domdoc implementation of IObjectWithSite */
3307 static HRESULT WINAPI
3308 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3310 domdoc *This = impl_from_IObjectWithSite(iface);
3311 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppvObject);
3314 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3316 domdoc *This = impl_from_IObjectWithSite(iface);
3317 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3320 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3322 domdoc *This = impl_from_IObjectWithSite(iface);
3323 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3326 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3328 domdoc *This = impl_from_IObjectWithSite(iface);
3330 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3335 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3338 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3340 domdoc *This = impl_from_IObjectWithSite(iface);
3342 TRACE("(%p)->(%p)\n", iface, punk);
3348 IUnknown_Release( This->site );
3355 IUnknown_AddRef( punk );
3358 IUnknown_Release( This->site );
3365 static const IObjectWithSiteVtbl domdocObjectSite =
3367 domdoc_ObjectWithSite_QueryInterface,
3368 domdoc_ObjectWithSite_AddRef,
3369 domdoc_ObjectWithSite_Release,
3370 domdoc_ObjectWithSite_SetSite,
3371 domdoc_ObjectWithSite_GetSite
3374 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3376 domdoc *This = impl_from_IObjectSafety(iface);
3377 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppv);
3380 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3382 domdoc *This = impl_from_IObjectSafety(iface);
3383 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3386 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3388 domdoc *This = impl_from_IObjectSafety(iface);
3389 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3392 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3394 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3395 DWORD *supported, DWORD *enabled)
3397 domdoc *This = impl_from_IObjectSafety(iface);
3399 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3401 if(!supported || !enabled) return E_POINTER;
3403 *supported = SAFETY_SUPPORTED_OPTIONS;
3404 *enabled = This->safeopt;
3409 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3410 DWORD mask, DWORD enabled)
3412 domdoc *This = impl_from_IObjectSafety(iface);
3413 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3415 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3418 This->safeopt = enabled & mask & SAFETY_SUPPORTED_OPTIONS;
3422 #undef SAFETY_SUPPORTED_OPTIONS
3424 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3425 domdoc_Safety_QueryInterface,
3426 domdoc_Safety_AddRef,
3427 domdoc_Safety_Release,
3428 domdoc_Safety_GetInterfaceSafetyOptions,
3429 domdoc_Safety_SetInterfaceSafetyOptions
3432 static const tid_t domdoc_iface_tids[] = {
3434 IXMLDOMDocument_tid,
3435 IXMLDOMDocument2_tid,
3438 static dispex_static_data_t domdoc_dispex = {
3440 IXMLDOMDocument2_tid,
3445 HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3449 doc = heap_alloc( sizeof (*doc) );
3451 return E_OUTOFMEMORY;
3453 doc->IXMLDOMDocument3_iface.lpVtbl = &domdoc_vtbl;
3454 doc->IPersistStreamInit_iface.lpVtbl = &xmldoc_IPersistStreamInit_VTable;
3455 doc->IObjectWithSite_iface.lpVtbl = &domdocObjectSite;
3456 doc->IObjectSafety_iface.lpVtbl = &domdocObjectSafetyVtbl;
3457 doc->ISupportErrorInfo_iface.lpVtbl = &support_error_vtbl;
3458 doc->IConnectionPointContainer_iface.lpVtbl = &ConnectionPointContainerVtbl;
3460 doc->async = VARIANT_TRUE;
3461 doc->validating = 0;
3463 doc->properties = properties_from_xmlDocPtr(xmldoc);
3469 doc->cp_list = NULL;
3470 memset(doc->events, 0, sizeof(doc->events));
3472 /* events connection points */
3473 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3474 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3475 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3477 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->IXMLDOMDocument3_iface,
3480 *document = &doc->IXMLDOMDocument3_iface;
3482 TRACE("returning iface %p\n", *document);
3486 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3491 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
3493 xmldoc = xmlNewDoc(NULL);
3495 return E_OUTOFMEMORY;
3497 xmldoc->_private = create_priv();
3498 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
3500 hr = get_domdoc_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3503 free_properties(properties_from_xmlDocPtr(xmldoc));
3504 heap_free(xmldoc->_private);
3512 IUnknown* create_domdoc( xmlNodePtr document )
3517 TRACE("(%p)\n", document);
3519 hr = get_domdoc_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3528 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3530 MESSAGE("This program tried to use a DOMDocument object, but\n"
3531 "libxml2 support was not present at compile time.\n");