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>
51 #include "wine/debug.h"
52 #include "wine/list.h"
54 #include "msxml_private.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
60 /* not defined in older versions */
61 #define XML_SAVE_FORMAT 1
62 #define XML_SAVE_NO_DECL 2
63 #define XML_SAVE_NO_EMPTY 4
64 #define XML_SAVE_NO_XHTML 8
65 #define XML_SAVE_XHTML 16
66 #define XML_SAVE_AS_XML 32
67 #define XML_SAVE_AS_HTML 64
69 static const WCHAR PropertySelectionLanguageW[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
70 static const WCHAR PropertySelectionNamespacesW[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
71 static const WCHAR PropertyProhibitDTDW[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
72 static const WCHAR PropertyNewParserW[] = {'N','e','w','P','a','r','s','e','r',0};
73 static const WCHAR PropValueXPathW[] = {'X','P','a','t','h',0};
74 static const WCHAR PropValueXSLPatternW[] = {'X','S','L','P','a','t','t','e','r','n',0};
75 static const WCHAR PropertyResolveExternalsW[] = {'R','e','s','o','l','v','e','E','x','t','e','r','n','a','l','s',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. */
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 IConnectionPoint IConnectionPoint_iface;
99 ConnectionPoint *next;
100 IConnectionPointContainer *container;
107 IPropertyNotifySink *propnotif;
113 EVENTID_READYSTATECHANGE = 0,
114 EVENTID_DATAAVAILABLE,
115 EVENTID_TRANSFORMNODE,
122 IXMLDOMDocument3 IXMLDOMDocument3_iface;
123 IPersistStreamInit IPersistStreamInit_iface;
124 IObjectWithSite IObjectWithSite_iface;
125 IObjectSafety IObjectSafety_iface;
126 IConnectionPointContainer IConnectionPointContainer_iface;
129 VARIANT_BOOL validating;
130 VARIANT_BOOL resolving;
131 domdoc_properties* properties;
144 /* connection list */
145 ConnectionPoint *cp_list;
146 ConnectionPoint cp_domdocevents;
147 ConnectionPoint cp_propnotif;
148 ConnectionPoint cp_dispatch;
151 IDispatch *events[EVENTID_LAST];
153 IXMLDOMSchemaCollection2 *namespaces;
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(MSXML_VERSION version)
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 properties->version = version;
302 properties->XPath = (version == MSXML4 || version == MSXML6);
307 static domdoc_properties* copy_properties(domdoc_properties const* properties)
309 domdoc_properties* pcopy = heap_alloc(sizeof(domdoc_properties));
310 select_ns_entry const* ns = NULL;
311 select_ns_entry* new_ns = NULL;
312 int len = (properties->selectNsStr_len+1)*sizeof(xmlChar);
317 pcopy->version = properties->version;
318 pcopy->preserving = properties->preserving;
319 pcopy->schemaCache = properties->schemaCache;
320 if (pcopy->schemaCache)
321 IXMLDOMSchemaCollection2_AddRef(pcopy->schemaCache);
322 pcopy->XPath = properties->XPath;
323 pcopy->selectNsStr_len = properties->selectNsStr_len;
324 list_init( &pcopy->selectNsList );
325 pcopy->selectNsStr = heap_alloc(len);
326 memcpy((xmlChar*)pcopy->selectNsStr, properties->selectNsStr, len);
327 offset = pcopy->selectNsStr - properties->selectNsStr;
329 LIST_FOR_EACH_ENTRY( ns, (&properties->selectNsList), select_ns_entry, entry )
331 new_ns = heap_alloc(sizeof(select_ns_entry));
332 memcpy(new_ns, ns, sizeof(select_ns_entry));
333 new_ns->href += offset;
334 new_ns->prefix += offset;
335 list_add_tail(&pcopy->selectNsList, &new_ns->entry);
343 static void free_properties(domdoc_properties* properties)
347 if (properties->schemaCache)
348 IXMLDOMSchemaCollection2_Release(properties->schemaCache);
349 clear_selectNsList(&properties->selectNsList);
350 heap_free((xmlChar*)properties->selectNsStr);
351 heap_free(properties);
355 static void release_namespaces(domdoc *This)
357 if (This->namespaces)
359 IXMLDOMSchemaCollection2_Release(This->namespaces);
360 This->namespaces = NULL;
364 /* links a "<?xml" node as a first child */
365 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
368 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
371 /* unlinks a first "<?xml" child if it was created */
372 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
374 static const xmlChar xmlA[] = "xml";
375 xmlNodePtr node, first_child;
379 /* xml declaration node could be created automatically after parsing or added
381 first_child = doc->children;
382 if (first_child && first_child->type == XML_PI_NODE && xmlStrEqual(first_child->name, xmlA))
385 xmlUnlinkNode( node );
393 BOOL is_preserving_whitespace(xmlNodePtr node)
395 domdoc_properties* properties = NULL;
396 /* during parsing the xmlDoc._private stuff is not there */
397 if (priv_from_xmlDocPtr(node->doc))
398 properties = properties_from_xmlDocPtr(node->doc);
399 return ((properties && properties->preserving == VARIANT_TRUE) ||
400 xmlNodeGetSpacePreserve(node) == 1);
403 static inline BOOL strn_isspace(xmlChar const* str, int len)
405 for (; str && len > 0 && *str; ++str, --len)
412 static void sax_characters(void *ctx, const xmlChar *ch, int len)
414 xmlParserCtxtPtr ctxt;
417 ctxt = (xmlParserCtxtPtr) ctx;
418 This = (const domdoc*) ctxt->_private;
422 /* during domdoc_loadXML() the xmlDocPtr->_private data is not available */
423 if (!This->properties->preserving &&
424 !is_preserving_whitespace(ctxt->node) &&
425 strn_isspace(ch, len))
429 xmlSAX2Characters(ctxt, ch, len);
432 static void LIBXML2_LOG_CALLBACK sax_error(void* ctx, char const* msg, ...)
436 LIBXML2_CALLBACK_ERR(doparse, msg, ap);
440 static void LIBXML2_LOG_CALLBACK sax_warning(void* ctx, char const* msg, ...)
444 LIBXML2_CALLBACK_WARN(doparse, msg, ap);
448 static void sax_serror(void* ctx, xmlErrorPtr err)
450 LIBXML2_CALLBACK_SERROR(doparse, err);
453 static xmlDocPtr doparse(domdoc* This, char const* ptr, int len, xmlCharEncoding encoding)
455 xmlDocPtr doc = NULL;
456 xmlParserCtxtPtr pctx;
457 static xmlSAXHandler sax_handler = {
458 xmlSAX2InternalSubset, /* internalSubset */
459 xmlSAX2IsStandalone, /* isStandalone */
460 xmlSAX2HasInternalSubset, /* hasInternalSubset */
461 xmlSAX2HasExternalSubset, /* hasExternalSubset */
462 xmlSAX2ResolveEntity, /* resolveEntity */
463 xmlSAX2GetEntity, /* getEntity */
464 xmlSAX2EntityDecl, /* entityDecl */
465 xmlSAX2NotationDecl, /* notationDecl */
466 xmlSAX2AttributeDecl, /* attributeDecl */
467 xmlSAX2ElementDecl, /* elementDecl */
468 xmlSAX2UnparsedEntityDecl, /* unparsedEntityDecl */
469 xmlSAX2SetDocumentLocator, /* setDocumentLocator */
470 xmlSAX2StartDocument, /* startDocument */
471 xmlSAX2EndDocument, /* endDocument */
472 xmlSAX2StartElement, /* startElement */
473 xmlSAX2EndElement, /* endElement */
474 xmlSAX2Reference, /* reference */
475 sax_characters, /* characters */
476 sax_characters, /* ignorableWhitespace */
477 xmlSAX2ProcessingInstruction, /* processingInstruction */
478 xmlSAX2Comment, /* comment */
479 sax_warning, /* warning */
480 sax_error, /* error */
481 sax_error, /* fatalError */
482 xmlSAX2GetParameterEntity, /* getParameterEntity */
483 xmlSAX2CDataBlock, /* cdataBlock */
484 xmlSAX2ExternalSubset, /* externalSubset */
487 xmlSAX2StartElementNs, /* startElementNs */
488 xmlSAX2EndElementNs, /* endElementNs */
489 sax_serror /* serror */
492 pctx = xmlCreateMemoryParserCtxt(ptr, len);
495 ERR("Failed to create parser context\n");
499 if (pctx->sax) xmlFree(pctx->sax);
500 pctx->sax = &sax_handler;
501 pctx->_private = This;
504 if (encoding != XML_CHAR_ENCODING_NONE)
505 xmlSwitchEncoding(pctx, encoding);
507 xmlParseDocument(pctx);
509 if (pctx->wellFormed)
515 xmlFreeDoc(pctx->myDoc);
519 xmlFreeParserCtxt(pctx);
521 /* TODO: put this in one of the SAX callbacks */
522 /* create first child as a <?xml...?> */
523 if (doc && doc->standalone != -1)
527 xmlChar *xmlbuff = (xmlChar*)buff;
529 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
531 /* version attribute can't be omitted */
532 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
533 xmlNodeAddContent( node, xmlbuff );
537 sprintf(buff, " encoding=\"%s\"", doc->encoding);
538 xmlNodeAddContent( node, xmlbuff );
541 if (doc->standalone != -2)
543 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
544 xmlNodeAddContent( node, xmlbuff );
547 xmldoc_link_xmldecl( doc, node );
553 void xmldoc_init(xmlDocPtr doc, MSXML_VERSION version)
555 doc->_private = create_priv();
556 priv_from_xmlDocPtr(doc)->properties = create_properties(version);
559 LONG xmldoc_add_ref(xmlDocPtr doc)
561 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
562 TRACE("(%p)->(%d)\n", doc, ref);
566 LONG xmldoc_release(xmlDocPtr doc)
568 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
569 LONG ref = InterlockedDecrement(&priv->refs);
570 TRACE("(%p)->(%d)\n", doc, ref);
573 orphan_entry *orphan, *orphan2;
574 TRACE("freeing docptr %p\n", doc);
576 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
578 xmlFreeNode( orphan->node );
581 free_properties(priv->properties);
582 heap_free(doc->_private);
590 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
592 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
595 entry = heap_alloc( sizeof (*entry) );
597 return E_OUTOFMEMORY;
600 list_add_head( &priv->orphans, &entry->entry );
604 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
606 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
607 orphan_entry *entry, *entry2;
609 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
611 if( entry->node == node )
613 list_remove( &entry->entry );
622 static inline xmlDocPtr get_doc( domdoc *This )
624 return (xmlDocPtr)This->node.node;
627 static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
629 release_namespaces(This);
633 priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
634 if (xmldoc_release(get_doc(This)) != 0)
635 priv_from_xmlDocPtr(get_doc(This))->properties =
636 copy_properties(This->properties);
639 This->node.node = (xmlNodePtr) xml;
643 xmldoc_add_ref(get_doc(This));
644 priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
650 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
652 return CONTAINING_RECORD(iface, domdoc, IXMLDOMDocument3_iface);
655 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
657 return CONTAINING_RECORD(iface, domdoc, IPersistStreamInit_iface);
660 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
662 return CONTAINING_RECORD(iface, domdoc, IObjectWithSite_iface);
665 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
667 return CONTAINING_RECORD(iface, domdoc, IObjectSafety_iface);
670 static inline domdoc *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
672 return CONTAINING_RECORD(iface, domdoc, IConnectionPointContainer_iface);
675 /************************************************************************
676 * domdoc implementation of IPersistStream.
678 static HRESULT WINAPI PersistStreamInit_QueryInterface(
679 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
681 domdoc* This = impl_from_IPersistStreamInit(iface);
682 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppvObj);
685 static ULONG WINAPI PersistStreamInit_AddRef(
686 IPersistStreamInit *iface)
688 domdoc* This = impl_from_IPersistStreamInit(iface);
689 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
692 static ULONG WINAPI PersistStreamInit_Release(
693 IPersistStreamInit *iface)
695 domdoc* This = impl_from_IPersistStreamInit(iface);
696 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
699 static HRESULT WINAPI PersistStreamInit_GetClassID(
700 IPersistStreamInit *iface, CLSID *classid)
702 domdoc* This = impl_from_IPersistStreamInit(iface);
703 TRACE("(%p)->(%p)\n", This, classid);
708 *classid = *DOMDocument_version(This->properties->version);
713 static HRESULT WINAPI PersistStreamInit_IsDirty(
714 IPersistStreamInit *iface)
716 domdoc *This = impl_from_IPersistStreamInit(iface);
717 FIXME("(%p): stub!\n", This);
721 static HRESULT WINAPI PersistStreamInit_Load(
722 IPersistStreamInit *iface, LPSTREAM pStm)
724 domdoc *This = impl_from_IPersistStreamInit(iface);
727 DWORD read, written, len;
730 xmlDocPtr xmldoc = NULL;
732 TRACE("(%p)->(%p)\n", This, pStm);
737 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
743 IStream_Read(pStm, buf, sizeof(buf), &read);
744 hr = IStream_Write(This->stream, buf, read, &written);
745 } while(SUCCEEDED(hr) && written != 0 && read != 0);
749 ERR("Failed to copy stream\n");
753 hr = GetHGlobalFromStream(This->stream, &hglobal);
757 len = GlobalSize(hglobal);
758 ptr = GlobalLock(hglobal);
760 xmldoc = doparse(This, ptr, len, XML_CHAR_ENCODING_NONE);
761 GlobalUnlock(hglobal);
765 ERR("Failed to parse xml\n");
769 xmldoc->_private = create_priv();
771 return attach_xmldoc(This, xmldoc);
774 static HRESULT WINAPI PersistStreamInit_Save(
775 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
777 domdoc *This = impl_from_IPersistStreamInit(iface);
781 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
783 hr = IXMLDOMDocument3_get_xml(&This->IXMLDOMDocument3_iface, &xmlString);
786 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
788 hr = IStream_Write( stream, xmlString, len, NULL );
789 SysFreeString(xmlString);
792 TRACE("ret 0x%08x\n", hr);
797 static HRESULT WINAPI PersistStreamInit_GetSizeMax(
798 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
800 domdoc *This = impl_from_IPersistStreamInit(iface);
801 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
805 static HRESULT WINAPI PersistStreamInit_InitNew(
806 IPersistStreamInit *iface)
808 domdoc *This = impl_from_IPersistStreamInit(iface);
809 TRACE("(%p)\n", This);
813 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
815 PersistStreamInit_QueryInterface,
816 PersistStreamInit_AddRef,
817 PersistStreamInit_Release,
818 PersistStreamInit_GetClassID,
819 PersistStreamInit_IsDirty,
820 PersistStreamInit_Load,
821 PersistStreamInit_Save,
822 PersistStreamInit_GetSizeMax,
823 PersistStreamInit_InitNew
826 /* IXMLDOMDocument3 interface */
828 static const tid_t domdoc_se_tids[] = {
831 IXMLDOMDocument2_tid,
832 IXMLDOMDocument3_tid,
836 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
838 domdoc *This = impl_from_IXMLDOMDocument3( iface );
840 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
844 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
845 IsEqualGUID( riid, &IID_IDispatch ) ||
846 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
847 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
848 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
849 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
853 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
854 IsEqualGUID(&IID_IPersistStreamInit, riid))
856 *ppvObject = &This->IPersistStreamInit_iface;
858 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
860 *ppvObject = &This->IObjectWithSite_iface;
862 else if (IsEqualGUID(&IID_IObjectSafety, riid))
864 *ppvObject = &This->IObjectSafety_iface;
866 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
868 return node_create_supporterrorinfo(domdoc_se_tids, ppvObject);
870 else if(node_query_interface(&This->node, riid, ppvObject))
872 return *ppvObject ? S_OK : E_NOINTERFACE;
874 else if (IsEqualGUID( riid, &IID_IConnectionPointContainer ))
876 *ppvObject = &This->IConnectionPointContainer_iface;
880 TRACE("interface %s not implemented\n", debugstr_guid(riid));
881 return E_NOINTERFACE;
884 IUnknown_AddRef((IUnknown*)*ppvObject);
889 static ULONG WINAPI domdoc_AddRef( IXMLDOMDocument3 *iface )
891 domdoc *This = impl_from_IXMLDOMDocument3( iface );
892 ULONG ref = InterlockedIncrement( &This->ref );
893 TRACE("(%p)->(%d)\n", This, ref );
897 static ULONG WINAPI domdoc_Release( IXMLDOMDocument3 *iface )
899 domdoc *This = impl_from_IXMLDOMDocument3( iface );
900 LONG ref = InterlockedDecrement( &This->ref );
902 TRACE("(%p)->(%d)\n", This, ref );
909 detach_bsc(This->bsc);
912 IUnknown_Release( This->site );
913 destroy_xmlnode(&This->node);
915 IStream_Release(This->stream);
917 for (eid = 0; eid < EVENTID_LAST; eid++)
918 if (This->events[eid]) IDispatch_Release(This->events[eid]);
920 release_namespaces(This);
927 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
929 domdoc *This = impl_from_IXMLDOMDocument3( iface );
930 return IDispatchEx_GetTypeInfoCount(&This->node.dispex.IDispatchEx_iface, pctinfo);
933 static HRESULT WINAPI domdoc_GetTypeInfo(
934 IXMLDOMDocument3 *iface,
935 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
937 domdoc *This = impl_from_IXMLDOMDocument3( iface );
938 return IDispatchEx_GetTypeInfo(&This->node.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
941 static HRESULT WINAPI domdoc_GetIDsOfNames(
942 IXMLDOMDocument3 *iface,
949 domdoc *This = impl_from_IXMLDOMDocument3( iface );
950 return IDispatchEx_GetIDsOfNames(&This->node.dispex.IDispatchEx_iface,
951 riid, rgszNames, cNames, lcid, rgDispId);
954 static HRESULT WINAPI domdoc_Invoke(
955 IXMLDOMDocument3 *iface,
960 DISPPARAMS* pDispParams,
962 EXCEPINFO* pExcepInfo,
965 domdoc *This = impl_from_IXMLDOMDocument3( iface );
966 return IDispatchEx_Invoke(&This->node.dispex.IDispatchEx_iface,
967 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
970 static HRESULT WINAPI domdoc_get_nodeName(
971 IXMLDOMDocument3 *iface,
974 domdoc *This = impl_from_IXMLDOMDocument3( iface );
976 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
978 TRACE("(%p)->(%p)\n", This, name);
980 return return_bstr(documentW, name);
984 static HRESULT WINAPI domdoc_get_nodeValue(
985 IXMLDOMDocument3 *iface,
988 domdoc *This = impl_from_IXMLDOMDocument3( iface );
990 TRACE("(%p)->(%p)\n", This, value);
995 V_VT(value) = VT_NULL;
996 V_BSTR(value) = NULL; /* tests show that we should do this */
1001 static HRESULT WINAPI domdoc_put_nodeValue(
1002 IXMLDOMDocument3 *iface,
1005 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1006 TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
1011 static HRESULT WINAPI domdoc_get_nodeType(
1012 IXMLDOMDocument3 *iface,
1015 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1017 TRACE("(%p)->(%p)\n", This, type);
1019 *type = NODE_DOCUMENT;
1024 static HRESULT WINAPI domdoc_get_parentNode(
1025 IXMLDOMDocument3 *iface,
1026 IXMLDOMNode** parent )
1028 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1030 TRACE("(%p)->(%p)\n", This, parent);
1032 return node_get_parent(&This->node, parent);
1036 static HRESULT WINAPI domdoc_get_childNodes(
1037 IXMLDOMDocument3 *iface,
1038 IXMLDOMNodeList** childList )
1040 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1042 TRACE("(%p)->(%p)\n", This, childList);
1044 return node_get_child_nodes(&This->node, childList);
1048 static HRESULT WINAPI domdoc_get_firstChild(
1049 IXMLDOMDocument3 *iface,
1050 IXMLDOMNode** firstChild )
1052 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1054 TRACE("(%p)->(%p)\n", This, firstChild);
1056 return node_get_first_child(&This->node, firstChild);
1060 static HRESULT WINAPI domdoc_get_lastChild(
1061 IXMLDOMDocument3 *iface,
1062 IXMLDOMNode** lastChild )
1064 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1066 TRACE("(%p)->(%p)\n", This, lastChild);
1068 return node_get_last_child(&This->node, lastChild);
1072 static HRESULT WINAPI domdoc_get_previousSibling(
1073 IXMLDOMDocument3 *iface,
1074 IXMLDOMNode** previousSibling )
1076 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1078 TRACE("(%p)->(%p)\n", This, previousSibling);
1080 return return_null_node(previousSibling);
1084 static HRESULT WINAPI domdoc_get_nextSibling(
1085 IXMLDOMDocument3 *iface,
1086 IXMLDOMNode** nextSibling )
1088 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1090 TRACE("(%p)->(%p)\n", This, nextSibling);
1092 return return_null_node(nextSibling);
1096 static HRESULT WINAPI domdoc_get_attributes(
1097 IXMLDOMDocument3 *iface,
1098 IXMLDOMNamedNodeMap** attributeMap )
1100 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1102 TRACE("(%p)->(%p)\n", This, attributeMap);
1104 return return_null_ptr((void**)attributeMap);
1108 static HRESULT WINAPI domdoc_insertBefore(
1109 IXMLDOMDocument3 *iface,
1110 IXMLDOMNode* newChild,
1112 IXMLDOMNode** outNewChild )
1114 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1116 TRACE("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), outNewChild);
1118 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1122 static HRESULT WINAPI domdoc_replaceChild(
1123 IXMLDOMDocument3 *iface,
1124 IXMLDOMNode* newChild,
1125 IXMLDOMNode* oldChild,
1126 IXMLDOMNode** outOldChild)
1128 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1130 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1132 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1136 static HRESULT WINAPI domdoc_removeChild(
1137 IXMLDOMDocument3 *iface,
1139 IXMLDOMNode **oldChild)
1141 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1142 TRACE("(%p)->(%p %p)\n", This, child, oldChild);
1143 return node_remove_child(&This->node, child, oldChild);
1147 static HRESULT WINAPI domdoc_appendChild(
1148 IXMLDOMDocument3 *iface,
1150 IXMLDOMNode **outChild)
1152 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1153 TRACE("(%p)->(%p %p)\n", This, child, outChild);
1154 return node_append_child(&This->node, child, outChild);
1158 static HRESULT WINAPI domdoc_hasChildNodes(
1159 IXMLDOMDocument3 *iface,
1162 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1163 TRACE("(%p)->(%p)\n", This, ret);
1164 return node_has_childnodes(&This->node, ret);
1168 static HRESULT WINAPI domdoc_get_ownerDocument(
1169 IXMLDOMDocument3 *iface,
1170 IXMLDOMDocument **doc)
1172 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1173 TRACE("(%p)->(%p)\n", This, doc);
1174 return node_get_owner_doc(&This->node, doc);
1178 static HRESULT WINAPI domdoc_cloneNode(
1179 IXMLDOMDocument3 *iface,
1181 IXMLDOMNode** outNode)
1183 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1184 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
1185 return node_clone( &This->node, deep, outNode );
1189 static HRESULT WINAPI domdoc_get_nodeTypeString(
1190 IXMLDOMDocument3 *iface,
1193 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1194 static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
1196 TRACE("(%p)->(%p)\n", This, p);
1198 return return_bstr(documentW, p);
1202 static HRESULT WINAPI domdoc_get_text(
1203 IXMLDOMDocument3 *iface,
1206 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1207 TRACE("(%p)->(%p)\n", This, p);
1208 return node_get_text(&This->node, p);
1212 static HRESULT WINAPI domdoc_put_text(
1213 IXMLDOMDocument3 *iface,
1216 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1217 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1222 static HRESULT WINAPI domdoc_get_specified(
1223 IXMLDOMDocument3 *iface,
1224 VARIANT_BOOL* isSpecified )
1226 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1227 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1228 *isSpecified = VARIANT_TRUE;
1233 static HRESULT WINAPI domdoc_get_definition(
1234 IXMLDOMDocument3 *iface,
1235 IXMLDOMNode** definitionNode )
1237 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1238 FIXME("(%p)->(%p)\n", This, definitionNode);
1243 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1244 IXMLDOMDocument3 *iface,
1247 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1248 TRACE("(%p)->(%p)\n", This, v);
1249 return return_null_var(v);
1252 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1253 IXMLDOMDocument3 *iface,
1254 VARIANT typedValue )
1256 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1257 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1262 static HRESULT WINAPI domdoc_get_dataType(
1263 IXMLDOMDocument3 *iface,
1266 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1267 TRACE("(%p)->(%p)\n", This, typename);
1268 return return_null_var( typename );
1272 static HRESULT WINAPI domdoc_put_dataType(
1273 IXMLDOMDocument3 *iface,
1276 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1278 FIXME("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
1281 return E_INVALIDARG;
1286 static int XMLCALL domdoc_get_xml_writecallback(void *ctx, const char *data, int len)
1288 return xmlBufferAdd((xmlBufferPtr)ctx, (xmlChar*)data, len) == 0 ? len : 0;
1291 static HRESULT WINAPI domdoc_get_xml(
1292 IXMLDOMDocument3 *iface,
1295 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1296 xmlSaveCtxtPtr ctxt;
1301 TRACE("(%p)->(%p)\n", This, p);
1304 return E_INVALIDARG;
1308 buf = xmlBufferCreate();
1310 return E_OUTOFMEMORY;
1312 options = XML_SAVE_FORMAT | XML_SAVE_NO_DECL;
1313 ctxt = xmlSaveToIO(domdoc_get_xml_writecallback, NULL, buf, "UTF-8", options);
1318 return E_OUTOFMEMORY;
1321 ret = xmlSaveDoc(ctxt, get_doc(This));
1322 /* flushes on close */
1325 TRACE("%ld, len=%d\n", ret, xmlBufferLength(buf));
1326 if(ret != -1 && xmlBufferLength(buf) > 0)
1330 content = bstr_from_xmlChar(xmlBufferContent(buf));
1331 content = EnsureCorrectEOL(content);
1337 *p = SysAllocStringLen(NULL, 0);
1342 return *p ? S_OK : E_OUTOFMEMORY;
1346 static HRESULT WINAPI domdoc_transformNode(
1347 IXMLDOMDocument3 *iface,
1351 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1352 TRACE("(%p)->(%p %p)\n", This, node, p);
1353 return node_transform_node(&This->node, node, p);
1357 static HRESULT WINAPI domdoc_selectNodes(
1358 IXMLDOMDocument3 *iface,
1360 IXMLDOMNodeList **outList)
1362 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1363 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList);
1364 return node_select_nodes(&This->node, p, outList);
1368 static HRESULT WINAPI domdoc_selectSingleNode(
1369 IXMLDOMDocument3 *iface,
1371 IXMLDOMNode **outNode)
1373 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1374 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode);
1375 return node_select_singlenode(&This->node, p, outNode);
1379 static HRESULT WINAPI domdoc_get_parsed(
1380 IXMLDOMDocument3 *iface,
1381 VARIANT_BOOL* isParsed )
1383 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1384 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1385 *isParsed = VARIANT_TRUE;
1389 static HRESULT WINAPI domdoc_get_namespaceURI(
1390 IXMLDOMDocument3 *iface,
1391 BSTR* namespaceURI )
1393 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1394 TRACE("(%p)->(%p)\n", This, namespaceURI);
1395 return return_null_bstr( namespaceURI );
1398 static HRESULT WINAPI domdoc_get_prefix(
1399 IXMLDOMDocument3 *iface,
1402 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1403 TRACE("(%p)->(%p)\n", This, prefix);
1404 return return_null_bstr( prefix );
1408 static HRESULT WINAPI domdoc_get_baseName(
1409 IXMLDOMDocument3 *iface,
1412 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1413 TRACE("(%p)->(%p)\n", This, name);
1414 return return_null_bstr( name );
1418 static HRESULT WINAPI domdoc_transformNodeToObject(
1419 IXMLDOMDocument3 *iface,
1420 IXMLDOMNode* stylesheet,
1421 VARIANT outputObject)
1423 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1424 FIXME("(%p)->(%p %s)\n", This, stylesheet, debugstr_variant(&outputObject));
1429 static HRESULT WINAPI domdoc_get_doctype(
1430 IXMLDOMDocument3 *iface,
1431 IXMLDOMDocumentType** doctype )
1433 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1438 TRACE("(%p)->(%p)\n", This, doctype);
1440 if (!doctype) return E_INVALIDARG;
1444 dtd = xmlGetIntSubset(get_doc(This));
1445 if (!dtd) return S_FALSE;
1447 node = create_node((xmlNodePtr)dtd);
1448 if (!node) return S_FALSE;
1450 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentType, (void**)doctype);
1451 IXMLDOMNode_Release(node);
1457 static HRESULT WINAPI domdoc_get_implementation(
1458 IXMLDOMDocument3 *iface,
1459 IXMLDOMImplementation** impl )
1461 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1463 TRACE("(%p)->(%p)\n", This, impl);
1466 return E_INVALIDARG;
1468 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1473 static HRESULT WINAPI domdoc_get_documentElement(
1474 IXMLDOMDocument3 *iface,
1475 IXMLDOMElement** DOMElement )
1477 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1478 IXMLDOMNode *element_node;
1482 TRACE("(%p)->(%p)\n", This, DOMElement);
1485 return E_INVALIDARG;
1489 root = xmlDocGetRootElement( get_doc(This) );
1493 element_node = create_node( root );
1494 if(!element_node) return S_FALSE;
1496 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1497 IXMLDOMNode_Release(element_node);
1503 static HRESULT WINAPI domdoc_put_documentElement(
1504 IXMLDOMDocument3 *iface,
1505 IXMLDOMElement* DOMElement )
1507 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1508 IXMLDOMNode *elementNode;
1513 TRACE("(%p)->(%p)\n", This, DOMElement);
1515 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1519 xmlNode = get_node_obj( elementNode );
1520 if(!xmlNode) return E_FAIL;
1522 if(!xmlNode->node->parent)
1523 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1524 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1526 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1527 IXMLDOMNode_Release( elementNode );
1530 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1536 static HRESULT WINAPI domdoc_createElement(
1537 IXMLDOMDocument3 *iface,
1539 IXMLDOMElement** element )
1541 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1546 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1548 if (!element || !tagname) return E_INVALIDARG;
1550 V_VT(&type) = VT_I1;
1551 V_I1(&type) = NODE_ELEMENT;
1553 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1556 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1557 IXMLDOMNode_Release(node);
1564 static HRESULT WINAPI domdoc_createDocumentFragment(
1565 IXMLDOMDocument3 *iface,
1566 IXMLDOMDocumentFragment** frag )
1568 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1573 TRACE("(%p)->(%p)\n", This, frag);
1575 if (!frag) return E_INVALIDARG;
1579 V_VT(&type) = VT_I1;
1580 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1582 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1585 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1586 IXMLDOMNode_Release(node);
1593 static HRESULT WINAPI domdoc_createTextNode(
1594 IXMLDOMDocument3 *iface,
1596 IXMLDOMText** text )
1598 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1603 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1605 if (!text) return E_INVALIDARG;
1609 V_VT(&type) = VT_I1;
1610 V_I1(&type) = NODE_TEXT;
1612 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1615 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1616 IXMLDOMNode_Release(node);
1617 hr = IXMLDOMText_put_data(*text, data);
1624 static HRESULT WINAPI domdoc_createComment(
1625 IXMLDOMDocument3 *iface,
1627 IXMLDOMComment** comment )
1629 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1634 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1636 if (!comment) return E_INVALIDARG;
1640 V_VT(&type) = VT_I1;
1641 V_I1(&type) = NODE_COMMENT;
1643 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1646 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1647 IXMLDOMNode_Release(node);
1648 hr = IXMLDOMComment_put_data(*comment, data);
1655 static HRESULT WINAPI domdoc_createCDATASection(
1656 IXMLDOMDocument3 *iface,
1658 IXMLDOMCDATASection** cdata )
1660 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1665 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1667 if (!cdata) return E_INVALIDARG;
1671 V_VT(&type) = VT_I1;
1672 V_I1(&type) = NODE_CDATA_SECTION;
1674 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1677 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1678 IXMLDOMNode_Release(node);
1679 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1686 static HRESULT WINAPI domdoc_createProcessingInstruction(
1687 IXMLDOMDocument3 *iface,
1690 IXMLDOMProcessingInstruction** pi )
1692 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1697 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1699 if (!pi) return E_INVALIDARG;
1703 V_VT(&type) = VT_I1;
1704 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1706 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1711 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1712 node_obj = get_node_obj(node);
1713 hr = node_set_content(node_obj, data);
1715 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1716 IXMLDOMNode_Release(node);
1723 static HRESULT WINAPI domdoc_createAttribute(
1724 IXMLDOMDocument3 *iface,
1726 IXMLDOMAttribute** attribute )
1728 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1733 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1735 if (!attribute || !name) return E_INVALIDARG;
1737 V_VT(&type) = VT_I1;
1738 V_I1(&type) = NODE_ATTRIBUTE;
1740 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1743 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1744 IXMLDOMNode_Release(node);
1751 static HRESULT WINAPI domdoc_createEntityReference(
1752 IXMLDOMDocument3 *iface,
1754 IXMLDOMEntityReference** entityref )
1756 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1761 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1763 if (!entityref) return E_INVALIDARG;
1767 V_VT(&type) = VT_I1;
1768 V_I1(&type) = NODE_ENTITY_REFERENCE;
1770 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1773 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1774 IXMLDOMNode_Release(node);
1780 xmlChar* tagName_to_XPath(const BSTR tagName)
1782 xmlChar *query, *tmp;
1783 static const xmlChar mod_pre[] = "*[local-name()='";
1784 static const xmlChar mod_post[] = "']";
1785 static const xmlChar prefix[] = "descendant::";
1786 const WCHAR *tokBegin, *tokEnd;
1789 query = xmlStrdup(prefix);
1792 while (tokBegin && *tokBegin)
1797 query = xmlStrcat(query, BAD_CAST "/");
1801 query = xmlStrcat(query, BAD_CAST "*");
1805 query = xmlStrcat(query, mod_pre);
1807 while (*tokEnd && *tokEnd != '/')
1809 len = WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, NULL, 0, NULL, NULL);
1810 tmp = xmlMalloc(len);
1811 WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, (char*)tmp, len, NULL, NULL);
1812 query = xmlStrncat(query, tmp, len);
1815 query = xmlStrcat(query, mod_post);
1822 static HRESULT WINAPI domdoc_getElementsByTagName(
1823 IXMLDOMDocument3 *iface,
1825 IXMLDOMNodeList** resultList )
1827 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1832 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1834 if (!tagName || !resultList) return E_INVALIDARG;
1836 XPath = This->properties->XPath;
1837 This->properties->XPath = TRUE;
1838 query = tagName_to_XPath(tagName);
1839 hr = create_selection((xmlNodePtr)get_doc(This), query, resultList);
1841 This->properties->XPath = XPath;
1846 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1852 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1854 return E_INVALIDARG;
1861 static HRESULT WINAPI domdoc_createNode(
1862 IXMLDOMDocument3 *iface,
1866 IXMLDOMNode** node )
1868 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1869 DOMNodeType node_type;
1871 xmlChar *xml_name, *href;
1874 TRACE("(%p)->(%s %s %s %p)\n", This, debugstr_variant(&Type), debugstr_w(name), debugstr_w(namespaceURI), node);
1876 if(!node) return E_INVALIDARG;
1878 hr = get_node_type(Type, &node_type);
1879 if(FAILED(hr)) return hr;
1881 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1882 FIXME("nodes with namespaces currently not supported.\n");
1884 TRACE("node_type %d\n", node_type);
1886 /* exit earlier for types that need name */
1890 case NODE_ATTRIBUTE:
1891 case NODE_ENTITY_REFERENCE:
1892 case NODE_PROCESSING_INSTRUCTION:
1893 if (!name || *name == 0) return E_FAIL;
1899 xml_name = xmlchar_from_wchar(name);
1900 /* prevent empty href to be allocated */
1901 href = namespaceURI ? xmlchar_from_wchar(namespaceURI) : NULL;
1907 xmlChar *local, *prefix;
1909 local = xmlSplitQName2(xml_name, &prefix);
1911 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
1913 /* allow to create default namespace xmlns= */
1914 if (local || (href && *href))
1916 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
1917 xmlSetNs(xmlnode, ns);
1925 case NODE_ATTRIBUTE:
1926 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1929 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1931 case NODE_CDATA_SECTION:
1932 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1934 case NODE_ENTITY_REFERENCE:
1935 xmlnode = xmlNewReference(get_doc(This), xml_name);
1937 case NODE_PROCESSING_INSTRUCTION:
1938 #ifdef HAVE_XMLNEWDOCPI
1939 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1941 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1946 xmlnode = xmlNewDocComment(get_doc(This), NULL);
1948 case NODE_DOCUMENT_FRAGMENT:
1949 xmlnode = xmlNewDocFragment(get_doc(This));
1951 /* unsupported types */
1953 case NODE_DOCUMENT_TYPE:
1956 heap_free(xml_name);
1957 return E_INVALIDARG;
1959 FIXME("unhandled node type %d\n", node_type);
1964 *node = create_node(xmlnode);
1965 heap_free(xml_name);
1970 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1971 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1978 static HRESULT WINAPI domdoc_nodeFromID(
1979 IXMLDOMDocument3 *iface,
1981 IXMLDOMNode** node )
1983 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1984 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1988 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1993 xmldoc = doparse(This, ptr, len, XML_CHAR_ENCODING_NONE);
1995 xmldoc->_private = create_priv();
1996 return attach_xmldoc(This, xmldoc);
2002 static HRESULT domdoc_load_moniker(domdoc *This, IMoniker *mon)
2007 hr = bind_url(mon, domdoc_onDataAvailable, This, &bsc);
2012 hr = detach_bsc(This->bsc);
2021 static HRESULT WINAPI domdoc_load(
2022 IXMLDOMDocument3 *iface,
2024 VARIANT_BOOL* isSuccessful )
2026 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2027 LPWSTR filename = NULL;
2028 HRESULT hr = S_FALSE;
2029 IXMLDOMDocument3 *pNewDoc = NULL;
2030 IStream *pStream = NULL;
2033 TRACE("(%p)->(%s)\n", This, debugstr_variant(&source));
2037 *isSuccessful = VARIANT_FALSE;
2039 assert( &This->node );
2041 switch( V_VT(&source) )
2044 filename = V_BSTR(&source);
2046 case VT_BSTR|VT_BYREF:
2047 if (!V_BSTRREF(&source)) return E_INVALIDARG;
2048 filename = *V_BSTRREF(&source);
2050 case VT_ARRAY|VT_UI1:
2052 SAFEARRAY *psa = V_ARRAY(&source);
2055 UINT dim = SafeArrayGetDim(psa);
2060 ERR("SAFEARRAY == NULL\n");
2061 hr = This->error = E_INVALIDARG;
2064 /* Only takes UTF-8 strings.
2065 * NOT NULL-terminated. */
2066 SafeArrayAccessData(psa, (void**)&str);
2067 SafeArrayGetUBound(psa, 1, &len);
2069 if ((xmldoc = doparse(This, str, ++len, XML_CHAR_ENCODING_UTF8)))
2071 hr = This->error = S_OK;
2072 *isSuccessful = VARIANT_TRUE;
2073 TRACE("parsed document %p\n", xmldoc);
2077 This->error = E_FAIL;
2078 TRACE("failed to parse document\n");
2081 SafeArrayUnaccessData(psa);
2085 xmldoc->_private = create_priv();
2086 return attach_xmldoc(This, xmldoc);
2090 FIXME("unhandled SAFEARRAY dim: %d\n", dim);
2091 hr = This->error = E_NOTIMPL;
2096 if (!V_UNKNOWN(&source)) return E_INVALIDARG;
2097 hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
2102 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
2104 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
2105 xmldoc->_private = create_priv();
2106 hr = attach_xmldoc(This, xmldoc);
2109 *isSuccessful = VARIANT_TRUE;
2114 hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IStream, (void**)&pStream);
2117 IPersistStream *pDocStream;
2118 hr = IXMLDOMDocument3_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
2121 hr = IPersistStream_Load(pDocStream, pStream);
2122 IStream_Release(pStream);
2125 *isSuccessful = VARIANT_TRUE;
2127 TRACE("Using IStream to load Document\n");
2132 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
2137 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
2142 /* ISequentialStream */
2143 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&source)->lpVtbl);
2147 FIXME("VT type not supported (%d)\n", V_VT(&source));
2154 hr = create_moniker_from_url( filename, &mon);
2155 if ( SUCCEEDED(hr) )
2157 hr = domdoc_load_moniker( This, mon );
2158 IMoniker_Release(mon);
2162 This->error = E_FAIL;
2165 hr = This->error = S_OK;
2166 *isSuccessful = VARIANT_TRUE;
2170 if(!filename || FAILED(hr)) {
2171 xmldoc = xmlNewDoc(NULL);
2172 xmldoc->_private = create_priv();
2173 hr = attach_xmldoc(This, xmldoc);
2178 TRACE("ret (%d)\n", hr);
2184 static HRESULT WINAPI domdoc_get_readyState(
2185 IXMLDOMDocument3 *iface,
2188 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2189 FIXME("stub! (%p)->(%p)\n", This, value);
2192 return E_INVALIDARG;
2194 *value = READYSTATE_COMPLETE;
2199 static HRESULT WINAPI domdoc_get_parseError(
2200 IXMLDOMDocument3 *iface,
2201 IXMLDOMParseError** errorObj )
2203 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2204 static const WCHAR err[] = {'e','r','r','o','r',0};
2205 BSTR error_string = NULL;
2207 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2210 error_string = SysAllocString(err);
2212 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2213 if(!*errorObj) return E_OUTOFMEMORY;
2218 static HRESULT WINAPI domdoc_get_url(
2219 IXMLDOMDocument3 *iface,
2222 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2223 FIXME("(%p)->(%p)\n", This, urlString);
2228 static HRESULT WINAPI domdoc_get_async(
2229 IXMLDOMDocument3 *iface,
2230 VARIANT_BOOL* isAsync )
2232 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2234 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2235 *isAsync = This->async;
2240 static HRESULT WINAPI domdoc_put_async(
2241 IXMLDOMDocument3 *iface,
2242 VARIANT_BOOL isAsync )
2244 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2246 TRACE("(%p)->(%d)\n", This, isAsync);
2247 This->async = isAsync;
2252 static HRESULT WINAPI domdoc_abort(
2253 IXMLDOMDocument3 *iface )
2255 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2256 FIXME("%p\n", This);
2260 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2261 static HRESULT WINAPI domdoc_loadXML(
2262 IXMLDOMDocument3 *iface,
2264 VARIANT_BOOL* isSuccessful )
2266 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2267 xmlDocPtr xmldoc = NULL;
2268 HRESULT hr = S_FALSE, hr2;
2270 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), isSuccessful );
2272 assert ( &This->node );
2276 *isSuccessful = VARIANT_FALSE;
2282 /* skip leading spaces if needed */
2283 if (This->properties->version == MSXML_DEFAULT || This->properties->version == MSXML26)
2284 while (*ptr && isspaceW(*ptr)) ptr++;
2286 xmldoc = doparse(This, (char*)ptr, strlenW(ptr)*sizeof(WCHAR), XML_CHAR_ENCODING_UTF16LE);
2289 This->error = E_FAIL;
2290 TRACE("failed to parse document\n");
2294 hr = This->error = S_OK;
2295 *isSuccessful = VARIANT_TRUE;
2296 TRACE("parsed document %p\n", xmldoc);
2302 xmldoc = xmlNewDoc(NULL);
2303 xmldoc->_private = create_priv();
2304 hr2 = attach_xmldoc(This, xmldoc);
2311 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2315 if(!WriteFile(ctx, buffer, len, &written, NULL))
2317 WARN("write error\n");
2324 static int XMLCALL domdoc_save_closecallback(void *ctx)
2326 return CloseHandle(ctx) ? 0 : -1;
2329 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2334 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2335 TRACE("0x%08x %p %d %u\n", hr, buffer, len, written);
2338 WARN("stream write error: 0x%08x\n", hr);
2345 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2347 IStream_Release((IStream*)ctx);
2351 static HRESULT WINAPI domdoc_save(
2352 IXMLDOMDocument3 *iface,
2353 VARIANT destination )
2355 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2356 xmlSaveCtxtPtr ctx = NULL;
2360 TRACE("(%p)->(%s)\n", This, debugstr_variant(&destination));
2362 switch (V_VT(&destination))
2366 IUnknown *pUnk = V_UNKNOWN(&destination);
2367 IXMLDOMDocument3 *document;
2370 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2373 VARIANT_BOOL success;
2376 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2379 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2383 IXMLDOMDocument3_Release(document);
2387 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2390 int options = get_doc(This)->standalone == -1 ? XML_SAVE_NO_DECL : 0;
2391 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2392 domdoc_stream_save_closecallback, stream, NULL, options);
2396 IStream_Release(stream);
2404 case VT_BSTR | VT_BYREF:
2406 int options = get_doc(This)->standalone == -1 ? XML_SAVE_NO_DECL : 0;
2408 /* save with file path */
2409 HANDLE handle = CreateFileW( (V_VT(&destination) & VT_BYREF)? *V_BSTRREF(&destination) : V_BSTR(&destination),
2410 GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2411 if( handle == INVALID_HANDLE_VALUE )
2413 WARN("failed to create file\n");
2417 /* disable top XML declaration */
2418 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2419 handle, NULL, options);
2422 CloseHandle(handle);
2429 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination));
2433 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2434 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2435 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2437 /* will release resources through close callback */
2443 static HRESULT WINAPI domdoc_get_validateOnParse(
2444 IXMLDOMDocument3 *iface,
2445 VARIANT_BOOL* isValidating )
2447 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2448 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2449 *isValidating = This->validating;
2454 static HRESULT WINAPI domdoc_put_validateOnParse(
2455 IXMLDOMDocument3 *iface,
2456 VARIANT_BOOL isValidating )
2458 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2459 TRACE("(%p)->(%d)\n", This, isValidating);
2460 This->validating = isValidating;
2465 static HRESULT WINAPI domdoc_get_resolveExternals(
2466 IXMLDOMDocument3 *iface,
2467 VARIANT_BOOL* isResolving )
2469 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2470 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2471 *isResolving = This->resolving;
2476 static HRESULT WINAPI domdoc_put_resolveExternals(
2477 IXMLDOMDocument3 *iface,
2478 VARIANT_BOOL isResolving )
2480 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2481 TRACE("(%p)->(%d)\n", This, isResolving);
2482 This->resolving = isResolving;
2487 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2488 IXMLDOMDocument3 *iface,
2489 VARIANT_BOOL* isPreserving )
2491 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2492 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->properties->preserving);
2493 *isPreserving = This->properties->preserving;
2498 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2499 IXMLDOMDocument3 *iface,
2500 VARIANT_BOOL isPreserving )
2502 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2503 TRACE("(%p)->(%d)\n", This, isPreserving);
2504 This->properties->preserving = isPreserving;
2509 static HRESULT WINAPI domdoc_put_onreadystatechange(
2510 IXMLDOMDocument3 *iface,
2513 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2515 TRACE("(%p)->(%s)\n", This, debugstr_variant(&event));
2516 return set_doc_event(This, EVENTID_READYSTATECHANGE, &event);
2520 static HRESULT WINAPI domdoc_put_onDataAvailable(IXMLDOMDocument3 *iface, VARIANT sink)
2522 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2523 FIXME("(%p)->(%s): stub\n", This, debugstr_variant(&sink));
2527 static HRESULT WINAPI domdoc_put_onTransformNode(IXMLDOMDocument3 *iface, VARIANT sink )
2529 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2530 FIXME("(%p)->(%s): stub\n", This, debugstr_variant(&sink));
2534 static HRESULT WINAPI domdoc_get_namespaces(
2535 IXMLDOMDocument3* iface,
2536 IXMLDOMSchemaCollection** collection )
2538 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2541 FIXME("(%p)->(%p): semi-stub\n", This, collection);
2543 if (!collection) return E_POINTER;
2545 if (!This->namespaces)
2547 hr = SchemaCache_create(This->properties->version, NULL, (void**)&This->namespaces);
2548 if (hr != S_OK) return hr;
2550 hr = cache_from_doc_ns(This->namespaces, &This->node);
2552 release_namespaces(This);
2555 if (This->namespaces)
2556 return IXMLDOMSchemaCollection2_QueryInterface(This->namespaces,
2557 &IID_IXMLDOMSchemaCollection, (void**)collection);
2562 static HRESULT WINAPI domdoc_get_schemas(
2563 IXMLDOMDocument3* iface,
2566 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2567 IXMLDOMSchemaCollection2* cur_schema = This->properties->schemaCache;
2568 HRESULT hr = S_FALSE;
2570 TRACE("(%p)->(%p)\n", This, schema);
2572 V_VT(schema) = VT_NULL;
2573 /* just to reset pointer part, cause that's what application is expected to use */
2574 V_DISPATCH(schema) = NULL;
2578 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(schema));
2580 V_VT(schema) = VT_DISPATCH;
2585 static HRESULT WINAPI domdoc_putref_schemas(
2586 IXMLDOMDocument3* iface,
2589 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2590 HRESULT hr = E_FAIL;
2591 IXMLDOMSchemaCollection2* new_schema = NULL;
2593 FIXME("(%p)->(%s): semi-stub\n", This, debugstr_variant(&schema));
2594 switch(V_VT(&schema))
2597 if (V_UNKNOWN(&schema))
2599 hr = IUnknown_QueryInterface(V_UNKNOWN(&schema), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2604 if (V_DISPATCH(&schema))
2606 hr = IDispatch_QueryInterface(V_DISPATCH(&schema), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2616 WARN("Can't get schema from vt %x\n", V_VT(&schema));
2621 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->properties->schemaCache, new_schema);
2622 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2628 static inline BOOL is_wellformed(xmlDocPtr doc)
2630 #ifdef HAVE_XMLDOC_PROPERTIES
2631 return doc->properties & XML_DOC_WELLFORMED;
2633 /* Not a full check, but catches the worst violations */
2637 for (child = doc->children; child != NULL; child = child->next)
2639 switch (child->type)
2641 case XML_ELEMENT_NODE:
2646 case XML_CDATA_SECTION_NODE:
2658 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2662 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2666 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2670 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2674 static HRESULT WINAPI domdoc_validateNode(
2675 IXMLDOMDocument3* iface,
2677 IXMLDOMParseError** err)
2679 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2680 LONG state, err_code = 0;
2684 TRACE("(%p)->(%p, %p)\n", This, node, err);
2685 IXMLDOMDocument3_get_readyState(iface, &state);
2686 if (state != READYSTATE_COMPLETE)
2689 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2696 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2700 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2703 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2707 if (!is_wellformed(get_doc(This)))
2709 ERR("doc not well-formed\n");
2711 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2715 /* DTD validation */
2716 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2718 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2719 vctx->error = validate_error;
2720 vctx->warning = validate_warning;
2723 if (!((node == (IXMLDOMNode*)iface)?
2724 xmlValidateDocument(vctx, get_doc(This)) :
2725 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2727 /* TODO: get a real error code here */
2728 TRACE("DTD validation failed\n");
2729 err_code = E_XML_INVALID;
2732 xmlFreeValidCtxt(vctx);
2735 /* Schema validation */
2736 if (hr == S_OK && This->properties->schemaCache != NULL)
2739 hr = SchemaCache_validate_tree(This->properties->schemaCache, get_node_obj(node)->node);
2743 /* TODO: get a real error code here */
2746 TRACE("schema validation succeeded\n");
2750 ERR("schema validation failed\n");
2751 err_code = E_XML_INVALID;
2756 /* not really OK, just didn't find a schema for the ns */
2763 ERR("no DTD or schema found\n");
2764 err_code = E_XML_NODTD;
2769 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2774 static HRESULT WINAPI domdoc_validate(
2775 IXMLDOMDocument3* iface,
2776 IXMLDOMParseError** err)
2778 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2779 TRACE("(%p)->(%p)\n", This, err);
2780 return IXMLDOMDocument3_validateNode(iface, (IXMLDOMNode*)iface, err);
2783 static HRESULT WINAPI domdoc_setProperty(
2784 IXMLDOMDocument3* iface,
2788 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2790 TRACE("(%p)->(%s %s)\n", This, debugstr_w(p), debugstr_variant(&value));
2792 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2798 V_VT(&varStr) = VT_EMPTY;
2799 if (V_VT(&value) != VT_BSTR)
2801 if (FAILED(hr = VariantChangeType(&varStr, &value, 0, VT_BSTR)))
2803 bstr = V_BSTR(&varStr);
2806 bstr = V_BSTR(&value);
2809 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2810 This->properties->XPath = TRUE;
2811 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2812 This->properties->XPath = FALSE;
2816 VariantClear(&varStr);
2819 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2821 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2822 struct list *pNsList;
2827 V_VT(&varStr) = VT_EMPTY;
2828 if (V_VT(&value) != VT_BSTR)
2830 if (FAILED(hr = VariantChangeType(&varStr, &value, 0, VT_BSTR)))
2832 bstr = V_BSTR(&varStr);
2835 bstr = V_BSTR(&value);
2839 pNsList = &(This->properties->selectNsList);
2840 clear_selectNsList(pNsList);
2842 nsStr = xmlchar_from_wchar(bstr);
2844 TRACE("property value: \"%s\"\n", debugstr_w(bstr));
2846 This->properties->selectNsStr = nsStr;
2847 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2850 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2851 select_ns_entry* ns_entry = NULL;
2852 xmlXPathContextPtr ctx;
2854 ctx = xmlXPathNewContext(This->node.node->doc);
2857 /* skip leading spaces */
2858 while (*pTokBegin == ' ' || *pTokBegin == '\n' ||
2859 *pTokBegin == '\t' || *pTokBegin == '\r')
2862 for (; *pTokBegin; pTokBegin = pTokEnd)
2865 memset(ns_entry, 0, sizeof(select_ns_entry));
2867 ns_entry = heap_alloc_zero(sizeof(select_ns_entry));
2869 while (*pTokBegin == ' ')
2871 pTokEnd = pTokBegin;
2872 while (*pTokEnd != ' ' && *pTokEnd != 0)
2875 /* so it failed to advance which means we've got some trailing spaces */
2876 if (pTokEnd == pTokBegin) break;
2878 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2881 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2882 debugstr_w(bstr), debugstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2887 if (*pTokBegin == '=')
2889 /*valid for XSLPattern?*/
2890 FIXME("Setting default xmlns not supported - skipping.\n");
2893 else if (*pTokBegin == ':')
2895 ns_entry->prefix = ++pTokBegin;
2896 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2899 if (pTokInner == pTokEnd)
2902 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2903 debugstr_w(bstr), debugstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2907 ns_entry->prefix_end = *pTokInner;
2911 if (pTokEnd-pTokInner > 1 &&
2912 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2913 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2915 ns_entry->href = ++pTokInner;
2916 ns_entry->href_end = *(pTokEnd-1);
2918 list_add_tail(pNsList, &ns_entry->entry);
2919 /*let libxml figure out if they're valid from here ;)*/
2920 if (xmlXPathRegisterNs(ctx, ns_entry->prefix, ns_entry->href) != 0)
2929 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2930 debugstr_w(bstr), debugstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2931 list_add_tail(pNsList, &ns_entry->entry);
2944 heap_free(ns_entry);
2945 xmlXPathFreeContext(ctx);
2948 VariantClear(&varStr);
2951 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2952 lstrcmpiW(p, PropertyNewParserW) == 0 ||
2953 lstrcmpiW(p, PropertyResolveExternalsW) == 0)
2956 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&value));
2960 FIXME("Unknown property %s\n", debugstr_w(p));
2964 static HRESULT WINAPI domdoc_getProperty(
2965 IXMLDOMDocument3* iface,
2969 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2971 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2974 return E_INVALIDARG;
2976 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2978 V_VT(var) = VT_BSTR;
2979 V_BSTR(var) = This->properties->XPath ?
2980 SysAllocString(PropValueXPathW) :
2981 SysAllocString(PropValueXSLPatternW);
2982 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2984 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2987 BSTR rebuiltStr, cur;
2988 const xmlChar *nsStr;
2989 struct list *pNsList;
2990 select_ns_entry* pNsEntry;
2992 V_VT(var) = VT_BSTR;
2993 nsStr = This->properties->selectNsStr;
2994 pNsList = &This->properties->selectNsList;
2995 lenA = This->properties->selectNsStr_len;
2996 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
2997 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
2998 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
3000 /* this is fine because all of the chars that end tokens are ASCII*/
3001 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
3003 while (*cur != 0) ++cur;
3004 if (pNsEntry->prefix_end)
3006 *cur = pNsEntry->prefix_end;
3007 while (*cur != 0) ++cur;
3010 if (pNsEntry->href_end)
3012 *cur = pNsEntry->href_end;
3015 V_BSTR(var) = SysAllocString(rebuiltStr);
3016 heap_free(rebuiltStr);
3020 FIXME("Unknown property %s\n", debugstr_w(p));
3024 static HRESULT WINAPI domdoc_importNode(
3025 IXMLDOMDocument3* iface,
3028 IXMLDOMNode** clone)
3030 domdoc *This = impl_from_IXMLDOMDocument3( iface );
3031 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
3035 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl =
3037 domdoc_QueryInterface,
3040 domdoc_GetTypeInfoCount,
3042 domdoc_GetIDsOfNames,
3044 domdoc_get_nodeName,
3045 domdoc_get_nodeValue,
3046 domdoc_put_nodeValue,
3047 domdoc_get_nodeType,
3048 domdoc_get_parentNode,
3049 domdoc_get_childNodes,
3050 domdoc_get_firstChild,
3051 domdoc_get_lastChild,
3052 domdoc_get_previousSibling,
3053 domdoc_get_nextSibling,
3054 domdoc_get_attributes,
3055 domdoc_insertBefore,
3056 domdoc_replaceChild,
3059 domdoc_hasChildNodes,
3060 domdoc_get_ownerDocument,
3062 domdoc_get_nodeTypeString,
3065 domdoc_get_specified,
3066 domdoc_get_definition,
3067 domdoc_get_nodeTypedValue,
3068 domdoc_put_nodeTypedValue,
3069 domdoc_get_dataType,
3070 domdoc_put_dataType,
3072 domdoc_transformNode,
3074 domdoc_selectSingleNode,
3076 domdoc_get_namespaceURI,
3078 domdoc_get_baseName,
3079 domdoc_transformNodeToObject,
3081 domdoc_get_implementation,
3082 domdoc_get_documentElement,
3083 domdoc_put_documentElement,
3084 domdoc_createElement,
3085 domdoc_createDocumentFragment,
3086 domdoc_createTextNode,
3087 domdoc_createComment,
3088 domdoc_createCDATASection,
3089 domdoc_createProcessingInstruction,
3090 domdoc_createAttribute,
3091 domdoc_createEntityReference,
3092 domdoc_getElementsByTagName,
3096 domdoc_get_readyState,
3097 domdoc_get_parseError,
3104 domdoc_get_validateOnParse,
3105 domdoc_put_validateOnParse,
3106 domdoc_get_resolveExternals,
3107 domdoc_put_resolveExternals,
3108 domdoc_get_preserveWhiteSpace,
3109 domdoc_put_preserveWhiteSpace,
3110 domdoc_put_onreadystatechange,
3111 domdoc_put_onDataAvailable,
3112 domdoc_put_onTransformNode,
3113 domdoc_get_namespaces,
3115 domdoc_putref_schemas,
3119 domdoc_validateNode,
3123 /* IConnectionPointContainer */
3124 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
3125 REFIID riid, void **ppv)
3127 domdoc *This = impl_from_IConnectionPointContainer(iface);
3128 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppv);
3131 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
3133 domdoc *This = impl_from_IConnectionPointContainer(iface);
3134 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3137 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
3139 domdoc *This = impl_from_IConnectionPointContainer(iface);
3140 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3143 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
3144 IEnumConnectionPoints **ppEnum)
3146 domdoc *This = impl_from_IConnectionPointContainer(iface);
3147 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3151 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
3152 REFIID riid, IConnectionPoint **cp)
3154 domdoc *This = impl_from_IConnectionPointContainer(iface);
3155 ConnectionPoint *iter;
3157 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
3161 for(iter = This->cp_list; iter; iter = iter->next)
3163 if (IsEqualGUID(iter->iid, riid))
3164 *cp = &iter->IConnectionPoint_iface;
3169 IConnectionPoint_AddRef(*cp);
3173 FIXME("unsupported riid %s\n", debugstr_guid(riid));
3174 return CONNECT_E_NOCONNECTION;
3178 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
3180 ConnectionPointContainer_QueryInterface,
3181 ConnectionPointContainer_AddRef,
3182 ConnectionPointContainer_Release,
3183 ConnectionPointContainer_EnumConnectionPoints,
3184 ConnectionPointContainer_FindConnectionPoint
3187 /* IConnectionPoint */
3188 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
3189 REFIID riid, void **ppv)
3191 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3193 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3197 if (IsEqualGUID(&IID_IUnknown, riid) ||
3198 IsEqualGUID(&IID_IConnectionPoint, riid))
3205 IConnectionPoint_AddRef(iface);
3209 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3210 return E_NOINTERFACE;
3213 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3215 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3216 return IConnectionPointContainer_AddRef(This->container);
3219 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3221 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3222 return IConnectionPointContainer_Release(This->container);
3225 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3227 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3229 TRACE("(%p)->(%p)\n", This, iid);
3231 if (!iid) return E_POINTER;
3237 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3238 IConnectionPointContainer **container)
3240 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3242 TRACE("(%p)->(%p)\n", This, container);
3244 if (!container) return E_POINTER;
3246 *container = This->container;
3247 IConnectionPointContainer_AddRef(*container);
3251 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
3254 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3255 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
3259 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3261 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3263 TRACE("(%p)->(%d)\n", This, cookie);
3265 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3266 return CONNECT_E_NOCONNECTION;
3268 IUnknown_Release(This->sinks[cookie-1].unk);
3269 This->sinks[cookie-1].unk = NULL;
3274 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3275 IEnumConnections **ppEnum)
3277 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3278 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3282 static const IConnectionPointVtbl ConnectionPointVtbl =
3284 ConnectionPoint_QueryInterface,
3285 ConnectionPoint_AddRef,
3286 ConnectionPoint_Release,
3287 ConnectionPoint_GetConnectionInterface,
3288 ConnectionPoint_GetConnectionPointContainer,
3289 ConnectionPoint_Advise,
3290 ConnectionPoint_Unadvise,
3291 ConnectionPoint_EnumConnections
3294 static void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3296 cp->IConnectionPoint_iface.lpVtbl = &ConnectionPointVtbl;
3302 cp->next = doc->cp_list;
3305 cp->container = &doc->IConnectionPointContainer_iface;
3308 /* domdoc implementation of IObjectWithSite */
3309 static HRESULT WINAPI
3310 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3312 domdoc *This = impl_from_IObjectWithSite(iface);
3313 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppvObject);
3316 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3318 domdoc *This = impl_from_IObjectWithSite(iface);
3319 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3322 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3324 domdoc *This = impl_from_IObjectWithSite(iface);
3325 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3328 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3330 domdoc *This = impl_from_IObjectWithSite(iface);
3332 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3337 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3340 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3342 domdoc *This = impl_from_IObjectWithSite(iface);
3344 TRACE("(%p)->(%p)\n", iface, punk);
3350 IUnknown_Release( This->site );
3357 IUnknown_AddRef( punk );
3360 IUnknown_Release( This->site );
3367 static const IObjectWithSiteVtbl domdocObjectSite =
3369 domdoc_ObjectWithSite_QueryInterface,
3370 domdoc_ObjectWithSite_AddRef,
3371 domdoc_ObjectWithSite_Release,
3372 domdoc_ObjectWithSite_SetSite,
3373 domdoc_ObjectWithSite_GetSite
3376 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3378 domdoc *This = impl_from_IObjectSafety(iface);
3379 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppv);
3382 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3384 domdoc *This = impl_from_IObjectSafety(iface);
3385 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3388 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3390 domdoc *This = impl_from_IObjectSafety(iface);
3391 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3394 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3396 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3397 DWORD *supported, DWORD *enabled)
3399 domdoc *This = impl_from_IObjectSafety(iface);
3401 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3403 if(!supported || !enabled) return E_POINTER;
3405 *supported = SAFETY_SUPPORTED_OPTIONS;
3406 *enabled = This->safeopt;
3411 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3412 DWORD mask, DWORD enabled)
3414 domdoc *This = impl_from_IObjectSafety(iface);
3415 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3417 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3420 This->safeopt = (This->safeopt & ~mask) | (mask & enabled);
3425 #undef SAFETY_SUPPORTED_OPTIONS
3427 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3428 domdoc_Safety_QueryInterface,
3429 domdoc_Safety_AddRef,
3430 domdoc_Safety_Release,
3431 domdoc_Safety_GetInterfaceSafetyOptions,
3432 domdoc_Safety_SetInterfaceSafetyOptions
3435 static const tid_t domdoc_iface_tids[] = {
3436 IXMLDOMDocument3_tid,
3440 static dispex_static_data_t domdoc_dispex = {
3442 IXMLDOMDocument3_tid,
3447 HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3451 doc = heap_alloc( sizeof (*doc) );
3453 return E_OUTOFMEMORY;
3455 doc->IXMLDOMDocument3_iface.lpVtbl = &XMLDOMDocument3Vtbl;
3456 doc->IPersistStreamInit_iface.lpVtbl = &xmldoc_IPersistStreamInit_VTable;
3457 doc->IObjectWithSite_iface.lpVtbl = &domdocObjectSite;
3458 doc->IObjectSafety_iface.lpVtbl = &domdocObjectSafetyVtbl;
3459 doc->IConnectionPointContainer_iface.lpVtbl = &ConnectionPointContainerVtbl;
3461 doc->async = VARIANT_TRUE;
3462 doc->validating = 0;
3464 doc->properties = properties_from_xmlDocPtr(xmldoc);
3470 doc->cp_list = NULL;
3471 doc->namespaces = NULL;
3472 memset(doc->events, 0, sizeof(doc->events));
3474 /* events connection points */
3475 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3476 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3477 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3479 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->IXMLDOMDocument3_iface,
3482 *document = &doc->IXMLDOMDocument3_iface;
3484 TRACE("returning iface %p\n", *document);
3488 HRESULT DOMDocument_create(MSXML_VERSION version, IUnknown *pUnkOuter, void **ppObj)
3493 TRACE("(%d, %p, %p)\n", version, pUnkOuter, ppObj);
3495 xmldoc = xmlNewDoc(NULL);
3497 return E_OUTOFMEMORY;
3499 xmldoc_init(xmldoc, version);
3501 hr = get_domdoc_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3504 free_properties(properties_from_xmlDocPtr(xmldoc));
3505 heap_free(xmldoc->_private);
3513 IUnknown* create_domdoc( xmlNodePtr document )
3518 TRACE("(%p)\n", document);
3520 hr = get_domdoc_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3529 HRESULT DOMDocument_create(MSXML_VERSION version, IUnknown *pUnkOuter, void **ppObj)
3531 MESSAGE("This program tried to use a DOMDocument object, but\n"
3532 "libxml2 support was not present at compile time.\n");