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 /* Data used by domdoc_getProperty()/domdoc_setProperty().
74 * We need to preserve this when reloading a document,
75 * and also need access to it from the libxml backend. */
76 typedef struct _domdoc_properties {
77 VARIANT_BOOL preserving;
78 struct list selectNsList;
79 xmlChar const* selectNsStr;
84 typedef struct ConnectionPoint ConnectionPoint;
85 typedef struct domdoc domdoc;
87 struct ConnectionPoint
89 const IConnectionPointVtbl *lpVtblConnectionPoint;
92 ConnectionPoint *next;
93 IConnectionPointContainer *container;
100 IPropertyNotifySink *propnotif;
108 const struct IXMLDOMDocument3Vtbl *lpVtbl;
109 const struct IPersistStreamInitVtbl *lpvtblIPersistStreamInit;
110 const struct IObjectWithSiteVtbl *lpvtblIObjectWithSite;
111 const struct IObjectSafetyVtbl *lpvtblIObjectSafety;
112 const struct ISupportErrorInfoVtbl *lpvtblISupportErrorInfo;
113 const struct IConnectionPointContainerVtbl *lpVtblConnectionPointContainer;
116 VARIANT_BOOL validating;
117 VARIANT_BOOL resolving;
118 domdoc_properties* properties;
119 IXMLDOMSchemaCollection2* schema;
132 /* connection list */
133 ConnectionPoint *cp_list;
134 ConnectionPoint cp_domdocevents;
135 ConnectionPoint cp_propnotif;
136 ConnectionPoint cp_dispatch;
139 static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface)
141 return (ConnectionPoint *)((char*)iface - FIELD_OFFSET(ConnectionPoint, lpVtblConnectionPoint));
145 In native windows, the whole lifetime management of XMLDOMNodes is
146 managed automatically using reference counts. Wine emulates that by
147 maintaining a reference count to the document that is increased for
148 each IXMLDOMNode pointer passed out for this document. If all these
149 pointers are gone, the document is unreachable and gets freed, that
150 is, all nodes in the tree of the document get freed.
152 You are able to create nodes that are associated to a document (in
153 fact, in msxml's XMLDOM model, all nodes are associated to a document),
154 but not in the tree of that document, for example using the createFoo
155 functions from IXMLDOMDocument. These nodes do not get cleaned up
156 by libxml, so we have to do it ourselves.
158 To catch these nodes, a list of "orphan nodes" is introduced.
159 It contains pointers to all roots of node trees that are
160 associated with the document without being part of the document
161 tree. All nodes with parent==NULL (except for the document root nodes)
162 should be in the orphan node list of their document. All orphan nodes
163 get freed together with the document itself.
166 typedef struct _xmldoc_priv {
169 domdoc_properties* properties;
172 typedef struct _orphan_entry {
177 typedef struct _select_ns_entry {
179 xmlChar const* prefix;
185 static inline xmldoc_priv * priv_from_xmlDocPtr(const xmlDocPtr doc)
187 return doc->_private;
190 static inline domdoc_properties * properties_from_xmlDocPtr(xmlDocPtr doc)
192 return priv_from_xmlDocPtr(doc)->properties;
195 BOOL is_xpathmode(const xmlDocPtr doc)
197 return properties_from_xmlDocPtr(doc)->XPath;
200 int registerNamespaces(xmlXPathContextPtr ctxt)
203 const select_ns_entry* ns = NULL;
204 const struct list* pNsList = &properties_from_xmlDocPtr(ctxt->doc)->selectNsList;
206 TRACE("(%p)\n", ctxt);
208 LIST_FOR_EACH_ENTRY( ns, pNsList, select_ns_entry, entry )
210 xmlXPathRegisterNs(ctxt, ns->prefix, ns->href);
217 static inline void clear_selectNsList(struct list* pNsList)
219 select_ns_entry *ns, *ns2;
220 LIST_FOR_EACH_ENTRY_SAFE( ns, ns2, pNsList, select_ns_entry, entry )
227 static xmldoc_priv * create_priv(void)
230 priv = heap_alloc( sizeof (*priv) );
235 list_init( &priv->orphans );
236 priv->properties = NULL;
242 static domdoc_properties * create_properties(const GUID *clsid)
244 domdoc_properties *properties = heap_alloc(sizeof(domdoc_properties));
246 list_init( &properties->selectNsList );
247 properties->preserving = VARIANT_FALSE;
248 properties->selectNsStr = heap_alloc_zero(sizeof(xmlChar));
249 properties->selectNsStr_len = 0;
250 properties->XPath = FALSE;
252 /* properties that are dependent on object versions */
253 if (IsEqualCLSID( clsid, &CLSID_DOMDocument40 ) ||
254 IsEqualCLSID( clsid, &CLSID_DOMDocument60 ))
256 properties->XPath = TRUE;
262 static domdoc_properties* copy_properties(domdoc_properties const* properties)
264 domdoc_properties* pcopy = heap_alloc(sizeof(domdoc_properties));
265 select_ns_entry const* ns = NULL;
266 select_ns_entry* new_ns = NULL;
267 int len = (properties->selectNsStr_len+1)*sizeof(xmlChar);
272 pcopy->preserving = properties->preserving;
273 pcopy->XPath = properties->XPath;
274 pcopy->selectNsStr_len = properties->selectNsStr_len;
275 list_init( &pcopy->selectNsList );
276 pcopy->selectNsStr = heap_alloc(len);
277 memcpy((xmlChar*)pcopy->selectNsStr, properties->selectNsStr, len);
278 offset = pcopy->selectNsStr - properties->selectNsStr;
280 LIST_FOR_EACH_ENTRY( ns, (&properties->selectNsList), select_ns_entry, entry )
282 new_ns = heap_alloc(sizeof(select_ns_entry));
283 memcpy(new_ns, ns, sizeof(select_ns_entry));
284 new_ns->href += offset;
285 new_ns->prefix += offset;
286 list_add_tail(&pcopy->selectNsList, &new_ns->entry);
294 static void free_properties(domdoc_properties* properties)
298 clear_selectNsList(&properties->selectNsList);
299 heap_free((xmlChar*)properties->selectNsStr);
300 heap_free(properties);
304 /* links a "<?xml" node as a first child */
305 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
308 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
311 /* unlinks a first "<?xml" child if it was created */
312 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
318 if (doc->standalone != -1)
320 node = doc->children;
321 xmlUnlinkNode( node );
329 BOOL is_preserving_whitespace(xmlNodePtr node)
331 domdoc_properties* properties = NULL;
332 /* during parsing the xmlDoc._private stuff is not there */
333 if (priv_from_xmlDocPtr(node->doc))
334 properties = properties_from_xmlDocPtr(node->doc);
335 return ((properties && properties->preserving == VARIANT_TRUE) ||
336 xmlNodeGetSpacePreserve(node) == 1);
339 static inline BOOL strn_isspace(xmlChar const* str, int len)
341 for (; str && len > 0 && *str; ++str, --len)
348 static void sax_characters(void *ctx, const xmlChar *ch, int len)
350 xmlParserCtxtPtr pctx;
353 pctx = (xmlParserCtxtPtr) ctx;
354 This = (domdoc const*) pctx->_private;
356 /* during domdoc_loadXML() the xmlDocPtr->_private data is not available */
357 if (!This->properties->preserving &&
358 !is_preserving_whitespace(pctx->node) &&
359 strn_isspace(ch, len))
362 xmlSAX2Characters(ctx, ch, len);
365 static void LIBXML2_LOG_CALLBACK sax_error(void* ctx, char const* msg, ...)
369 LIBXML2_CALLBACK_ERR(doparse, msg, ap);
373 static void LIBXML2_LOG_CALLBACK sax_warning(void* ctx, char const* msg, ...)
377 LIBXML2_CALLBACK_WARN(doparse, msg, ap);
381 static void sax_serror(void* ctx, xmlErrorPtr err)
383 LIBXML2_CALLBACK_SERROR(doparse, err);
386 static xmlDocPtr doparse(domdoc* This, char *ptr, int len, xmlChar const* encoding)
388 xmlDocPtr doc = NULL;
389 xmlParserCtxtPtr pctx;
390 static xmlSAXHandler sax_handler = {
391 xmlSAX2InternalSubset, /* internalSubset */
392 xmlSAX2IsStandalone, /* isStandalone */
393 xmlSAX2HasInternalSubset, /* hasInternalSubset */
394 xmlSAX2HasExternalSubset, /* hasExternalSubset */
395 xmlSAX2ResolveEntity, /* resolveEntity */
396 xmlSAX2GetEntity, /* getEntity */
397 xmlSAX2EntityDecl, /* entityDecl */
398 xmlSAX2NotationDecl, /* notationDecl */
399 xmlSAX2AttributeDecl, /* attributeDecl */
400 xmlSAX2ElementDecl, /* elementDecl */
401 xmlSAX2UnparsedEntityDecl, /* unparsedEntityDecl */
402 xmlSAX2SetDocumentLocator, /* setDocumentLocator */
403 xmlSAX2StartDocument, /* startDocument */
404 xmlSAX2EndDocument, /* endDocument */
405 xmlSAX2StartElement, /* startElement */
406 xmlSAX2EndElement, /* endElement */
407 xmlSAX2Reference, /* reference */
408 sax_characters, /* characters */
409 sax_characters, /* ignorableWhitespace */
410 xmlSAX2ProcessingInstruction, /* processingInstruction */
411 xmlSAX2Comment, /* comment */
412 sax_warning, /* warning */
413 sax_error, /* error */
414 sax_error, /* fatalError */
415 xmlSAX2GetParameterEntity, /* getParameterEntity */
416 xmlSAX2CDataBlock, /* cdataBlock */
417 xmlSAX2ExternalSubset, /* externalSubset */
420 xmlSAX2StartElementNs, /* startElementNs */
421 xmlSAX2EndElementNs, /* endElementNs */
422 sax_serror /* serror */
426 pctx = xmlCreateMemoryParserCtxt(ptr, len);
429 ERR("Failed to create parser context\n");
433 if (pctx->sax) xmlFree(pctx->sax);
434 pctx->sax = &sax_handler;
435 pctx->_private = This;
437 pctx->encoding = xmlStrdup(encoding);
438 xmlParseDocument(pctx);
440 if (pctx->wellFormed)
446 xmlFreeDoc(pctx->myDoc);
450 xmlFreeParserCtxt(pctx);
452 /* TODO: put this in one of the SAX callbacks */
453 /* create first child as a <?xml...?> */
454 if (doc && doc->standalone != -1)
458 xmlChar *xmlbuff = (xmlChar*)buff;
460 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
462 /* version attribute can't be omitted */
463 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
464 xmlNodeAddContent( node, xmlbuff );
468 sprintf(buff, " encoding=\"%s\"", doc->encoding);
469 xmlNodeAddContent( node, xmlbuff );
472 if (doc->standalone != -2)
474 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
475 xmlNodeAddContent( node, xmlbuff );
478 xmldoc_link_xmldecl( doc, node );
484 void xmldoc_init(xmlDocPtr doc, const GUID *clsid)
486 doc->_private = create_priv();
487 priv_from_xmlDocPtr(doc)->properties = create_properties(clsid);
490 LONG xmldoc_add_ref(xmlDocPtr doc)
492 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
493 TRACE("(%p)->(%d)\n", doc, ref);
497 LONG xmldoc_release(xmlDocPtr doc)
499 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
500 LONG ref = InterlockedDecrement(&priv->refs);
501 TRACE("(%p)->(%d)\n", doc, ref);
504 orphan_entry *orphan, *orphan2;
505 TRACE("freeing docptr %p\n", doc);
507 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
509 xmlFreeNode( orphan->node );
512 free_properties(priv->properties);
513 heap_free(doc->_private);
521 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
523 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
526 entry = heap_alloc( sizeof (*entry) );
528 return E_OUTOFMEMORY;
531 list_add_head( &priv->orphans, &entry->entry );
535 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
537 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
538 orphan_entry *entry, *entry2;
540 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
542 if( entry->node == node )
544 list_remove( &entry->entry );
553 static inline xmlDocPtr get_doc( domdoc *This )
555 return (xmlDocPtr)This->node.node;
558 static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
562 priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
563 if (xmldoc_release(get_doc(This)) != 0)
564 priv_from_xmlDocPtr(get_doc(This))->properties =
565 copy_properties(This->properties);
568 This->node.node = (xmlNodePtr) xml;
572 xmldoc_add_ref(get_doc(This));
573 priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
579 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
581 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
584 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
586 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStreamInit));
589 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
591 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
594 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
596 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
599 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
601 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblISupportErrorInfo));
604 static inline domdoc *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
606 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtblConnectionPointContainer));
609 /************************************************************************
610 * domdoc implementation of IPersistStream.
612 static HRESULT WINAPI domdoc_IPersistStreamInit_QueryInterface(
613 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
615 domdoc *this = impl_from_IPersistStreamInit(iface);
616 return IXMLDOMDocument2_QueryInterface((IXMLDOMDocument2 *)this, riid, ppvObj);
619 static ULONG WINAPI domdoc_IPersistStreamInit_AddRef(
620 IPersistStreamInit *iface)
622 domdoc *this = impl_from_IPersistStreamInit(iface);
623 return IXMLDOMDocument2_AddRef((IXMLDOMDocument2 *)this);
626 static ULONG WINAPI domdoc_IPersistStreamInit_Release(
627 IPersistStreamInit *iface)
629 domdoc *this = impl_from_IPersistStreamInit(iface);
630 return IXMLDOMDocument2_Release((IXMLDOMDocument2 *)this);
633 static HRESULT WINAPI domdoc_IPersistStreamInit_GetClassID(
634 IPersistStreamInit *iface, CLSID *classid)
636 TRACE("(%p,%p): stub!\n", iface, classid);
641 *classid = CLSID_DOMDocument2;
646 static HRESULT WINAPI domdoc_IPersistStreamInit_IsDirty(
647 IPersistStreamInit *iface)
649 domdoc *This = impl_from_IPersistStreamInit(iface);
650 FIXME("(%p): stub!\n", This);
654 static HRESULT WINAPI domdoc_IPersistStreamInit_Load(
655 IPersistStreamInit *iface, LPSTREAM pStm)
657 domdoc *This = impl_from_IPersistStreamInit(iface);
660 DWORD read, written, len;
663 xmlDocPtr xmldoc = NULL;
665 TRACE("(%p)->(%p)\n", This, pStm);
670 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
676 IStream_Read(pStm, buf, sizeof(buf), &read);
677 hr = IStream_Write(This->stream, buf, read, &written);
678 } while(SUCCEEDED(hr) && written != 0 && read != 0);
682 ERR("Failed to copy stream\n");
686 hr = GetHGlobalFromStream(This->stream, &hglobal);
690 len = GlobalSize(hglobal);
691 ptr = GlobalLock(hglobal);
693 xmldoc = doparse(This, ptr, len, NULL);
694 GlobalUnlock(hglobal);
698 ERR("Failed to parse xml\n");
702 xmldoc->_private = create_priv();
704 return attach_xmldoc(This, xmldoc);
707 static HRESULT WINAPI domdoc_IPersistStreamInit_Save(
708 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
710 domdoc *This = impl_from_IPersistStreamInit(iface);
714 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
716 hr = IXMLDOMDocument3_get_xml( (IXMLDOMDocument3*)&This->lpVtbl, &xmlString );
719 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
721 hr = IStream_Write( stream, xmlString, len, NULL );
722 SysFreeString(xmlString);
725 TRACE("ret 0x%08x\n", hr);
730 static HRESULT WINAPI domdoc_IPersistStreamInit_GetSizeMax(
731 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
733 domdoc *This = impl_from_IPersistStreamInit(iface);
734 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
738 static HRESULT WINAPI domdoc_IPersistStreamInit_InitNew(
739 IPersistStreamInit *iface)
741 domdoc *This = impl_from_IPersistStreamInit(iface);
742 TRACE("(%p)\n", This);
746 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
748 domdoc_IPersistStreamInit_QueryInterface,
749 domdoc_IPersistStreamInit_AddRef,
750 domdoc_IPersistStreamInit_Release,
751 domdoc_IPersistStreamInit_GetClassID,
752 domdoc_IPersistStreamInit_IsDirty,
753 domdoc_IPersistStreamInit_Load,
754 domdoc_IPersistStreamInit_Save,
755 domdoc_IPersistStreamInit_GetSizeMax,
756 domdoc_IPersistStreamInit_InitNew
759 /* ISupportErrorInfo interface */
760 static HRESULT WINAPI support_error_QueryInterface(
761 ISupportErrorInfo *iface,
762 REFIID riid, void** ppvObj )
764 domdoc *This = impl_from_ISupportErrorInfo(iface);
765 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3 *)This, riid, ppvObj);
768 static ULONG WINAPI support_error_AddRef(
769 ISupportErrorInfo *iface )
771 domdoc *This = impl_from_ISupportErrorInfo(iface);
772 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
775 static ULONG WINAPI support_error_Release(
776 ISupportErrorInfo *iface )
778 domdoc *This = impl_from_ISupportErrorInfo(iface);
779 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
782 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
783 ISupportErrorInfo *iface,
786 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
790 static const struct ISupportErrorInfoVtbl support_error_vtbl =
792 support_error_QueryInterface,
793 support_error_AddRef,
794 support_error_Release,
795 support_error_InterfaceSupportsErrorInfo
798 /* IXMLDOMDocument2 interface */
799 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
801 domdoc *This = impl_from_IXMLDOMDocument3( iface );
803 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
807 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
808 IsEqualGUID( riid, &IID_IDispatch ) ||
809 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
810 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
811 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
812 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
816 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
817 IsEqualGUID(&IID_IPersistStreamInit, riid))
819 *ppvObject = &(This->lpvtblIPersistStreamInit);
821 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
823 *ppvObject = &(This->lpvtblIObjectWithSite);
825 else if (IsEqualGUID(&IID_IObjectSafety, riid))
827 *ppvObject = &(This->lpvtblIObjectSafety);
829 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
831 *ppvObject = &This->lpvtblISupportErrorInfo;
833 else if(node_query_interface(&This->node, riid, ppvObject))
835 return *ppvObject ? S_OK : E_NOINTERFACE;
837 else if (IsEqualGUID( riid, &IID_IConnectionPointContainer ))
839 *ppvObject = &This->lpVtblConnectionPointContainer;
841 else if(IsEqualGUID(&IID_IRunnableObject, riid))
843 TRACE("IID_IRunnableObject not supported returning NULL\n");
844 return E_NOINTERFACE;
848 FIXME("interface %s not implemented\n", debugstr_guid(riid));
849 return E_NOINTERFACE;
852 IUnknown_AddRef((IUnknown*)*ppvObject);
858 static ULONG WINAPI domdoc_AddRef(
859 IXMLDOMDocument3 *iface )
861 domdoc *This = impl_from_IXMLDOMDocument3( iface );
862 TRACE("%p\n", This );
863 return InterlockedIncrement( &This->ref );
867 static ULONG WINAPI domdoc_Release(
868 IXMLDOMDocument3 *iface )
870 domdoc *This = impl_from_IXMLDOMDocument3( iface );
873 TRACE("%p\n", This );
875 ref = InterlockedDecrement( &This->ref );
879 detach_bsc(This->bsc);
882 IUnknown_Release( This->site );
883 destroy_xmlnode(&This->node);
884 if(This->schema) IXMLDOMSchemaCollection2_Release(This->schema);
885 if (This->stream) IStream_Release(This->stream);
886 HeapFree( GetProcessHeap(), 0, This );
892 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
894 domdoc *This = impl_from_IXMLDOMDocument3( iface );
896 TRACE("(%p)->(%p)\n", This, pctinfo);
903 static HRESULT WINAPI domdoc_GetTypeInfo(
904 IXMLDOMDocument3 *iface,
905 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
907 domdoc *This = impl_from_IXMLDOMDocument3( iface );
910 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
912 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
917 static HRESULT WINAPI domdoc_GetIDsOfNames(
918 IXMLDOMDocument3 *iface,
925 domdoc *This = impl_from_IXMLDOMDocument3( iface );
929 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
932 if(!rgszNames || cNames == 0 || !rgDispId)
935 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
938 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
939 ITypeInfo_Release(typeinfo);
946 static HRESULT WINAPI domdoc_Invoke(
947 IXMLDOMDocument3 *iface,
952 DISPPARAMS* pDispParams,
954 EXCEPINFO* pExcepInfo,
957 domdoc *This = impl_from_IXMLDOMDocument3( iface );
961 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
962 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
964 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
967 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
968 pVarResult, pExcepInfo, puArgErr);
969 ITypeInfo_Release(typeinfo);
976 static HRESULT WINAPI domdoc_get_nodeName(
977 IXMLDOMDocument3 *iface,
980 domdoc *This = impl_from_IXMLDOMDocument3( iface );
982 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
984 TRACE("(%p)->(%p)\n", This, name);
986 return return_bstr(documentW, name);
990 static HRESULT WINAPI domdoc_get_nodeValue(
991 IXMLDOMDocument3 *iface,
994 domdoc *This = impl_from_IXMLDOMDocument3( iface );
996 TRACE("(%p)->(%p)\n", This, value);
1001 V_VT(value) = VT_NULL;
1002 V_BSTR(value) = NULL; /* tests show that we should do this */
1007 static HRESULT WINAPI domdoc_put_nodeValue(
1008 IXMLDOMDocument3 *iface,
1011 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1012 TRACE("(%p)->(v%d)\n", This, V_VT(&value));
1017 static HRESULT WINAPI domdoc_get_nodeType(
1018 IXMLDOMDocument3 *iface,
1021 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1023 TRACE("(%p)->(%p)\n", This, type);
1025 *type = NODE_DOCUMENT;
1030 static HRESULT WINAPI domdoc_get_parentNode(
1031 IXMLDOMDocument3 *iface,
1032 IXMLDOMNode** parent )
1034 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1036 TRACE("(%p)->(%p)\n", This, parent);
1038 return node_get_parent(&This->node, parent);
1042 static HRESULT WINAPI domdoc_get_childNodes(
1043 IXMLDOMDocument3 *iface,
1044 IXMLDOMNodeList** childList )
1046 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1048 TRACE("(%p)->(%p)\n", This, childList);
1050 return node_get_child_nodes(&This->node, childList);
1054 static HRESULT WINAPI domdoc_get_firstChild(
1055 IXMLDOMDocument3 *iface,
1056 IXMLDOMNode** firstChild )
1058 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1060 TRACE("(%p)->(%p)\n", This, firstChild);
1062 return node_get_first_child(&This->node, firstChild);
1066 static HRESULT WINAPI domdoc_get_lastChild(
1067 IXMLDOMDocument3 *iface,
1068 IXMLDOMNode** lastChild )
1070 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1072 TRACE("(%p)->(%p)\n", This, lastChild);
1074 return node_get_last_child(&This->node, lastChild);
1078 static HRESULT WINAPI domdoc_get_previousSibling(
1079 IXMLDOMDocument3 *iface,
1080 IXMLDOMNode** previousSibling )
1082 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1084 TRACE("(%p)->(%p)\n", This, previousSibling);
1086 return return_null_node(previousSibling);
1090 static HRESULT WINAPI domdoc_get_nextSibling(
1091 IXMLDOMDocument3 *iface,
1092 IXMLDOMNode** nextSibling )
1094 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1096 TRACE("(%p)->(%p)\n", This, nextSibling);
1098 return return_null_node(nextSibling);
1102 static HRESULT WINAPI domdoc_get_attributes(
1103 IXMLDOMDocument3 *iface,
1104 IXMLDOMNamedNodeMap** attributeMap )
1106 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1108 TRACE("(%p)->(%p)\n", This, attributeMap);
1110 return return_null_ptr((void**)attributeMap);
1114 static HRESULT WINAPI domdoc_insertBefore(
1115 IXMLDOMDocument3 *iface,
1116 IXMLDOMNode* newChild,
1118 IXMLDOMNode** outNewChild )
1120 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1122 TRACE("(%p)->(%p x%d %p)\n", This, newChild, V_VT(&refChild), outNewChild);
1124 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1128 static HRESULT WINAPI domdoc_replaceChild(
1129 IXMLDOMDocument3 *iface,
1130 IXMLDOMNode* newChild,
1131 IXMLDOMNode* oldChild,
1132 IXMLDOMNode** outOldChild)
1134 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1136 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1138 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1142 static HRESULT WINAPI domdoc_removeChild(
1143 IXMLDOMDocument3 *iface,
1144 IXMLDOMNode* childNode,
1145 IXMLDOMNode** oldChild)
1147 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1148 return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), childNode, oldChild );
1152 static HRESULT WINAPI domdoc_appendChild(
1153 IXMLDOMDocument3 *iface,
1154 IXMLDOMNode* newChild,
1155 IXMLDOMNode** outNewChild)
1157 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1158 return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newChild, outNewChild );
1162 static HRESULT WINAPI domdoc_hasChildNodes(
1163 IXMLDOMDocument3 *iface,
1164 VARIANT_BOOL* hasChild)
1166 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1167 return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), hasChild );
1171 static HRESULT WINAPI domdoc_get_ownerDocument(
1172 IXMLDOMDocument3 *iface,
1173 IXMLDOMDocument** DOMDocument)
1175 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1176 return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), DOMDocument );
1180 static HRESULT WINAPI domdoc_cloneNode(
1181 IXMLDOMDocument3 *iface,
1183 IXMLDOMNode** outNode)
1185 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1186 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
1187 return node_clone( &This->node, deep, outNode );
1191 static HRESULT WINAPI domdoc_get_nodeTypeString(
1192 IXMLDOMDocument3 *iface,
1195 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1196 static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
1198 TRACE("(%p)->(%p)\n", This, p);
1200 return return_bstr(documentW, p);
1204 static HRESULT WINAPI domdoc_get_text(
1205 IXMLDOMDocument3 *iface,
1208 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1209 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), text );
1213 static HRESULT WINAPI domdoc_put_text(
1214 IXMLDOMDocument3 *iface,
1217 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1218 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1223 static HRESULT WINAPI domdoc_get_specified(
1224 IXMLDOMDocument3 *iface,
1225 VARIANT_BOOL* isSpecified )
1227 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1228 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1229 *isSpecified = VARIANT_TRUE;
1234 static HRESULT WINAPI domdoc_get_definition(
1235 IXMLDOMDocument3 *iface,
1236 IXMLDOMNode** definitionNode )
1238 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1239 FIXME("(%p)->(%p)\n", This, definitionNode);
1244 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1245 IXMLDOMDocument3 *iface,
1246 VARIANT* typedValue )
1248 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1249 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
1252 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1253 IXMLDOMDocument3 *iface,
1254 VARIANT typedValue )
1256 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1257 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
1261 static HRESULT WINAPI domdoc_get_dataType(
1262 IXMLDOMDocument3 *iface,
1265 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1266 TRACE("(%p)->(%p)\n", This, typename);
1267 return return_null_var( typename );
1271 static HRESULT WINAPI domdoc_put_dataType(
1272 IXMLDOMDocument3 *iface,
1275 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1276 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
1280 static HRESULT WINAPI domdoc_get_xml(
1281 IXMLDOMDocument3 *iface,
1284 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1286 TRACE("(%p)->(%p)\n", This, p);
1288 return node_get_xml(&This->node, TRUE, TRUE, p);
1292 static HRESULT WINAPI domdoc_transformNode(
1293 IXMLDOMDocument3 *iface,
1294 IXMLDOMNode* styleSheet,
1297 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1298 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), styleSheet, xmlString );
1302 static HRESULT WINAPI domdoc_selectNodes(
1303 IXMLDOMDocument3 *iface,
1305 IXMLDOMNodeList** resultList )
1307 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1308 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), queryString, resultList );
1312 static HRESULT WINAPI domdoc_selectSingleNode(
1313 IXMLDOMDocument3 *iface,
1315 IXMLDOMNode** resultNode )
1317 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1318 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), queryString, resultNode );
1322 static HRESULT WINAPI domdoc_get_parsed(
1323 IXMLDOMDocument3 *iface,
1324 VARIANT_BOOL* isParsed )
1326 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1327 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1328 *isParsed = VARIANT_TRUE;
1333 static HRESULT WINAPI domdoc_get_namespaceURI(
1334 IXMLDOMDocument3 *iface,
1335 BSTR* namespaceURI )
1337 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1338 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), namespaceURI );
1342 static HRESULT WINAPI domdoc_get_prefix(
1343 IXMLDOMDocument3 *iface,
1346 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1347 TRACE("(%p)->(%p)\n", This, prefix);
1348 return return_null_bstr( prefix );
1352 static HRESULT WINAPI domdoc_get_baseName(
1353 IXMLDOMDocument3 *iface,
1356 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1357 TRACE("(%p)->(%p)\n", This, name);
1358 return return_null_bstr( name );
1362 static HRESULT WINAPI domdoc_transformNodeToObject(
1363 IXMLDOMDocument3 *iface,
1364 IXMLDOMNode* stylesheet,
1365 VARIANT outputObject)
1367 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1368 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), stylesheet, outputObject );
1372 static HRESULT WINAPI domdoc_get_doctype(
1373 IXMLDOMDocument3 *iface,
1374 IXMLDOMDocumentType** documentType )
1376 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1377 FIXME("(%p)\n", This);
1382 static HRESULT WINAPI domdoc_get_implementation(
1383 IXMLDOMDocument3 *iface,
1384 IXMLDOMImplementation** impl )
1386 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1388 TRACE("(%p)->(%p)\n", This, impl);
1391 return E_INVALIDARG;
1393 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1398 static HRESULT WINAPI domdoc_get_documentElement(
1399 IXMLDOMDocument3 *iface,
1400 IXMLDOMElement** DOMElement )
1402 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1403 IXMLDOMNode *element_node;
1407 TRACE("(%p)->(%p)\n", This, DOMElement);
1410 return E_INVALIDARG;
1414 root = xmlDocGetRootElement( get_doc(This) );
1418 element_node = create_node( root );
1419 if(!element_node) return S_FALSE;
1421 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1422 IXMLDOMNode_Release(element_node);
1428 static HRESULT WINAPI domdoc_put_documentElement(
1429 IXMLDOMDocument3 *iface,
1430 IXMLDOMElement* DOMElement )
1432 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1433 IXMLDOMNode *elementNode;
1438 TRACE("(%p)->(%p)\n", This, DOMElement);
1440 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1444 xmlNode = get_node_obj( elementNode );
1446 FIXME("elementNode is not our object\n");
1450 if(!xmlNode->node->parent)
1451 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1452 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1454 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1455 IXMLDOMNode_Release( elementNode );
1458 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1464 static HRESULT WINAPI domdoc_createElement(
1465 IXMLDOMDocument3 *iface,
1467 IXMLDOMElement** element )
1469 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1474 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1476 if (!element || !tagname) return E_INVALIDARG;
1478 V_VT(&type) = VT_I1;
1479 V_I1(&type) = NODE_ELEMENT;
1481 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1484 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1485 IXMLDOMNode_Release(node);
1492 static HRESULT WINAPI domdoc_createDocumentFragment(
1493 IXMLDOMDocument3 *iface,
1494 IXMLDOMDocumentFragment** frag )
1496 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1501 TRACE("(%p)->(%p)\n", This, frag);
1503 if (!frag) return E_INVALIDARG;
1507 V_VT(&type) = VT_I1;
1508 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1510 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1513 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1514 IXMLDOMNode_Release(node);
1521 static HRESULT WINAPI domdoc_createTextNode(
1522 IXMLDOMDocument3 *iface,
1524 IXMLDOMText** text )
1526 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1531 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1533 if (!text) return E_INVALIDARG;
1537 V_VT(&type) = VT_I1;
1538 V_I1(&type) = NODE_TEXT;
1540 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1543 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1544 IXMLDOMNode_Release(node);
1545 hr = IXMLDOMText_put_data(*text, data);
1552 static HRESULT WINAPI domdoc_createComment(
1553 IXMLDOMDocument3 *iface,
1555 IXMLDOMComment** comment )
1557 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1562 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1564 if (!comment) return E_INVALIDARG;
1568 V_VT(&type) = VT_I1;
1569 V_I1(&type) = NODE_COMMENT;
1571 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1574 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1575 IXMLDOMNode_Release(node);
1576 hr = IXMLDOMComment_put_data(*comment, data);
1583 static HRESULT WINAPI domdoc_createCDATASection(
1584 IXMLDOMDocument3 *iface,
1586 IXMLDOMCDATASection** cdata )
1588 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1593 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1595 if (!cdata) return E_INVALIDARG;
1599 V_VT(&type) = VT_I1;
1600 V_I1(&type) = NODE_CDATA_SECTION;
1602 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1605 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1606 IXMLDOMNode_Release(node);
1607 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1614 static HRESULT WINAPI domdoc_createProcessingInstruction(
1615 IXMLDOMDocument3 *iface,
1618 IXMLDOMProcessingInstruction** pi )
1620 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1625 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1627 if (!pi) return E_INVALIDARG;
1631 V_VT(&type) = VT_I1;
1632 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1634 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1639 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1640 node_obj = get_node_obj(node);
1641 hr = node_set_content(node_obj, data);
1643 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1644 IXMLDOMNode_Release(node);
1651 static HRESULT WINAPI domdoc_createAttribute(
1652 IXMLDOMDocument3 *iface,
1654 IXMLDOMAttribute** attribute )
1656 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1661 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1663 if (!attribute || !name) return E_INVALIDARG;
1665 V_VT(&type) = VT_I1;
1666 V_I1(&type) = NODE_ATTRIBUTE;
1668 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1671 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1672 IXMLDOMNode_Release(node);
1679 static HRESULT WINAPI domdoc_createEntityReference(
1680 IXMLDOMDocument3 *iface,
1682 IXMLDOMEntityReference** entityref )
1684 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1689 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1691 if (!entityref) return E_INVALIDARG;
1695 V_VT(&type) = VT_I1;
1696 V_I1(&type) = NODE_ENTITY_REFERENCE;
1698 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1701 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1702 IXMLDOMNode_Release(node);
1709 static HRESULT WINAPI domdoc_getElementsByTagName(
1710 IXMLDOMDocument3 *iface,
1712 IXMLDOMNodeList** resultList )
1714 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1717 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagName), resultList);
1719 if (!tagName || !resultList) return E_INVALIDARG;
1721 if (tagName[0] == '*' && tagName[1] == 0)
1723 static const WCHAR formatallW[] = {'/','/','*',0};
1724 hr = queryresult_create((xmlNodePtr)get_doc(This), formatallW, resultList);
1728 static const WCHAR xpathformat[] =
1729 { '/','/','*','[','l','o','c','a','l','-','n','a','m','e','(',')','=','\'' };
1730 static const WCHAR closeW[] = { '\'',']',0 };
1736 length = lstrlenW(tagName);
1738 /* without two WCHARs from format specifier */
1739 ptr = pattern = heap_alloc(sizeof(xpathformat) + length*sizeof(WCHAR) + sizeof(closeW));
1741 memcpy(ptr, xpathformat, sizeof(xpathformat));
1742 ptr += sizeof(xpathformat)/sizeof(WCHAR);
1743 memcpy(ptr, tagName, length*sizeof(WCHAR));
1745 memcpy(ptr, closeW, sizeof(closeW));
1747 hr = queryresult_create((xmlNodePtr)get_doc(This), pattern, resultList);
1754 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1760 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1762 return E_INVALIDARG;
1769 static HRESULT WINAPI domdoc_createNode(
1770 IXMLDOMDocument3 *iface,
1774 IXMLDOMNode** node )
1776 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1777 DOMNodeType node_type;
1779 xmlChar *xml_name, *href;
1782 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1784 if(!node) return E_INVALIDARG;
1786 hr = get_node_type(Type, &node_type);
1787 if(FAILED(hr)) return hr;
1789 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1790 FIXME("nodes with namespaces currently not supported.\n");
1792 TRACE("node_type %d\n", node_type);
1794 /* exit earlier for types that need name */
1798 case NODE_ATTRIBUTE:
1799 case NODE_ENTITY_REFERENCE:
1800 case NODE_PROCESSING_INSTRUCTION:
1801 if (!name || *name == 0) return E_FAIL;
1806 xml_name = xmlChar_from_wchar(name);
1807 /* prevent empty href to be allocated */
1808 href = namespaceURI ? xmlChar_from_wchar(namespaceURI) : NULL;
1814 xmlChar *local, *prefix;
1816 local = xmlSplitQName2(xml_name, &prefix);
1818 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
1820 /* allow to create default namespace xmlns= */
1821 if (local || (href && *href))
1823 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
1824 xmlSetNs(xmlnode, ns);
1832 case NODE_ATTRIBUTE:
1833 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1836 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1838 case NODE_CDATA_SECTION:
1839 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1841 case NODE_ENTITY_REFERENCE:
1842 xmlnode = xmlNewReference(get_doc(This), xml_name);
1844 case NODE_PROCESSING_INSTRUCTION:
1845 #ifdef HAVE_XMLNEWDOCPI
1846 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1848 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1853 xmlnode = xmlNewDocComment(get_doc(This), NULL);
1855 case NODE_DOCUMENT_FRAGMENT:
1856 xmlnode = xmlNewDocFragment(get_doc(This));
1858 /* unsupported types */
1860 case NODE_DOCUMENT_TYPE:
1863 heap_free(xml_name);
1864 return E_INVALIDARG;
1866 FIXME("unhandled node type %d\n", node_type);
1871 *node = create_node(xmlnode);
1872 heap_free(xml_name);
1877 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1878 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1885 static HRESULT WINAPI domdoc_nodeFromID(
1886 IXMLDOMDocument3 *iface,
1888 IXMLDOMNode** node )
1890 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1891 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1895 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1900 xmldoc = doparse(This, ptr, len, NULL);
1902 xmldoc->_private = create_priv();
1903 return attach_xmldoc(This, xmldoc);
1909 static HRESULT doread( domdoc *This, LPWSTR filename )
1914 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1919 detach_bsc(This->bsc);
1925 static HRESULT WINAPI domdoc_load(
1926 IXMLDOMDocument3 *iface,
1928 VARIANT_BOOL* isSuccessful )
1930 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1931 LPWSTR filename = NULL;
1932 HRESULT hr = S_FALSE;
1933 IXMLDOMDocument3 *pNewDoc = NULL;
1934 IStream *pStream = NULL;
1937 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
1939 *isSuccessful = VARIANT_FALSE;
1941 assert( &This->node );
1943 switch( V_VT(&xmlSource) )
1946 filename = V_BSTR(&xmlSource);
1949 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
1954 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
1955 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1956 hr = attach_xmldoc(This, xmldoc);
1959 *isSuccessful = VARIANT_TRUE;
1964 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1967 IPersistStream *pDocStream;
1968 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1971 hr = IPersistStream_Load(pDocStream, pStream);
1972 IStream_Release(pStream);
1975 *isSuccessful = VARIANT_TRUE;
1977 TRACE("Using IStream to load Document\n");
1982 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1987 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1992 /* ISequentialStream */
1993 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1997 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
2000 TRACE("filename (%s)\n", debugstr_w(filename));
2004 hr = doread( This, filename );
2007 This->error = E_FAIL;
2010 hr = This->error = S_OK;
2011 *isSuccessful = VARIANT_TRUE;
2015 if(!filename || FAILED(hr)) {
2016 xmldoc = xmlNewDoc(NULL);
2017 xmldoc->_private = create_priv();
2018 hr = attach_xmldoc(This, xmldoc);
2023 TRACE("ret (%d)\n", hr);
2029 static HRESULT WINAPI domdoc_get_readyState(
2030 IXMLDOMDocument3 *iface,
2033 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2034 FIXME("stub! (%p)->(%p)\n", This, value);
2037 return E_INVALIDARG;
2039 *value = READYSTATE_COMPLETE;
2044 static HRESULT WINAPI domdoc_get_parseError(
2045 IXMLDOMDocument3 *iface,
2046 IXMLDOMParseError** errorObj )
2048 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2049 static const WCHAR err[] = {'e','r','r','o','r',0};
2050 BSTR error_string = NULL;
2052 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2055 error_string = SysAllocString(err);
2057 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2058 if(!*errorObj) return E_OUTOFMEMORY;
2063 static HRESULT WINAPI domdoc_get_url(
2064 IXMLDOMDocument3 *iface,
2067 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2068 FIXME("(%p)->(%p)\n", This, urlString);
2073 static HRESULT WINAPI domdoc_get_async(
2074 IXMLDOMDocument3 *iface,
2075 VARIANT_BOOL* isAsync )
2077 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2079 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2080 *isAsync = This->async;
2085 static HRESULT WINAPI domdoc_put_async(
2086 IXMLDOMDocument3 *iface,
2087 VARIANT_BOOL isAsync )
2089 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2091 TRACE("(%p)->(%d)\n", This, isAsync);
2092 This->async = isAsync;
2097 static HRESULT WINAPI domdoc_abort(
2098 IXMLDOMDocument3 *iface )
2100 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2101 FIXME("%p\n", This);
2106 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
2111 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
2112 str = heap_alloc( len );
2115 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
2121 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2122 static HRESULT WINAPI domdoc_loadXML(
2123 IXMLDOMDocument3 *iface,
2125 VARIANT_BOOL* isSuccessful )
2127 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2128 static const xmlChar encoding[] = "UTF-8";
2129 xmlDocPtr xmldoc = NULL;
2130 HRESULT hr = S_FALSE, hr2;
2134 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2136 assert ( &This->node );
2140 *isSuccessful = VARIANT_FALSE;
2142 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
2144 xmldoc = doparse(This, str, len, encoding);
2148 This->error = E_FAIL;
2149 TRACE("failed to parse document\n");
2153 hr = This->error = S_OK;
2154 *isSuccessful = VARIANT_TRUE;
2155 TRACE("parsed document %p\n", xmldoc);
2160 xmldoc = xmlNewDoc(NULL);
2162 xmldoc->_private = create_priv();
2164 hr2 = attach_xmldoc(This, xmldoc);
2171 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2175 if(!WriteFile(ctx, buffer, len, &written, NULL))
2177 WARN("write error\n");
2184 static int XMLCALL domdoc_save_closecallback(void *ctx)
2186 return CloseHandle(ctx) ? 0 : -1;
2189 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2194 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2197 WARN("stream write error: 0x%08x\n", hr);
2204 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2206 IStream_Release((IStream*)ctx);
2210 static HRESULT WINAPI domdoc_save(
2211 IXMLDOMDocument3 *iface,
2212 VARIANT destination )
2214 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2215 xmlSaveCtxtPtr ctx = NULL;
2219 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
2220 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
2222 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
2224 FIXME("Unhandled vt %d\n", V_VT(&destination));
2228 if(V_VT(&destination) == VT_UNKNOWN)
2230 IUnknown *pUnk = V_UNKNOWN(&destination);
2231 IXMLDOMDocument2 *document;
2234 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2237 VARIANT_BOOL success;
2240 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2243 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2247 IXMLDOMDocument3_Release(document);
2251 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2254 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2255 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2259 IStream_Release(stream);
2266 /* save with file path */
2267 HANDLE handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
2268 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2269 if( handle == INVALID_HANDLE_VALUE )
2271 WARN("failed to create file\n");
2275 /* disable top XML declaration */
2276 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2277 handle, NULL, XML_SAVE_NO_DECL);
2280 CloseHandle(handle);
2285 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2286 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2287 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2289 /* will release resources through close callback */
2295 static HRESULT WINAPI domdoc_get_validateOnParse(
2296 IXMLDOMDocument3 *iface,
2297 VARIANT_BOOL* isValidating )
2299 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2300 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2301 *isValidating = This->validating;
2306 static HRESULT WINAPI domdoc_put_validateOnParse(
2307 IXMLDOMDocument3 *iface,
2308 VARIANT_BOOL isValidating )
2310 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2311 TRACE("(%p)->(%d)\n", This, isValidating);
2312 This->validating = isValidating;
2317 static HRESULT WINAPI domdoc_get_resolveExternals(
2318 IXMLDOMDocument3 *iface,
2319 VARIANT_BOOL* isResolving )
2321 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2322 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2323 *isResolving = This->resolving;
2328 static HRESULT WINAPI domdoc_put_resolveExternals(
2329 IXMLDOMDocument3 *iface,
2330 VARIANT_BOOL isResolving )
2332 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2333 TRACE("(%p)->(%d)\n", This, isResolving);
2334 This->resolving = isResolving;
2339 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2340 IXMLDOMDocument3 *iface,
2341 VARIANT_BOOL* isPreserving )
2343 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2344 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->properties->preserving);
2345 *isPreserving = This->properties->preserving;
2350 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2351 IXMLDOMDocument3 *iface,
2352 VARIANT_BOOL isPreserving )
2354 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2355 TRACE("(%p)->(%d)\n", This, isPreserving);
2356 This->properties->preserving = isPreserving;
2361 static HRESULT WINAPI domdoc_put_onReadyStateChange(
2362 IXMLDOMDocument3 *iface,
2363 VARIANT readyStateChangeSink )
2365 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2366 FIXME("%p\n", This);
2371 static HRESULT WINAPI domdoc_put_onDataAvailable(
2372 IXMLDOMDocument3 *iface,
2373 VARIANT onDataAvailableSink )
2375 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2376 FIXME("%p\n", This);
2380 static HRESULT WINAPI domdoc_put_onTransformNode(
2381 IXMLDOMDocument3 *iface,
2382 VARIANT onTransformNodeSink )
2384 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2385 FIXME("%p\n", This);
2389 static HRESULT WINAPI domdoc_get_namespaces(
2390 IXMLDOMDocument3* iface,
2391 IXMLDOMSchemaCollection** schemaCollection )
2393 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2394 FIXME("(%p)->(%p)\n", This, schemaCollection);
2398 static HRESULT WINAPI domdoc_get_schemas(
2399 IXMLDOMDocument3* iface,
2402 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2403 HRESULT hr = S_FALSE;
2404 IXMLDOMSchemaCollection2* cur_schema = This->schema;
2406 TRACE("(%p)->(%p)\n", This, var1);
2408 VariantInit(var1); /* Test shows we don't call VariantClear here */
2409 V_VT(var1) = VT_NULL;
2413 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2415 V_VT(var1) = VT_DISPATCH;
2420 static HRESULT WINAPI domdoc_putref_schemas(
2421 IXMLDOMDocument3* iface,
2424 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2425 HRESULT hr = E_FAIL;
2426 IXMLDOMSchemaCollection2* new_schema = NULL;
2428 FIXME("(%p): semi-stub\n", This);
2432 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2436 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2445 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2450 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
2451 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2457 static inline BOOL is_wellformed(xmlDocPtr doc)
2459 #ifdef HAVE_XMLDOC_PROPERTIES
2460 return doc->properties & XML_DOC_WELLFORMED;
2462 /* Not a full check, but catches the worst violations */
2466 for (child = doc->children; child != NULL; child = child->next)
2468 switch (child->type)
2470 case XML_ELEMENT_NODE:
2475 case XML_CDATA_SECTION_NODE:
2487 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2491 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2495 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2499 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2503 static HRESULT WINAPI domdoc_validateNode(
2504 IXMLDOMDocument3* iface,
2506 IXMLDOMParseError** err)
2508 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2509 LONG state, err_code = 0;
2513 TRACE("(%p)->(%p, %p)\n", This, node, err);
2514 domdoc_get_readyState(iface, &state);
2515 if (state != READYSTATE_COMPLETE)
2518 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2525 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2529 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2532 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2536 if (!is_wellformed(get_doc(This)))
2538 ERR("doc not well-formed");
2540 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2544 /* DTD validation */
2545 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2547 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2548 vctx->error = validate_error;
2549 vctx->warning = validate_warning;
2552 if (!((node == (IXMLDOMNode*)iface)?
2553 xmlValidateDocument(vctx, get_doc(This)) :
2554 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2556 /* TODO: get a real error code here */
2557 TRACE("DTD validation failed\n");
2558 err_code = E_XML_INVALID;
2561 xmlFreeValidCtxt(vctx);
2564 /* Schema validation */
2565 if (hr == S_OK && This->schema != NULL)
2568 hr = SchemaCache_validate_tree(This->schema, get_node_obj(node)->node);
2572 /* TODO: get a real error code here */
2573 TRACE("schema validation failed\n");
2575 err_code = E_XML_INVALID;
2579 /* not really OK, just didn't find a schema for the ns */
2586 TRACE("no DTD or schema found\n");
2587 err_code = E_XML_NODTD;
2592 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2597 static HRESULT WINAPI domdoc_validate(
2598 IXMLDOMDocument3* iface,
2599 IXMLDOMParseError** err)
2601 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2602 TRACE("(%p)->(%p)\n", This, err);
2603 return domdoc_validateNode(iface, (IXMLDOMNode*)iface, err);
2606 static HRESULT WINAPI domdoc_setProperty(
2607 IXMLDOMDocument3* iface,
2611 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2613 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2615 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2621 V_VT(&varStr) = VT_EMPTY;
2622 if (V_VT(&var) != VT_BSTR)
2624 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2626 bstr = V_BSTR(&varStr);
2629 bstr = V_BSTR(&var);
2632 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2633 This->properties->XPath = TRUE;
2634 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2635 This->properties->XPath = FALSE;
2639 VariantClear(&varStr);
2642 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2647 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2648 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2649 xmlXPathContextPtr ctx;
2650 struct list *pNsList;
2651 select_ns_entry* pNsEntry = NULL;
2653 V_VT(&varStr) = VT_EMPTY;
2654 if (V_VT(&var) != VT_BSTR)
2656 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2658 bstr = V_BSTR(&varStr);
2661 bstr = V_BSTR(&var);
2665 pNsList = &(This->properties->selectNsList);
2666 clear_selectNsList(pNsList);
2668 nsStr = xmlChar_from_wchar(bstr);
2671 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2673 This->properties->selectNsStr = nsStr;
2674 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2677 ctx = xmlXPathNewContext(This->node.node->doc);
2680 for (; *pTokBegin; pTokBegin = pTokEnd)
2682 if (pNsEntry != NULL)
2683 memset(pNsEntry, 0, sizeof(select_ns_entry));
2685 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2687 while (*pTokBegin == ' ')
2689 pTokEnd = pTokBegin;
2690 while (*pTokEnd != ' ' && *pTokEnd != 0)
2693 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2696 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2697 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2702 if (*pTokBegin == '=')
2704 /*valid for XSLPattern?*/
2705 FIXME("Setting default xmlns not supported - skipping.\n");
2706 pTokBegin = pTokEnd;
2709 else if (*pTokBegin == ':')
2711 pNsEntry->prefix = ++pTokBegin;
2712 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2715 if (pTokInner == pTokEnd)
2718 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2719 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2723 pNsEntry->prefix_end = *pTokInner;
2727 if (pTokEnd-pTokInner > 1 &&
2728 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2729 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2731 pNsEntry->href = ++pTokInner;
2732 pNsEntry->href_end = *(pTokEnd-1);
2734 list_add_tail(pNsList, &pNsEntry->entry);
2735 /*let libxml figure out if they're valid from here ;)*/
2736 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2745 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2746 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2747 list_add_tail(pNsList, &pNsEntry->entry);
2760 heap_free(pNsEntry);
2761 xmlXPathFreeContext(ctx);
2764 VariantClear(&varStr);
2767 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2768 lstrcmpiW(p, PropertyNewParserW) == 0)
2771 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2775 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2779 static HRESULT WINAPI domdoc_getProperty(
2780 IXMLDOMDocument3* iface,
2784 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2786 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2789 return E_INVALIDARG;
2791 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2793 V_VT(var) = VT_BSTR;
2794 V_BSTR(var) = This->properties->XPath ?
2795 SysAllocString(PropValueXPathW) :
2796 SysAllocString(PropValueXSLPatternW);
2797 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2799 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2802 BSTR rebuiltStr, cur;
2803 const xmlChar *nsStr;
2804 struct list *pNsList;
2805 select_ns_entry* pNsEntry;
2807 V_VT(var) = VT_BSTR;
2808 nsStr = This->properties->selectNsStr;
2809 pNsList = &This->properties->selectNsList;
2810 lenA = This->properties->selectNsStr_len;
2811 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
2812 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
2813 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
2815 /* this is fine because all of the chars that end tokens are ASCII*/
2816 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
2818 while (*cur != 0) ++cur;
2819 if (pNsEntry->prefix_end)
2821 *cur = pNsEntry->prefix_end;
2822 while (*cur != 0) ++cur;
2825 if (pNsEntry->href_end)
2827 *cur = pNsEntry->href_end;
2830 V_BSTR(var) = SysAllocString(rebuiltStr);
2831 heap_free(rebuiltStr);
2835 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2839 static HRESULT WINAPI domdoc_importNode(
2840 IXMLDOMDocument3* iface,
2843 IXMLDOMNode** clone)
2845 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2846 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
2850 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
2852 domdoc_QueryInterface,
2855 domdoc_GetTypeInfoCount,
2857 domdoc_GetIDsOfNames,
2859 domdoc_get_nodeName,
2860 domdoc_get_nodeValue,
2861 domdoc_put_nodeValue,
2862 domdoc_get_nodeType,
2863 domdoc_get_parentNode,
2864 domdoc_get_childNodes,
2865 domdoc_get_firstChild,
2866 domdoc_get_lastChild,
2867 domdoc_get_previousSibling,
2868 domdoc_get_nextSibling,
2869 domdoc_get_attributes,
2870 domdoc_insertBefore,
2871 domdoc_replaceChild,
2874 domdoc_hasChildNodes,
2875 domdoc_get_ownerDocument,
2877 domdoc_get_nodeTypeString,
2880 domdoc_get_specified,
2881 domdoc_get_definition,
2882 domdoc_get_nodeTypedValue,
2883 domdoc_put_nodeTypedValue,
2884 domdoc_get_dataType,
2885 domdoc_put_dataType,
2887 domdoc_transformNode,
2889 domdoc_selectSingleNode,
2891 domdoc_get_namespaceURI,
2893 domdoc_get_baseName,
2894 domdoc_transformNodeToObject,
2896 domdoc_get_implementation,
2897 domdoc_get_documentElement,
2898 domdoc_put_documentElement,
2899 domdoc_createElement,
2900 domdoc_createDocumentFragment,
2901 domdoc_createTextNode,
2902 domdoc_createComment,
2903 domdoc_createCDATASection,
2904 domdoc_createProcessingInstruction,
2905 domdoc_createAttribute,
2906 domdoc_createEntityReference,
2907 domdoc_getElementsByTagName,
2911 domdoc_get_readyState,
2912 domdoc_get_parseError,
2919 domdoc_get_validateOnParse,
2920 domdoc_put_validateOnParse,
2921 domdoc_get_resolveExternals,
2922 domdoc_put_resolveExternals,
2923 domdoc_get_preserveWhiteSpace,
2924 domdoc_put_preserveWhiteSpace,
2925 domdoc_put_onReadyStateChange,
2926 domdoc_put_onDataAvailable,
2927 domdoc_put_onTransformNode,
2928 domdoc_get_namespaces,
2930 domdoc_putref_schemas,
2934 domdoc_validateNode,
2938 /* IConnectionPointContainer */
2939 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
2940 REFIID riid, void **ppv)
2942 domdoc *This = impl_from_IConnectionPointContainer(iface);
2943 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)This, riid, ppv);
2946 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
2948 domdoc *This = impl_from_IConnectionPointContainer(iface);
2949 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)This);
2952 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
2954 domdoc *This = impl_from_IConnectionPointContainer(iface);
2955 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)This);
2958 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
2959 IEnumConnectionPoints **ppEnum)
2961 domdoc *This = impl_from_IConnectionPointContainer(iface);
2962 FIXME("(%p)->(%p): stub\n", This, ppEnum);
2966 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
2967 REFIID riid, IConnectionPoint **cp)
2969 domdoc *This = impl_from_IConnectionPointContainer(iface);
2970 ConnectionPoint *iter;
2972 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
2976 for(iter = This->cp_list; iter; iter = iter->next)
2978 if (IsEqualGUID(iter->iid, riid))
2979 *cp = (IConnectionPoint*)&iter->lpVtblConnectionPoint;
2984 IConnectionPoint_AddRef(*cp);
2988 FIXME("unsupported riid %s\n", debugstr_guid(riid));
2989 return CONNECT_E_NOCONNECTION;
2993 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
2995 ConnectionPointContainer_QueryInterface,
2996 ConnectionPointContainer_AddRef,
2997 ConnectionPointContainer_Release,
2998 ConnectionPointContainer_EnumConnectionPoints,
2999 ConnectionPointContainer_FindConnectionPoint
3002 /* IConnectionPoint */
3003 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
3004 REFIID riid, void **ppv)
3006 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3008 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3012 if (IsEqualGUID(&IID_IUnknown, riid) ||
3013 IsEqualGUID(&IID_IConnectionPoint, riid))
3020 IConnectionPoint_AddRef(iface);
3024 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3025 return E_NOINTERFACE;
3028 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3030 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3031 return IConnectionPointContainer_AddRef(This->container);
3034 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3036 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3037 return IConnectionPointContainer_Release(This->container);
3040 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3042 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3044 TRACE("(%p)->(%p)\n", This, iid);
3046 if (!iid) return E_POINTER;
3052 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3053 IConnectionPointContainer **container)
3055 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3057 TRACE("(%p)->(%p)\n", This, container);
3059 if (!container) return E_POINTER;
3061 *container = This->container;
3062 IConnectionPointContainer_AddRef(*container);
3066 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
3069 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3070 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
3074 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3076 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3078 TRACE("(%p)->(%d)\n", This, cookie);
3080 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3081 return CONNECT_E_NOCONNECTION;
3083 IUnknown_Release(This->sinks[cookie-1].unk);
3084 This->sinks[cookie-1].unk = NULL;
3089 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3090 IEnumConnections **ppEnum)
3092 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3093 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3097 static const IConnectionPointVtbl ConnectionPointVtbl =
3099 ConnectionPoint_QueryInterface,
3100 ConnectionPoint_AddRef,
3101 ConnectionPoint_Release,
3102 ConnectionPoint_GetConnectionInterface,
3103 ConnectionPoint_GetConnectionPointContainer,
3104 ConnectionPoint_Advise,
3105 ConnectionPoint_Unadvise,
3106 ConnectionPoint_EnumConnections
3109 void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3111 cp->lpVtblConnectionPoint = &ConnectionPointVtbl;
3117 cp->next = doc->cp_list;
3120 cp->container = (IConnectionPointContainer*)&doc->lpVtblConnectionPointContainer;
3123 /* domdoc implementation of IObjectWithSite */
3124 static HRESULT WINAPI
3125 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3127 domdoc *This = impl_from_IObjectWithSite(iface);
3128 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppvObject );
3131 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3133 domdoc *This = impl_from_IObjectWithSite(iface);
3134 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3137 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3139 domdoc *This = impl_from_IObjectWithSite(iface);
3140 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3143 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3145 domdoc *This = impl_from_IObjectWithSite(iface);
3147 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3152 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3155 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3157 domdoc *This = impl_from_IObjectWithSite(iface);
3159 TRACE("(%p)->(%p)\n", iface, punk);
3165 IUnknown_Release( This->site );
3172 IUnknown_AddRef( punk );
3175 IUnknown_Release( This->site );
3182 static const IObjectWithSiteVtbl domdocObjectSite =
3184 domdoc_ObjectWithSite_QueryInterface,
3185 domdoc_ObjectWithSite_AddRef,
3186 domdoc_ObjectWithSite_Release,
3187 domdoc_ObjectWithSite_SetSite,
3188 domdoc_ObjectWithSite_GetSite
3191 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3193 domdoc *This = impl_from_IObjectSafety(iface);
3194 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppv );
3197 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3199 domdoc *This = impl_from_IObjectSafety(iface);
3200 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3203 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3205 domdoc *This = impl_from_IObjectSafety(iface);
3206 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3209 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3211 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3212 DWORD *supported, DWORD *enabled)
3214 domdoc *This = impl_from_IObjectSafety(iface);
3216 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3218 if(!supported || !enabled) return E_POINTER;
3220 *supported = SAFETY_SUPPORTED_OPTIONS;
3221 *enabled = This->safeopt;
3226 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3227 DWORD mask, DWORD enabled)
3229 domdoc *This = impl_from_IObjectSafety(iface);
3230 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3232 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3235 This->safeopt = enabled & mask & SAFETY_SUPPORTED_OPTIONS;
3239 #undef SAFETY_SUPPORTED_OPTIONS
3241 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3242 domdoc_Safety_QueryInterface,
3243 domdoc_Safety_AddRef,
3244 domdoc_Safety_Release,
3245 domdoc_Safety_GetInterfaceSafetyOptions,
3246 domdoc_Safety_SetInterfaceSafetyOptions
3249 static const tid_t domdoc_iface_tids[] = {
3251 IXMLDOMDocument_tid,
3252 IXMLDOMDocument2_tid,
3255 static dispex_static_data_t domdoc_dispex = {
3257 IXMLDOMDocument2_tid,
3262 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3266 doc = heap_alloc( sizeof (*doc) );
3268 return E_OUTOFMEMORY;
3270 doc->lpVtbl = &domdoc_vtbl;
3271 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
3272 doc->lpvtblIObjectWithSite = &domdocObjectSite;
3273 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
3274 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
3275 doc->lpVtblConnectionPointContainer = &ConnectionPointContainerVtbl;
3277 doc->async = VARIANT_TRUE;
3278 doc->validating = 0;
3280 doc->properties = properties_from_xmlDocPtr(xmldoc);
3287 doc->cp_list = NULL;
3289 /* events connection points */
3290 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3291 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3292 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3294 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->lpVtbl, &domdoc_dispex);
3296 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
3298 TRACE("returning iface %p\n", *document);
3302 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3307 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
3309 xmldoc = xmlNewDoc(NULL);
3311 return E_OUTOFMEMORY;
3313 xmldoc->_private = create_priv();
3314 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
3316 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3319 free_properties(properties_from_xmlDocPtr(xmldoc));
3320 heap_free(xmldoc->_private);
3328 IUnknown* create_domdoc( xmlNodePtr document )
3333 TRACE("(%p)\n", document);
3335 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3344 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3346 MESSAGE("This program tried to use a DOMDocument object, but\n"
3347 "libxml2 support was not present at compile time.\n");