2 * DOM Document implementation
4 * Copyright 2005 Mike McCormack
5 * Copyright 2010 Adam Martinson for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define NONAMELESSUNION
30 # include <libxml/parser.h>
31 # include <libxml/xmlerror.h>
32 # include <libxml/xpathInternals.h>
33 # include <libxml/xmlsave.h>
34 # include <libxml/SAX2.h>
35 # include <libxml/parserInternals.h>
52 #include "wine/debug.h"
53 #include "wine/list.h"
55 #include "msxml_private.h"
57 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
61 /* not defined in older versions */
62 #define XML_SAVE_FORMAT 1
63 #define XML_SAVE_NO_DECL 2
64 #define XML_SAVE_NO_EMPTY 4
65 #define XML_SAVE_NO_XHTML 8
66 #define XML_SAVE_XHTML 16
67 #define XML_SAVE_AS_XML 32
68 #define XML_SAVE_AS_HTML 64
70 static const WCHAR PropertySelectionLanguageW[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
71 static const WCHAR PropertySelectionNamespacesW[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
72 static const WCHAR PropertyProhibitDTDW[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
73 static const WCHAR PropertyNewParserW[] = {'N','e','w','P','a','r','s','e','r',0};
74 static const WCHAR PropValueXPathW[] = {'X','P','a','t','h',0};
75 static const WCHAR PropValueXSLPatternW[] = {'X','S','L','P','a','t','t','e','r','n',0};
76 static const WCHAR PropertyResolveExternalsW[] = {'R','e','s','o','l','v','e','E','x','t','e','r','n','a','l','s',0};
78 /* Anything that passes the test_get_ownerDocument()
79 * tests can go here (data shared between all instances).
80 * We need to preserve this when reloading a document,
81 * and also need access to it from the libxml backend. */
82 typedef struct _domdoc_properties {
83 MSXML_VERSION version;
84 VARIANT_BOOL preserving;
85 IXMLDOMSchemaCollection2* schemaCache;
86 struct list selectNsList;
87 xmlChar const* selectNsStr;
92 typedef struct ConnectionPoint ConnectionPoint;
93 typedef struct domdoc domdoc;
95 struct ConnectionPoint
97 const IConnectionPointVtbl *lpVtblConnectionPoint;
100 ConnectionPoint *next;
101 IConnectionPointContainer *container;
108 IPropertyNotifySink *propnotif;
114 EVENTID_READYSTATECHANGE = 0,
115 EVENTID_DATAAVAILABLE,
116 EVENTID_TRANSFORMNODE,
123 const struct IXMLDOMDocument3Vtbl *lpVtbl;
124 const struct IPersistStreamInitVtbl *lpvtblIPersistStreamInit;
125 const struct IObjectWithSiteVtbl *lpvtblIObjectWithSite;
126 const struct IObjectSafetyVtbl *lpvtblIObjectSafety;
127 const struct ISupportErrorInfoVtbl *lpvtblISupportErrorInfo;
128 const struct IConnectionPointContainerVtbl *lpVtblConnectionPointContainer;
131 VARIANT_BOOL validating;
132 VARIANT_BOOL resolving;
133 domdoc_properties* properties;
146 /* connection list */
147 ConnectionPoint *cp_list;
148 ConnectionPoint cp_domdocevents;
149 ConnectionPoint cp_propnotif;
150 ConnectionPoint cp_dispatch;
153 IDispatch *events[EVENTID_LAST];
156 static HRESULT set_doc_event(domdoc *doc, eventid_t eid, const VARIANT *v)
164 IUnknown_QueryInterface(V_UNKNOWN(v), &IID_IDispatch, (void**)&disp);
169 disp = V_DISPATCH(v);
170 if (disp) IDispatch_AddRef(disp);
173 return DISP_E_TYPEMISMATCH;
176 if (doc->events[eid]) IDispatch_Release(doc->events[eid]);
177 doc->events[eid] = disp;
182 static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface)
184 return (ConnectionPoint *)((char*)iface - FIELD_OFFSET(ConnectionPoint, lpVtblConnectionPoint));
188 In native windows, the whole lifetime management of XMLDOMNodes is
189 managed automatically using reference counts. Wine emulates that by
190 maintaining a reference count to the document that is increased for
191 each IXMLDOMNode pointer passed out for this document. If all these
192 pointers are gone, the document is unreachable and gets freed, that
193 is, all nodes in the tree of the document get freed.
195 You are able to create nodes that are associated to a document (in
196 fact, in msxml's XMLDOM model, all nodes are associated to a document),
197 but not in the tree of that document, for example using the createFoo
198 functions from IXMLDOMDocument. These nodes do not get cleaned up
199 by libxml, so we have to do it ourselves.
201 To catch these nodes, a list of "orphan nodes" is introduced.
202 It contains pointers to all roots of node trees that are
203 associated with the document without being part of the document
204 tree. All nodes with parent==NULL (except for the document root nodes)
205 should be in the orphan node list of their document. All orphan nodes
206 get freed together with the document itself.
209 typedef struct _xmldoc_priv {
212 domdoc_properties* properties;
215 typedef struct _orphan_entry {
220 typedef struct _select_ns_entry {
222 xmlChar const* prefix;
228 static inline xmldoc_priv * priv_from_xmlDocPtr(const xmlDocPtr doc)
230 return doc->_private;
233 static inline domdoc_properties * properties_from_xmlDocPtr(xmlDocPtr doc)
235 return priv_from_xmlDocPtr(doc)->properties;
238 BOOL is_xpathmode(const xmlDocPtr doc)
240 return properties_from_xmlDocPtr(doc)->XPath;
243 void set_xpathmode(xmlDocPtr doc, BOOL xpath)
245 properties_from_xmlDocPtr(doc)->XPath = xpath;
248 int registerNamespaces(xmlXPathContextPtr ctxt)
251 const select_ns_entry* ns = NULL;
252 const struct list* pNsList = &properties_from_xmlDocPtr(ctxt->doc)->selectNsList;
254 TRACE("(%p)\n", ctxt);
256 LIST_FOR_EACH_ENTRY( ns, pNsList, select_ns_entry, entry )
258 xmlXPathRegisterNs(ctxt, ns->prefix, ns->href);
265 static inline void clear_selectNsList(struct list* pNsList)
267 select_ns_entry *ns, *ns2;
268 LIST_FOR_EACH_ENTRY_SAFE( ns, ns2, pNsList, select_ns_entry, entry )
275 static xmldoc_priv * create_priv(void)
278 priv = heap_alloc( sizeof (*priv) );
283 list_init( &priv->orphans );
284 priv->properties = NULL;
290 static domdoc_properties * create_properties(const GUID *clsid)
292 domdoc_properties *properties = heap_alloc(sizeof(domdoc_properties));
294 list_init(&properties->selectNsList);
295 properties->preserving = VARIANT_FALSE;
296 properties->schemaCache = NULL;
297 properties->selectNsStr = heap_alloc_zero(sizeof(xmlChar));
298 properties->selectNsStr_len = 0;
300 /* properties that are dependent on object versions */
301 if (IsEqualCLSID(clsid, &CLSID_DOMDocument30))
303 properties->version = MSXML3;
304 properties->XPath = FALSE;
306 else if (IsEqualCLSID(clsid, &CLSID_DOMDocument40))
308 properties->version = MSXML4;
309 properties->XPath = TRUE;
311 else if (IsEqualCLSID(clsid, &CLSID_DOMDocument60))
313 properties->version = MSXML6;
314 properties->XPath = TRUE;
318 properties->version = MSXML_DEFAULT;
319 properties->XPath = FALSE;
325 static domdoc_properties* copy_properties(domdoc_properties const* properties)
327 domdoc_properties* pcopy = heap_alloc(sizeof(domdoc_properties));
328 select_ns_entry const* ns = NULL;
329 select_ns_entry* new_ns = NULL;
330 int len = (properties->selectNsStr_len+1)*sizeof(xmlChar);
335 pcopy->version = properties->version;
336 pcopy->preserving = properties->preserving;
337 pcopy->schemaCache = properties->schemaCache;
338 if (pcopy->schemaCache)
339 IXMLDOMSchemaCollection2_AddRef(pcopy->schemaCache);
340 pcopy->XPath = properties->XPath;
341 pcopy->selectNsStr_len = properties->selectNsStr_len;
342 list_init( &pcopy->selectNsList );
343 pcopy->selectNsStr = heap_alloc(len);
344 memcpy((xmlChar*)pcopy->selectNsStr, properties->selectNsStr, len);
345 offset = pcopy->selectNsStr - properties->selectNsStr;
347 LIST_FOR_EACH_ENTRY( ns, (&properties->selectNsList), select_ns_entry, entry )
349 new_ns = heap_alloc(sizeof(select_ns_entry));
350 memcpy(new_ns, ns, sizeof(select_ns_entry));
351 new_ns->href += offset;
352 new_ns->prefix += offset;
353 list_add_tail(&pcopy->selectNsList, &new_ns->entry);
361 static void free_properties(domdoc_properties* properties)
365 if (properties->schemaCache)
366 IXMLDOMSchemaCollection2_Release(properties->schemaCache);
367 clear_selectNsList(&properties->selectNsList);
368 heap_free((xmlChar*)properties->selectNsStr);
369 heap_free(properties);
373 static BOOL xmldoc_has_decl(xmlDocPtr doc)
375 return doc->children && (xmlStrEqual(doc->children->name, (xmlChar*)"xml") == 1);
378 /* links a "<?xml" node as a first child */
379 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
382 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
385 /* unlinks a first "<?xml" child if it was created */
386 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
392 if (doc->standalone != -1)
394 node = doc->children;
395 xmlUnlinkNode( node );
403 BOOL is_preserving_whitespace(xmlNodePtr node)
405 domdoc_properties* properties = NULL;
406 /* during parsing the xmlDoc._private stuff is not there */
407 if (priv_from_xmlDocPtr(node->doc))
408 properties = properties_from_xmlDocPtr(node->doc);
409 return ((properties && properties->preserving == VARIANT_TRUE) ||
410 xmlNodeGetSpacePreserve(node) == 1);
413 static inline BOOL strn_isspace(xmlChar const* str, int len)
415 for (; str && len > 0 && *str; ++str, --len)
422 static void sax_characters(void *ctx, const xmlChar *ch, int len)
424 xmlParserCtxtPtr ctxt;
427 ctxt = (xmlParserCtxtPtr) ctx;
428 This = (const domdoc*) ctxt->_private;
432 /* during domdoc_loadXML() the xmlDocPtr->_private data is not available */
433 if (!This->properties->preserving &&
434 !is_preserving_whitespace(ctxt->node) &&
435 strn_isspace(ch, len))
439 xmlSAX2Characters(ctxt, ch, len);
442 static void LIBXML2_LOG_CALLBACK sax_error(void* ctx, char const* msg, ...)
446 LIBXML2_CALLBACK_ERR(doparse, msg, ap);
450 static void LIBXML2_LOG_CALLBACK sax_warning(void* ctx, char const* msg, ...)
454 LIBXML2_CALLBACK_WARN(doparse, msg, ap);
458 static void sax_serror(void* ctx, xmlErrorPtr err)
460 LIBXML2_CALLBACK_SERROR(doparse, err);
463 static xmlDocPtr doparse(domdoc* This, char *ptr, int len, xmlChar const* encoding)
465 xmlDocPtr doc = NULL;
466 xmlParserCtxtPtr pctx;
467 static xmlSAXHandler sax_handler = {
468 xmlSAX2InternalSubset, /* internalSubset */
469 xmlSAX2IsStandalone, /* isStandalone */
470 xmlSAX2HasInternalSubset, /* hasInternalSubset */
471 xmlSAX2HasExternalSubset, /* hasExternalSubset */
472 xmlSAX2ResolveEntity, /* resolveEntity */
473 xmlSAX2GetEntity, /* getEntity */
474 xmlSAX2EntityDecl, /* entityDecl */
475 xmlSAX2NotationDecl, /* notationDecl */
476 xmlSAX2AttributeDecl, /* attributeDecl */
477 xmlSAX2ElementDecl, /* elementDecl */
478 xmlSAX2UnparsedEntityDecl, /* unparsedEntityDecl */
479 xmlSAX2SetDocumentLocator, /* setDocumentLocator */
480 xmlSAX2StartDocument, /* startDocument */
481 xmlSAX2EndDocument, /* endDocument */
482 xmlSAX2StartElement, /* startElement */
483 xmlSAX2EndElement, /* endElement */
484 xmlSAX2Reference, /* reference */
485 sax_characters, /* characters */
486 sax_characters, /* ignorableWhitespace */
487 xmlSAX2ProcessingInstruction, /* processingInstruction */
488 xmlSAX2Comment, /* comment */
489 sax_warning, /* warning */
490 sax_error, /* error */
491 sax_error, /* fatalError */
492 xmlSAX2GetParameterEntity, /* getParameterEntity */
493 xmlSAX2CDataBlock, /* cdataBlock */
494 xmlSAX2ExternalSubset, /* externalSubset */
497 xmlSAX2StartElementNs, /* startElementNs */
498 xmlSAX2EndElementNs, /* endElementNs */
499 sax_serror /* serror */
503 pctx = xmlCreateMemoryParserCtxt(ptr, len);
506 ERR("Failed to create parser context\n");
510 if (pctx->sax) xmlFree(pctx->sax);
511 pctx->sax = &sax_handler;
512 pctx->_private = This;
514 pctx->encoding = xmlStrdup(encoding);
515 xmlParseDocument(pctx);
517 if (pctx->wellFormed)
523 xmlFreeDoc(pctx->myDoc);
527 xmlFreeParserCtxt(pctx);
529 /* TODO: put this in one of the SAX callbacks */
530 /* create first child as a <?xml...?> */
531 if (doc && doc->standalone != -1)
535 xmlChar *xmlbuff = (xmlChar*)buff;
537 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
539 /* version attribute can't be omitted */
540 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
541 xmlNodeAddContent( node, xmlbuff );
545 sprintf(buff, " encoding=\"%s\"", doc->encoding);
546 xmlNodeAddContent( node, xmlbuff );
549 if (doc->standalone != -2)
551 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
552 xmlNodeAddContent( node, xmlbuff );
555 xmldoc_link_xmldecl( doc, node );
561 void xmldoc_init(xmlDocPtr doc, const GUID *clsid)
563 doc->_private = create_priv();
564 priv_from_xmlDocPtr(doc)->properties = create_properties(clsid);
567 LONG xmldoc_add_ref(xmlDocPtr doc)
569 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
570 TRACE("(%p)->(%d)\n", doc, ref);
574 LONG xmldoc_release(xmlDocPtr doc)
576 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
577 LONG ref = InterlockedDecrement(&priv->refs);
578 TRACE("(%p)->(%d)\n", doc, ref);
581 orphan_entry *orphan, *orphan2;
582 TRACE("freeing docptr %p\n", doc);
584 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
586 xmlFreeNode( orphan->node );
589 free_properties(priv->properties);
590 heap_free(doc->_private);
598 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
600 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
603 entry = heap_alloc( sizeof (*entry) );
605 return E_OUTOFMEMORY;
608 list_add_head( &priv->orphans, &entry->entry );
612 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
614 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
615 orphan_entry *entry, *entry2;
617 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
619 if( entry->node == node )
621 list_remove( &entry->entry );
630 static inline xmlDocPtr get_doc( domdoc *This )
632 return (xmlDocPtr)This->node.node;
635 static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
639 priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
640 if (xmldoc_release(get_doc(This)) != 0)
641 priv_from_xmlDocPtr(get_doc(This))->properties =
642 copy_properties(This->properties);
645 This->node.node = (xmlNodePtr) xml;
649 xmldoc_add_ref(get_doc(This));
650 priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
656 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
658 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
661 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
663 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStreamInit));
666 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
668 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
671 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
673 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
676 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
678 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblISupportErrorInfo));
681 static inline domdoc *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
683 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtblConnectionPointContainer));
686 /************************************************************************
687 * domdoc implementation of IPersistStream.
689 static HRESULT WINAPI domdoc_IPersistStreamInit_QueryInterface(
690 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
692 domdoc* This = impl_from_IPersistStreamInit(iface);
693 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)&This->lpVtbl, riid, ppvObj);
696 static ULONG WINAPI domdoc_IPersistStreamInit_AddRef(
697 IPersistStreamInit *iface)
699 domdoc* This = impl_from_IPersistStreamInit(iface);
700 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)&This->lpVtbl);
703 static ULONG WINAPI domdoc_IPersistStreamInit_Release(
704 IPersistStreamInit *iface)
706 domdoc* This = impl_from_IPersistStreamInit(iface);
707 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)&This->lpVtbl);
710 static HRESULT WINAPI domdoc_IPersistStreamInit_GetClassID(
711 IPersistStreamInit *iface, CLSID *classid)
713 domdoc* This = impl_from_IPersistStreamInit(iface);
714 TRACE("(%p)->(%p)\n", This, classid);
719 *classid = *DOMDocument_version(This->properties->version);
724 static HRESULT WINAPI domdoc_IPersistStreamInit_IsDirty(
725 IPersistStreamInit *iface)
727 domdoc *This = impl_from_IPersistStreamInit(iface);
728 FIXME("(%p): stub!\n", This);
732 static HRESULT WINAPI domdoc_IPersistStreamInit_Load(
733 IPersistStreamInit *iface, LPSTREAM pStm)
735 domdoc *This = impl_from_IPersistStreamInit(iface);
738 DWORD read, written, len;
741 xmlDocPtr xmldoc = NULL;
743 TRACE("(%p)->(%p)\n", This, pStm);
748 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
754 IStream_Read(pStm, buf, sizeof(buf), &read);
755 hr = IStream_Write(This->stream, buf, read, &written);
756 } while(SUCCEEDED(hr) && written != 0 && read != 0);
760 ERR("Failed to copy stream\n");
764 hr = GetHGlobalFromStream(This->stream, &hglobal);
768 len = GlobalSize(hglobal);
769 ptr = GlobalLock(hglobal);
771 xmldoc = doparse(This, ptr, len, NULL);
772 GlobalUnlock(hglobal);
776 ERR("Failed to parse xml\n");
780 xmldoc->_private = create_priv();
782 return attach_xmldoc(This, xmldoc);
785 static HRESULT WINAPI domdoc_IPersistStreamInit_Save(
786 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
788 domdoc *This = impl_from_IPersistStreamInit(iface);
792 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
794 hr = IXMLDOMDocument3_get_xml( (IXMLDOMDocument3*)&This->lpVtbl, &xmlString );
797 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
799 hr = IStream_Write( stream, xmlString, len, NULL );
800 SysFreeString(xmlString);
803 TRACE("ret 0x%08x\n", hr);
808 static HRESULT WINAPI domdoc_IPersistStreamInit_GetSizeMax(
809 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
811 domdoc *This = impl_from_IPersistStreamInit(iface);
812 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
816 static HRESULT WINAPI domdoc_IPersistStreamInit_InitNew(
817 IPersistStreamInit *iface)
819 domdoc *This = impl_from_IPersistStreamInit(iface);
820 TRACE("(%p)\n", This);
824 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
826 domdoc_IPersistStreamInit_QueryInterface,
827 domdoc_IPersistStreamInit_AddRef,
828 domdoc_IPersistStreamInit_Release,
829 domdoc_IPersistStreamInit_GetClassID,
830 domdoc_IPersistStreamInit_IsDirty,
831 domdoc_IPersistStreamInit_Load,
832 domdoc_IPersistStreamInit_Save,
833 domdoc_IPersistStreamInit_GetSizeMax,
834 domdoc_IPersistStreamInit_InitNew
837 /* ISupportErrorInfo interface */
838 static HRESULT WINAPI support_error_QueryInterface(
839 ISupportErrorInfo *iface,
840 REFIID riid, void** ppvObj )
842 domdoc *This = impl_from_ISupportErrorInfo(iface);
843 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3 *)This, riid, ppvObj);
846 static ULONG WINAPI support_error_AddRef(
847 ISupportErrorInfo *iface )
849 domdoc *This = impl_from_ISupportErrorInfo(iface);
850 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
853 static ULONG WINAPI support_error_Release(
854 ISupportErrorInfo *iface )
856 domdoc *This = impl_from_ISupportErrorInfo(iface);
857 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
860 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
861 ISupportErrorInfo *iface,
864 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
868 static const struct ISupportErrorInfoVtbl support_error_vtbl =
870 support_error_QueryInterface,
871 support_error_AddRef,
872 support_error_Release,
873 support_error_InterfaceSupportsErrorInfo
876 /* IXMLDOMDocument2 interface */
877 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
879 domdoc *This = impl_from_IXMLDOMDocument3( iface );
881 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
885 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
886 IsEqualGUID( riid, &IID_IDispatch ) ||
887 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
888 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
889 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
890 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
894 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
895 IsEqualGUID(&IID_IPersistStreamInit, riid))
897 *ppvObject = &(This->lpvtblIPersistStreamInit);
899 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
901 *ppvObject = &(This->lpvtblIObjectWithSite);
903 else if (IsEqualGUID(&IID_IObjectSafety, riid))
905 *ppvObject = &(This->lpvtblIObjectSafety);
907 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
909 *ppvObject = &This->lpvtblISupportErrorInfo;
911 else if(node_query_interface(&This->node, riid, ppvObject))
913 return *ppvObject ? S_OK : E_NOINTERFACE;
915 else if (IsEqualGUID( riid, &IID_IConnectionPointContainer ))
917 *ppvObject = &This->lpVtblConnectionPointContainer;
921 TRACE("interface %s not implemented\n", debugstr_guid(riid));
922 return E_NOINTERFACE;
925 IUnknown_AddRef((IUnknown*)*ppvObject);
931 static ULONG WINAPI domdoc_AddRef(
932 IXMLDOMDocument3 *iface )
934 domdoc *This = impl_from_IXMLDOMDocument3( iface );
935 ULONG ref = InterlockedIncrement( &This->ref );
936 TRACE("(%p)->(%d)\n", This, ref );
941 static ULONG WINAPI domdoc_Release(
942 IXMLDOMDocument3 *iface )
944 domdoc *This = impl_from_IXMLDOMDocument3( iface );
945 LONG ref = InterlockedDecrement( &This->ref );
947 TRACE("(%p)->(%d)\n", This, ref );
954 detach_bsc(This->bsc);
957 IUnknown_Release( This->site );
958 destroy_xmlnode(&This->node);
960 IStream_Release(This->stream);
962 for (eid = 0; eid < EVENTID_LAST; eid++)
963 if (This->events[eid]) IDispatch_Release(This->events[eid]);
971 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
973 domdoc *This = impl_from_IXMLDOMDocument3( iface );
975 TRACE("(%p)->(%p)\n", This, pctinfo);
982 static HRESULT WINAPI domdoc_GetTypeInfo(
983 IXMLDOMDocument3 *iface,
984 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
986 domdoc *This = impl_from_IXMLDOMDocument3( iface );
989 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
991 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
996 static HRESULT WINAPI domdoc_GetIDsOfNames(
997 IXMLDOMDocument3 *iface,
1004 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1005 ITypeInfo *typeinfo;
1008 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1011 if(!rgszNames || cNames == 0 || !rgDispId)
1012 return E_INVALIDARG;
1014 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
1017 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1018 ITypeInfo_Release(typeinfo);
1025 static HRESULT WINAPI domdoc_Invoke(
1026 IXMLDOMDocument3 *iface,
1027 DISPID dispIdMember,
1031 DISPPARAMS* pDispParams,
1032 VARIANT* pVarResult,
1033 EXCEPINFO* pExcepInfo,
1036 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1037 ITypeInfo *typeinfo;
1040 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1041 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1043 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
1046 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
1047 pVarResult, pExcepInfo, puArgErr);
1048 ITypeInfo_Release(typeinfo);
1055 static HRESULT WINAPI domdoc_get_nodeName(
1056 IXMLDOMDocument3 *iface,
1059 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1061 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
1063 TRACE("(%p)->(%p)\n", This, name);
1065 return return_bstr(documentW, name);
1069 static HRESULT WINAPI domdoc_get_nodeValue(
1070 IXMLDOMDocument3 *iface,
1073 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1075 TRACE("(%p)->(%p)\n", This, value);
1078 return E_INVALIDARG;
1080 V_VT(value) = VT_NULL;
1081 V_BSTR(value) = NULL; /* tests show that we should do this */
1086 static HRESULT WINAPI domdoc_put_nodeValue(
1087 IXMLDOMDocument3 *iface,
1090 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1091 TRACE("(%p)->(v%d)\n", This, V_VT(&value));
1096 static HRESULT WINAPI domdoc_get_nodeType(
1097 IXMLDOMDocument3 *iface,
1100 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1102 TRACE("(%p)->(%p)\n", This, type);
1104 *type = NODE_DOCUMENT;
1109 static HRESULT WINAPI domdoc_get_parentNode(
1110 IXMLDOMDocument3 *iface,
1111 IXMLDOMNode** parent )
1113 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1115 TRACE("(%p)->(%p)\n", This, parent);
1117 return node_get_parent(&This->node, parent);
1121 static HRESULT WINAPI domdoc_get_childNodes(
1122 IXMLDOMDocument3 *iface,
1123 IXMLDOMNodeList** childList )
1125 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1127 TRACE("(%p)->(%p)\n", This, childList);
1129 return node_get_child_nodes(&This->node, childList);
1133 static HRESULT WINAPI domdoc_get_firstChild(
1134 IXMLDOMDocument3 *iface,
1135 IXMLDOMNode** firstChild )
1137 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1139 TRACE("(%p)->(%p)\n", This, firstChild);
1141 return node_get_first_child(&This->node, firstChild);
1145 static HRESULT WINAPI domdoc_get_lastChild(
1146 IXMLDOMDocument3 *iface,
1147 IXMLDOMNode** lastChild )
1149 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1151 TRACE("(%p)->(%p)\n", This, lastChild);
1153 return node_get_last_child(&This->node, lastChild);
1157 static HRESULT WINAPI domdoc_get_previousSibling(
1158 IXMLDOMDocument3 *iface,
1159 IXMLDOMNode** previousSibling )
1161 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1163 TRACE("(%p)->(%p)\n", This, previousSibling);
1165 return return_null_node(previousSibling);
1169 static HRESULT WINAPI domdoc_get_nextSibling(
1170 IXMLDOMDocument3 *iface,
1171 IXMLDOMNode** nextSibling )
1173 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1175 TRACE("(%p)->(%p)\n", This, nextSibling);
1177 return return_null_node(nextSibling);
1181 static HRESULT WINAPI domdoc_get_attributes(
1182 IXMLDOMDocument3 *iface,
1183 IXMLDOMNamedNodeMap** attributeMap )
1185 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1187 TRACE("(%p)->(%p)\n", This, attributeMap);
1189 return return_null_ptr((void**)attributeMap);
1193 static HRESULT WINAPI domdoc_insertBefore(
1194 IXMLDOMDocument3 *iface,
1195 IXMLDOMNode* newChild,
1197 IXMLDOMNode** outNewChild )
1199 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1201 TRACE("(%p)->(%p x%d %p)\n", This, newChild, V_VT(&refChild), outNewChild);
1203 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1207 static HRESULT WINAPI domdoc_replaceChild(
1208 IXMLDOMDocument3 *iface,
1209 IXMLDOMNode* newChild,
1210 IXMLDOMNode* oldChild,
1211 IXMLDOMNode** outOldChild)
1213 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1215 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1217 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1221 static HRESULT WINAPI domdoc_removeChild(
1222 IXMLDOMDocument3 *iface,
1224 IXMLDOMNode **oldChild)
1226 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1227 TRACE("(%p)->(%p %p)\n", This, child, oldChild);
1228 return node_remove_child(&This->node, child, oldChild);
1232 static HRESULT WINAPI domdoc_appendChild(
1233 IXMLDOMDocument3 *iface,
1235 IXMLDOMNode **outChild)
1237 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1238 TRACE("(%p)->(%p %p)\n", This, child, outChild);
1239 return node_append_child(&This->node, child, outChild);
1243 static HRESULT WINAPI domdoc_hasChildNodes(
1244 IXMLDOMDocument3 *iface,
1247 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1248 TRACE("(%p)->(%p)\n", This, ret);
1249 return node_has_childnodes(&This->node, ret);
1253 static HRESULT WINAPI domdoc_get_ownerDocument(
1254 IXMLDOMDocument3 *iface,
1255 IXMLDOMDocument **doc)
1257 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1258 TRACE("(%p)->(%p)\n", This, doc);
1259 return node_get_owner_doc(&This->node, doc);
1263 static HRESULT WINAPI domdoc_cloneNode(
1264 IXMLDOMDocument3 *iface,
1266 IXMLDOMNode** outNode)
1268 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1269 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
1270 return node_clone( &This->node, deep, outNode );
1274 static HRESULT WINAPI domdoc_get_nodeTypeString(
1275 IXMLDOMDocument3 *iface,
1278 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1279 static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
1281 TRACE("(%p)->(%p)\n", This, p);
1283 return return_bstr(documentW, p);
1287 static HRESULT WINAPI domdoc_get_text(
1288 IXMLDOMDocument3 *iface,
1291 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1292 TRACE("(%p)->(%p)\n", This, p);
1293 return node_get_text(&This->node, p);
1297 static HRESULT WINAPI domdoc_put_text(
1298 IXMLDOMDocument3 *iface,
1301 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1302 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1307 static HRESULT WINAPI domdoc_get_specified(
1308 IXMLDOMDocument3 *iface,
1309 VARIANT_BOOL* isSpecified )
1311 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1312 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1313 *isSpecified = VARIANT_TRUE;
1318 static HRESULT WINAPI domdoc_get_definition(
1319 IXMLDOMDocument3 *iface,
1320 IXMLDOMNode** definitionNode )
1322 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1323 FIXME("(%p)->(%p)\n", This, definitionNode);
1328 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1329 IXMLDOMDocument3 *iface,
1332 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1333 TRACE("(%p)->(%p)\n", This, v);
1334 return return_null_var(v);
1337 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1338 IXMLDOMDocument3 *iface,
1339 VARIANT typedValue )
1341 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1342 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1347 static HRESULT WINAPI domdoc_get_dataType(
1348 IXMLDOMDocument3 *iface,
1351 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1352 TRACE("(%p)->(%p)\n", This, typename);
1353 return return_null_var( typename );
1357 static HRESULT WINAPI domdoc_put_dataType(
1358 IXMLDOMDocument3 *iface,
1361 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1363 FIXME("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
1366 return E_INVALIDARG;
1371 static int XMLCALL domdoc_get_xml_writecallback(void *ctx, const char *data, int len)
1373 return xmlBufferAdd((xmlBufferPtr)ctx, (xmlChar*)data, len) == 0 ? len : 0;
1376 static HRESULT WINAPI domdoc_get_xml(
1377 IXMLDOMDocument3 *iface,
1380 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1381 xmlSaveCtxtPtr ctxt;
1386 TRACE("(%p)->(%p)\n", This, p);
1389 return E_INVALIDARG;
1393 buf = xmlBufferCreate();
1395 return E_OUTOFMEMORY;
1397 options = xmldoc_has_decl(get_doc(This)) ? XML_SAVE_NO_DECL : 0;
1398 options |= XML_SAVE_FORMAT;
1399 ctxt = xmlSaveToIO(domdoc_get_xml_writecallback, NULL, buf, "UTF-8", options);
1404 return E_OUTOFMEMORY;
1407 ret = xmlSaveDoc(ctxt, get_doc(This));
1408 /* flushes on close */
1411 TRACE("%ld, len=%d\n", ret, xmlBufferLength(buf));
1412 if(ret != -1 && xmlBufferLength(buf) > 0)
1416 content = bstr_from_xmlChar(xmlBufferContent(buf));
1417 content = EnsureCorrectEOL(content);
1423 *p = SysAllocStringLen(NULL, 0);
1428 return *p ? S_OK : E_OUTOFMEMORY;
1432 static HRESULT WINAPI domdoc_transformNode(
1433 IXMLDOMDocument3 *iface,
1437 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1438 TRACE("(%p)->(%p %p)\n", This, node, p);
1439 return node_transform_node(&This->node, node, p);
1443 static HRESULT WINAPI domdoc_selectNodes(
1444 IXMLDOMDocument3 *iface,
1446 IXMLDOMNodeList **outList)
1448 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1449 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList);
1450 return node_select_nodes(&This->node, p, outList);
1454 static HRESULT WINAPI domdoc_selectSingleNode(
1455 IXMLDOMDocument3 *iface,
1457 IXMLDOMNode **outNode)
1459 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1460 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode);
1461 return node_select_singlenode(&This->node, p, outNode);
1465 static HRESULT WINAPI domdoc_get_parsed(
1466 IXMLDOMDocument3 *iface,
1467 VARIANT_BOOL* isParsed )
1469 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1470 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1471 *isParsed = VARIANT_TRUE;
1476 static HRESULT WINAPI domdoc_get_namespaceURI(
1477 IXMLDOMDocument3 *iface,
1478 BSTR* namespaceURI )
1480 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1481 TRACE("(%p)->(%p)\n", This, namespaceURI);
1482 return node_get_namespaceURI(&This->node, namespaceURI);
1486 static HRESULT WINAPI domdoc_get_prefix(
1487 IXMLDOMDocument3 *iface,
1490 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1491 TRACE("(%p)->(%p)\n", This, prefix);
1492 return return_null_bstr( prefix );
1496 static HRESULT WINAPI domdoc_get_baseName(
1497 IXMLDOMDocument3 *iface,
1500 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1501 TRACE("(%p)->(%p)\n", This, name);
1502 return return_null_bstr( name );
1506 static HRESULT WINAPI domdoc_transformNodeToObject(
1507 IXMLDOMDocument3 *iface,
1508 IXMLDOMNode* stylesheet,
1509 VARIANT outputObject)
1511 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1512 FIXME("(%p)->(%p %s)\n", This, stylesheet, debugstr_variant(&outputObject));
1517 static HRESULT WINAPI domdoc_get_doctype(
1518 IXMLDOMDocument3 *iface,
1519 IXMLDOMDocumentType** doctype )
1521 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1526 TRACE("(%p)->(%p)\n", This, doctype);
1528 if (!doctype) return E_INVALIDARG;
1532 dtd = xmlGetIntSubset(get_doc(This));
1533 if (!dtd) return S_FALSE;
1535 node = create_node((xmlNodePtr)dtd);
1536 if (!node) return S_FALSE;
1538 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentType, (void**)doctype);
1539 IXMLDOMNode_Release(node);
1545 static HRESULT WINAPI domdoc_get_implementation(
1546 IXMLDOMDocument3 *iface,
1547 IXMLDOMImplementation** impl )
1549 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1551 TRACE("(%p)->(%p)\n", This, impl);
1554 return E_INVALIDARG;
1556 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1561 static HRESULT WINAPI domdoc_get_documentElement(
1562 IXMLDOMDocument3 *iface,
1563 IXMLDOMElement** DOMElement )
1565 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1566 IXMLDOMNode *element_node;
1570 TRACE("(%p)->(%p)\n", This, DOMElement);
1573 return E_INVALIDARG;
1577 root = xmlDocGetRootElement( get_doc(This) );
1581 element_node = create_node( root );
1582 if(!element_node) return S_FALSE;
1584 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1585 IXMLDOMNode_Release(element_node);
1591 static HRESULT WINAPI domdoc_put_documentElement(
1592 IXMLDOMDocument3 *iface,
1593 IXMLDOMElement* DOMElement )
1595 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1596 IXMLDOMNode *elementNode;
1601 TRACE("(%p)->(%p)\n", This, DOMElement);
1603 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1607 xmlNode = get_node_obj( elementNode );
1608 if(!xmlNode) return E_FAIL;
1610 if(!xmlNode->node->parent)
1611 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1612 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1614 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1615 IXMLDOMNode_Release( elementNode );
1618 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1624 static HRESULT WINAPI domdoc_createElement(
1625 IXMLDOMDocument3 *iface,
1627 IXMLDOMElement** element )
1629 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1634 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1636 if (!element || !tagname) return E_INVALIDARG;
1638 V_VT(&type) = VT_I1;
1639 V_I1(&type) = NODE_ELEMENT;
1641 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1644 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1645 IXMLDOMNode_Release(node);
1652 static HRESULT WINAPI domdoc_createDocumentFragment(
1653 IXMLDOMDocument3 *iface,
1654 IXMLDOMDocumentFragment** frag )
1656 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1661 TRACE("(%p)->(%p)\n", This, frag);
1663 if (!frag) return E_INVALIDARG;
1667 V_VT(&type) = VT_I1;
1668 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1670 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1673 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1674 IXMLDOMNode_Release(node);
1681 static HRESULT WINAPI domdoc_createTextNode(
1682 IXMLDOMDocument3 *iface,
1684 IXMLDOMText** text )
1686 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1691 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1693 if (!text) return E_INVALIDARG;
1697 V_VT(&type) = VT_I1;
1698 V_I1(&type) = NODE_TEXT;
1700 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1703 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1704 IXMLDOMNode_Release(node);
1705 hr = IXMLDOMText_put_data(*text, data);
1712 static HRESULT WINAPI domdoc_createComment(
1713 IXMLDOMDocument3 *iface,
1715 IXMLDOMComment** comment )
1717 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1722 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1724 if (!comment) return E_INVALIDARG;
1728 V_VT(&type) = VT_I1;
1729 V_I1(&type) = NODE_COMMENT;
1731 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1734 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1735 IXMLDOMNode_Release(node);
1736 hr = IXMLDOMComment_put_data(*comment, data);
1743 static HRESULT WINAPI domdoc_createCDATASection(
1744 IXMLDOMDocument3 *iface,
1746 IXMLDOMCDATASection** cdata )
1748 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1753 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1755 if (!cdata) return E_INVALIDARG;
1759 V_VT(&type) = VT_I1;
1760 V_I1(&type) = NODE_CDATA_SECTION;
1762 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1765 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1766 IXMLDOMNode_Release(node);
1767 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1774 static HRESULT WINAPI domdoc_createProcessingInstruction(
1775 IXMLDOMDocument3 *iface,
1778 IXMLDOMProcessingInstruction** pi )
1780 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1785 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1787 if (!pi) return E_INVALIDARG;
1791 V_VT(&type) = VT_I1;
1792 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1794 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1799 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1800 node_obj = get_node_obj(node);
1801 hr = node_set_content(node_obj, data);
1803 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1804 IXMLDOMNode_Release(node);
1811 static HRESULT WINAPI domdoc_createAttribute(
1812 IXMLDOMDocument3 *iface,
1814 IXMLDOMAttribute** attribute )
1816 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1821 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1823 if (!attribute || !name) return E_INVALIDARG;
1825 V_VT(&type) = VT_I1;
1826 V_I1(&type) = NODE_ATTRIBUTE;
1828 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1831 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1832 IXMLDOMNode_Release(node);
1839 static HRESULT WINAPI domdoc_createEntityReference(
1840 IXMLDOMDocument3 *iface,
1842 IXMLDOMEntityReference** entityref )
1844 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1849 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1851 if (!entityref) return E_INVALIDARG;
1855 V_VT(&type) = VT_I1;
1856 V_I1(&type) = NODE_ENTITY_REFERENCE;
1858 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1861 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1862 IXMLDOMNode_Release(node);
1868 xmlChar* tagName_to_XPath(const BSTR tagName)
1870 xmlChar *query, *tmp;
1871 static const xmlChar mod_pre[] = "*[local-name()='";
1872 static const xmlChar mod_post[] = "']";
1873 static const xmlChar prefix[] = "descendant::";
1874 const WCHAR *tokBegin, *tokEnd;
1877 query = xmlStrdup(prefix);
1880 while (tokBegin && *tokBegin)
1885 query = xmlStrcat(query, BAD_CAST "/");
1889 query = xmlStrcat(query, BAD_CAST "*");
1893 query = xmlStrcat(query, mod_pre);
1895 while (*tokEnd && *tokEnd != '/')
1897 len = WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, NULL, 0, NULL, NULL);
1898 tmp = xmlMalloc(len);
1899 WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, (char*)tmp, len, NULL, NULL);
1900 query = xmlStrncat(query, tmp, len);
1903 query = xmlStrcat(query, mod_post);
1910 static HRESULT WINAPI domdoc_getElementsByTagName(
1911 IXMLDOMDocument3 *iface,
1913 IXMLDOMNodeList** resultList )
1915 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1920 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1922 if (!tagName || !resultList) return E_INVALIDARG;
1924 XPath = This->properties->XPath;
1925 This->properties->XPath = TRUE;
1926 query = tagName_to_XPath(tagName);
1927 hr = create_selection((xmlNodePtr)get_doc(This), query, resultList);
1929 This->properties->XPath = XPath;
1934 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1940 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1942 return E_INVALIDARG;
1949 static HRESULT WINAPI domdoc_createNode(
1950 IXMLDOMDocument3 *iface,
1954 IXMLDOMNode** node )
1956 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1957 DOMNodeType node_type;
1959 xmlChar *xml_name, *href;
1962 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1964 if(!node) return E_INVALIDARG;
1966 hr = get_node_type(Type, &node_type);
1967 if(FAILED(hr)) return hr;
1969 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1970 FIXME("nodes with namespaces currently not supported.\n");
1972 TRACE("node_type %d\n", node_type);
1974 /* exit earlier for types that need name */
1978 case NODE_ATTRIBUTE:
1979 case NODE_ENTITY_REFERENCE:
1980 case NODE_PROCESSING_INSTRUCTION:
1981 if (!name || *name == 0) return E_FAIL;
1986 xml_name = xmlchar_from_wchar(name);
1987 /* prevent empty href to be allocated */
1988 href = namespaceURI ? xmlchar_from_wchar(namespaceURI) : NULL;
1994 xmlChar *local, *prefix;
1996 local = xmlSplitQName2(xml_name, &prefix);
1998 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
2000 /* allow to create default namespace xmlns= */
2001 if (local || (href && *href))
2003 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
2004 xmlSetNs(xmlnode, ns);
2012 case NODE_ATTRIBUTE:
2013 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
2016 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
2018 case NODE_CDATA_SECTION:
2019 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
2021 case NODE_ENTITY_REFERENCE:
2022 xmlnode = xmlNewReference(get_doc(This), xml_name);
2024 case NODE_PROCESSING_INSTRUCTION:
2025 #ifdef HAVE_XMLNEWDOCPI
2026 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
2028 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2033 xmlnode = xmlNewDocComment(get_doc(This), NULL);
2035 case NODE_DOCUMENT_FRAGMENT:
2036 xmlnode = xmlNewDocFragment(get_doc(This));
2038 /* unsupported types */
2040 case NODE_DOCUMENT_TYPE:
2043 heap_free(xml_name);
2044 return E_INVALIDARG;
2046 FIXME("unhandled node type %d\n", node_type);
2051 *node = create_node(xmlnode);
2052 heap_free(xml_name);
2057 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
2058 xmldoc_add_orphan(xmlnode->doc, xmlnode);
2065 static HRESULT WINAPI domdoc_nodeFromID(
2066 IXMLDOMDocument3 *iface,
2068 IXMLDOMNode** node )
2070 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2071 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
2075 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
2080 xmldoc = doparse(This, ptr, len, NULL);
2082 xmldoc->_private = create_priv();
2083 return attach_xmldoc(This, xmldoc);
2089 static HRESULT doread( domdoc *This, LPWSTR filename )
2094 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
2099 detach_bsc(This->bsc);
2105 static HRESULT WINAPI domdoc_load(
2106 IXMLDOMDocument3 *iface,
2108 VARIANT_BOOL* isSuccessful )
2110 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2111 LPWSTR filename = NULL;
2112 HRESULT hr = S_FALSE;
2113 IXMLDOMDocument3 *pNewDoc = NULL;
2114 IStream *pStream = NULL;
2117 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
2119 *isSuccessful = VARIANT_FALSE;
2121 assert( &This->node );
2123 switch( V_VT(&xmlSource) )
2126 filename = V_BSTR(&xmlSource);
2129 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
2134 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
2135 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
2136 hr = attach_xmldoc(This, xmldoc);
2139 *isSuccessful = VARIANT_TRUE;
2144 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
2147 IPersistStream *pDocStream;
2148 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
2151 hr = IPersistStream_Load(pDocStream, pStream);
2152 IStream_Release(pStream);
2155 *isSuccessful = VARIANT_TRUE;
2157 TRACE("Using IStream to load Document\n");
2162 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
2167 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
2172 /* ISequentialStream */
2173 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
2177 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
2180 TRACE("filename (%s)\n", debugstr_w(filename));
2184 hr = doread( This, filename );
2187 This->error = E_FAIL;
2190 hr = This->error = S_OK;
2191 *isSuccessful = VARIANT_TRUE;
2195 if(!filename || FAILED(hr)) {
2196 xmldoc = xmlNewDoc(NULL);
2197 xmldoc->_private = create_priv();
2198 hr = attach_xmldoc(This, xmldoc);
2203 TRACE("ret (%d)\n", hr);
2209 static HRESULT WINAPI domdoc_get_readyState(
2210 IXMLDOMDocument3 *iface,
2213 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2214 FIXME("stub! (%p)->(%p)\n", This, value);
2217 return E_INVALIDARG;
2219 *value = READYSTATE_COMPLETE;
2224 static HRESULT WINAPI domdoc_get_parseError(
2225 IXMLDOMDocument3 *iface,
2226 IXMLDOMParseError** errorObj )
2228 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2229 static const WCHAR err[] = {'e','r','r','o','r',0};
2230 BSTR error_string = NULL;
2232 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2235 error_string = SysAllocString(err);
2237 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2238 if(!*errorObj) return E_OUTOFMEMORY;
2243 static HRESULT WINAPI domdoc_get_url(
2244 IXMLDOMDocument3 *iface,
2247 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2248 FIXME("(%p)->(%p)\n", This, urlString);
2253 static HRESULT WINAPI domdoc_get_async(
2254 IXMLDOMDocument3 *iface,
2255 VARIANT_BOOL* isAsync )
2257 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2259 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2260 *isAsync = This->async;
2265 static HRESULT WINAPI domdoc_put_async(
2266 IXMLDOMDocument3 *iface,
2267 VARIANT_BOOL isAsync )
2269 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2271 TRACE("(%p)->(%d)\n", This, isAsync);
2272 This->async = isAsync;
2277 static HRESULT WINAPI domdoc_abort(
2278 IXMLDOMDocument3 *iface )
2280 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2281 FIXME("%p\n", This);
2286 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
2291 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
2292 str = heap_alloc( len );
2295 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
2301 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2302 static HRESULT WINAPI domdoc_loadXML(
2303 IXMLDOMDocument3 *iface,
2305 VARIANT_BOOL* isSuccessful )
2307 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2308 static const xmlChar encoding[] = "UTF-8";
2309 xmlDocPtr xmldoc = NULL;
2310 HRESULT hr = S_FALSE, hr2;
2314 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2316 assert ( &This->node );
2320 *isSuccessful = VARIANT_FALSE;
2322 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
2324 xmldoc = doparse(This, str, len, encoding);
2328 This->error = E_FAIL;
2329 TRACE("failed to parse document\n");
2333 hr = This->error = S_OK;
2334 *isSuccessful = VARIANT_TRUE;
2335 TRACE("parsed document %p\n", xmldoc);
2340 xmldoc = xmlNewDoc(NULL);
2342 xmldoc->_private = create_priv();
2344 hr2 = attach_xmldoc(This, xmldoc);
2351 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2355 if(!WriteFile(ctx, buffer, len, &written, NULL))
2357 WARN("write error\n");
2364 static int XMLCALL domdoc_save_closecallback(void *ctx)
2366 return CloseHandle(ctx) ? 0 : -1;
2369 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2374 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2377 WARN("stream write error: 0x%08x\n", hr);
2384 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2386 IStream_Release((IStream*)ctx);
2390 static HRESULT WINAPI domdoc_save(
2391 IXMLDOMDocument3 *iface,
2392 VARIANT destination )
2394 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2395 xmlSaveCtxtPtr ctx = NULL;
2399 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
2400 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
2402 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
2404 FIXME("Unhandled vt %d\n", V_VT(&destination));
2408 if(V_VT(&destination) == VT_UNKNOWN)
2410 IUnknown *pUnk = V_UNKNOWN(&destination);
2411 IXMLDOMDocument2 *document;
2414 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2417 VARIANT_BOOL success;
2420 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2423 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2427 IXMLDOMDocument3_Release(document);
2431 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2434 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2435 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2439 IStream_Release(stream);
2446 /* save with file path */
2447 HANDLE handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
2448 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2449 if( handle == INVALID_HANDLE_VALUE )
2451 WARN("failed to create file\n");
2455 /* disable top XML declaration */
2456 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2457 handle, NULL, XML_SAVE_NO_DECL);
2460 CloseHandle(handle);
2465 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2466 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2467 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2469 /* will release resources through close callback */
2475 static HRESULT WINAPI domdoc_get_validateOnParse(
2476 IXMLDOMDocument3 *iface,
2477 VARIANT_BOOL* isValidating )
2479 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2480 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2481 *isValidating = This->validating;
2486 static HRESULT WINAPI domdoc_put_validateOnParse(
2487 IXMLDOMDocument3 *iface,
2488 VARIANT_BOOL isValidating )
2490 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2491 TRACE("(%p)->(%d)\n", This, isValidating);
2492 This->validating = isValidating;
2497 static HRESULT WINAPI domdoc_get_resolveExternals(
2498 IXMLDOMDocument3 *iface,
2499 VARIANT_BOOL* isResolving )
2501 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2502 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2503 *isResolving = This->resolving;
2508 static HRESULT WINAPI domdoc_put_resolveExternals(
2509 IXMLDOMDocument3 *iface,
2510 VARIANT_BOOL isResolving )
2512 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2513 TRACE("(%p)->(%d)\n", This, isResolving);
2514 This->resolving = isResolving;
2519 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2520 IXMLDOMDocument3 *iface,
2521 VARIANT_BOOL* isPreserving )
2523 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2524 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->properties->preserving);
2525 *isPreserving = This->properties->preserving;
2530 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2531 IXMLDOMDocument3 *iface,
2532 VARIANT_BOOL isPreserving )
2534 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2535 TRACE("(%p)->(%d)\n", This, isPreserving);
2536 This->properties->preserving = isPreserving;
2541 static HRESULT WINAPI domdoc_put_onreadystatechange(
2542 IXMLDOMDocument3 *iface,
2545 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2547 TRACE("(%p)->(%s)\n", This, debugstr_variant(&event));
2548 return set_doc_event(This, EVENTID_READYSTATECHANGE, &event);
2552 static HRESULT WINAPI domdoc_put_onDataAvailable(
2553 IXMLDOMDocument3 *iface,
2554 VARIANT onDataAvailableSink )
2556 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2557 FIXME("%p\n", This);
2561 static HRESULT WINAPI domdoc_put_onTransformNode(
2562 IXMLDOMDocument3 *iface,
2563 VARIANT onTransformNodeSink )
2565 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2566 FIXME("%p\n", This);
2570 static HRESULT WINAPI domdoc_get_namespaces(
2571 IXMLDOMDocument3* iface,
2572 IXMLDOMSchemaCollection** schemaCollection )
2574 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2575 FIXME("(%p)->(%p)\n", This, schemaCollection);
2579 static HRESULT WINAPI domdoc_get_schemas(
2580 IXMLDOMDocument3* iface,
2583 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2584 HRESULT hr = S_FALSE;
2585 IXMLDOMSchemaCollection2* cur_schema = This->properties->schemaCache;
2587 TRACE("(%p)->(%p)\n", This, var1);
2589 VariantInit(var1); /* Test shows we don't call VariantClear here */
2590 V_VT(var1) = VT_NULL;
2594 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2596 V_VT(var1) = VT_DISPATCH;
2601 static HRESULT WINAPI domdoc_putref_schemas(
2602 IXMLDOMDocument3* iface,
2605 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2606 HRESULT hr = E_FAIL;
2607 IXMLDOMSchemaCollection2* new_schema = NULL;
2609 FIXME("(%p): semi-stub\n", This);
2613 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2617 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2626 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2631 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->properties->schemaCache, new_schema);
2632 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2638 static inline BOOL is_wellformed(xmlDocPtr doc)
2640 #ifdef HAVE_XMLDOC_PROPERTIES
2641 return doc->properties & XML_DOC_WELLFORMED;
2643 /* Not a full check, but catches the worst violations */
2647 for (child = doc->children; child != NULL; child = child->next)
2649 switch (child->type)
2651 case XML_ELEMENT_NODE:
2656 case XML_CDATA_SECTION_NODE:
2668 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2672 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2676 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2680 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2684 static HRESULT WINAPI domdoc_validateNode(
2685 IXMLDOMDocument3* iface,
2687 IXMLDOMParseError** err)
2689 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2690 LONG state, err_code = 0;
2694 TRACE("(%p)->(%p, %p)\n", This, node, err);
2695 domdoc_get_readyState(iface, &state);
2696 if (state != READYSTATE_COMPLETE)
2699 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2706 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2710 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2713 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2717 if (!is_wellformed(get_doc(This)))
2719 ERR("doc not well-formed\n");
2721 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2725 /* DTD validation */
2726 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2728 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2729 vctx->error = validate_error;
2730 vctx->warning = validate_warning;
2733 if (!((node == (IXMLDOMNode*)iface)?
2734 xmlValidateDocument(vctx, get_doc(This)) :
2735 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2737 /* TODO: get a real error code here */
2738 TRACE("DTD validation failed\n");
2739 err_code = E_XML_INVALID;
2742 xmlFreeValidCtxt(vctx);
2745 /* Schema validation */
2746 if (hr == S_OK && This->properties->schemaCache != NULL)
2749 hr = SchemaCache_validate_tree(This->properties->schemaCache, get_node_obj(node)->node);
2753 /* TODO: get a real error code here */
2756 TRACE("schema validation succeeded\n");
2760 ERR("schema validation failed\n");
2761 err_code = E_XML_INVALID;
2766 /* not really OK, just didn't find a schema for the ns */
2773 ERR("no DTD or schema found\n");
2774 err_code = E_XML_NODTD;
2779 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2784 static HRESULT WINAPI domdoc_validate(
2785 IXMLDOMDocument3* iface,
2786 IXMLDOMParseError** err)
2788 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2789 TRACE("(%p)->(%p)\n", This, err);
2790 return domdoc_validateNode(iface, (IXMLDOMNode*)iface, err);
2793 static HRESULT WINAPI domdoc_setProperty(
2794 IXMLDOMDocument3* iface,
2798 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2800 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2802 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2808 V_VT(&varStr) = VT_EMPTY;
2809 if (V_VT(&var) != VT_BSTR)
2811 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2813 bstr = V_BSTR(&varStr);
2816 bstr = V_BSTR(&var);
2819 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2820 This->properties->XPath = TRUE;
2821 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2822 This->properties->XPath = FALSE;
2826 VariantClear(&varStr);
2829 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2834 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2835 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2836 xmlXPathContextPtr ctx;
2837 struct list *pNsList;
2838 select_ns_entry* pNsEntry = NULL;
2840 V_VT(&varStr) = VT_EMPTY;
2841 if (V_VT(&var) != VT_BSTR)
2843 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2845 bstr = V_BSTR(&varStr);
2848 bstr = V_BSTR(&var);
2852 pNsList = &(This->properties->selectNsList);
2853 clear_selectNsList(pNsList);
2855 nsStr = xmlchar_from_wchar(bstr);
2857 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2859 This->properties->selectNsStr = nsStr;
2860 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2863 ctx = xmlXPathNewContext(This->node.node->doc);
2866 for (; *pTokBegin; pTokBegin = pTokEnd)
2868 if (pNsEntry != NULL)
2869 memset(pNsEntry, 0, sizeof(select_ns_entry));
2871 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2873 while (*pTokBegin == ' ')
2875 pTokEnd = pTokBegin;
2876 while (*pTokEnd != ' ' && *pTokEnd != 0)
2879 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2882 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2883 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2888 if (*pTokBegin == '=')
2890 /*valid for XSLPattern?*/
2891 FIXME("Setting default xmlns not supported - skipping.\n");
2892 pTokBegin = pTokEnd;
2895 else if (*pTokBegin == ':')
2897 pNsEntry->prefix = ++pTokBegin;
2898 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2901 if (pTokInner == pTokEnd)
2904 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2905 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2909 pNsEntry->prefix_end = *pTokInner;
2913 if (pTokEnd-pTokInner > 1 &&
2914 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2915 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2917 pNsEntry->href = ++pTokInner;
2918 pNsEntry->href_end = *(pTokEnd-1);
2920 list_add_tail(pNsList, &pNsEntry->entry);
2921 /*let libxml figure out if they're valid from here ;)*/
2922 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2931 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2932 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2933 list_add_tail(pNsList, &pNsEntry->entry);
2946 heap_free(pNsEntry);
2947 xmlXPathFreeContext(ctx);
2950 VariantClear(&varStr);
2953 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2954 lstrcmpiW(p, PropertyNewParserW) == 0 ||
2955 lstrcmpiW(p, PropertyResolveExternalsW) == 0)
2958 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2962 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2966 static HRESULT WINAPI domdoc_getProperty(
2967 IXMLDOMDocument3* iface,
2971 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2973 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2976 return E_INVALIDARG;
2978 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2980 V_VT(var) = VT_BSTR;
2981 V_BSTR(var) = This->properties->XPath ?
2982 SysAllocString(PropValueXPathW) :
2983 SysAllocString(PropValueXSLPatternW);
2984 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2986 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2989 BSTR rebuiltStr, cur;
2990 const xmlChar *nsStr;
2991 struct list *pNsList;
2992 select_ns_entry* pNsEntry;
2994 V_VT(var) = VT_BSTR;
2995 nsStr = This->properties->selectNsStr;
2996 pNsList = &This->properties->selectNsList;
2997 lenA = This->properties->selectNsStr_len;
2998 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
2999 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
3000 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
3002 /* this is fine because all of the chars that end tokens are ASCII*/
3003 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
3005 while (*cur != 0) ++cur;
3006 if (pNsEntry->prefix_end)
3008 *cur = pNsEntry->prefix_end;
3009 while (*cur != 0) ++cur;
3012 if (pNsEntry->href_end)
3014 *cur = pNsEntry->href_end;
3017 V_BSTR(var) = SysAllocString(rebuiltStr);
3018 heap_free(rebuiltStr);
3022 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
3026 static HRESULT WINAPI domdoc_importNode(
3027 IXMLDOMDocument3* iface,
3030 IXMLDOMNode** clone)
3032 domdoc *This = impl_from_IXMLDOMDocument3( iface );
3033 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
3037 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
3039 domdoc_QueryInterface,
3042 domdoc_GetTypeInfoCount,
3044 domdoc_GetIDsOfNames,
3046 domdoc_get_nodeName,
3047 domdoc_get_nodeValue,
3048 domdoc_put_nodeValue,
3049 domdoc_get_nodeType,
3050 domdoc_get_parentNode,
3051 domdoc_get_childNodes,
3052 domdoc_get_firstChild,
3053 domdoc_get_lastChild,
3054 domdoc_get_previousSibling,
3055 domdoc_get_nextSibling,
3056 domdoc_get_attributes,
3057 domdoc_insertBefore,
3058 domdoc_replaceChild,
3061 domdoc_hasChildNodes,
3062 domdoc_get_ownerDocument,
3064 domdoc_get_nodeTypeString,
3067 domdoc_get_specified,
3068 domdoc_get_definition,
3069 domdoc_get_nodeTypedValue,
3070 domdoc_put_nodeTypedValue,
3071 domdoc_get_dataType,
3072 domdoc_put_dataType,
3074 domdoc_transformNode,
3076 domdoc_selectSingleNode,
3078 domdoc_get_namespaceURI,
3080 domdoc_get_baseName,
3081 domdoc_transformNodeToObject,
3083 domdoc_get_implementation,
3084 domdoc_get_documentElement,
3085 domdoc_put_documentElement,
3086 domdoc_createElement,
3087 domdoc_createDocumentFragment,
3088 domdoc_createTextNode,
3089 domdoc_createComment,
3090 domdoc_createCDATASection,
3091 domdoc_createProcessingInstruction,
3092 domdoc_createAttribute,
3093 domdoc_createEntityReference,
3094 domdoc_getElementsByTagName,
3098 domdoc_get_readyState,
3099 domdoc_get_parseError,
3106 domdoc_get_validateOnParse,
3107 domdoc_put_validateOnParse,
3108 domdoc_get_resolveExternals,
3109 domdoc_put_resolveExternals,
3110 domdoc_get_preserveWhiteSpace,
3111 domdoc_put_preserveWhiteSpace,
3112 domdoc_put_onreadystatechange,
3113 domdoc_put_onDataAvailable,
3114 domdoc_put_onTransformNode,
3115 domdoc_get_namespaces,
3117 domdoc_putref_schemas,
3121 domdoc_validateNode,
3125 /* IConnectionPointContainer */
3126 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
3127 REFIID riid, void **ppv)
3129 domdoc *This = impl_from_IConnectionPointContainer(iface);
3130 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)This, riid, ppv);
3133 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
3135 domdoc *This = impl_from_IConnectionPointContainer(iface);
3136 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)This);
3139 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
3141 domdoc *This = impl_from_IConnectionPointContainer(iface);
3142 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)This);
3145 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
3146 IEnumConnectionPoints **ppEnum)
3148 domdoc *This = impl_from_IConnectionPointContainer(iface);
3149 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3153 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
3154 REFIID riid, IConnectionPoint **cp)
3156 domdoc *This = impl_from_IConnectionPointContainer(iface);
3157 ConnectionPoint *iter;
3159 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
3163 for(iter = This->cp_list; iter; iter = iter->next)
3165 if (IsEqualGUID(iter->iid, riid))
3166 *cp = (IConnectionPoint*)&iter->lpVtblConnectionPoint;
3171 IConnectionPoint_AddRef(*cp);
3175 FIXME("unsupported riid %s\n", debugstr_guid(riid));
3176 return CONNECT_E_NOCONNECTION;
3180 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
3182 ConnectionPointContainer_QueryInterface,
3183 ConnectionPointContainer_AddRef,
3184 ConnectionPointContainer_Release,
3185 ConnectionPointContainer_EnumConnectionPoints,
3186 ConnectionPointContainer_FindConnectionPoint
3189 /* IConnectionPoint */
3190 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
3191 REFIID riid, void **ppv)
3193 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3195 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3199 if (IsEqualGUID(&IID_IUnknown, riid) ||
3200 IsEqualGUID(&IID_IConnectionPoint, riid))
3207 IConnectionPoint_AddRef(iface);
3211 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3212 return E_NOINTERFACE;
3215 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3217 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3218 return IConnectionPointContainer_AddRef(This->container);
3221 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3223 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3224 return IConnectionPointContainer_Release(This->container);
3227 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3229 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3231 TRACE("(%p)->(%p)\n", This, iid);
3233 if (!iid) return E_POINTER;
3239 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3240 IConnectionPointContainer **container)
3242 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3244 TRACE("(%p)->(%p)\n", This, container);
3246 if (!container) return E_POINTER;
3248 *container = This->container;
3249 IConnectionPointContainer_AddRef(*container);
3253 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
3256 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3257 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
3261 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3263 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3265 TRACE("(%p)->(%d)\n", This, cookie);
3267 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3268 return CONNECT_E_NOCONNECTION;
3270 IUnknown_Release(This->sinks[cookie-1].unk);
3271 This->sinks[cookie-1].unk = NULL;
3276 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3277 IEnumConnections **ppEnum)
3279 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3280 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3284 static const IConnectionPointVtbl ConnectionPointVtbl =
3286 ConnectionPoint_QueryInterface,
3287 ConnectionPoint_AddRef,
3288 ConnectionPoint_Release,
3289 ConnectionPoint_GetConnectionInterface,
3290 ConnectionPoint_GetConnectionPointContainer,
3291 ConnectionPoint_Advise,
3292 ConnectionPoint_Unadvise,
3293 ConnectionPoint_EnumConnections
3296 void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3298 cp->lpVtblConnectionPoint = &ConnectionPointVtbl;
3304 cp->next = doc->cp_list;
3307 cp->container = (IConnectionPointContainer*)&doc->lpVtblConnectionPointContainer;
3310 /* domdoc implementation of IObjectWithSite */
3311 static HRESULT WINAPI
3312 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3314 domdoc *This = impl_from_IObjectWithSite(iface);
3315 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppvObject );
3318 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3320 domdoc *This = impl_from_IObjectWithSite(iface);
3321 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3324 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3326 domdoc *This = impl_from_IObjectWithSite(iface);
3327 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3330 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3332 domdoc *This = impl_from_IObjectWithSite(iface);
3334 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3339 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3342 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3344 domdoc *This = impl_from_IObjectWithSite(iface);
3346 TRACE("(%p)->(%p)\n", iface, punk);
3352 IUnknown_Release( This->site );
3359 IUnknown_AddRef( punk );
3362 IUnknown_Release( This->site );
3369 static const IObjectWithSiteVtbl domdocObjectSite =
3371 domdoc_ObjectWithSite_QueryInterface,
3372 domdoc_ObjectWithSite_AddRef,
3373 domdoc_ObjectWithSite_Release,
3374 domdoc_ObjectWithSite_SetSite,
3375 domdoc_ObjectWithSite_GetSite
3378 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3380 domdoc *This = impl_from_IObjectSafety(iface);
3381 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppv );
3384 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3386 domdoc *This = impl_from_IObjectSafety(iface);
3387 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3390 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3392 domdoc *This = impl_from_IObjectSafety(iface);
3393 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3396 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3398 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3399 DWORD *supported, DWORD *enabled)
3401 domdoc *This = impl_from_IObjectSafety(iface);
3403 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3405 if(!supported || !enabled) return E_POINTER;
3407 *supported = SAFETY_SUPPORTED_OPTIONS;
3408 *enabled = This->safeopt;
3413 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3414 DWORD mask, DWORD enabled)
3416 domdoc *This = impl_from_IObjectSafety(iface);
3417 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3419 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3422 This->safeopt = enabled & mask & SAFETY_SUPPORTED_OPTIONS;
3426 #undef SAFETY_SUPPORTED_OPTIONS
3428 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3429 domdoc_Safety_QueryInterface,
3430 domdoc_Safety_AddRef,
3431 domdoc_Safety_Release,
3432 domdoc_Safety_GetInterfaceSafetyOptions,
3433 domdoc_Safety_SetInterfaceSafetyOptions
3436 static const tid_t domdoc_iface_tids[] = {
3438 IXMLDOMDocument_tid,
3439 IXMLDOMDocument2_tid,
3442 static dispex_static_data_t domdoc_dispex = {
3444 IXMLDOMDocument2_tid,
3449 HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3453 doc = heap_alloc( sizeof (*doc) );
3455 return E_OUTOFMEMORY;
3457 doc->lpVtbl = &domdoc_vtbl;
3458 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
3459 doc->lpvtblIObjectWithSite = &domdocObjectSite;
3460 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
3461 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
3462 doc->lpVtblConnectionPointContainer = &ConnectionPointContainerVtbl;
3464 doc->async = VARIANT_TRUE;
3465 doc->validating = 0;
3467 doc->properties = properties_from_xmlDocPtr(xmldoc);
3473 doc->cp_list = NULL;
3474 memset(doc->events, 0, sizeof(doc->events));
3476 /* events connection points */
3477 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3478 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3479 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3481 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->lpVtbl, &domdoc_dispex);
3483 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
3485 TRACE("returning iface %p\n", *document);
3489 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3494 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
3496 xmldoc = xmlNewDoc(NULL);
3498 return E_OUTOFMEMORY;
3500 xmldoc->_private = create_priv();
3501 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
3503 hr = get_domdoc_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3506 free_properties(properties_from_xmlDocPtr(xmldoc));
3507 heap_free(xmldoc->_private);
3515 IUnknown* create_domdoc( xmlNodePtr document )
3520 TRACE("(%p)\n", document);
3522 hr = get_domdoc_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3531 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3533 MESSAGE("This program tried to use a DOMDocument object, but\n"
3534 "libxml2 support was not present at compile time.\n");