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,
1242 VARIANT_BOOL* hasChild)
1244 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1245 return IXMLDOMNode_hasChildNodes( &This->node.IXMLDOMNode_iface, hasChild );
1249 static HRESULT WINAPI domdoc_get_ownerDocument(
1250 IXMLDOMDocument3 *iface,
1251 IXMLDOMDocument** DOMDocument)
1253 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1254 return IXMLDOMNode_get_ownerDocument( &This->node.IXMLDOMNode_iface, DOMDocument );
1258 static HRESULT WINAPI domdoc_cloneNode(
1259 IXMLDOMDocument3 *iface,
1261 IXMLDOMNode** outNode)
1263 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1264 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
1265 return node_clone( &This->node, deep, outNode );
1269 static HRESULT WINAPI domdoc_get_nodeTypeString(
1270 IXMLDOMDocument3 *iface,
1273 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1274 static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
1276 TRACE("(%p)->(%p)\n", This, p);
1278 return return_bstr(documentW, p);
1282 static HRESULT WINAPI domdoc_get_text(
1283 IXMLDOMDocument3 *iface,
1286 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1287 return IXMLDOMNode_get_text( &This->node.IXMLDOMNode_iface, text );
1291 static HRESULT WINAPI domdoc_put_text(
1292 IXMLDOMDocument3 *iface,
1295 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1296 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1301 static HRESULT WINAPI domdoc_get_specified(
1302 IXMLDOMDocument3 *iface,
1303 VARIANT_BOOL* isSpecified )
1305 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1306 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1307 *isSpecified = VARIANT_TRUE;
1312 static HRESULT WINAPI domdoc_get_definition(
1313 IXMLDOMDocument3 *iface,
1314 IXMLDOMNode** definitionNode )
1316 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1317 FIXME("(%p)->(%p)\n", This, definitionNode);
1322 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1323 IXMLDOMDocument3 *iface,
1324 VARIANT* typedValue )
1326 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1327 FIXME("(%p)->(%p)\n", This, typedValue);
1328 return return_null_var(typedValue);
1331 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1332 IXMLDOMDocument3 *iface,
1333 VARIANT typedValue )
1335 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1336 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1341 static HRESULT WINAPI domdoc_get_dataType(
1342 IXMLDOMDocument3 *iface,
1345 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1346 TRACE("(%p)->(%p)\n", This, typename);
1347 return return_null_var( typename );
1351 static HRESULT WINAPI domdoc_put_dataType(
1352 IXMLDOMDocument3 *iface,
1355 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1357 FIXME("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
1360 return E_INVALIDARG;
1365 static int XMLCALL domdoc_get_xml_writecallback(void *ctx, const char *data, int len)
1367 return xmlBufferAdd((xmlBufferPtr)ctx, (xmlChar*)data, len) == 0 ? len : 0;
1370 static HRESULT WINAPI domdoc_get_xml(
1371 IXMLDOMDocument3 *iface,
1374 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1375 xmlSaveCtxtPtr ctxt;
1380 TRACE("(%p)->(%p)\n", This, p);
1383 return E_INVALIDARG;
1387 buf = xmlBufferCreate();
1389 return E_OUTOFMEMORY;
1391 options = xmldoc_has_decl(get_doc(This)) ? XML_SAVE_NO_DECL : 0;
1392 options |= XML_SAVE_FORMAT;
1393 ctxt = xmlSaveToIO(domdoc_get_xml_writecallback, NULL, buf, "UTF-8", options);
1398 return E_OUTOFMEMORY;
1401 ret = xmlSaveDoc(ctxt, get_doc(This));
1402 /* flushes on close */
1405 TRACE("%ld, len=%d\n", ret, xmlBufferLength(buf));
1406 if(ret != -1 && xmlBufferLength(buf) > 0)
1410 content = bstr_from_xmlChar(xmlBufferContent(buf));
1411 content = EnsureCorrectEOL(content);
1417 *p = SysAllocStringLen(NULL, 0);
1422 return *p ? S_OK : E_OUTOFMEMORY;
1426 static HRESULT WINAPI domdoc_transformNode(
1427 IXMLDOMDocument3 *iface,
1428 IXMLDOMNode* styleSheet,
1431 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1432 return IXMLDOMNode_transformNode( &This->node.IXMLDOMNode_iface, styleSheet, xmlString );
1436 static HRESULT WINAPI domdoc_selectNodes(
1437 IXMLDOMDocument3 *iface,
1439 IXMLDOMNodeList** resultList )
1441 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1442 return IXMLDOMNode_selectNodes( &This->node.IXMLDOMNode_iface, queryString, resultList );
1446 static HRESULT WINAPI domdoc_selectSingleNode(
1447 IXMLDOMDocument3 *iface,
1449 IXMLDOMNode** resultNode )
1451 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1452 return IXMLDOMNode_selectSingleNode( &This->node.IXMLDOMNode_iface, queryString, resultNode );
1456 static HRESULT WINAPI domdoc_get_parsed(
1457 IXMLDOMDocument3 *iface,
1458 VARIANT_BOOL* isParsed )
1460 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1461 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1462 *isParsed = VARIANT_TRUE;
1467 static HRESULT WINAPI domdoc_get_namespaceURI(
1468 IXMLDOMDocument3 *iface,
1469 BSTR* namespaceURI )
1471 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1472 TRACE("(%p)->(%p)\n", This, namespaceURI);
1473 return node_get_namespaceURI(&This->node, namespaceURI);
1477 static HRESULT WINAPI domdoc_get_prefix(
1478 IXMLDOMDocument3 *iface,
1481 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1482 TRACE("(%p)->(%p)\n", This, prefix);
1483 return return_null_bstr( prefix );
1487 static HRESULT WINAPI domdoc_get_baseName(
1488 IXMLDOMDocument3 *iface,
1491 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1492 TRACE("(%p)->(%p)\n", This, name);
1493 return return_null_bstr( name );
1497 static HRESULT WINAPI domdoc_transformNodeToObject(
1498 IXMLDOMDocument3 *iface,
1499 IXMLDOMNode* stylesheet,
1500 VARIANT outputObject)
1502 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1503 FIXME("(%p)->(%p %s)\n", This, stylesheet, debugstr_variant(&outputObject));
1508 static HRESULT WINAPI domdoc_get_doctype(
1509 IXMLDOMDocument3 *iface,
1510 IXMLDOMDocumentType** documentType )
1512 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1513 FIXME("(%p)\n", This);
1518 static HRESULT WINAPI domdoc_get_implementation(
1519 IXMLDOMDocument3 *iface,
1520 IXMLDOMImplementation** impl )
1522 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1524 TRACE("(%p)->(%p)\n", This, impl);
1527 return E_INVALIDARG;
1529 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1534 static HRESULT WINAPI domdoc_get_documentElement(
1535 IXMLDOMDocument3 *iface,
1536 IXMLDOMElement** DOMElement )
1538 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1539 IXMLDOMNode *element_node;
1543 TRACE("(%p)->(%p)\n", This, DOMElement);
1546 return E_INVALIDARG;
1550 root = xmlDocGetRootElement( get_doc(This) );
1554 element_node = create_node( root );
1555 if(!element_node) return S_FALSE;
1557 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1558 IXMLDOMNode_Release(element_node);
1564 static HRESULT WINAPI domdoc_put_documentElement(
1565 IXMLDOMDocument3 *iface,
1566 IXMLDOMElement* DOMElement )
1568 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1569 IXMLDOMNode *elementNode;
1574 TRACE("(%p)->(%p)\n", This, DOMElement);
1576 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1580 xmlNode = get_node_obj( elementNode );
1582 FIXME("elementNode is not our object\n");
1586 if(!xmlNode->node->parent)
1587 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1588 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1590 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1591 IXMLDOMNode_Release( elementNode );
1594 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1600 static HRESULT WINAPI domdoc_createElement(
1601 IXMLDOMDocument3 *iface,
1603 IXMLDOMElement** element )
1605 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1610 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1612 if (!element || !tagname) return E_INVALIDARG;
1614 V_VT(&type) = VT_I1;
1615 V_I1(&type) = NODE_ELEMENT;
1617 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1620 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1621 IXMLDOMNode_Release(node);
1628 static HRESULT WINAPI domdoc_createDocumentFragment(
1629 IXMLDOMDocument3 *iface,
1630 IXMLDOMDocumentFragment** frag )
1632 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1637 TRACE("(%p)->(%p)\n", This, frag);
1639 if (!frag) return E_INVALIDARG;
1643 V_VT(&type) = VT_I1;
1644 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1646 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1649 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1650 IXMLDOMNode_Release(node);
1657 static HRESULT WINAPI domdoc_createTextNode(
1658 IXMLDOMDocument3 *iface,
1660 IXMLDOMText** text )
1662 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1667 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1669 if (!text) return E_INVALIDARG;
1673 V_VT(&type) = VT_I1;
1674 V_I1(&type) = NODE_TEXT;
1676 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1679 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1680 IXMLDOMNode_Release(node);
1681 hr = IXMLDOMText_put_data(*text, data);
1688 static HRESULT WINAPI domdoc_createComment(
1689 IXMLDOMDocument3 *iface,
1691 IXMLDOMComment** comment )
1693 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1698 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1700 if (!comment) return E_INVALIDARG;
1704 V_VT(&type) = VT_I1;
1705 V_I1(&type) = NODE_COMMENT;
1707 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1710 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1711 IXMLDOMNode_Release(node);
1712 hr = IXMLDOMComment_put_data(*comment, data);
1719 static HRESULT WINAPI domdoc_createCDATASection(
1720 IXMLDOMDocument3 *iface,
1722 IXMLDOMCDATASection** cdata )
1724 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1729 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1731 if (!cdata) return E_INVALIDARG;
1735 V_VT(&type) = VT_I1;
1736 V_I1(&type) = NODE_CDATA_SECTION;
1738 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1741 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1742 IXMLDOMNode_Release(node);
1743 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1750 static HRESULT WINAPI domdoc_createProcessingInstruction(
1751 IXMLDOMDocument3 *iface,
1754 IXMLDOMProcessingInstruction** pi )
1756 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1761 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1763 if (!pi) return E_INVALIDARG;
1767 V_VT(&type) = VT_I1;
1768 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1770 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1775 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1776 node_obj = get_node_obj(node);
1777 hr = node_set_content(node_obj, data);
1779 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1780 IXMLDOMNode_Release(node);
1787 static HRESULT WINAPI domdoc_createAttribute(
1788 IXMLDOMDocument3 *iface,
1790 IXMLDOMAttribute** attribute )
1792 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1797 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1799 if (!attribute || !name) return E_INVALIDARG;
1801 V_VT(&type) = VT_I1;
1802 V_I1(&type) = NODE_ATTRIBUTE;
1804 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1807 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1808 IXMLDOMNode_Release(node);
1815 static HRESULT WINAPI domdoc_createEntityReference(
1816 IXMLDOMDocument3 *iface,
1818 IXMLDOMEntityReference** entityref )
1820 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1825 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1827 if (!entityref) return E_INVALIDARG;
1831 V_VT(&type) = VT_I1;
1832 V_I1(&type) = NODE_ENTITY_REFERENCE;
1834 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1837 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1838 IXMLDOMNode_Release(node);
1844 xmlChar* tagName_to_XPath(const BSTR tagName)
1846 xmlChar *query, *tmp;
1847 static const xmlChar mod_pre[] = "*[local-name()='";
1848 static const xmlChar mod_post[] = "']";
1849 static const xmlChar prefix[] = "descendant::";
1850 const WCHAR *tokBegin, *tokEnd;
1853 query = xmlStrdup(prefix);
1856 while (tokBegin && *tokBegin)
1861 query = xmlStrcat(query, BAD_CAST "/");
1865 query = xmlStrcat(query, BAD_CAST "*");
1869 query = xmlStrcat(query, mod_pre);
1871 while (*tokEnd && *tokEnd != '/')
1873 len = WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, NULL, 0, NULL, NULL);
1874 tmp = xmlMalloc(len);
1875 WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, (char*)tmp, len, NULL, NULL);
1876 query = xmlStrncat(query, tmp, len);
1879 query = xmlStrcat(query, mod_post);
1886 static HRESULT WINAPI domdoc_getElementsByTagName(
1887 IXMLDOMDocument3 *iface,
1889 IXMLDOMNodeList** resultList )
1891 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1896 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1898 if (!tagName || !resultList) return E_INVALIDARG;
1900 XPath = This->properties->XPath;
1901 This->properties->XPath = TRUE;
1902 query = tagName_to_XPath(tagName);
1903 hr = queryresult_create((xmlNodePtr)get_doc(This), query, resultList);
1905 This->properties->XPath = XPath;
1910 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1916 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1918 return E_INVALIDARG;
1925 static HRESULT WINAPI domdoc_createNode(
1926 IXMLDOMDocument3 *iface,
1930 IXMLDOMNode** node )
1932 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1933 DOMNodeType node_type;
1935 xmlChar *xml_name, *href;
1938 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1940 if(!node) return E_INVALIDARG;
1942 hr = get_node_type(Type, &node_type);
1943 if(FAILED(hr)) return hr;
1945 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1946 FIXME("nodes with namespaces currently not supported.\n");
1948 TRACE("node_type %d\n", node_type);
1950 /* exit earlier for types that need name */
1954 case NODE_ATTRIBUTE:
1955 case NODE_ENTITY_REFERENCE:
1956 case NODE_PROCESSING_INSTRUCTION:
1957 if (!name || *name == 0) return E_FAIL;
1962 xml_name = xmlChar_from_wchar(name);
1963 /* prevent empty href to be allocated */
1964 href = namespaceURI ? xmlChar_from_wchar(namespaceURI) : NULL;
1970 xmlChar *local, *prefix;
1972 local = xmlSplitQName2(xml_name, &prefix);
1974 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
1976 /* allow to create default namespace xmlns= */
1977 if (local || (href && *href))
1979 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
1980 xmlSetNs(xmlnode, ns);
1988 case NODE_ATTRIBUTE:
1989 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1992 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1994 case NODE_CDATA_SECTION:
1995 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1997 case NODE_ENTITY_REFERENCE:
1998 xmlnode = xmlNewReference(get_doc(This), xml_name);
2000 case NODE_PROCESSING_INSTRUCTION:
2001 #ifdef HAVE_XMLNEWDOCPI
2002 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
2004 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2009 xmlnode = xmlNewDocComment(get_doc(This), NULL);
2011 case NODE_DOCUMENT_FRAGMENT:
2012 xmlnode = xmlNewDocFragment(get_doc(This));
2014 /* unsupported types */
2016 case NODE_DOCUMENT_TYPE:
2019 heap_free(xml_name);
2020 return E_INVALIDARG;
2022 FIXME("unhandled node type %d\n", node_type);
2027 *node = create_node(xmlnode);
2028 heap_free(xml_name);
2033 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
2034 xmldoc_add_orphan(xmlnode->doc, xmlnode);
2041 static HRESULT WINAPI domdoc_nodeFromID(
2042 IXMLDOMDocument3 *iface,
2044 IXMLDOMNode** node )
2046 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2047 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
2051 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
2056 xmldoc = doparse(This, ptr, len, NULL);
2058 xmldoc->_private = create_priv();
2059 return attach_xmldoc(This, xmldoc);
2065 static HRESULT doread( domdoc *This, LPWSTR filename )
2070 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
2075 detach_bsc(This->bsc);
2081 static HRESULT WINAPI domdoc_load(
2082 IXMLDOMDocument3 *iface,
2084 VARIANT_BOOL* isSuccessful )
2086 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2087 LPWSTR filename = NULL;
2088 HRESULT hr = S_FALSE;
2089 IXMLDOMDocument3 *pNewDoc = NULL;
2090 IStream *pStream = NULL;
2093 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
2095 *isSuccessful = VARIANT_FALSE;
2097 assert( &This->node );
2099 switch( V_VT(&xmlSource) )
2102 filename = V_BSTR(&xmlSource);
2105 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
2110 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
2111 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
2112 hr = attach_xmldoc(This, xmldoc);
2115 *isSuccessful = VARIANT_TRUE;
2120 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
2123 IPersistStream *pDocStream;
2124 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
2127 hr = IPersistStream_Load(pDocStream, pStream);
2128 IStream_Release(pStream);
2131 *isSuccessful = VARIANT_TRUE;
2133 TRACE("Using IStream to load Document\n");
2138 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
2143 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
2148 /* ISequentialStream */
2149 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
2153 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
2156 TRACE("filename (%s)\n", debugstr_w(filename));
2160 hr = doread( This, filename );
2163 This->error = E_FAIL;
2166 hr = This->error = S_OK;
2167 *isSuccessful = VARIANT_TRUE;
2171 if(!filename || FAILED(hr)) {
2172 xmldoc = xmlNewDoc(NULL);
2173 xmldoc->_private = create_priv();
2174 hr = attach_xmldoc(This, xmldoc);
2179 TRACE("ret (%d)\n", hr);
2185 static HRESULT WINAPI domdoc_get_readyState(
2186 IXMLDOMDocument3 *iface,
2189 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2190 FIXME("stub! (%p)->(%p)\n", This, value);
2193 return E_INVALIDARG;
2195 *value = READYSTATE_COMPLETE;
2200 static HRESULT WINAPI domdoc_get_parseError(
2201 IXMLDOMDocument3 *iface,
2202 IXMLDOMParseError** errorObj )
2204 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2205 static const WCHAR err[] = {'e','r','r','o','r',0};
2206 BSTR error_string = NULL;
2208 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2211 error_string = SysAllocString(err);
2213 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2214 if(!*errorObj) return E_OUTOFMEMORY;
2219 static HRESULT WINAPI domdoc_get_url(
2220 IXMLDOMDocument3 *iface,
2223 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2224 FIXME("(%p)->(%p)\n", This, urlString);
2229 static HRESULT WINAPI domdoc_get_async(
2230 IXMLDOMDocument3 *iface,
2231 VARIANT_BOOL* isAsync )
2233 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2235 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2236 *isAsync = This->async;
2241 static HRESULT WINAPI domdoc_put_async(
2242 IXMLDOMDocument3 *iface,
2243 VARIANT_BOOL isAsync )
2245 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2247 TRACE("(%p)->(%d)\n", This, isAsync);
2248 This->async = isAsync;
2253 static HRESULT WINAPI domdoc_abort(
2254 IXMLDOMDocument3 *iface )
2256 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2257 FIXME("%p\n", This);
2262 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
2267 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
2268 str = heap_alloc( len );
2271 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
2277 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2278 static HRESULT WINAPI domdoc_loadXML(
2279 IXMLDOMDocument3 *iface,
2281 VARIANT_BOOL* isSuccessful )
2283 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2284 static const xmlChar encoding[] = "UTF-8";
2285 xmlDocPtr xmldoc = NULL;
2286 HRESULT hr = S_FALSE, hr2;
2290 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2292 assert ( &This->node );
2296 *isSuccessful = VARIANT_FALSE;
2298 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
2300 xmldoc = doparse(This, str, len, encoding);
2304 This->error = E_FAIL;
2305 TRACE("failed to parse document\n");
2309 hr = This->error = S_OK;
2310 *isSuccessful = VARIANT_TRUE;
2311 TRACE("parsed document %p\n", xmldoc);
2316 xmldoc = xmlNewDoc(NULL);
2318 xmldoc->_private = create_priv();
2320 hr2 = attach_xmldoc(This, xmldoc);
2327 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2331 if(!WriteFile(ctx, buffer, len, &written, NULL))
2333 WARN("write error\n");
2340 static int XMLCALL domdoc_save_closecallback(void *ctx)
2342 return CloseHandle(ctx) ? 0 : -1;
2345 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2350 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2353 WARN("stream write error: 0x%08x\n", hr);
2360 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2362 IStream_Release((IStream*)ctx);
2366 static HRESULT WINAPI domdoc_save(
2367 IXMLDOMDocument3 *iface,
2368 VARIANT destination )
2370 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2371 xmlSaveCtxtPtr ctx = NULL;
2375 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
2376 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
2378 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
2380 FIXME("Unhandled vt %d\n", V_VT(&destination));
2384 if(V_VT(&destination) == VT_UNKNOWN)
2386 IUnknown *pUnk = V_UNKNOWN(&destination);
2387 IXMLDOMDocument2 *document;
2390 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2393 VARIANT_BOOL success;
2396 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2399 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2403 IXMLDOMDocument3_Release(document);
2407 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2410 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2411 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2415 IStream_Release(stream);
2422 /* save with file path */
2423 HANDLE handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
2424 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2425 if( handle == INVALID_HANDLE_VALUE )
2427 WARN("failed to create file\n");
2431 /* disable top XML declaration */
2432 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2433 handle, NULL, XML_SAVE_NO_DECL);
2436 CloseHandle(handle);
2441 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2442 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2443 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2445 /* will release resources through close callback */
2451 static HRESULT WINAPI domdoc_get_validateOnParse(
2452 IXMLDOMDocument3 *iface,
2453 VARIANT_BOOL* isValidating )
2455 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2456 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2457 *isValidating = This->validating;
2462 static HRESULT WINAPI domdoc_put_validateOnParse(
2463 IXMLDOMDocument3 *iface,
2464 VARIANT_BOOL isValidating )
2466 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2467 TRACE("(%p)->(%d)\n", This, isValidating);
2468 This->validating = isValidating;
2473 static HRESULT WINAPI domdoc_get_resolveExternals(
2474 IXMLDOMDocument3 *iface,
2475 VARIANT_BOOL* isResolving )
2477 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2478 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2479 *isResolving = This->resolving;
2484 static HRESULT WINAPI domdoc_put_resolveExternals(
2485 IXMLDOMDocument3 *iface,
2486 VARIANT_BOOL isResolving )
2488 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2489 TRACE("(%p)->(%d)\n", This, isResolving);
2490 This->resolving = isResolving;
2495 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2496 IXMLDOMDocument3 *iface,
2497 VARIANT_BOOL* isPreserving )
2499 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2500 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->properties->preserving);
2501 *isPreserving = This->properties->preserving;
2506 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2507 IXMLDOMDocument3 *iface,
2508 VARIANT_BOOL isPreserving )
2510 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2511 TRACE("(%p)->(%d)\n", This, isPreserving);
2512 This->properties->preserving = isPreserving;
2517 static HRESULT WINAPI domdoc_put_onreadystatechange(
2518 IXMLDOMDocument3 *iface,
2521 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2523 TRACE("(%p)->(%s)\n", This, debugstr_variant(&event));
2524 return set_doc_event(This, EVENTID_READYSTATECHANGE, &event);
2528 static HRESULT WINAPI domdoc_put_onDataAvailable(
2529 IXMLDOMDocument3 *iface,
2530 VARIANT onDataAvailableSink )
2532 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2533 FIXME("%p\n", This);
2537 static HRESULT WINAPI domdoc_put_onTransformNode(
2538 IXMLDOMDocument3 *iface,
2539 VARIANT onTransformNodeSink )
2541 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2542 FIXME("%p\n", This);
2546 static HRESULT WINAPI domdoc_get_namespaces(
2547 IXMLDOMDocument3* iface,
2548 IXMLDOMSchemaCollection** schemaCollection )
2550 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2551 FIXME("(%p)->(%p)\n", This, schemaCollection);
2555 static HRESULT WINAPI domdoc_get_schemas(
2556 IXMLDOMDocument3* iface,
2559 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2560 HRESULT hr = S_FALSE;
2561 IXMLDOMSchemaCollection2* cur_schema = This->properties->schemaCache;
2563 TRACE("(%p)->(%p)\n", This, var1);
2565 VariantInit(var1); /* Test shows we don't call VariantClear here */
2566 V_VT(var1) = VT_NULL;
2570 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2572 V_VT(var1) = VT_DISPATCH;
2577 static HRESULT WINAPI domdoc_putref_schemas(
2578 IXMLDOMDocument3* iface,
2581 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2582 HRESULT hr = E_FAIL;
2583 IXMLDOMSchemaCollection2* new_schema = NULL;
2585 FIXME("(%p): semi-stub\n", This);
2589 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2593 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2602 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2607 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->properties->schemaCache, new_schema);
2608 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2614 static inline BOOL is_wellformed(xmlDocPtr doc)
2616 #ifdef HAVE_XMLDOC_PROPERTIES
2617 return doc->properties & XML_DOC_WELLFORMED;
2619 /* Not a full check, but catches the worst violations */
2623 for (child = doc->children; child != NULL; child = child->next)
2625 switch (child->type)
2627 case XML_ELEMENT_NODE:
2632 case XML_CDATA_SECTION_NODE:
2644 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2648 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2652 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2656 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2660 static HRESULT WINAPI domdoc_validateNode(
2661 IXMLDOMDocument3* iface,
2663 IXMLDOMParseError** err)
2665 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2666 LONG state, err_code = 0;
2670 TRACE("(%p)->(%p, %p)\n", This, node, err);
2671 domdoc_get_readyState(iface, &state);
2672 if (state != READYSTATE_COMPLETE)
2675 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2682 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2686 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2689 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2693 if (!is_wellformed(get_doc(This)))
2695 ERR("doc not well-formed\n");
2697 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2701 /* DTD validation */
2702 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2704 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2705 vctx->error = validate_error;
2706 vctx->warning = validate_warning;
2709 if (!((node == (IXMLDOMNode*)iface)?
2710 xmlValidateDocument(vctx, get_doc(This)) :
2711 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2713 /* TODO: get a real error code here */
2714 TRACE("DTD validation failed\n");
2715 err_code = E_XML_INVALID;
2718 xmlFreeValidCtxt(vctx);
2721 /* Schema validation */
2722 if (hr == S_OK && This->properties->schemaCache != NULL)
2725 hr = SchemaCache_validate_tree(This->properties->schemaCache, get_node_obj(node)->node);
2729 /* TODO: get a real error code here */
2732 TRACE("schema validation succeeded\n");
2736 ERR("schema validation failed\n");
2737 err_code = E_XML_INVALID;
2742 /* not really OK, just didn't find a schema for the ns */
2749 ERR("no DTD or schema found\n");
2750 err_code = E_XML_NODTD;
2755 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2760 static HRESULT WINAPI domdoc_validate(
2761 IXMLDOMDocument3* iface,
2762 IXMLDOMParseError** err)
2764 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2765 TRACE("(%p)->(%p)\n", This, err);
2766 return domdoc_validateNode(iface, (IXMLDOMNode*)iface, err);
2769 static HRESULT WINAPI domdoc_setProperty(
2770 IXMLDOMDocument3* iface,
2774 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2776 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2778 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2784 V_VT(&varStr) = VT_EMPTY;
2785 if (V_VT(&var) != VT_BSTR)
2787 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2789 bstr = V_BSTR(&varStr);
2792 bstr = V_BSTR(&var);
2795 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2796 This->properties->XPath = TRUE;
2797 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2798 This->properties->XPath = FALSE;
2802 VariantClear(&varStr);
2805 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2810 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2811 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2812 xmlXPathContextPtr ctx;
2813 struct list *pNsList;
2814 select_ns_entry* pNsEntry = NULL;
2816 V_VT(&varStr) = VT_EMPTY;
2817 if (V_VT(&var) != VT_BSTR)
2819 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2821 bstr = V_BSTR(&varStr);
2824 bstr = V_BSTR(&var);
2828 pNsList = &(This->properties->selectNsList);
2829 clear_selectNsList(pNsList);
2831 nsStr = xmlChar_from_wchar(bstr);
2834 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2836 This->properties->selectNsStr = nsStr;
2837 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2840 ctx = xmlXPathNewContext(This->node.node->doc);
2843 for (; *pTokBegin; pTokBegin = pTokEnd)
2845 if (pNsEntry != NULL)
2846 memset(pNsEntry, 0, sizeof(select_ns_entry));
2848 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2850 while (*pTokBegin == ' ')
2852 pTokEnd = pTokBegin;
2853 while (*pTokEnd != ' ' && *pTokEnd != 0)
2856 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2859 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2860 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2865 if (*pTokBegin == '=')
2867 /*valid for XSLPattern?*/
2868 FIXME("Setting default xmlns not supported - skipping.\n");
2869 pTokBegin = pTokEnd;
2872 else if (*pTokBegin == ':')
2874 pNsEntry->prefix = ++pTokBegin;
2875 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2878 if (pTokInner == pTokEnd)
2881 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2882 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2886 pNsEntry->prefix_end = *pTokInner;
2890 if (pTokEnd-pTokInner > 1 &&
2891 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2892 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2894 pNsEntry->href = ++pTokInner;
2895 pNsEntry->href_end = *(pTokEnd-1);
2897 list_add_tail(pNsList, &pNsEntry->entry);
2898 /*let libxml figure out if they're valid from here ;)*/
2899 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2908 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2909 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2910 list_add_tail(pNsList, &pNsEntry->entry);
2923 heap_free(pNsEntry);
2924 xmlXPathFreeContext(ctx);
2927 VariantClear(&varStr);
2930 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2931 lstrcmpiW(p, PropertyNewParserW) == 0)
2934 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2938 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2942 static HRESULT WINAPI domdoc_getProperty(
2943 IXMLDOMDocument3* iface,
2947 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2949 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2952 return E_INVALIDARG;
2954 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2956 V_VT(var) = VT_BSTR;
2957 V_BSTR(var) = This->properties->XPath ?
2958 SysAllocString(PropValueXPathW) :
2959 SysAllocString(PropValueXSLPatternW);
2960 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2962 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2965 BSTR rebuiltStr, cur;
2966 const xmlChar *nsStr;
2967 struct list *pNsList;
2968 select_ns_entry* pNsEntry;
2970 V_VT(var) = VT_BSTR;
2971 nsStr = This->properties->selectNsStr;
2972 pNsList = &This->properties->selectNsList;
2973 lenA = This->properties->selectNsStr_len;
2974 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
2975 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
2976 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
2978 /* this is fine because all of the chars that end tokens are ASCII*/
2979 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
2981 while (*cur != 0) ++cur;
2982 if (pNsEntry->prefix_end)
2984 *cur = pNsEntry->prefix_end;
2985 while (*cur != 0) ++cur;
2988 if (pNsEntry->href_end)
2990 *cur = pNsEntry->href_end;
2993 V_BSTR(var) = SysAllocString(rebuiltStr);
2994 heap_free(rebuiltStr);
2998 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
3002 static HRESULT WINAPI domdoc_importNode(
3003 IXMLDOMDocument3* iface,
3006 IXMLDOMNode** clone)
3008 domdoc *This = impl_from_IXMLDOMDocument3( iface );
3009 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
3013 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
3015 domdoc_QueryInterface,
3018 domdoc_GetTypeInfoCount,
3020 domdoc_GetIDsOfNames,
3022 domdoc_get_nodeName,
3023 domdoc_get_nodeValue,
3024 domdoc_put_nodeValue,
3025 domdoc_get_nodeType,
3026 domdoc_get_parentNode,
3027 domdoc_get_childNodes,
3028 domdoc_get_firstChild,
3029 domdoc_get_lastChild,
3030 domdoc_get_previousSibling,
3031 domdoc_get_nextSibling,
3032 domdoc_get_attributes,
3033 domdoc_insertBefore,
3034 domdoc_replaceChild,
3037 domdoc_hasChildNodes,
3038 domdoc_get_ownerDocument,
3040 domdoc_get_nodeTypeString,
3043 domdoc_get_specified,
3044 domdoc_get_definition,
3045 domdoc_get_nodeTypedValue,
3046 domdoc_put_nodeTypedValue,
3047 domdoc_get_dataType,
3048 domdoc_put_dataType,
3050 domdoc_transformNode,
3052 domdoc_selectSingleNode,
3054 domdoc_get_namespaceURI,
3056 domdoc_get_baseName,
3057 domdoc_transformNodeToObject,
3059 domdoc_get_implementation,
3060 domdoc_get_documentElement,
3061 domdoc_put_documentElement,
3062 domdoc_createElement,
3063 domdoc_createDocumentFragment,
3064 domdoc_createTextNode,
3065 domdoc_createComment,
3066 domdoc_createCDATASection,
3067 domdoc_createProcessingInstruction,
3068 domdoc_createAttribute,
3069 domdoc_createEntityReference,
3070 domdoc_getElementsByTagName,
3074 domdoc_get_readyState,
3075 domdoc_get_parseError,
3082 domdoc_get_validateOnParse,
3083 domdoc_put_validateOnParse,
3084 domdoc_get_resolveExternals,
3085 domdoc_put_resolveExternals,
3086 domdoc_get_preserveWhiteSpace,
3087 domdoc_put_preserveWhiteSpace,
3088 domdoc_put_onreadystatechange,
3089 domdoc_put_onDataAvailable,
3090 domdoc_put_onTransformNode,
3091 domdoc_get_namespaces,
3093 domdoc_putref_schemas,
3097 domdoc_validateNode,
3101 /* IConnectionPointContainer */
3102 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
3103 REFIID riid, void **ppv)
3105 domdoc *This = impl_from_IConnectionPointContainer(iface);
3106 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)This, riid, ppv);
3109 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
3111 domdoc *This = impl_from_IConnectionPointContainer(iface);
3112 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)This);
3115 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
3117 domdoc *This = impl_from_IConnectionPointContainer(iface);
3118 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)This);
3121 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
3122 IEnumConnectionPoints **ppEnum)
3124 domdoc *This = impl_from_IConnectionPointContainer(iface);
3125 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3129 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
3130 REFIID riid, IConnectionPoint **cp)
3132 domdoc *This = impl_from_IConnectionPointContainer(iface);
3133 ConnectionPoint *iter;
3135 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
3139 for(iter = This->cp_list; iter; iter = iter->next)
3141 if (IsEqualGUID(iter->iid, riid))
3142 *cp = (IConnectionPoint*)&iter->lpVtblConnectionPoint;
3147 IConnectionPoint_AddRef(*cp);
3151 FIXME("unsupported riid %s\n", debugstr_guid(riid));
3152 return CONNECT_E_NOCONNECTION;
3156 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
3158 ConnectionPointContainer_QueryInterface,
3159 ConnectionPointContainer_AddRef,
3160 ConnectionPointContainer_Release,
3161 ConnectionPointContainer_EnumConnectionPoints,
3162 ConnectionPointContainer_FindConnectionPoint
3165 /* IConnectionPoint */
3166 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
3167 REFIID riid, void **ppv)
3169 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3171 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3175 if (IsEqualGUID(&IID_IUnknown, riid) ||
3176 IsEqualGUID(&IID_IConnectionPoint, riid))
3183 IConnectionPoint_AddRef(iface);
3187 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3188 return E_NOINTERFACE;
3191 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3193 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3194 return IConnectionPointContainer_AddRef(This->container);
3197 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3199 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3200 return IConnectionPointContainer_Release(This->container);
3203 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3205 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3207 TRACE("(%p)->(%p)\n", This, iid);
3209 if (!iid) return E_POINTER;
3215 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3216 IConnectionPointContainer **container)
3218 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3220 TRACE("(%p)->(%p)\n", This, container);
3222 if (!container) return E_POINTER;
3224 *container = This->container;
3225 IConnectionPointContainer_AddRef(*container);
3229 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
3232 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3233 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
3237 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3239 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3241 TRACE("(%p)->(%d)\n", This, cookie);
3243 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3244 return CONNECT_E_NOCONNECTION;
3246 IUnknown_Release(This->sinks[cookie-1].unk);
3247 This->sinks[cookie-1].unk = NULL;
3252 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3253 IEnumConnections **ppEnum)
3255 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3256 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3260 static const IConnectionPointVtbl ConnectionPointVtbl =
3262 ConnectionPoint_QueryInterface,
3263 ConnectionPoint_AddRef,
3264 ConnectionPoint_Release,
3265 ConnectionPoint_GetConnectionInterface,
3266 ConnectionPoint_GetConnectionPointContainer,
3267 ConnectionPoint_Advise,
3268 ConnectionPoint_Unadvise,
3269 ConnectionPoint_EnumConnections
3272 void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3274 cp->lpVtblConnectionPoint = &ConnectionPointVtbl;
3280 cp->next = doc->cp_list;
3283 cp->container = (IConnectionPointContainer*)&doc->lpVtblConnectionPointContainer;
3286 /* domdoc implementation of IObjectWithSite */
3287 static HRESULT WINAPI
3288 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3290 domdoc *This = impl_from_IObjectWithSite(iface);
3291 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppvObject );
3294 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3296 domdoc *This = impl_from_IObjectWithSite(iface);
3297 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3300 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3302 domdoc *This = impl_from_IObjectWithSite(iface);
3303 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3306 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3308 domdoc *This = impl_from_IObjectWithSite(iface);
3310 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3315 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3318 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3320 domdoc *This = impl_from_IObjectWithSite(iface);
3322 TRACE("(%p)->(%p)\n", iface, punk);
3328 IUnknown_Release( This->site );
3335 IUnknown_AddRef( punk );
3338 IUnknown_Release( This->site );
3345 static const IObjectWithSiteVtbl domdocObjectSite =
3347 domdoc_ObjectWithSite_QueryInterface,
3348 domdoc_ObjectWithSite_AddRef,
3349 domdoc_ObjectWithSite_Release,
3350 domdoc_ObjectWithSite_SetSite,
3351 domdoc_ObjectWithSite_GetSite
3354 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3356 domdoc *This = impl_from_IObjectSafety(iface);
3357 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppv );
3360 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3362 domdoc *This = impl_from_IObjectSafety(iface);
3363 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3366 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3368 domdoc *This = impl_from_IObjectSafety(iface);
3369 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3372 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3374 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3375 DWORD *supported, DWORD *enabled)
3377 domdoc *This = impl_from_IObjectSafety(iface);
3379 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3381 if(!supported || !enabled) return E_POINTER;
3383 *supported = SAFETY_SUPPORTED_OPTIONS;
3384 *enabled = This->safeopt;
3389 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3390 DWORD mask, DWORD enabled)
3392 domdoc *This = impl_from_IObjectSafety(iface);
3393 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3395 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3398 This->safeopt = enabled & mask & SAFETY_SUPPORTED_OPTIONS;
3402 #undef SAFETY_SUPPORTED_OPTIONS
3404 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3405 domdoc_Safety_QueryInterface,
3406 domdoc_Safety_AddRef,
3407 domdoc_Safety_Release,
3408 domdoc_Safety_GetInterfaceSafetyOptions,
3409 domdoc_Safety_SetInterfaceSafetyOptions
3412 static const tid_t domdoc_iface_tids[] = {
3414 IXMLDOMDocument_tid,
3415 IXMLDOMDocument2_tid,
3418 static dispex_static_data_t domdoc_dispex = {
3420 IXMLDOMDocument2_tid,
3425 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3429 doc = heap_alloc( sizeof (*doc) );
3431 return E_OUTOFMEMORY;
3433 doc->lpVtbl = &domdoc_vtbl;
3434 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
3435 doc->lpvtblIObjectWithSite = &domdocObjectSite;
3436 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
3437 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
3438 doc->lpVtblConnectionPointContainer = &ConnectionPointContainerVtbl;
3440 doc->async = VARIANT_TRUE;
3441 doc->validating = 0;
3443 doc->properties = properties_from_xmlDocPtr(xmldoc);
3449 doc->cp_list = NULL;
3450 memset(doc->events, 0, sizeof(doc->events));
3452 /* events connection points */
3453 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3454 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3455 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3457 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->lpVtbl, &domdoc_dispex);
3459 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
3461 TRACE("returning iface %p\n", *document);
3465 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3470 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
3472 xmldoc = xmlNewDoc(NULL);
3474 return E_OUTOFMEMORY;
3476 xmldoc->_private = create_priv();
3477 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
3479 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3482 free_properties(properties_from_xmlDocPtr(xmldoc));
3483 heap_free(xmldoc->_private);
3491 IUnknown* create_domdoc( xmlNodePtr document )
3496 TRACE("(%p)\n", document);
3498 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3507 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3509 MESSAGE("This program tried to use a DOMDocument object, but\n"
3510 "libxml2 support was not present at compile time.\n");