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
43 #include "wine/debug.h"
44 #include "wine/list.h"
46 #include "msxml_private.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
52 #include <libxml/xpathInternals.h>
53 #include <libxml/xmlsave.h>
54 #include <libxml/SAX2.h>
55 #include <libxml/parserInternals.h>
57 /* not defined in older versions */
58 #define XML_SAVE_FORMAT 1
59 #define XML_SAVE_NO_DECL 2
60 #define XML_SAVE_NO_EMPTY 4
61 #define XML_SAVE_NO_XHTML 8
62 #define XML_SAVE_XHTML 16
63 #define XML_SAVE_AS_XML 32
64 #define XML_SAVE_AS_HTML 64
66 static const WCHAR PropertySelectionLanguageW[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
67 static const WCHAR PropertySelectionNamespacesW[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
68 static const WCHAR PropertyProhibitDTDW[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
69 static const WCHAR PropertyNewParserW[] = {'N','e','w','P','a','r','s','e','r',0};
70 static const WCHAR PropValueXPathW[] = {'X','P','a','t','h',0};
71 static const WCHAR PropValueXSLPatternW[] = {'X','S','L','P','a','t','t','e','r','n',0};
73 /* Anything that passes the test_get_ownerDocument()
74 * tests can go here (data shared between all instances).
75 * We need to preserve this when reloading a document,
76 * and also need access to it from the libxml backend. */
77 typedef struct _domdoc_properties {
78 MSXML_VERSION version;
79 VARIANT_BOOL preserving;
80 IXMLDOMSchemaCollection2* schemaCache;
81 struct list selectNsList;
82 xmlChar const* selectNsStr;
87 typedef struct ConnectionPoint ConnectionPoint;
88 typedef struct domdoc domdoc;
90 struct ConnectionPoint
92 const IConnectionPointVtbl *lpVtblConnectionPoint;
95 ConnectionPoint *next;
96 IConnectionPointContainer *container;
103 IPropertyNotifySink *propnotif;
109 EVENTID_READYSTATECHANGE = 0,
110 EVENTID_DATAAVAILABLE,
111 EVENTID_TRANSFORMNODE,
118 const struct IXMLDOMDocument3Vtbl *lpVtbl;
119 const struct IPersistStreamInitVtbl *lpvtblIPersistStreamInit;
120 const struct IObjectWithSiteVtbl *lpvtblIObjectWithSite;
121 const struct IObjectSafetyVtbl *lpvtblIObjectSafety;
122 const struct ISupportErrorInfoVtbl *lpvtblISupportErrorInfo;
123 const struct IConnectionPointContainerVtbl *lpVtblConnectionPointContainer;
126 VARIANT_BOOL validating;
127 VARIANT_BOOL resolving;
128 domdoc_properties* properties;
141 /* connection list */
142 ConnectionPoint *cp_list;
143 ConnectionPoint cp_domdocevents;
144 ConnectionPoint cp_propnotif;
145 ConnectionPoint cp_dispatch;
148 IDispatch *events[EVENTID_LAST];
151 static HRESULT set_doc_event(domdoc *doc, eventid_t eid, const VARIANT *v)
159 IUnknown_QueryInterface(V_UNKNOWN(v), &IID_IDispatch, (void**)&disp);
164 disp = V_DISPATCH(v);
165 if (disp) IDispatch_AddRef(disp);
168 return DISP_E_TYPEMISMATCH;
171 if (doc->events[eid]) IDispatch_Release(doc->events[eid]);
172 doc->events[eid] = disp;
177 static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface)
179 return (ConnectionPoint *)((char*)iface - FIELD_OFFSET(ConnectionPoint, lpVtblConnectionPoint));
183 In native windows, the whole lifetime management of XMLDOMNodes is
184 managed automatically using reference counts. Wine emulates that by
185 maintaining a reference count to the document that is increased for
186 each IXMLDOMNode pointer passed out for this document. If all these
187 pointers are gone, the document is unreachable and gets freed, that
188 is, all nodes in the tree of the document get freed.
190 You are able to create nodes that are associated to a document (in
191 fact, in msxml's XMLDOM model, all nodes are associated to a document),
192 but not in the tree of that document, for example using the createFoo
193 functions from IXMLDOMDocument. These nodes do not get cleaned up
194 by libxml, so we have to do it ourselves.
196 To catch these nodes, a list of "orphan nodes" is introduced.
197 It contains pointers to all roots of node trees that are
198 associated with the document without being part of the document
199 tree. All nodes with parent==NULL (except for the document root nodes)
200 should be in the orphan node list of their document. All orphan nodes
201 get freed together with the document itself.
204 typedef struct _xmldoc_priv {
207 domdoc_properties* properties;
210 typedef struct _orphan_entry {
215 typedef struct _select_ns_entry {
217 xmlChar const* prefix;
223 static inline xmldoc_priv * priv_from_xmlDocPtr(const xmlDocPtr doc)
225 return doc->_private;
228 static inline domdoc_properties * properties_from_xmlDocPtr(xmlDocPtr doc)
230 return priv_from_xmlDocPtr(doc)->properties;
233 BOOL is_xpathmode(const xmlDocPtr doc)
235 return properties_from_xmlDocPtr(doc)->XPath;
238 void set_xpathmode(xmlDocPtr doc, BOOL xpath)
240 properties_from_xmlDocPtr(doc)->XPath = xpath;
243 int registerNamespaces(xmlXPathContextPtr ctxt)
246 const select_ns_entry* ns = NULL;
247 const struct list* pNsList = &properties_from_xmlDocPtr(ctxt->doc)->selectNsList;
249 TRACE("(%p)\n", ctxt);
251 LIST_FOR_EACH_ENTRY( ns, pNsList, select_ns_entry, entry )
253 xmlXPathRegisterNs(ctxt, ns->prefix, ns->href);
260 static inline void clear_selectNsList(struct list* pNsList)
262 select_ns_entry *ns, *ns2;
263 LIST_FOR_EACH_ENTRY_SAFE( ns, ns2, pNsList, select_ns_entry, entry )
270 static xmldoc_priv * create_priv(void)
273 priv = heap_alloc( sizeof (*priv) );
278 list_init( &priv->orphans );
279 priv->properties = NULL;
285 static domdoc_properties * create_properties(const GUID *clsid)
287 domdoc_properties *properties = heap_alloc(sizeof(domdoc_properties));
289 list_init(&properties->selectNsList);
290 properties->preserving = VARIANT_FALSE;
291 properties->schemaCache = NULL;
292 properties->selectNsStr = heap_alloc_zero(sizeof(xmlChar));
293 properties->selectNsStr_len = 0;
295 /* properties that are dependent on object versions */
296 if (IsEqualCLSID(clsid, &CLSID_DOMDocument30))
298 properties->version = MSXML3;
299 properties->XPath = FALSE;
301 else if (IsEqualCLSID(clsid, &CLSID_DOMDocument40))
303 properties->version = MSXML4;
304 properties->XPath = TRUE;
306 else if (IsEqualCLSID(clsid, &CLSID_DOMDocument60))
308 properties->version = MSXML6;
309 properties->XPath = TRUE;
313 properties->version = MSXML_DEFAULT;
314 properties->XPath = FALSE;
320 static domdoc_properties* copy_properties(domdoc_properties const* properties)
322 domdoc_properties* pcopy = heap_alloc(sizeof(domdoc_properties));
323 select_ns_entry const* ns = NULL;
324 select_ns_entry* new_ns = NULL;
325 int len = (properties->selectNsStr_len+1)*sizeof(xmlChar);
330 pcopy->version = properties->version;
331 pcopy->preserving = properties->preserving;
332 pcopy->schemaCache = properties->schemaCache;
333 if (pcopy->schemaCache)
334 IXMLDOMSchemaCollection2_AddRef(pcopy->schemaCache);
335 pcopy->XPath = properties->XPath;
336 pcopy->selectNsStr_len = properties->selectNsStr_len;
337 list_init( &pcopy->selectNsList );
338 pcopy->selectNsStr = heap_alloc(len);
339 memcpy((xmlChar*)pcopy->selectNsStr, properties->selectNsStr, len);
340 offset = pcopy->selectNsStr - properties->selectNsStr;
342 LIST_FOR_EACH_ENTRY( ns, (&properties->selectNsList), select_ns_entry, entry )
344 new_ns = heap_alloc(sizeof(select_ns_entry));
345 memcpy(new_ns, ns, sizeof(select_ns_entry));
346 new_ns->href += offset;
347 new_ns->prefix += offset;
348 list_add_tail(&pcopy->selectNsList, &new_ns->entry);
356 static void free_properties(domdoc_properties* properties)
360 if (properties->schemaCache)
361 IXMLDOMSchemaCollection2_Release(properties->schemaCache);
362 clear_selectNsList(&properties->selectNsList);
363 heap_free((xmlChar*)properties->selectNsStr);
364 heap_free(properties);
368 static BOOL xmldoc_has_decl(xmlDocPtr doc)
370 return doc->children && (xmlStrEqual(doc->children->name, (xmlChar*)"xml") == 1);
373 /* links a "<?xml" node as a first child */
374 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
377 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
380 /* unlinks a first "<?xml" child if it was created */
381 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
387 if (doc->standalone != -1)
389 node = doc->children;
390 xmlUnlinkNode( node );
398 BOOL is_preserving_whitespace(xmlNodePtr node)
400 domdoc_properties* properties = NULL;
401 /* during parsing the xmlDoc._private stuff is not there */
402 if (priv_from_xmlDocPtr(node->doc))
403 properties = properties_from_xmlDocPtr(node->doc);
404 return ((properties && properties->preserving == VARIANT_TRUE) ||
405 xmlNodeGetSpacePreserve(node) == 1);
408 static inline BOOL strn_isspace(xmlChar const* str, int len)
410 for (; str && len > 0 && *str; ++str, --len)
417 static void sax_characters(void *ctx, const xmlChar *ch, int len)
419 xmlParserCtxtPtr pctx;
422 pctx = (xmlParserCtxtPtr) ctx;
423 This = (domdoc const*) pctx->_private;
425 /* during domdoc_loadXML() the xmlDocPtr->_private data is not available */
426 if (!This->properties->preserving &&
427 !is_preserving_whitespace(pctx->node) &&
428 strn_isspace(ch, len))
431 xmlSAX2Characters(ctx, ch, len);
434 static void LIBXML2_LOG_CALLBACK sax_error(void* ctx, char const* msg, ...)
438 LIBXML2_CALLBACK_ERR(doparse, msg, ap);
442 static void LIBXML2_LOG_CALLBACK sax_warning(void* ctx, char const* msg, ...)
446 LIBXML2_CALLBACK_WARN(doparse, msg, ap);
450 static void sax_serror(void* ctx, xmlErrorPtr err)
452 LIBXML2_CALLBACK_SERROR(doparse, err);
455 static xmlDocPtr doparse(domdoc* This, char *ptr, int len, xmlChar const* encoding)
457 xmlDocPtr doc = NULL;
458 xmlParserCtxtPtr pctx;
459 static xmlSAXHandler sax_handler = {
460 xmlSAX2InternalSubset, /* internalSubset */
461 xmlSAX2IsStandalone, /* isStandalone */
462 xmlSAX2HasInternalSubset, /* hasInternalSubset */
463 xmlSAX2HasExternalSubset, /* hasExternalSubset */
464 xmlSAX2ResolveEntity, /* resolveEntity */
465 xmlSAX2GetEntity, /* getEntity */
466 xmlSAX2EntityDecl, /* entityDecl */
467 xmlSAX2NotationDecl, /* notationDecl */
468 xmlSAX2AttributeDecl, /* attributeDecl */
469 xmlSAX2ElementDecl, /* elementDecl */
470 xmlSAX2UnparsedEntityDecl, /* unparsedEntityDecl */
471 xmlSAX2SetDocumentLocator, /* setDocumentLocator */
472 xmlSAX2StartDocument, /* startDocument */
473 xmlSAX2EndDocument, /* endDocument */
474 xmlSAX2StartElement, /* startElement */
475 xmlSAX2EndElement, /* endElement */
476 xmlSAX2Reference, /* reference */
477 sax_characters, /* characters */
478 sax_characters, /* ignorableWhitespace */
479 xmlSAX2ProcessingInstruction, /* processingInstruction */
480 xmlSAX2Comment, /* comment */
481 sax_warning, /* warning */
482 sax_error, /* error */
483 sax_error, /* fatalError */
484 xmlSAX2GetParameterEntity, /* getParameterEntity */
485 xmlSAX2CDataBlock, /* cdataBlock */
486 xmlSAX2ExternalSubset, /* externalSubset */
489 xmlSAX2StartElementNs, /* startElementNs */
490 xmlSAX2EndElementNs, /* endElementNs */
491 sax_serror /* serror */
495 pctx = xmlCreateMemoryParserCtxt(ptr, len);
498 ERR("Failed to create parser context\n");
502 if (pctx->sax) xmlFree(pctx->sax);
503 pctx->sax = &sax_handler;
504 pctx->_private = This;
506 pctx->encoding = xmlStrdup(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, const GUID *clsid)
555 doc->_private = create_priv();
556 priv_from_xmlDocPtr(doc)->properties = create_properties(clsid);
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 )
631 priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
632 if (xmldoc_release(get_doc(This)) != 0)
633 priv_from_xmlDocPtr(get_doc(This))->properties =
634 copy_properties(This->properties);
637 This->node.node = (xmlNodePtr) xml;
641 xmldoc_add_ref(get_doc(This));
642 priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
648 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
650 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
653 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
655 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStreamInit));
658 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
660 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
663 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
665 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
668 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
670 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblISupportErrorInfo));
673 static inline domdoc *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
675 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtblConnectionPointContainer));
678 /************************************************************************
679 * domdoc implementation of IPersistStream.
681 static HRESULT WINAPI domdoc_IPersistStreamInit_QueryInterface(
682 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
684 domdoc* This = impl_from_IPersistStreamInit(iface);
685 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)&This->lpVtbl, riid, ppvObj);
688 static ULONG WINAPI domdoc_IPersistStreamInit_AddRef(
689 IPersistStreamInit *iface)
691 domdoc* This = impl_from_IPersistStreamInit(iface);
692 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)&This->lpVtbl);
695 static ULONG WINAPI domdoc_IPersistStreamInit_Release(
696 IPersistStreamInit *iface)
698 domdoc* This = impl_from_IPersistStreamInit(iface);
699 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)&This->lpVtbl);
702 static HRESULT WINAPI domdoc_IPersistStreamInit_GetClassID(
703 IPersistStreamInit *iface, CLSID *classid)
705 domdoc* This = impl_from_IPersistStreamInit(iface);
706 TRACE("(%p)->(%p)\n", This, classid);
711 *classid = *DOMDocument_version(This->properties->version);
716 static HRESULT WINAPI domdoc_IPersistStreamInit_IsDirty(
717 IPersistStreamInit *iface)
719 domdoc *This = impl_from_IPersistStreamInit(iface);
720 FIXME("(%p): stub!\n", This);
724 static HRESULT WINAPI domdoc_IPersistStreamInit_Load(
725 IPersistStreamInit *iface, LPSTREAM pStm)
727 domdoc *This = impl_from_IPersistStreamInit(iface);
730 DWORD read, written, len;
733 xmlDocPtr xmldoc = NULL;
735 TRACE("(%p)->(%p)\n", This, pStm);
740 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
746 IStream_Read(pStm, buf, sizeof(buf), &read);
747 hr = IStream_Write(This->stream, buf, read, &written);
748 } while(SUCCEEDED(hr) && written != 0 && read != 0);
752 ERR("Failed to copy stream\n");
756 hr = GetHGlobalFromStream(This->stream, &hglobal);
760 len = GlobalSize(hglobal);
761 ptr = GlobalLock(hglobal);
763 xmldoc = doparse(This, ptr, len, NULL);
764 GlobalUnlock(hglobal);
768 ERR("Failed to parse xml\n");
772 xmldoc->_private = create_priv();
774 return attach_xmldoc(This, xmldoc);
777 static HRESULT WINAPI domdoc_IPersistStreamInit_Save(
778 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
780 domdoc *This = impl_from_IPersistStreamInit(iface);
784 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
786 hr = IXMLDOMDocument3_get_xml( (IXMLDOMDocument3*)&This->lpVtbl, &xmlString );
789 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
791 hr = IStream_Write( stream, xmlString, len, NULL );
792 SysFreeString(xmlString);
795 TRACE("ret 0x%08x\n", hr);
800 static HRESULT WINAPI domdoc_IPersistStreamInit_GetSizeMax(
801 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
803 domdoc *This = impl_from_IPersistStreamInit(iface);
804 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
808 static HRESULT WINAPI domdoc_IPersistStreamInit_InitNew(
809 IPersistStreamInit *iface)
811 domdoc *This = impl_from_IPersistStreamInit(iface);
812 TRACE("(%p)\n", This);
816 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
818 domdoc_IPersistStreamInit_QueryInterface,
819 domdoc_IPersistStreamInit_AddRef,
820 domdoc_IPersistStreamInit_Release,
821 domdoc_IPersistStreamInit_GetClassID,
822 domdoc_IPersistStreamInit_IsDirty,
823 domdoc_IPersistStreamInit_Load,
824 domdoc_IPersistStreamInit_Save,
825 domdoc_IPersistStreamInit_GetSizeMax,
826 domdoc_IPersistStreamInit_InitNew
829 /* ISupportErrorInfo interface */
830 static HRESULT WINAPI support_error_QueryInterface(
831 ISupportErrorInfo *iface,
832 REFIID riid, void** ppvObj )
834 domdoc *This = impl_from_ISupportErrorInfo(iface);
835 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3 *)This, riid, ppvObj);
838 static ULONG WINAPI support_error_AddRef(
839 ISupportErrorInfo *iface )
841 domdoc *This = impl_from_ISupportErrorInfo(iface);
842 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
845 static ULONG WINAPI support_error_Release(
846 ISupportErrorInfo *iface )
848 domdoc *This = impl_from_ISupportErrorInfo(iface);
849 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
852 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
853 ISupportErrorInfo *iface,
856 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
860 static const struct ISupportErrorInfoVtbl support_error_vtbl =
862 support_error_QueryInterface,
863 support_error_AddRef,
864 support_error_Release,
865 support_error_InterfaceSupportsErrorInfo
868 /* IXMLDOMDocument2 interface */
869 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
871 domdoc *This = impl_from_IXMLDOMDocument3( iface );
873 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
877 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
878 IsEqualGUID( riid, &IID_IDispatch ) ||
879 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
880 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
881 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
882 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
886 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
887 IsEqualGUID(&IID_IPersistStreamInit, riid))
889 *ppvObject = &(This->lpvtblIPersistStreamInit);
891 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
893 *ppvObject = &(This->lpvtblIObjectWithSite);
895 else if (IsEqualGUID(&IID_IObjectSafety, riid))
897 *ppvObject = &(This->lpvtblIObjectSafety);
899 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
901 *ppvObject = &This->lpvtblISupportErrorInfo;
903 else if(node_query_interface(&This->node, riid, ppvObject))
905 return *ppvObject ? S_OK : E_NOINTERFACE;
907 else if (IsEqualGUID( riid, &IID_IConnectionPointContainer ))
909 *ppvObject = &This->lpVtblConnectionPointContainer;
911 else if(IsEqualGUID(&IID_IRunnableObject, riid))
913 TRACE("IID_IRunnableObject not supported returning NULL\n");
914 return E_NOINTERFACE;
918 FIXME("interface %s not implemented\n", debugstr_guid(riid));
919 return E_NOINTERFACE;
922 IUnknown_AddRef((IUnknown*)*ppvObject);
928 static ULONG WINAPI domdoc_AddRef(
929 IXMLDOMDocument3 *iface )
931 domdoc *This = impl_from_IXMLDOMDocument3( iface );
932 ULONG ref = InterlockedIncrement( &This->ref );
933 TRACE("(%p)->(%d)\n", This, ref );
938 static ULONG WINAPI domdoc_Release(
939 IXMLDOMDocument3 *iface )
941 domdoc *This = impl_from_IXMLDOMDocument3( iface );
942 LONG ref = InterlockedDecrement( &This->ref );
944 TRACE("(%p)->(%d)\n", This, ref );
951 detach_bsc(This->bsc);
954 IUnknown_Release( This->site );
955 destroy_xmlnode(&This->node);
957 IStream_Release(This->stream);
959 for (eid = 0; eid < EVENTID_LAST; eid++)
960 if (This->events[eid]) IDispatch_Release(This->events[eid]);
968 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
970 domdoc *This = impl_from_IXMLDOMDocument3( iface );
972 TRACE("(%p)->(%p)\n", This, pctinfo);
979 static HRESULT WINAPI domdoc_GetTypeInfo(
980 IXMLDOMDocument3 *iface,
981 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
983 domdoc *This = impl_from_IXMLDOMDocument3( iface );
986 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
988 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
993 static HRESULT WINAPI domdoc_GetIDsOfNames(
994 IXMLDOMDocument3 *iface,
1001 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1002 ITypeInfo *typeinfo;
1005 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1008 if(!rgszNames || cNames == 0 || !rgDispId)
1009 return E_INVALIDARG;
1011 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
1014 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1015 ITypeInfo_Release(typeinfo);
1022 static HRESULT WINAPI domdoc_Invoke(
1023 IXMLDOMDocument3 *iface,
1024 DISPID dispIdMember,
1028 DISPPARAMS* pDispParams,
1029 VARIANT* pVarResult,
1030 EXCEPINFO* pExcepInfo,
1033 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1034 ITypeInfo *typeinfo;
1037 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1038 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1040 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
1043 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
1044 pVarResult, pExcepInfo, puArgErr);
1045 ITypeInfo_Release(typeinfo);
1052 static HRESULT WINAPI domdoc_get_nodeName(
1053 IXMLDOMDocument3 *iface,
1056 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1058 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
1060 TRACE("(%p)->(%p)\n", This, name);
1062 return return_bstr(documentW, name);
1066 static HRESULT WINAPI domdoc_get_nodeValue(
1067 IXMLDOMDocument3 *iface,
1070 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1072 TRACE("(%p)->(%p)\n", This, value);
1075 return E_INVALIDARG;
1077 V_VT(value) = VT_NULL;
1078 V_BSTR(value) = NULL; /* tests show that we should do this */
1083 static HRESULT WINAPI domdoc_put_nodeValue(
1084 IXMLDOMDocument3 *iface,
1087 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1088 TRACE("(%p)->(v%d)\n", This, V_VT(&value));
1093 static HRESULT WINAPI domdoc_get_nodeType(
1094 IXMLDOMDocument3 *iface,
1097 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1099 TRACE("(%p)->(%p)\n", This, type);
1101 *type = NODE_DOCUMENT;
1106 static HRESULT WINAPI domdoc_get_parentNode(
1107 IXMLDOMDocument3 *iface,
1108 IXMLDOMNode** parent )
1110 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1112 TRACE("(%p)->(%p)\n", This, parent);
1114 return node_get_parent(&This->node, parent);
1118 static HRESULT WINAPI domdoc_get_childNodes(
1119 IXMLDOMDocument3 *iface,
1120 IXMLDOMNodeList** childList )
1122 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1124 TRACE("(%p)->(%p)\n", This, childList);
1126 return node_get_child_nodes(&This->node, childList);
1130 static HRESULT WINAPI domdoc_get_firstChild(
1131 IXMLDOMDocument3 *iface,
1132 IXMLDOMNode** firstChild )
1134 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1136 TRACE("(%p)->(%p)\n", This, firstChild);
1138 return node_get_first_child(&This->node, firstChild);
1142 static HRESULT WINAPI domdoc_get_lastChild(
1143 IXMLDOMDocument3 *iface,
1144 IXMLDOMNode** lastChild )
1146 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1148 TRACE("(%p)->(%p)\n", This, lastChild);
1150 return node_get_last_child(&This->node, lastChild);
1154 static HRESULT WINAPI domdoc_get_previousSibling(
1155 IXMLDOMDocument3 *iface,
1156 IXMLDOMNode** previousSibling )
1158 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1160 TRACE("(%p)->(%p)\n", This, previousSibling);
1162 return return_null_node(previousSibling);
1166 static HRESULT WINAPI domdoc_get_nextSibling(
1167 IXMLDOMDocument3 *iface,
1168 IXMLDOMNode** nextSibling )
1170 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1172 TRACE("(%p)->(%p)\n", This, nextSibling);
1174 return return_null_node(nextSibling);
1178 static HRESULT WINAPI domdoc_get_attributes(
1179 IXMLDOMDocument3 *iface,
1180 IXMLDOMNamedNodeMap** attributeMap )
1182 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1184 TRACE("(%p)->(%p)\n", This, attributeMap);
1186 return return_null_ptr((void**)attributeMap);
1190 static HRESULT WINAPI domdoc_insertBefore(
1191 IXMLDOMDocument3 *iface,
1192 IXMLDOMNode* newChild,
1194 IXMLDOMNode** outNewChild )
1196 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1198 TRACE("(%p)->(%p x%d %p)\n", This, newChild, V_VT(&refChild), outNewChild);
1200 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1204 static HRESULT WINAPI domdoc_replaceChild(
1205 IXMLDOMDocument3 *iface,
1206 IXMLDOMNode* newChild,
1207 IXMLDOMNode* oldChild,
1208 IXMLDOMNode** outOldChild)
1210 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1212 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1214 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1218 static HRESULT WINAPI domdoc_removeChild(
1219 IXMLDOMDocument3 *iface,
1221 IXMLDOMNode **oldChild)
1223 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1224 TRACE("(%p)->(%p %p)\n", This, child, oldChild);
1225 return node_remove_child(&This->node, child, oldChild);
1229 static HRESULT WINAPI domdoc_appendChild(
1230 IXMLDOMDocument3 *iface,
1232 IXMLDOMNode **outChild)
1234 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1235 TRACE("(%p)->(%p %p)\n", This, child, outChild);
1236 return node_append_child(&This->node, child, outChild);
1240 static HRESULT WINAPI domdoc_hasChildNodes(
1241 IXMLDOMDocument3 *iface,
1244 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1245 TRACE("(%p)->(%p)\n", This, ret);
1246 return node_has_childnodes(&This->node, ret);
1250 static HRESULT WINAPI domdoc_get_ownerDocument(
1251 IXMLDOMDocument3 *iface,
1252 IXMLDOMDocument **doc)
1254 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1255 TRACE("(%p)->(%p)\n", This, doc);
1256 return node_get_owner_doc(&This->node, doc);
1260 static HRESULT WINAPI domdoc_cloneNode(
1261 IXMLDOMDocument3 *iface,
1263 IXMLDOMNode** outNode)
1265 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1266 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
1267 return node_clone( &This->node, deep, outNode );
1271 static HRESULT WINAPI domdoc_get_nodeTypeString(
1272 IXMLDOMDocument3 *iface,
1275 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1276 static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
1278 TRACE("(%p)->(%p)\n", This, p);
1280 return return_bstr(documentW, p);
1284 static HRESULT WINAPI domdoc_get_text(
1285 IXMLDOMDocument3 *iface,
1288 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1289 TRACE("(%p)->(%p)\n", This, p);
1290 return node_get_text(&This->node, p);
1294 static HRESULT WINAPI domdoc_put_text(
1295 IXMLDOMDocument3 *iface,
1298 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1299 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1304 static HRESULT WINAPI domdoc_get_specified(
1305 IXMLDOMDocument3 *iface,
1306 VARIANT_BOOL* isSpecified )
1308 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1309 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1310 *isSpecified = VARIANT_TRUE;
1315 static HRESULT WINAPI domdoc_get_definition(
1316 IXMLDOMDocument3 *iface,
1317 IXMLDOMNode** definitionNode )
1319 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1320 FIXME("(%p)->(%p)\n", This, definitionNode);
1325 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1326 IXMLDOMDocument3 *iface,
1327 VARIANT* typedValue )
1329 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1330 FIXME("(%p)->(%p)\n", This, typedValue);
1331 return return_null_var(typedValue);
1334 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1335 IXMLDOMDocument3 *iface,
1336 VARIANT typedValue )
1338 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1339 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1344 static HRESULT WINAPI domdoc_get_dataType(
1345 IXMLDOMDocument3 *iface,
1348 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1349 TRACE("(%p)->(%p)\n", This, typename);
1350 return return_null_var( typename );
1354 static HRESULT WINAPI domdoc_put_dataType(
1355 IXMLDOMDocument3 *iface,
1358 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1360 FIXME("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
1363 return E_INVALIDARG;
1368 static int XMLCALL domdoc_get_xml_writecallback(void *ctx, const char *data, int len)
1370 return xmlBufferAdd((xmlBufferPtr)ctx, (xmlChar*)data, len) == 0 ? len : 0;
1373 static HRESULT WINAPI domdoc_get_xml(
1374 IXMLDOMDocument3 *iface,
1377 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1378 xmlSaveCtxtPtr ctxt;
1383 TRACE("(%p)->(%p)\n", This, p);
1386 return E_INVALIDARG;
1390 buf = xmlBufferCreate();
1392 return E_OUTOFMEMORY;
1394 options = xmldoc_has_decl(get_doc(This)) ? XML_SAVE_NO_DECL : 0;
1395 options |= XML_SAVE_FORMAT;
1396 ctxt = xmlSaveToIO(domdoc_get_xml_writecallback, NULL, buf, "UTF-8", options);
1401 return E_OUTOFMEMORY;
1404 ret = xmlSaveDoc(ctxt, get_doc(This));
1405 /* flushes on close */
1408 TRACE("%ld, len=%d\n", ret, xmlBufferLength(buf));
1409 if(ret != -1 && xmlBufferLength(buf) > 0)
1413 content = bstr_from_xmlChar(xmlBufferContent(buf));
1414 content = EnsureCorrectEOL(content);
1420 *p = SysAllocStringLen(NULL, 0);
1425 return *p ? S_OK : E_OUTOFMEMORY;
1429 static HRESULT WINAPI domdoc_transformNode(
1430 IXMLDOMDocument3 *iface,
1431 IXMLDOMNode* styleSheet,
1434 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1435 return IXMLDOMNode_transformNode( &This->node.IXMLDOMNode_iface, styleSheet, xmlString );
1439 static HRESULT WINAPI domdoc_selectNodes(
1440 IXMLDOMDocument3 *iface,
1442 IXMLDOMNodeList** resultList )
1444 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1445 return IXMLDOMNode_selectNodes( &This->node.IXMLDOMNode_iface, queryString, resultList );
1449 static HRESULT WINAPI domdoc_selectSingleNode(
1450 IXMLDOMDocument3 *iface,
1452 IXMLDOMNode** resultNode )
1454 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1455 return IXMLDOMNode_selectSingleNode( &This->node.IXMLDOMNode_iface, queryString, resultNode );
1459 static HRESULT WINAPI domdoc_get_parsed(
1460 IXMLDOMDocument3 *iface,
1461 VARIANT_BOOL* isParsed )
1463 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1464 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1465 *isParsed = VARIANT_TRUE;
1470 static HRESULT WINAPI domdoc_get_namespaceURI(
1471 IXMLDOMDocument3 *iface,
1472 BSTR* namespaceURI )
1474 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1475 TRACE("(%p)->(%p)\n", This, namespaceURI);
1476 return node_get_namespaceURI(&This->node, namespaceURI);
1480 static HRESULT WINAPI domdoc_get_prefix(
1481 IXMLDOMDocument3 *iface,
1484 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1485 TRACE("(%p)->(%p)\n", This, prefix);
1486 return return_null_bstr( prefix );
1490 static HRESULT WINAPI domdoc_get_baseName(
1491 IXMLDOMDocument3 *iface,
1494 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1495 TRACE("(%p)->(%p)\n", This, name);
1496 return return_null_bstr( name );
1500 static HRESULT WINAPI domdoc_transformNodeToObject(
1501 IXMLDOMDocument3 *iface,
1502 IXMLDOMNode* stylesheet,
1503 VARIANT outputObject)
1505 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1506 FIXME("(%p)->(%p %s)\n", This, stylesheet, debugstr_variant(&outputObject));
1511 static HRESULT WINAPI domdoc_get_doctype(
1512 IXMLDOMDocument3 *iface,
1513 IXMLDOMDocumentType** documentType )
1515 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1516 FIXME("(%p)\n", This);
1521 static HRESULT WINAPI domdoc_get_implementation(
1522 IXMLDOMDocument3 *iface,
1523 IXMLDOMImplementation** impl )
1525 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1527 TRACE("(%p)->(%p)\n", This, impl);
1530 return E_INVALIDARG;
1532 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1537 static HRESULT WINAPI domdoc_get_documentElement(
1538 IXMLDOMDocument3 *iface,
1539 IXMLDOMElement** DOMElement )
1541 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1542 IXMLDOMNode *element_node;
1546 TRACE("(%p)->(%p)\n", This, DOMElement);
1549 return E_INVALIDARG;
1553 root = xmlDocGetRootElement( get_doc(This) );
1557 element_node = create_node( root );
1558 if(!element_node) return S_FALSE;
1560 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1561 IXMLDOMNode_Release(element_node);
1567 static HRESULT WINAPI domdoc_put_documentElement(
1568 IXMLDOMDocument3 *iface,
1569 IXMLDOMElement* DOMElement )
1571 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1572 IXMLDOMNode *elementNode;
1577 TRACE("(%p)->(%p)\n", This, DOMElement);
1579 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1583 xmlNode = get_node_obj( elementNode );
1585 FIXME("elementNode is not our object\n");
1589 if(!xmlNode->node->parent)
1590 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1591 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1593 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1594 IXMLDOMNode_Release( elementNode );
1597 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1603 static HRESULT WINAPI domdoc_createElement(
1604 IXMLDOMDocument3 *iface,
1606 IXMLDOMElement** element )
1608 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1613 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1615 if (!element || !tagname) return E_INVALIDARG;
1617 V_VT(&type) = VT_I1;
1618 V_I1(&type) = NODE_ELEMENT;
1620 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1623 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1624 IXMLDOMNode_Release(node);
1631 static HRESULT WINAPI domdoc_createDocumentFragment(
1632 IXMLDOMDocument3 *iface,
1633 IXMLDOMDocumentFragment** frag )
1635 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1640 TRACE("(%p)->(%p)\n", This, frag);
1642 if (!frag) return E_INVALIDARG;
1646 V_VT(&type) = VT_I1;
1647 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1649 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1652 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1653 IXMLDOMNode_Release(node);
1660 static HRESULT WINAPI domdoc_createTextNode(
1661 IXMLDOMDocument3 *iface,
1663 IXMLDOMText** text )
1665 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1670 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1672 if (!text) return E_INVALIDARG;
1676 V_VT(&type) = VT_I1;
1677 V_I1(&type) = NODE_TEXT;
1679 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1682 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1683 IXMLDOMNode_Release(node);
1684 hr = IXMLDOMText_put_data(*text, data);
1691 static HRESULT WINAPI domdoc_createComment(
1692 IXMLDOMDocument3 *iface,
1694 IXMLDOMComment** comment )
1696 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1701 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1703 if (!comment) return E_INVALIDARG;
1707 V_VT(&type) = VT_I1;
1708 V_I1(&type) = NODE_COMMENT;
1710 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1713 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1714 IXMLDOMNode_Release(node);
1715 hr = IXMLDOMComment_put_data(*comment, data);
1722 static HRESULT WINAPI domdoc_createCDATASection(
1723 IXMLDOMDocument3 *iface,
1725 IXMLDOMCDATASection** cdata )
1727 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1732 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1734 if (!cdata) return E_INVALIDARG;
1738 V_VT(&type) = VT_I1;
1739 V_I1(&type) = NODE_CDATA_SECTION;
1741 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1744 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1745 IXMLDOMNode_Release(node);
1746 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1753 static HRESULT WINAPI domdoc_createProcessingInstruction(
1754 IXMLDOMDocument3 *iface,
1757 IXMLDOMProcessingInstruction** pi )
1759 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1764 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1766 if (!pi) return E_INVALIDARG;
1770 V_VT(&type) = VT_I1;
1771 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1773 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1778 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1779 node_obj = get_node_obj(node);
1780 hr = node_set_content(node_obj, data);
1782 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1783 IXMLDOMNode_Release(node);
1790 static HRESULT WINAPI domdoc_createAttribute(
1791 IXMLDOMDocument3 *iface,
1793 IXMLDOMAttribute** attribute )
1795 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1800 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1802 if (!attribute || !name) return E_INVALIDARG;
1804 V_VT(&type) = VT_I1;
1805 V_I1(&type) = NODE_ATTRIBUTE;
1807 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1810 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1811 IXMLDOMNode_Release(node);
1818 static HRESULT WINAPI domdoc_createEntityReference(
1819 IXMLDOMDocument3 *iface,
1821 IXMLDOMEntityReference** entityref )
1823 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1828 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1830 if (!entityref) return E_INVALIDARG;
1834 V_VT(&type) = VT_I1;
1835 V_I1(&type) = NODE_ENTITY_REFERENCE;
1837 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1840 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1841 IXMLDOMNode_Release(node);
1847 xmlChar* tagName_to_XPath(const BSTR tagName)
1849 xmlChar *query, *tmp;
1850 static const xmlChar mod_pre[] = "*[local-name()='";
1851 static const xmlChar mod_post[] = "']";
1852 static const xmlChar prefix[] = "descendant::";
1853 const WCHAR *tokBegin, *tokEnd;
1856 query = xmlStrdup(prefix);
1859 while (tokBegin && *tokBegin)
1864 query = xmlStrcat(query, BAD_CAST "/");
1868 query = xmlStrcat(query, BAD_CAST "*");
1872 query = xmlStrcat(query, mod_pre);
1874 while (*tokEnd && *tokEnd != '/')
1876 len = WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, NULL, 0, NULL, NULL);
1877 tmp = xmlMalloc(len);
1878 WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, (char*)tmp, len, NULL, NULL);
1879 query = xmlStrncat(query, tmp, len);
1882 query = xmlStrcat(query, mod_post);
1889 static HRESULT WINAPI domdoc_getElementsByTagName(
1890 IXMLDOMDocument3 *iface,
1892 IXMLDOMNodeList** resultList )
1894 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1899 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1901 if (!tagName || !resultList) return E_INVALIDARG;
1903 XPath = This->properties->XPath;
1904 This->properties->XPath = TRUE;
1905 query = tagName_to_XPath(tagName);
1906 hr = queryresult_create((xmlNodePtr)get_doc(This), query, resultList);
1908 This->properties->XPath = XPath;
1913 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1919 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1921 return E_INVALIDARG;
1928 static HRESULT WINAPI domdoc_createNode(
1929 IXMLDOMDocument3 *iface,
1933 IXMLDOMNode** node )
1935 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1936 DOMNodeType node_type;
1938 xmlChar *xml_name, *href;
1941 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1943 if(!node) return E_INVALIDARG;
1945 hr = get_node_type(Type, &node_type);
1946 if(FAILED(hr)) return hr;
1948 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1949 FIXME("nodes with namespaces currently not supported.\n");
1951 TRACE("node_type %d\n", node_type);
1953 /* exit earlier for types that need name */
1957 case NODE_ATTRIBUTE:
1958 case NODE_ENTITY_REFERENCE:
1959 case NODE_PROCESSING_INSTRUCTION:
1960 if (!name || *name == 0) return E_FAIL;
1965 xml_name = xmlChar_from_wchar(name);
1966 /* prevent empty href to be allocated */
1967 href = namespaceURI ? xmlChar_from_wchar(namespaceURI) : NULL;
1973 xmlChar *local, *prefix;
1975 local = xmlSplitQName2(xml_name, &prefix);
1977 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
1979 /* allow to create default namespace xmlns= */
1980 if (local || (href && *href))
1982 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
1983 xmlSetNs(xmlnode, ns);
1991 case NODE_ATTRIBUTE:
1992 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1995 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1997 case NODE_CDATA_SECTION:
1998 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
2000 case NODE_ENTITY_REFERENCE:
2001 xmlnode = xmlNewReference(get_doc(This), xml_name);
2003 case NODE_PROCESSING_INSTRUCTION:
2004 #ifdef HAVE_XMLNEWDOCPI
2005 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
2007 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2012 xmlnode = xmlNewDocComment(get_doc(This), NULL);
2014 case NODE_DOCUMENT_FRAGMENT:
2015 xmlnode = xmlNewDocFragment(get_doc(This));
2017 /* unsupported types */
2019 case NODE_DOCUMENT_TYPE:
2022 heap_free(xml_name);
2023 return E_INVALIDARG;
2025 FIXME("unhandled node type %d\n", node_type);
2030 *node = create_node(xmlnode);
2031 heap_free(xml_name);
2036 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
2037 xmldoc_add_orphan(xmlnode->doc, xmlnode);
2044 static HRESULT WINAPI domdoc_nodeFromID(
2045 IXMLDOMDocument3 *iface,
2047 IXMLDOMNode** node )
2049 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2050 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
2054 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
2059 xmldoc = doparse(This, ptr, len, NULL);
2061 xmldoc->_private = create_priv();
2062 return attach_xmldoc(This, xmldoc);
2068 static HRESULT doread( domdoc *This, LPWSTR filename )
2073 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
2078 detach_bsc(This->bsc);
2084 static HRESULT WINAPI domdoc_load(
2085 IXMLDOMDocument3 *iface,
2087 VARIANT_BOOL* isSuccessful )
2089 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2090 LPWSTR filename = NULL;
2091 HRESULT hr = S_FALSE;
2092 IXMLDOMDocument3 *pNewDoc = NULL;
2093 IStream *pStream = NULL;
2096 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
2098 *isSuccessful = VARIANT_FALSE;
2100 assert( &This->node );
2102 switch( V_VT(&xmlSource) )
2105 filename = V_BSTR(&xmlSource);
2108 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
2113 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
2114 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
2115 hr = attach_xmldoc(This, xmldoc);
2118 *isSuccessful = VARIANT_TRUE;
2123 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
2126 IPersistStream *pDocStream;
2127 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
2130 hr = IPersistStream_Load(pDocStream, pStream);
2131 IStream_Release(pStream);
2134 *isSuccessful = VARIANT_TRUE;
2136 TRACE("Using IStream to load Document\n");
2141 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
2146 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
2151 /* ISequentialStream */
2152 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
2156 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
2159 TRACE("filename (%s)\n", debugstr_w(filename));
2163 hr = doread( This, filename );
2166 This->error = E_FAIL;
2169 hr = This->error = S_OK;
2170 *isSuccessful = VARIANT_TRUE;
2174 if(!filename || FAILED(hr)) {
2175 xmldoc = xmlNewDoc(NULL);
2176 xmldoc->_private = create_priv();
2177 hr = attach_xmldoc(This, xmldoc);
2182 TRACE("ret (%d)\n", hr);
2188 static HRESULT WINAPI domdoc_get_readyState(
2189 IXMLDOMDocument3 *iface,
2192 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2193 FIXME("stub! (%p)->(%p)\n", This, value);
2196 return E_INVALIDARG;
2198 *value = READYSTATE_COMPLETE;
2203 static HRESULT WINAPI domdoc_get_parseError(
2204 IXMLDOMDocument3 *iface,
2205 IXMLDOMParseError** errorObj )
2207 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2208 static const WCHAR err[] = {'e','r','r','o','r',0};
2209 BSTR error_string = NULL;
2211 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2214 error_string = SysAllocString(err);
2216 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2217 if(!*errorObj) return E_OUTOFMEMORY;
2222 static HRESULT WINAPI domdoc_get_url(
2223 IXMLDOMDocument3 *iface,
2226 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2227 FIXME("(%p)->(%p)\n", This, urlString);
2232 static HRESULT WINAPI domdoc_get_async(
2233 IXMLDOMDocument3 *iface,
2234 VARIANT_BOOL* isAsync )
2236 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2238 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2239 *isAsync = This->async;
2244 static HRESULT WINAPI domdoc_put_async(
2245 IXMLDOMDocument3 *iface,
2246 VARIANT_BOOL isAsync )
2248 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2250 TRACE("(%p)->(%d)\n", This, isAsync);
2251 This->async = isAsync;
2256 static HRESULT WINAPI domdoc_abort(
2257 IXMLDOMDocument3 *iface )
2259 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2260 FIXME("%p\n", This);
2265 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
2270 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
2271 str = heap_alloc( len );
2274 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
2280 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2281 static HRESULT WINAPI domdoc_loadXML(
2282 IXMLDOMDocument3 *iface,
2284 VARIANT_BOOL* isSuccessful )
2286 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2287 static const xmlChar encoding[] = "UTF-8";
2288 xmlDocPtr xmldoc = NULL;
2289 HRESULT hr = S_FALSE, hr2;
2293 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2295 assert ( &This->node );
2299 *isSuccessful = VARIANT_FALSE;
2301 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
2303 xmldoc = doparse(This, str, len, encoding);
2307 This->error = E_FAIL;
2308 TRACE("failed to parse document\n");
2312 hr = This->error = S_OK;
2313 *isSuccessful = VARIANT_TRUE;
2314 TRACE("parsed document %p\n", xmldoc);
2319 xmldoc = xmlNewDoc(NULL);
2321 xmldoc->_private = create_priv();
2323 hr2 = attach_xmldoc(This, xmldoc);
2330 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2334 if(!WriteFile(ctx, buffer, len, &written, NULL))
2336 WARN("write error\n");
2343 static int XMLCALL domdoc_save_closecallback(void *ctx)
2345 return CloseHandle(ctx) ? 0 : -1;
2348 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2353 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2356 WARN("stream write error: 0x%08x\n", hr);
2363 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2365 IStream_Release((IStream*)ctx);
2369 static HRESULT WINAPI domdoc_save(
2370 IXMLDOMDocument3 *iface,
2371 VARIANT destination )
2373 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2374 xmlSaveCtxtPtr ctx = NULL;
2378 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
2379 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
2381 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
2383 FIXME("Unhandled vt %d\n", V_VT(&destination));
2387 if(V_VT(&destination) == VT_UNKNOWN)
2389 IUnknown *pUnk = V_UNKNOWN(&destination);
2390 IXMLDOMDocument2 *document;
2393 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2396 VARIANT_BOOL success;
2399 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2402 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2406 IXMLDOMDocument3_Release(document);
2410 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2413 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2414 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2418 IStream_Release(stream);
2425 /* save with file path */
2426 HANDLE handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
2427 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2428 if( handle == INVALID_HANDLE_VALUE )
2430 WARN("failed to create file\n");
2434 /* disable top XML declaration */
2435 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2436 handle, NULL, XML_SAVE_NO_DECL);
2439 CloseHandle(handle);
2444 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2445 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2446 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2448 /* will release resources through close callback */
2454 static HRESULT WINAPI domdoc_get_validateOnParse(
2455 IXMLDOMDocument3 *iface,
2456 VARIANT_BOOL* isValidating )
2458 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2459 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2460 *isValidating = This->validating;
2465 static HRESULT WINAPI domdoc_put_validateOnParse(
2466 IXMLDOMDocument3 *iface,
2467 VARIANT_BOOL isValidating )
2469 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2470 TRACE("(%p)->(%d)\n", This, isValidating);
2471 This->validating = isValidating;
2476 static HRESULT WINAPI domdoc_get_resolveExternals(
2477 IXMLDOMDocument3 *iface,
2478 VARIANT_BOOL* isResolving )
2480 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2481 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2482 *isResolving = This->resolving;
2487 static HRESULT WINAPI domdoc_put_resolveExternals(
2488 IXMLDOMDocument3 *iface,
2489 VARIANT_BOOL isResolving )
2491 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2492 TRACE("(%p)->(%d)\n", This, isResolving);
2493 This->resolving = isResolving;
2498 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2499 IXMLDOMDocument3 *iface,
2500 VARIANT_BOOL* isPreserving )
2502 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2503 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->properties->preserving);
2504 *isPreserving = This->properties->preserving;
2509 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2510 IXMLDOMDocument3 *iface,
2511 VARIANT_BOOL isPreserving )
2513 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2514 TRACE("(%p)->(%d)\n", This, isPreserving);
2515 This->properties->preserving = isPreserving;
2520 static HRESULT WINAPI domdoc_put_onreadystatechange(
2521 IXMLDOMDocument3 *iface,
2524 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2526 TRACE("(%p)->(%s)\n", This, debugstr_variant(&event));
2527 return set_doc_event(This, EVENTID_READYSTATECHANGE, &event);
2531 static HRESULT WINAPI domdoc_put_onDataAvailable(
2532 IXMLDOMDocument3 *iface,
2533 VARIANT onDataAvailableSink )
2535 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2536 FIXME("%p\n", This);
2540 static HRESULT WINAPI domdoc_put_onTransformNode(
2541 IXMLDOMDocument3 *iface,
2542 VARIANT onTransformNodeSink )
2544 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2545 FIXME("%p\n", This);
2549 static HRESULT WINAPI domdoc_get_namespaces(
2550 IXMLDOMDocument3* iface,
2551 IXMLDOMSchemaCollection** schemaCollection )
2553 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2554 FIXME("(%p)->(%p)\n", This, schemaCollection);
2558 static HRESULT WINAPI domdoc_get_schemas(
2559 IXMLDOMDocument3* iface,
2562 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2563 HRESULT hr = S_FALSE;
2564 IXMLDOMSchemaCollection2* cur_schema = This->properties->schemaCache;
2566 TRACE("(%p)->(%p)\n", This, var1);
2568 VariantInit(var1); /* Test shows we don't call VariantClear here */
2569 V_VT(var1) = VT_NULL;
2573 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2575 V_VT(var1) = VT_DISPATCH;
2580 static HRESULT WINAPI domdoc_putref_schemas(
2581 IXMLDOMDocument3* iface,
2584 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2585 HRESULT hr = E_FAIL;
2586 IXMLDOMSchemaCollection2* new_schema = NULL;
2588 FIXME("(%p): semi-stub\n", This);
2592 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2596 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2605 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2610 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->properties->schemaCache, new_schema);
2611 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2617 static inline BOOL is_wellformed(xmlDocPtr doc)
2619 #ifdef HAVE_XMLDOC_PROPERTIES
2620 return doc->properties & XML_DOC_WELLFORMED;
2622 /* Not a full check, but catches the worst violations */
2626 for (child = doc->children; child != NULL; child = child->next)
2628 switch (child->type)
2630 case XML_ELEMENT_NODE:
2635 case XML_CDATA_SECTION_NODE:
2647 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2651 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2655 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2659 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2663 static HRESULT WINAPI domdoc_validateNode(
2664 IXMLDOMDocument3* iface,
2666 IXMLDOMParseError** err)
2668 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2669 LONG state, err_code = 0;
2673 TRACE("(%p)->(%p, %p)\n", This, node, err);
2674 domdoc_get_readyState(iface, &state);
2675 if (state != READYSTATE_COMPLETE)
2678 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2685 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2689 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2692 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2696 if (!is_wellformed(get_doc(This)))
2698 ERR("doc not well-formed\n");
2700 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2704 /* DTD validation */
2705 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2707 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2708 vctx->error = validate_error;
2709 vctx->warning = validate_warning;
2712 if (!((node == (IXMLDOMNode*)iface)?
2713 xmlValidateDocument(vctx, get_doc(This)) :
2714 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2716 /* TODO: get a real error code here */
2717 TRACE("DTD validation failed\n");
2718 err_code = E_XML_INVALID;
2721 xmlFreeValidCtxt(vctx);
2724 /* Schema validation */
2725 if (hr == S_OK && This->properties->schemaCache != NULL)
2728 hr = SchemaCache_validate_tree(This->properties->schemaCache, get_node_obj(node)->node);
2732 /* TODO: get a real error code here */
2735 TRACE("schema validation succeeded\n");
2739 ERR("schema validation failed\n");
2740 err_code = E_XML_INVALID;
2745 /* not really OK, just didn't find a schema for the ns */
2752 ERR("no DTD or schema found\n");
2753 err_code = E_XML_NODTD;
2758 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2763 static HRESULT WINAPI domdoc_validate(
2764 IXMLDOMDocument3* iface,
2765 IXMLDOMParseError** err)
2767 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2768 TRACE("(%p)->(%p)\n", This, err);
2769 return domdoc_validateNode(iface, (IXMLDOMNode*)iface, err);
2772 static HRESULT WINAPI domdoc_setProperty(
2773 IXMLDOMDocument3* iface,
2777 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2779 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2781 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2787 V_VT(&varStr) = VT_EMPTY;
2788 if (V_VT(&var) != VT_BSTR)
2790 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2792 bstr = V_BSTR(&varStr);
2795 bstr = V_BSTR(&var);
2798 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2799 This->properties->XPath = TRUE;
2800 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2801 This->properties->XPath = FALSE;
2805 VariantClear(&varStr);
2808 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2813 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2814 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2815 xmlXPathContextPtr ctx;
2816 struct list *pNsList;
2817 select_ns_entry* pNsEntry = NULL;
2819 V_VT(&varStr) = VT_EMPTY;
2820 if (V_VT(&var) != VT_BSTR)
2822 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2824 bstr = V_BSTR(&varStr);
2827 bstr = V_BSTR(&var);
2831 pNsList = &(This->properties->selectNsList);
2832 clear_selectNsList(pNsList);
2834 nsStr = xmlChar_from_wchar(bstr);
2837 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2839 This->properties->selectNsStr = nsStr;
2840 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2843 ctx = xmlXPathNewContext(This->node.node->doc);
2846 for (; *pTokBegin; pTokBegin = pTokEnd)
2848 if (pNsEntry != NULL)
2849 memset(pNsEntry, 0, sizeof(select_ns_entry));
2851 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2853 while (*pTokBegin == ' ')
2855 pTokEnd = pTokBegin;
2856 while (*pTokEnd != ' ' && *pTokEnd != 0)
2859 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2862 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2863 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2868 if (*pTokBegin == '=')
2870 /*valid for XSLPattern?*/
2871 FIXME("Setting default xmlns not supported - skipping.\n");
2872 pTokBegin = pTokEnd;
2875 else if (*pTokBegin == ':')
2877 pNsEntry->prefix = ++pTokBegin;
2878 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2881 if (pTokInner == pTokEnd)
2884 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2885 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2889 pNsEntry->prefix_end = *pTokInner;
2893 if (pTokEnd-pTokInner > 1 &&
2894 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2895 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2897 pNsEntry->href = ++pTokInner;
2898 pNsEntry->href_end = *(pTokEnd-1);
2900 list_add_tail(pNsList, &pNsEntry->entry);
2901 /*let libxml figure out if they're valid from here ;)*/
2902 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2911 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2912 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2913 list_add_tail(pNsList, &pNsEntry->entry);
2926 heap_free(pNsEntry);
2927 xmlXPathFreeContext(ctx);
2930 VariantClear(&varStr);
2933 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2934 lstrcmpiW(p, PropertyNewParserW) == 0)
2937 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2941 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2945 static HRESULT WINAPI domdoc_getProperty(
2946 IXMLDOMDocument3* iface,
2950 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2952 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2955 return E_INVALIDARG;
2957 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2959 V_VT(var) = VT_BSTR;
2960 V_BSTR(var) = This->properties->XPath ?
2961 SysAllocString(PropValueXPathW) :
2962 SysAllocString(PropValueXSLPatternW);
2963 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2965 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2968 BSTR rebuiltStr, cur;
2969 const xmlChar *nsStr;
2970 struct list *pNsList;
2971 select_ns_entry* pNsEntry;
2973 V_VT(var) = VT_BSTR;
2974 nsStr = This->properties->selectNsStr;
2975 pNsList = &This->properties->selectNsList;
2976 lenA = This->properties->selectNsStr_len;
2977 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
2978 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
2979 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
2981 /* this is fine because all of the chars that end tokens are ASCII*/
2982 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
2984 while (*cur != 0) ++cur;
2985 if (pNsEntry->prefix_end)
2987 *cur = pNsEntry->prefix_end;
2988 while (*cur != 0) ++cur;
2991 if (pNsEntry->href_end)
2993 *cur = pNsEntry->href_end;
2996 V_BSTR(var) = SysAllocString(rebuiltStr);
2997 heap_free(rebuiltStr);
3001 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
3005 static HRESULT WINAPI domdoc_importNode(
3006 IXMLDOMDocument3* iface,
3009 IXMLDOMNode** clone)
3011 domdoc *This = impl_from_IXMLDOMDocument3( iface );
3012 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
3016 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
3018 domdoc_QueryInterface,
3021 domdoc_GetTypeInfoCount,
3023 domdoc_GetIDsOfNames,
3025 domdoc_get_nodeName,
3026 domdoc_get_nodeValue,
3027 domdoc_put_nodeValue,
3028 domdoc_get_nodeType,
3029 domdoc_get_parentNode,
3030 domdoc_get_childNodes,
3031 domdoc_get_firstChild,
3032 domdoc_get_lastChild,
3033 domdoc_get_previousSibling,
3034 domdoc_get_nextSibling,
3035 domdoc_get_attributes,
3036 domdoc_insertBefore,
3037 domdoc_replaceChild,
3040 domdoc_hasChildNodes,
3041 domdoc_get_ownerDocument,
3043 domdoc_get_nodeTypeString,
3046 domdoc_get_specified,
3047 domdoc_get_definition,
3048 domdoc_get_nodeTypedValue,
3049 domdoc_put_nodeTypedValue,
3050 domdoc_get_dataType,
3051 domdoc_put_dataType,
3053 domdoc_transformNode,
3055 domdoc_selectSingleNode,
3057 domdoc_get_namespaceURI,
3059 domdoc_get_baseName,
3060 domdoc_transformNodeToObject,
3062 domdoc_get_implementation,
3063 domdoc_get_documentElement,
3064 domdoc_put_documentElement,
3065 domdoc_createElement,
3066 domdoc_createDocumentFragment,
3067 domdoc_createTextNode,
3068 domdoc_createComment,
3069 domdoc_createCDATASection,
3070 domdoc_createProcessingInstruction,
3071 domdoc_createAttribute,
3072 domdoc_createEntityReference,
3073 domdoc_getElementsByTagName,
3077 domdoc_get_readyState,
3078 domdoc_get_parseError,
3085 domdoc_get_validateOnParse,
3086 domdoc_put_validateOnParse,
3087 domdoc_get_resolveExternals,
3088 domdoc_put_resolveExternals,
3089 domdoc_get_preserveWhiteSpace,
3090 domdoc_put_preserveWhiteSpace,
3091 domdoc_put_onreadystatechange,
3092 domdoc_put_onDataAvailable,
3093 domdoc_put_onTransformNode,
3094 domdoc_get_namespaces,
3096 domdoc_putref_schemas,
3100 domdoc_validateNode,
3104 /* IConnectionPointContainer */
3105 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
3106 REFIID riid, void **ppv)
3108 domdoc *This = impl_from_IConnectionPointContainer(iface);
3109 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)This, riid, ppv);
3112 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
3114 domdoc *This = impl_from_IConnectionPointContainer(iface);
3115 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)This);
3118 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
3120 domdoc *This = impl_from_IConnectionPointContainer(iface);
3121 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)This);
3124 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
3125 IEnumConnectionPoints **ppEnum)
3127 domdoc *This = impl_from_IConnectionPointContainer(iface);
3128 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3132 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
3133 REFIID riid, IConnectionPoint **cp)
3135 domdoc *This = impl_from_IConnectionPointContainer(iface);
3136 ConnectionPoint *iter;
3138 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
3142 for(iter = This->cp_list; iter; iter = iter->next)
3144 if (IsEqualGUID(iter->iid, riid))
3145 *cp = (IConnectionPoint*)&iter->lpVtblConnectionPoint;
3150 IConnectionPoint_AddRef(*cp);
3154 FIXME("unsupported riid %s\n", debugstr_guid(riid));
3155 return CONNECT_E_NOCONNECTION;
3159 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
3161 ConnectionPointContainer_QueryInterface,
3162 ConnectionPointContainer_AddRef,
3163 ConnectionPointContainer_Release,
3164 ConnectionPointContainer_EnumConnectionPoints,
3165 ConnectionPointContainer_FindConnectionPoint
3168 /* IConnectionPoint */
3169 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
3170 REFIID riid, void **ppv)
3172 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3174 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3178 if (IsEqualGUID(&IID_IUnknown, riid) ||
3179 IsEqualGUID(&IID_IConnectionPoint, riid))
3186 IConnectionPoint_AddRef(iface);
3190 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3191 return E_NOINTERFACE;
3194 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3196 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3197 return IConnectionPointContainer_AddRef(This->container);
3200 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3202 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3203 return IConnectionPointContainer_Release(This->container);
3206 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3208 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3210 TRACE("(%p)->(%p)\n", This, iid);
3212 if (!iid) return E_POINTER;
3218 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3219 IConnectionPointContainer **container)
3221 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3223 TRACE("(%p)->(%p)\n", This, container);
3225 if (!container) return E_POINTER;
3227 *container = This->container;
3228 IConnectionPointContainer_AddRef(*container);
3232 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
3235 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3236 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
3240 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3242 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3244 TRACE("(%p)->(%d)\n", This, cookie);
3246 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3247 return CONNECT_E_NOCONNECTION;
3249 IUnknown_Release(This->sinks[cookie-1].unk);
3250 This->sinks[cookie-1].unk = NULL;
3255 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3256 IEnumConnections **ppEnum)
3258 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3259 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3263 static const IConnectionPointVtbl ConnectionPointVtbl =
3265 ConnectionPoint_QueryInterface,
3266 ConnectionPoint_AddRef,
3267 ConnectionPoint_Release,
3268 ConnectionPoint_GetConnectionInterface,
3269 ConnectionPoint_GetConnectionPointContainer,
3270 ConnectionPoint_Advise,
3271 ConnectionPoint_Unadvise,
3272 ConnectionPoint_EnumConnections
3275 void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3277 cp->lpVtblConnectionPoint = &ConnectionPointVtbl;
3283 cp->next = doc->cp_list;
3286 cp->container = (IConnectionPointContainer*)&doc->lpVtblConnectionPointContainer;
3289 /* domdoc implementation of IObjectWithSite */
3290 static HRESULT WINAPI
3291 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3293 domdoc *This = impl_from_IObjectWithSite(iface);
3294 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppvObject );
3297 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3299 domdoc *This = impl_from_IObjectWithSite(iface);
3300 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3303 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3305 domdoc *This = impl_from_IObjectWithSite(iface);
3306 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3309 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3311 domdoc *This = impl_from_IObjectWithSite(iface);
3313 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3318 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3321 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3323 domdoc *This = impl_from_IObjectWithSite(iface);
3325 TRACE("(%p)->(%p)\n", iface, punk);
3331 IUnknown_Release( This->site );
3338 IUnknown_AddRef( punk );
3341 IUnknown_Release( This->site );
3348 static const IObjectWithSiteVtbl domdocObjectSite =
3350 domdoc_ObjectWithSite_QueryInterface,
3351 domdoc_ObjectWithSite_AddRef,
3352 domdoc_ObjectWithSite_Release,
3353 domdoc_ObjectWithSite_SetSite,
3354 domdoc_ObjectWithSite_GetSite
3357 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3359 domdoc *This = impl_from_IObjectSafety(iface);
3360 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppv );
3363 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3365 domdoc *This = impl_from_IObjectSafety(iface);
3366 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3369 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3371 domdoc *This = impl_from_IObjectSafety(iface);
3372 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3375 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3377 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3378 DWORD *supported, DWORD *enabled)
3380 domdoc *This = impl_from_IObjectSafety(iface);
3382 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3384 if(!supported || !enabled) return E_POINTER;
3386 *supported = SAFETY_SUPPORTED_OPTIONS;
3387 *enabled = This->safeopt;
3392 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3393 DWORD mask, DWORD enabled)
3395 domdoc *This = impl_from_IObjectSafety(iface);
3396 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3398 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3401 This->safeopt = enabled & mask & SAFETY_SUPPORTED_OPTIONS;
3405 #undef SAFETY_SUPPORTED_OPTIONS
3407 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3408 domdoc_Safety_QueryInterface,
3409 domdoc_Safety_AddRef,
3410 domdoc_Safety_Release,
3411 domdoc_Safety_GetInterfaceSafetyOptions,
3412 domdoc_Safety_SetInterfaceSafetyOptions
3415 static const tid_t domdoc_iface_tids[] = {
3417 IXMLDOMDocument_tid,
3418 IXMLDOMDocument2_tid,
3421 static dispex_static_data_t domdoc_dispex = {
3423 IXMLDOMDocument2_tid,
3428 HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3432 doc = heap_alloc( sizeof (*doc) );
3434 return E_OUTOFMEMORY;
3436 doc->lpVtbl = &domdoc_vtbl;
3437 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
3438 doc->lpvtblIObjectWithSite = &domdocObjectSite;
3439 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
3440 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
3441 doc->lpVtblConnectionPointContainer = &ConnectionPointContainerVtbl;
3443 doc->async = VARIANT_TRUE;
3444 doc->validating = 0;
3446 doc->properties = properties_from_xmlDocPtr(xmldoc);
3452 doc->cp_list = NULL;
3453 memset(doc->events, 0, sizeof(doc->events));
3455 /* events connection points */
3456 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3457 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3458 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3460 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->lpVtbl, &domdoc_dispex);
3462 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
3464 TRACE("returning iface %p\n", *document);
3468 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3473 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
3475 xmldoc = xmlNewDoc(NULL);
3477 return E_OUTOFMEMORY;
3479 xmldoc->_private = create_priv();
3480 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
3482 hr = get_domdoc_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3485 free_properties(properties_from_xmlDocPtr(xmldoc));
3486 heap_free(xmldoc->_private);
3494 IUnknown* create_domdoc( xmlNodePtr document )
3499 TRACE("(%p)\n", document);
3501 hr = get_domdoc_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3510 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3512 MESSAGE("This program tried to use a DOMDocument object, but\n"
3513 "libxml2 support was not present at compile time.\n");