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 return IXMLDOMNode_get_nodeTypeString( IXMLDOMNode_from_impl(&This->node), nodeType );
1200 static HRESULT WINAPI domdoc_get_text(
1201 IXMLDOMDocument3 *iface,
1204 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1205 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), text );
1209 static HRESULT WINAPI domdoc_put_text(
1210 IXMLDOMDocument3 *iface,
1213 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1214 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1219 static HRESULT WINAPI domdoc_get_specified(
1220 IXMLDOMDocument3 *iface,
1221 VARIANT_BOOL* isSpecified )
1223 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1224 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1225 *isSpecified = VARIANT_TRUE;
1230 static HRESULT WINAPI domdoc_get_definition(
1231 IXMLDOMDocument3 *iface,
1232 IXMLDOMNode** definitionNode )
1234 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1235 FIXME("(%p)->(%p)\n", This, definitionNode);
1240 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1241 IXMLDOMDocument3 *iface,
1242 VARIANT* typedValue )
1244 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1245 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
1248 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1249 IXMLDOMDocument3 *iface,
1250 VARIANT typedValue )
1252 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1253 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
1257 static HRESULT WINAPI domdoc_get_dataType(
1258 IXMLDOMDocument3 *iface,
1261 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1262 TRACE("(%p)->(%p)\n", This, typename);
1263 return return_null_var( typename );
1267 static HRESULT WINAPI domdoc_put_dataType(
1268 IXMLDOMDocument3 *iface,
1271 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1272 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
1276 static HRESULT WINAPI domdoc_get_xml(
1277 IXMLDOMDocument3 *iface,
1280 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1282 TRACE("(%p)->(%p)\n", This, p);
1284 return node_get_xml(&This->node, TRUE, TRUE, p);
1288 static HRESULT WINAPI domdoc_transformNode(
1289 IXMLDOMDocument3 *iface,
1290 IXMLDOMNode* styleSheet,
1293 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1294 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), styleSheet, xmlString );
1298 static HRESULT WINAPI domdoc_selectNodes(
1299 IXMLDOMDocument3 *iface,
1301 IXMLDOMNodeList** resultList )
1303 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1304 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), queryString, resultList );
1308 static HRESULT WINAPI domdoc_selectSingleNode(
1309 IXMLDOMDocument3 *iface,
1311 IXMLDOMNode** resultNode )
1313 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1314 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), queryString, resultNode );
1318 static HRESULT WINAPI domdoc_get_parsed(
1319 IXMLDOMDocument3 *iface,
1320 VARIANT_BOOL* isParsed )
1322 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1323 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1324 *isParsed = VARIANT_TRUE;
1329 static HRESULT WINAPI domdoc_get_namespaceURI(
1330 IXMLDOMDocument3 *iface,
1331 BSTR* namespaceURI )
1333 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1334 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), namespaceURI );
1338 static HRESULT WINAPI domdoc_get_prefix(
1339 IXMLDOMDocument3 *iface,
1342 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1343 TRACE("(%p)->(%p)\n", This, prefix);
1344 return return_null_bstr( prefix );
1348 static HRESULT WINAPI domdoc_get_baseName(
1349 IXMLDOMDocument3 *iface,
1352 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1353 TRACE("(%p)->(%p)\n", This, name);
1354 return return_null_bstr( name );
1358 static HRESULT WINAPI domdoc_transformNodeToObject(
1359 IXMLDOMDocument3 *iface,
1360 IXMLDOMNode* stylesheet,
1361 VARIANT outputObject)
1363 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1364 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), stylesheet, outputObject );
1368 static HRESULT WINAPI domdoc_get_doctype(
1369 IXMLDOMDocument3 *iface,
1370 IXMLDOMDocumentType** documentType )
1372 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1373 FIXME("(%p)\n", This);
1378 static HRESULT WINAPI domdoc_get_implementation(
1379 IXMLDOMDocument3 *iface,
1380 IXMLDOMImplementation** impl )
1382 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1384 TRACE("(%p)->(%p)\n", This, impl);
1387 return E_INVALIDARG;
1389 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1394 static HRESULT WINAPI domdoc_get_documentElement(
1395 IXMLDOMDocument3 *iface,
1396 IXMLDOMElement** DOMElement )
1398 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1399 IXMLDOMNode *element_node;
1403 TRACE("(%p)->(%p)\n", This, DOMElement);
1406 return E_INVALIDARG;
1410 root = xmlDocGetRootElement( get_doc(This) );
1414 element_node = create_node( root );
1415 if(!element_node) return S_FALSE;
1417 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1418 IXMLDOMNode_Release(element_node);
1424 static HRESULT WINAPI domdoc_put_documentElement(
1425 IXMLDOMDocument3 *iface,
1426 IXMLDOMElement* DOMElement )
1428 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1429 IXMLDOMNode *elementNode;
1434 TRACE("(%p)->(%p)\n", This, DOMElement);
1436 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1440 xmlNode = get_node_obj( elementNode );
1442 FIXME("elementNode is not our object\n");
1446 if(!xmlNode->node->parent)
1447 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1448 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1450 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1451 IXMLDOMNode_Release( elementNode );
1454 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1460 static HRESULT WINAPI domdoc_createElement(
1461 IXMLDOMDocument3 *iface,
1463 IXMLDOMElement** element )
1465 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1470 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1472 if (!element || !tagname) return E_INVALIDARG;
1474 V_VT(&type) = VT_I1;
1475 V_I1(&type) = NODE_ELEMENT;
1477 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1480 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1481 IXMLDOMNode_Release(node);
1488 static HRESULT WINAPI domdoc_createDocumentFragment(
1489 IXMLDOMDocument3 *iface,
1490 IXMLDOMDocumentFragment** frag )
1492 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1497 TRACE("(%p)->(%p)\n", This, frag);
1499 if (!frag) return E_INVALIDARG;
1503 V_VT(&type) = VT_I1;
1504 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1506 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1509 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1510 IXMLDOMNode_Release(node);
1517 static HRESULT WINAPI domdoc_createTextNode(
1518 IXMLDOMDocument3 *iface,
1520 IXMLDOMText** text )
1522 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1527 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1529 if (!text) return E_INVALIDARG;
1533 V_VT(&type) = VT_I1;
1534 V_I1(&type) = NODE_TEXT;
1536 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1539 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1540 IXMLDOMNode_Release(node);
1541 hr = IXMLDOMText_put_data(*text, data);
1548 static HRESULT WINAPI domdoc_createComment(
1549 IXMLDOMDocument3 *iface,
1551 IXMLDOMComment** comment )
1553 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1558 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1560 if (!comment) return E_INVALIDARG;
1564 V_VT(&type) = VT_I1;
1565 V_I1(&type) = NODE_COMMENT;
1567 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1570 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1571 IXMLDOMNode_Release(node);
1572 hr = IXMLDOMComment_put_data(*comment, data);
1579 static HRESULT WINAPI domdoc_createCDATASection(
1580 IXMLDOMDocument3 *iface,
1582 IXMLDOMCDATASection** cdata )
1584 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1589 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1591 if (!cdata) return E_INVALIDARG;
1595 V_VT(&type) = VT_I1;
1596 V_I1(&type) = NODE_CDATA_SECTION;
1598 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1601 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1602 IXMLDOMNode_Release(node);
1603 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1610 static HRESULT WINAPI domdoc_createProcessingInstruction(
1611 IXMLDOMDocument3 *iface,
1614 IXMLDOMProcessingInstruction** pi )
1616 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1621 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1623 if (!pi) return E_INVALIDARG;
1627 V_VT(&type) = VT_I1;
1628 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1630 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1635 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1636 node_obj = get_node_obj(node);
1637 hr = node_set_content(node_obj, data);
1639 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1640 IXMLDOMNode_Release(node);
1647 static HRESULT WINAPI domdoc_createAttribute(
1648 IXMLDOMDocument3 *iface,
1650 IXMLDOMAttribute** attribute )
1652 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1657 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1659 if (!attribute || !name) return E_INVALIDARG;
1661 V_VT(&type) = VT_I1;
1662 V_I1(&type) = NODE_ATTRIBUTE;
1664 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1667 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1668 IXMLDOMNode_Release(node);
1675 static HRESULT WINAPI domdoc_createEntityReference(
1676 IXMLDOMDocument3 *iface,
1678 IXMLDOMEntityReference** entityref )
1680 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1685 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1687 if (!entityref) return E_INVALIDARG;
1691 V_VT(&type) = VT_I1;
1692 V_I1(&type) = NODE_ENTITY_REFERENCE;
1694 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1697 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1698 IXMLDOMNode_Release(node);
1705 static HRESULT WINAPI domdoc_getElementsByTagName(
1706 IXMLDOMDocument3 *iface,
1708 IXMLDOMNodeList** resultList )
1710 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1713 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagName), resultList);
1715 if (!tagName || !resultList) return E_INVALIDARG;
1717 if (tagName[0] == '*' && tagName[1] == 0)
1719 static const WCHAR formatallW[] = {'/','/','*',0};
1720 hr = queryresult_create((xmlNodePtr)get_doc(This), formatallW, resultList);
1724 static const WCHAR xpathformat[] =
1725 { '/','/','*','[','l','o','c','a','l','-','n','a','m','e','(',')','=','\'' };
1726 static const WCHAR closeW[] = { '\'',']',0 };
1732 length = lstrlenW(tagName);
1734 /* without two WCHARs from format specifier */
1735 ptr = pattern = heap_alloc(sizeof(xpathformat) + length*sizeof(WCHAR) + sizeof(closeW));
1737 memcpy(ptr, xpathformat, sizeof(xpathformat));
1738 ptr += sizeof(xpathformat)/sizeof(WCHAR);
1739 memcpy(ptr, tagName, length*sizeof(WCHAR));
1741 memcpy(ptr, closeW, sizeof(closeW));
1743 hr = queryresult_create((xmlNodePtr)get_doc(This), pattern, resultList);
1750 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1756 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1758 return E_INVALIDARG;
1765 static HRESULT WINAPI domdoc_createNode(
1766 IXMLDOMDocument3 *iface,
1770 IXMLDOMNode** node )
1772 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1773 DOMNodeType node_type;
1775 xmlChar *xml_name, *href;
1778 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1780 if(!node) return E_INVALIDARG;
1782 hr = get_node_type(Type, &node_type);
1783 if(FAILED(hr)) return hr;
1785 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1786 FIXME("nodes with namespaces currently not supported.\n");
1788 TRACE("node_type %d\n", node_type);
1790 /* exit earlier for types that need name */
1794 case NODE_ATTRIBUTE:
1795 case NODE_ENTITY_REFERENCE:
1796 case NODE_PROCESSING_INSTRUCTION:
1797 if (!name || *name == 0) return E_FAIL;
1802 xml_name = xmlChar_from_wchar(name);
1803 /* prevent empty href to be allocated */
1804 href = namespaceURI ? xmlChar_from_wchar(namespaceURI) : NULL;
1810 xmlChar *local, *prefix;
1812 local = xmlSplitQName2(xml_name, &prefix);
1814 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
1816 /* allow to create default namespace xmlns= */
1817 if (local || (href && *href))
1819 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
1820 xmlSetNs(xmlnode, ns);
1828 case NODE_ATTRIBUTE:
1829 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1832 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1834 case NODE_CDATA_SECTION:
1835 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1837 case NODE_ENTITY_REFERENCE:
1838 xmlnode = xmlNewReference(get_doc(This), xml_name);
1840 case NODE_PROCESSING_INSTRUCTION:
1841 #ifdef HAVE_XMLNEWDOCPI
1842 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1844 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1849 xmlnode = xmlNewDocComment(get_doc(This), NULL);
1851 case NODE_DOCUMENT_FRAGMENT:
1852 xmlnode = xmlNewDocFragment(get_doc(This));
1854 /* unsupported types */
1856 case NODE_DOCUMENT_TYPE:
1859 heap_free(xml_name);
1860 return E_INVALIDARG;
1862 FIXME("unhandled node type %d\n", node_type);
1867 *node = create_node(xmlnode);
1868 heap_free(xml_name);
1873 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1874 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1881 static HRESULT WINAPI domdoc_nodeFromID(
1882 IXMLDOMDocument3 *iface,
1884 IXMLDOMNode** node )
1886 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1887 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1891 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1896 xmldoc = doparse(This, ptr, len, NULL);
1898 xmldoc->_private = create_priv();
1899 return attach_xmldoc(This, xmldoc);
1905 static HRESULT doread( domdoc *This, LPWSTR filename )
1910 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1915 detach_bsc(This->bsc);
1921 static HRESULT WINAPI domdoc_load(
1922 IXMLDOMDocument3 *iface,
1924 VARIANT_BOOL* isSuccessful )
1926 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1927 LPWSTR filename = NULL;
1928 HRESULT hr = S_FALSE;
1929 IXMLDOMDocument3 *pNewDoc = NULL;
1930 IStream *pStream = NULL;
1933 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
1935 *isSuccessful = VARIANT_FALSE;
1937 assert( &This->node );
1939 switch( V_VT(&xmlSource) )
1942 filename = V_BSTR(&xmlSource);
1945 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
1950 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
1951 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1952 hr = attach_xmldoc(This, xmldoc);
1955 *isSuccessful = VARIANT_TRUE;
1960 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1963 IPersistStream *pDocStream;
1964 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1967 hr = IPersistStream_Load(pDocStream, pStream);
1968 IStream_Release(pStream);
1971 *isSuccessful = VARIANT_TRUE;
1973 TRACE("Using IStream to load Document\n");
1978 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1983 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1988 /* ISequentialStream */
1989 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1993 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1996 TRACE("filename (%s)\n", debugstr_w(filename));
2000 hr = doread( This, filename );
2003 This->error = E_FAIL;
2006 hr = This->error = S_OK;
2007 *isSuccessful = VARIANT_TRUE;
2011 if(!filename || FAILED(hr)) {
2012 xmldoc = xmlNewDoc(NULL);
2013 xmldoc->_private = create_priv();
2014 hr = attach_xmldoc(This, xmldoc);
2019 TRACE("ret (%d)\n", hr);
2025 static HRESULT WINAPI domdoc_get_readyState(
2026 IXMLDOMDocument3 *iface,
2029 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2030 FIXME("stub! (%p)->(%p)\n", This, value);
2033 return E_INVALIDARG;
2035 *value = READYSTATE_COMPLETE;
2040 static HRESULT WINAPI domdoc_get_parseError(
2041 IXMLDOMDocument3 *iface,
2042 IXMLDOMParseError** errorObj )
2044 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2045 static const WCHAR err[] = {'e','r','r','o','r',0};
2046 BSTR error_string = NULL;
2048 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2051 error_string = SysAllocString(err);
2053 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2054 if(!*errorObj) return E_OUTOFMEMORY;
2059 static HRESULT WINAPI domdoc_get_url(
2060 IXMLDOMDocument3 *iface,
2063 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2064 FIXME("(%p)->(%p)\n", This, urlString);
2069 static HRESULT WINAPI domdoc_get_async(
2070 IXMLDOMDocument3 *iface,
2071 VARIANT_BOOL* isAsync )
2073 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2075 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2076 *isAsync = This->async;
2081 static HRESULT WINAPI domdoc_put_async(
2082 IXMLDOMDocument3 *iface,
2083 VARIANT_BOOL isAsync )
2085 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2087 TRACE("(%p)->(%d)\n", This, isAsync);
2088 This->async = isAsync;
2093 static HRESULT WINAPI domdoc_abort(
2094 IXMLDOMDocument3 *iface )
2096 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2097 FIXME("%p\n", This);
2102 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
2107 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
2108 str = heap_alloc( len );
2111 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
2117 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2118 static HRESULT WINAPI domdoc_loadXML(
2119 IXMLDOMDocument3 *iface,
2121 VARIANT_BOOL* isSuccessful )
2123 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2124 static const xmlChar encoding[] = "UTF-8";
2125 xmlDocPtr xmldoc = NULL;
2126 HRESULT hr = S_FALSE, hr2;
2130 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2132 assert ( &This->node );
2136 *isSuccessful = VARIANT_FALSE;
2138 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
2140 xmldoc = doparse(This, str, len, encoding);
2144 This->error = E_FAIL;
2145 TRACE("failed to parse document\n");
2149 hr = This->error = S_OK;
2150 *isSuccessful = VARIANT_TRUE;
2151 TRACE("parsed document %p\n", xmldoc);
2156 xmldoc = xmlNewDoc(NULL);
2158 xmldoc->_private = create_priv();
2160 hr2 = attach_xmldoc(This, xmldoc);
2167 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2171 if(!WriteFile(ctx, buffer, len, &written, NULL))
2173 WARN("write error\n");
2180 static int XMLCALL domdoc_save_closecallback(void *ctx)
2182 return CloseHandle(ctx) ? 0 : -1;
2185 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2190 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2193 WARN("stream write error: 0x%08x\n", hr);
2200 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2202 IStream_Release((IStream*)ctx);
2206 static HRESULT WINAPI domdoc_save(
2207 IXMLDOMDocument3 *iface,
2208 VARIANT destination )
2210 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2211 xmlSaveCtxtPtr ctx = NULL;
2215 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
2216 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
2218 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
2220 FIXME("Unhandled vt %d\n", V_VT(&destination));
2224 if(V_VT(&destination) == VT_UNKNOWN)
2226 IUnknown *pUnk = V_UNKNOWN(&destination);
2227 IXMLDOMDocument2 *document;
2230 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2233 VARIANT_BOOL success;
2236 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2239 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2243 IXMLDOMDocument3_Release(document);
2247 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2250 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2251 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2255 IStream_Release(stream);
2262 /* save with file path */
2263 HANDLE handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
2264 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2265 if( handle == INVALID_HANDLE_VALUE )
2267 WARN("failed to create file\n");
2271 /* disable top XML declaration */
2272 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2273 handle, NULL, XML_SAVE_NO_DECL);
2276 CloseHandle(handle);
2281 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2282 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2283 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2285 /* will release resources through close callback */
2291 static HRESULT WINAPI domdoc_get_validateOnParse(
2292 IXMLDOMDocument3 *iface,
2293 VARIANT_BOOL* isValidating )
2295 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2296 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2297 *isValidating = This->validating;
2302 static HRESULT WINAPI domdoc_put_validateOnParse(
2303 IXMLDOMDocument3 *iface,
2304 VARIANT_BOOL isValidating )
2306 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2307 TRACE("(%p)->(%d)\n", This, isValidating);
2308 This->validating = isValidating;
2313 static HRESULT WINAPI domdoc_get_resolveExternals(
2314 IXMLDOMDocument3 *iface,
2315 VARIANT_BOOL* isResolving )
2317 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2318 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2319 *isResolving = This->resolving;
2324 static HRESULT WINAPI domdoc_put_resolveExternals(
2325 IXMLDOMDocument3 *iface,
2326 VARIANT_BOOL isResolving )
2328 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2329 TRACE("(%p)->(%d)\n", This, isResolving);
2330 This->resolving = isResolving;
2335 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2336 IXMLDOMDocument3 *iface,
2337 VARIANT_BOOL* isPreserving )
2339 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2340 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->properties->preserving);
2341 *isPreserving = This->properties->preserving;
2346 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2347 IXMLDOMDocument3 *iface,
2348 VARIANT_BOOL isPreserving )
2350 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2351 TRACE("(%p)->(%d)\n", This, isPreserving);
2352 This->properties->preserving = isPreserving;
2357 static HRESULT WINAPI domdoc_put_onReadyStateChange(
2358 IXMLDOMDocument3 *iface,
2359 VARIANT readyStateChangeSink )
2361 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2362 FIXME("%p\n", This);
2367 static HRESULT WINAPI domdoc_put_onDataAvailable(
2368 IXMLDOMDocument3 *iface,
2369 VARIANT onDataAvailableSink )
2371 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2372 FIXME("%p\n", This);
2376 static HRESULT WINAPI domdoc_put_onTransformNode(
2377 IXMLDOMDocument3 *iface,
2378 VARIANT onTransformNodeSink )
2380 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2381 FIXME("%p\n", This);
2385 static HRESULT WINAPI domdoc_get_namespaces(
2386 IXMLDOMDocument3* iface,
2387 IXMLDOMSchemaCollection** schemaCollection )
2389 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2390 FIXME("(%p)->(%p)\n", This, schemaCollection);
2394 static HRESULT WINAPI domdoc_get_schemas(
2395 IXMLDOMDocument3* iface,
2398 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2399 HRESULT hr = S_FALSE;
2400 IXMLDOMSchemaCollection2* cur_schema = This->schema;
2402 TRACE("(%p)->(%p)\n", This, var1);
2404 VariantInit(var1); /* Test shows we don't call VariantClear here */
2405 V_VT(var1) = VT_NULL;
2409 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2411 V_VT(var1) = VT_DISPATCH;
2416 static HRESULT WINAPI domdoc_putref_schemas(
2417 IXMLDOMDocument3* iface,
2420 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2421 HRESULT hr = E_FAIL;
2422 IXMLDOMSchemaCollection2* new_schema = NULL;
2424 FIXME("(%p): semi-stub\n", This);
2428 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2432 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2441 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2446 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
2447 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2453 static inline BOOL is_wellformed(xmlDocPtr doc)
2455 #ifdef HAVE_XMLDOC_PROPERTIES
2456 return doc->properties & XML_DOC_WELLFORMED;
2458 /* Not a full check, but catches the worst violations */
2462 for (child = doc->children; child != NULL; child = child->next)
2464 switch (child->type)
2466 case XML_ELEMENT_NODE:
2471 case XML_CDATA_SECTION_NODE:
2483 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2487 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2491 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2495 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2499 static HRESULT WINAPI domdoc_validateNode(
2500 IXMLDOMDocument3* iface,
2502 IXMLDOMParseError** err)
2504 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2505 LONG state, err_code = 0;
2509 TRACE("(%p)->(%p, %p)\n", This, node, err);
2510 domdoc_get_readyState(iface, &state);
2511 if (state != READYSTATE_COMPLETE)
2514 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2521 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2525 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2528 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2532 if (!is_wellformed(get_doc(This)))
2534 ERR("doc not well-formed");
2536 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2540 /* DTD validation */
2541 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2543 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2544 vctx->error = validate_error;
2545 vctx->warning = validate_warning;
2548 if (!((node == (IXMLDOMNode*)iface)?
2549 xmlValidateDocument(vctx, get_doc(This)) :
2550 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2552 /* TODO: get a real error code here */
2553 TRACE("DTD validation failed\n");
2554 err_code = E_XML_INVALID;
2557 xmlFreeValidCtxt(vctx);
2560 /* Schema validation */
2561 if (hr == S_OK && This->schema != NULL)
2564 hr = SchemaCache_validate_tree(This->schema, get_node_obj(node)->node);
2568 /* TODO: get a real error code here */
2569 TRACE("schema validation failed\n");
2571 err_code = E_XML_INVALID;
2575 /* not really OK, just didn't find a schema for the ns */
2582 TRACE("no DTD or schema found\n");
2583 err_code = E_XML_NODTD;
2588 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2593 static HRESULT WINAPI domdoc_validate(
2594 IXMLDOMDocument3* iface,
2595 IXMLDOMParseError** err)
2597 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2598 TRACE("(%p)->(%p)\n", This, err);
2599 return domdoc_validateNode(iface, (IXMLDOMNode*)iface, err);
2602 static HRESULT WINAPI domdoc_setProperty(
2603 IXMLDOMDocument3* iface,
2607 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2609 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2611 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2617 V_VT(&varStr) = VT_EMPTY;
2618 if (V_VT(&var) != VT_BSTR)
2620 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2622 bstr = V_BSTR(&varStr);
2625 bstr = V_BSTR(&var);
2628 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2629 This->properties->XPath = TRUE;
2630 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2631 This->properties->XPath = FALSE;
2635 VariantClear(&varStr);
2638 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2643 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2644 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2645 xmlXPathContextPtr ctx;
2646 struct list *pNsList;
2647 select_ns_entry* pNsEntry = NULL;
2649 V_VT(&varStr) = VT_EMPTY;
2650 if (V_VT(&var) != VT_BSTR)
2652 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2654 bstr = V_BSTR(&varStr);
2657 bstr = V_BSTR(&var);
2661 pNsList = &(This->properties->selectNsList);
2662 clear_selectNsList(pNsList);
2664 nsStr = xmlChar_from_wchar(bstr);
2667 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2669 This->properties->selectNsStr = nsStr;
2670 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2673 ctx = xmlXPathNewContext(This->node.node->doc);
2676 for (; *pTokBegin; pTokBegin = pTokEnd)
2678 if (pNsEntry != NULL)
2679 memset(pNsEntry, 0, sizeof(select_ns_entry));
2681 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2683 while (*pTokBegin == ' ')
2685 pTokEnd = pTokBegin;
2686 while (*pTokEnd != ' ' && *pTokEnd != 0)
2689 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2692 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2693 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2698 if (*pTokBegin == '=')
2700 /*valid for XSLPattern?*/
2701 FIXME("Setting default xmlns not supported - skipping.\n");
2702 pTokBegin = pTokEnd;
2705 else if (*pTokBegin == ':')
2707 pNsEntry->prefix = ++pTokBegin;
2708 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2711 if (pTokInner == pTokEnd)
2714 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2715 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2719 pNsEntry->prefix_end = *pTokInner;
2723 if (pTokEnd-pTokInner > 1 &&
2724 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2725 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2727 pNsEntry->href = ++pTokInner;
2728 pNsEntry->href_end = *(pTokEnd-1);
2730 list_add_tail(pNsList, &pNsEntry->entry);
2731 /*let libxml figure out if they're valid from here ;)*/
2732 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2741 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2742 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2743 list_add_tail(pNsList, &pNsEntry->entry);
2756 heap_free(pNsEntry);
2757 xmlXPathFreeContext(ctx);
2760 VariantClear(&varStr);
2763 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2764 lstrcmpiW(p, PropertyNewParserW) == 0)
2767 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2771 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2775 static HRESULT WINAPI domdoc_getProperty(
2776 IXMLDOMDocument3* iface,
2780 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2782 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2785 return E_INVALIDARG;
2787 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2789 V_VT(var) = VT_BSTR;
2790 V_BSTR(var) = This->properties->XPath ?
2791 SysAllocString(PropValueXPathW) :
2792 SysAllocString(PropValueXSLPatternW);
2793 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2795 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2798 BSTR rebuiltStr, cur;
2799 const xmlChar *nsStr;
2800 struct list *pNsList;
2801 select_ns_entry* pNsEntry;
2803 V_VT(var) = VT_BSTR;
2804 nsStr = This->properties->selectNsStr;
2805 pNsList = &This->properties->selectNsList;
2806 lenA = This->properties->selectNsStr_len;
2807 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
2808 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
2809 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
2811 /* this is fine because all of the chars that end tokens are ASCII*/
2812 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
2814 while (*cur != 0) ++cur;
2815 if (pNsEntry->prefix_end)
2817 *cur = pNsEntry->prefix_end;
2818 while (*cur != 0) ++cur;
2821 if (pNsEntry->href_end)
2823 *cur = pNsEntry->href_end;
2826 V_BSTR(var) = SysAllocString(rebuiltStr);
2827 heap_free(rebuiltStr);
2831 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2835 static HRESULT WINAPI domdoc_importNode(
2836 IXMLDOMDocument3* iface,
2839 IXMLDOMNode** clone)
2841 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2842 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
2846 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
2848 domdoc_QueryInterface,
2851 domdoc_GetTypeInfoCount,
2853 domdoc_GetIDsOfNames,
2855 domdoc_get_nodeName,
2856 domdoc_get_nodeValue,
2857 domdoc_put_nodeValue,
2858 domdoc_get_nodeType,
2859 domdoc_get_parentNode,
2860 domdoc_get_childNodes,
2861 domdoc_get_firstChild,
2862 domdoc_get_lastChild,
2863 domdoc_get_previousSibling,
2864 domdoc_get_nextSibling,
2865 domdoc_get_attributes,
2866 domdoc_insertBefore,
2867 domdoc_replaceChild,
2870 domdoc_hasChildNodes,
2871 domdoc_get_ownerDocument,
2873 domdoc_get_nodeTypeString,
2876 domdoc_get_specified,
2877 domdoc_get_definition,
2878 domdoc_get_nodeTypedValue,
2879 domdoc_put_nodeTypedValue,
2880 domdoc_get_dataType,
2881 domdoc_put_dataType,
2883 domdoc_transformNode,
2885 domdoc_selectSingleNode,
2887 domdoc_get_namespaceURI,
2889 domdoc_get_baseName,
2890 domdoc_transformNodeToObject,
2892 domdoc_get_implementation,
2893 domdoc_get_documentElement,
2894 domdoc_put_documentElement,
2895 domdoc_createElement,
2896 domdoc_createDocumentFragment,
2897 domdoc_createTextNode,
2898 domdoc_createComment,
2899 domdoc_createCDATASection,
2900 domdoc_createProcessingInstruction,
2901 domdoc_createAttribute,
2902 domdoc_createEntityReference,
2903 domdoc_getElementsByTagName,
2907 domdoc_get_readyState,
2908 domdoc_get_parseError,
2915 domdoc_get_validateOnParse,
2916 domdoc_put_validateOnParse,
2917 domdoc_get_resolveExternals,
2918 domdoc_put_resolveExternals,
2919 domdoc_get_preserveWhiteSpace,
2920 domdoc_put_preserveWhiteSpace,
2921 domdoc_put_onReadyStateChange,
2922 domdoc_put_onDataAvailable,
2923 domdoc_put_onTransformNode,
2924 domdoc_get_namespaces,
2926 domdoc_putref_schemas,
2930 domdoc_validateNode,
2934 /* IConnectionPointContainer */
2935 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
2936 REFIID riid, void **ppv)
2938 domdoc *This = impl_from_IConnectionPointContainer(iface);
2939 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)This, riid, ppv);
2942 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
2944 domdoc *This = impl_from_IConnectionPointContainer(iface);
2945 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)This);
2948 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
2950 domdoc *This = impl_from_IConnectionPointContainer(iface);
2951 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)This);
2954 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
2955 IEnumConnectionPoints **ppEnum)
2957 domdoc *This = impl_from_IConnectionPointContainer(iface);
2958 FIXME("(%p)->(%p): stub\n", This, ppEnum);
2962 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
2963 REFIID riid, IConnectionPoint **cp)
2965 domdoc *This = impl_from_IConnectionPointContainer(iface);
2966 ConnectionPoint *iter;
2968 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
2972 for(iter = This->cp_list; iter; iter = iter->next)
2974 if (IsEqualGUID(iter->iid, riid))
2975 *cp = (IConnectionPoint*)&iter->lpVtblConnectionPoint;
2980 IConnectionPoint_AddRef(*cp);
2984 FIXME("unsupported riid %s\n", debugstr_guid(riid));
2985 return CONNECT_E_NOCONNECTION;
2989 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
2991 ConnectionPointContainer_QueryInterface,
2992 ConnectionPointContainer_AddRef,
2993 ConnectionPointContainer_Release,
2994 ConnectionPointContainer_EnumConnectionPoints,
2995 ConnectionPointContainer_FindConnectionPoint
2998 /* IConnectionPoint */
2999 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
3000 REFIID riid, void **ppv)
3002 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3004 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3008 if (IsEqualGUID(&IID_IUnknown, riid) ||
3009 IsEqualGUID(&IID_IConnectionPoint, riid))
3016 IConnectionPoint_AddRef(iface);
3020 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3021 return E_NOINTERFACE;
3024 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3026 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3027 return IConnectionPointContainer_AddRef(This->container);
3030 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3032 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3033 return IConnectionPointContainer_Release(This->container);
3036 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3038 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3040 TRACE("(%p)->(%p)\n", This, iid);
3042 if (!iid) return E_POINTER;
3048 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3049 IConnectionPointContainer **container)
3051 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3053 TRACE("(%p)->(%p)\n", This, container);
3055 if (!container) return E_POINTER;
3057 *container = This->container;
3058 IConnectionPointContainer_AddRef(*container);
3062 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
3065 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3066 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
3070 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3072 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3074 TRACE("(%p)->(%d)\n", This, cookie);
3076 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3077 return CONNECT_E_NOCONNECTION;
3079 IUnknown_Release(This->sinks[cookie-1].unk);
3080 This->sinks[cookie-1].unk = NULL;
3085 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3086 IEnumConnections **ppEnum)
3088 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3089 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3093 static const IConnectionPointVtbl ConnectionPointVtbl =
3095 ConnectionPoint_QueryInterface,
3096 ConnectionPoint_AddRef,
3097 ConnectionPoint_Release,
3098 ConnectionPoint_GetConnectionInterface,
3099 ConnectionPoint_GetConnectionPointContainer,
3100 ConnectionPoint_Advise,
3101 ConnectionPoint_Unadvise,
3102 ConnectionPoint_EnumConnections
3105 void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3107 cp->lpVtblConnectionPoint = &ConnectionPointVtbl;
3113 cp->next = doc->cp_list;
3116 cp->container = (IConnectionPointContainer*)&doc->lpVtblConnectionPointContainer;
3119 /* domdoc implementation of IObjectWithSite */
3120 static HRESULT WINAPI
3121 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3123 domdoc *This = impl_from_IObjectWithSite(iface);
3124 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppvObject );
3127 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3129 domdoc *This = impl_from_IObjectWithSite(iface);
3130 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3133 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3135 domdoc *This = impl_from_IObjectWithSite(iface);
3136 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3139 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3141 domdoc *This = impl_from_IObjectWithSite(iface);
3143 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3148 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3151 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3153 domdoc *This = impl_from_IObjectWithSite(iface);
3155 TRACE("(%p)->(%p)\n", iface, punk);
3161 IUnknown_Release( This->site );
3168 IUnknown_AddRef( punk );
3171 IUnknown_Release( This->site );
3178 static const IObjectWithSiteVtbl domdocObjectSite =
3180 domdoc_ObjectWithSite_QueryInterface,
3181 domdoc_ObjectWithSite_AddRef,
3182 domdoc_ObjectWithSite_Release,
3183 domdoc_ObjectWithSite_SetSite,
3184 domdoc_ObjectWithSite_GetSite
3187 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3189 domdoc *This = impl_from_IObjectSafety(iface);
3190 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppv );
3193 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3195 domdoc *This = impl_from_IObjectSafety(iface);
3196 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3199 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3201 domdoc *This = impl_from_IObjectSafety(iface);
3202 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3205 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3207 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3208 DWORD *supported, DWORD *enabled)
3210 domdoc *This = impl_from_IObjectSafety(iface);
3212 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3214 if(!supported || !enabled) return E_POINTER;
3216 *supported = SAFETY_SUPPORTED_OPTIONS;
3217 *enabled = This->safeopt;
3222 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3223 DWORD mask, DWORD enabled)
3225 domdoc *This = impl_from_IObjectSafety(iface);
3226 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3228 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3231 This->safeopt = enabled & mask & SAFETY_SUPPORTED_OPTIONS;
3235 #undef SAFETY_SUPPORTED_OPTIONS
3237 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3238 domdoc_Safety_QueryInterface,
3239 domdoc_Safety_AddRef,
3240 domdoc_Safety_Release,
3241 domdoc_Safety_GetInterfaceSafetyOptions,
3242 domdoc_Safety_SetInterfaceSafetyOptions
3245 static const tid_t domdoc_iface_tids[] = {
3247 IXMLDOMDocument_tid,
3248 IXMLDOMDocument2_tid,
3251 static dispex_static_data_t domdoc_dispex = {
3253 IXMLDOMDocument2_tid,
3258 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3262 doc = heap_alloc( sizeof (*doc) );
3264 return E_OUTOFMEMORY;
3266 doc->lpVtbl = &domdoc_vtbl;
3267 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
3268 doc->lpvtblIObjectWithSite = &domdocObjectSite;
3269 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
3270 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
3271 doc->lpVtblConnectionPointContainer = &ConnectionPointContainerVtbl;
3273 doc->async = VARIANT_TRUE;
3274 doc->validating = 0;
3276 doc->properties = properties_from_xmlDocPtr(xmldoc);
3283 doc->cp_list = NULL;
3285 /* events connection points */
3286 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3287 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3288 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3290 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->lpVtbl, &domdoc_dispex);
3292 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
3294 TRACE("returning iface %p\n", *document);
3298 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3303 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
3305 xmldoc = xmlNewDoc(NULL);
3307 return E_OUTOFMEMORY;
3309 xmldoc->_private = create_priv();
3310 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
3312 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3315 free_properties(properties_from_xmlDocPtr(xmldoc));
3316 heap_free(xmldoc->_private);
3324 IUnknown* create_domdoc( xmlNodePtr document )
3329 TRACE("(%p)\n", document);
3331 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3340 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3342 MESSAGE("This program tried to use a DOMDocument object, but\n"
3343 "libxml2 support was not present at compile time.\n");