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 struct list selectNsList;
78 xmlChar const* selectNsStr;
83 typedef struct ConnectionPoint ConnectionPoint;
84 typedef struct domdoc domdoc;
86 struct ConnectionPoint
88 const IConnectionPointVtbl *lpVtblConnectionPoint;
91 ConnectionPoint *next;
92 IConnectionPointContainer *container;
99 IPropertyNotifySink *propnotif;
107 const struct IXMLDOMDocument3Vtbl *lpVtbl;
108 const struct IPersistStreamInitVtbl *lpvtblIPersistStreamInit;
109 const struct IObjectWithSiteVtbl *lpvtblIObjectWithSite;
110 const struct IObjectSafetyVtbl *lpvtblIObjectSafety;
111 const struct ISupportErrorInfoVtbl *lpvtblISupportErrorInfo;
112 const struct IConnectionPointContainerVtbl *lpVtblConnectionPointContainer;
115 VARIANT_BOOL validating;
116 VARIANT_BOOL resolving;
117 VARIANT_BOOL preserving;
118 domdoc_properties* properties;
119 IXMLDOMSchemaCollection *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->selectNsStr = heap_alloc_zero(sizeof(xmlChar));
248 properties->selectNsStr_len = 0;
249 properties->XPath = FALSE;
251 /* properties that are dependent on object versions */
252 if (IsEqualCLSID( clsid, &CLSID_DOMDocument40 ) ||
253 IsEqualCLSID( clsid, &CLSID_DOMDocument60 ))
255 properties->XPath = TRUE;
261 static domdoc_properties* copy_properties(domdoc_properties const* properties)
263 domdoc_properties* pcopy = heap_alloc(sizeof(domdoc_properties));
264 select_ns_entry const* ns = NULL;
265 select_ns_entry* new_ns = NULL;
266 int len = (properties->selectNsStr_len+1)*sizeof(xmlChar);
271 pcopy->XPath = properties->XPath;
272 pcopy->selectNsStr_len = properties->selectNsStr_len;
273 list_init( &pcopy->selectNsList );
274 pcopy->selectNsStr = heap_alloc(len);
275 memcpy((xmlChar*)pcopy->selectNsStr, properties->selectNsStr, len);
276 offset = pcopy->selectNsStr - properties->selectNsStr;
278 LIST_FOR_EACH_ENTRY( ns, (&properties->selectNsList), select_ns_entry, entry )
280 new_ns = heap_alloc(sizeof(select_ns_entry));
281 memcpy(new_ns, ns, sizeof(select_ns_entry));
282 new_ns->href += offset;
283 new_ns->prefix += offset;
284 list_add_tail(&pcopy->selectNsList, &new_ns->entry);
292 static void free_properties(domdoc_properties* properties)
296 clear_selectNsList(&properties->selectNsList);
297 heap_free((xmlChar*)properties->selectNsStr);
298 heap_free(properties);
302 /* links a "<?xml" node as a first child */
303 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
306 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
309 /* unlinks a first "<?xml" child if it was created */
310 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
316 if (doc->standalone != -1)
318 node = doc->children;
319 xmlUnlinkNode( node );
327 static inline BOOL strn_isspace(xmlChar const* str, int len)
329 for (; str && len > 0 && *str; ++str, --len)
336 static void sax_characters(void *ctx, const xmlChar *ch, int len)
338 xmlParserCtxtPtr pctx;
341 pctx = (xmlParserCtxtPtr) ctx;
342 This = (domdoc const*) pctx->_private;
344 if (!This->preserving)
346 xmlChar* ws = xmlGetNsProp(pctx->node, BAD_CAST "space", XML_XML_NAMESPACE);
347 if ((!ws || xmlStrcmp(ws, BAD_CAST "preserve") != 0) &&
348 strn_isspace(ch, len))
356 xmlSAX2Characters(ctx, ch, len);
359 static void LIBXML2_LOG_CALLBACK sax_error(void* ctx, char const* msg, ...)
363 LIBXML2_CALLBACK_ERR(doparse, msg, ap);
367 static void LIBXML2_LOG_CALLBACK sax_warning(void* ctx, char const* msg, ...)
371 LIBXML2_CALLBACK_WARN(doparse, msg, ap);
375 static void sax_serror(void* ctx, xmlErrorPtr err)
377 LIBXML2_CALLBACK_SERROR(doparse, err);
380 static xmlDocPtr doparse(domdoc* This, char *ptr, int len, xmlChar const* encoding)
382 xmlDocPtr doc = NULL;
383 xmlParserCtxtPtr pctx;
384 static xmlSAXHandler sax_handler = {
385 xmlSAX2InternalSubset, /* internalSubset */
386 xmlSAX2IsStandalone, /* isStandalone */
387 xmlSAX2HasInternalSubset, /* hasInternalSubset */
388 xmlSAX2HasExternalSubset, /* hasExternalSubset */
389 xmlSAX2ResolveEntity, /* resolveEntity */
390 xmlSAX2GetEntity, /* getEntity */
391 xmlSAX2EntityDecl, /* entityDecl */
392 xmlSAX2NotationDecl, /* notationDecl */
393 xmlSAX2AttributeDecl, /* attributeDecl */
394 xmlSAX2ElementDecl, /* elementDecl */
395 xmlSAX2UnparsedEntityDecl, /* unparsedEntityDecl */
396 xmlSAX2SetDocumentLocator, /* setDocumentLocator */
397 xmlSAX2StartDocument, /* startDocument */
398 xmlSAX2EndDocument, /* endDocument */
399 xmlSAX2StartElement, /* startElement */
400 xmlSAX2EndElement, /* endElement */
401 xmlSAX2Reference, /* reference */
402 sax_characters, /* characters */
403 sax_characters, /* ignorableWhitespace */
404 xmlSAX2ProcessingInstruction, /* processingInstruction */
405 xmlSAX2Comment, /* comment */
406 sax_warning, /* warning */
407 sax_error, /* error */
408 sax_error, /* fatalError */
409 xmlSAX2GetParameterEntity, /* getParameterEntity */
410 xmlSAX2CDataBlock, /* cdataBlock */
411 xmlSAX2ExternalSubset, /* externalSubset */
414 xmlSAX2StartElementNs, /* startElementNs */
415 xmlSAX2EndElementNs, /* endElementNs */
416 sax_serror /* serror */
420 pctx = xmlCreateMemoryParserCtxt(ptr, len);
423 ERR("Failed to create parser context\n");
427 if (pctx->sax) xmlFree(pctx->sax);
428 pctx->sax = &sax_handler;
429 pctx->_private = This;
431 pctx->encoding = xmlStrdup(encoding);
432 xmlParseDocument(pctx);
434 if (pctx->wellFormed)
440 xmlFreeDoc(pctx->myDoc);
444 xmlFreeParserCtxt(pctx);
446 /* TODO: put this in one of the SAX callbacks */
447 /* create first child as a <?xml...?> */
448 if (doc && doc->standalone != -1)
452 xmlChar *xmlbuff = (xmlChar*)buff;
454 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
456 /* version attribute can't be omitted */
457 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
458 xmlNodeAddContent( node, xmlbuff );
462 sprintf(buff, " encoding=\"%s\"", doc->encoding);
463 xmlNodeAddContent( node, xmlbuff );
466 if (doc->standalone != -2)
468 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
469 xmlNodeAddContent( node, xmlbuff );
472 xmldoc_link_xmldecl( doc, node );
478 void xmldoc_init(xmlDocPtr doc, const GUID *clsid)
480 doc->_private = create_priv();
481 priv_from_xmlDocPtr(doc)->properties = create_properties(clsid);
484 LONG xmldoc_add_ref(xmlDocPtr doc)
486 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
487 TRACE("(%p)->(%d)\n", doc, ref);
491 LONG xmldoc_release(xmlDocPtr doc)
493 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
494 LONG ref = InterlockedDecrement(&priv->refs);
495 TRACE("(%p)->(%d)\n", doc, ref);
498 orphan_entry *orphan, *orphan2;
499 TRACE("freeing docptr %p\n", doc);
501 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
503 xmlFreeNode( orphan->node );
506 free_properties(priv->properties);
507 heap_free(doc->_private);
515 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
517 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
520 entry = heap_alloc( sizeof (*entry) );
522 return E_OUTOFMEMORY;
525 list_add_head( &priv->orphans, &entry->entry );
529 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
531 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
532 orphan_entry *entry, *entry2;
534 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
536 if( entry->node == node )
538 list_remove( &entry->entry );
547 static inline xmlDocPtr get_doc( domdoc *This )
549 return (xmlDocPtr)This->node.node;
552 static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
556 priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
557 if (xmldoc_release(get_doc(This)) != 0)
558 priv_from_xmlDocPtr(get_doc(This))->properties =
559 copy_properties(This->properties);
562 This->node.node = (xmlNodePtr) xml;
566 xmldoc_add_ref(get_doc(This));
567 priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
573 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
575 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
578 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
580 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStreamInit));
583 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
585 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
588 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
590 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
593 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
595 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblISupportErrorInfo));
598 static inline domdoc *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
600 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtblConnectionPointContainer));
603 /************************************************************************
604 * domdoc implementation of IPersistStream.
606 static HRESULT WINAPI domdoc_IPersistStreamInit_QueryInterface(
607 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
609 domdoc *this = impl_from_IPersistStreamInit(iface);
610 return IXMLDOMDocument2_QueryInterface((IXMLDOMDocument2 *)this, riid, ppvObj);
613 static ULONG WINAPI domdoc_IPersistStreamInit_AddRef(
614 IPersistStreamInit *iface)
616 domdoc *this = impl_from_IPersistStreamInit(iface);
617 return IXMLDOMDocument2_AddRef((IXMLDOMDocument2 *)this);
620 static ULONG WINAPI domdoc_IPersistStreamInit_Release(
621 IPersistStreamInit *iface)
623 domdoc *this = impl_from_IPersistStreamInit(iface);
624 return IXMLDOMDocument2_Release((IXMLDOMDocument2 *)this);
627 static HRESULT WINAPI domdoc_IPersistStreamInit_GetClassID(
628 IPersistStreamInit *iface, CLSID *classid)
630 TRACE("(%p,%p): stub!\n", iface, classid);
635 *classid = CLSID_DOMDocument2;
640 static HRESULT WINAPI domdoc_IPersistStreamInit_IsDirty(
641 IPersistStreamInit *iface)
643 domdoc *This = impl_from_IPersistStreamInit(iface);
644 FIXME("(%p): stub!\n", This);
648 static HRESULT WINAPI domdoc_IPersistStreamInit_Load(
649 IPersistStreamInit *iface, LPSTREAM pStm)
651 domdoc *This = impl_from_IPersistStreamInit(iface);
654 DWORD read, written, len;
657 xmlDocPtr xmldoc = NULL;
659 TRACE("(%p)->(%p)\n", This, pStm);
664 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
670 IStream_Read(pStm, buf, sizeof(buf), &read);
671 hr = IStream_Write(This->stream, buf, read, &written);
672 } while(SUCCEEDED(hr) && written != 0 && read != 0);
676 ERR("Failed to copy stream\n");
680 hr = GetHGlobalFromStream(This->stream, &hglobal);
684 len = GlobalSize(hglobal);
685 ptr = GlobalLock(hglobal);
687 xmldoc = doparse(This, ptr, len, NULL);
688 GlobalUnlock(hglobal);
692 ERR("Failed to parse xml\n");
696 xmldoc->_private = create_priv();
698 return attach_xmldoc(This, xmldoc);
701 static HRESULT WINAPI domdoc_IPersistStreamInit_Save(
702 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
704 domdoc *This = impl_from_IPersistStreamInit(iface);
708 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
710 hr = IXMLDOMDocument3_get_xml( (IXMLDOMDocument3*)&This->lpVtbl, &xmlString );
713 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
715 hr = IStream_Write( stream, xmlString, len, NULL );
716 SysFreeString(xmlString);
719 TRACE("ret 0x%08x\n", hr);
724 static HRESULT WINAPI domdoc_IPersistStreamInit_GetSizeMax(
725 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
727 domdoc *This = impl_from_IPersistStreamInit(iface);
728 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
732 static HRESULT WINAPI domdoc_IPersistStreamInit_InitNew(
733 IPersistStreamInit *iface)
735 domdoc *This = impl_from_IPersistStreamInit(iface);
736 TRACE("(%p)\n", This);
740 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
742 domdoc_IPersistStreamInit_QueryInterface,
743 domdoc_IPersistStreamInit_AddRef,
744 domdoc_IPersistStreamInit_Release,
745 domdoc_IPersistStreamInit_GetClassID,
746 domdoc_IPersistStreamInit_IsDirty,
747 domdoc_IPersistStreamInit_Load,
748 domdoc_IPersistStreamInit_Save,
749 domdoc_IPersistStreamInit_GetSizeMax,
750 domdoc_IPersistStreamInit_InitNew
753 /* ISupportErrorInfo interface */
754 static HRESULT WINAPI support_error_QueryInterface(
755 ISupportErrorInfo *iface,
756 REFIID riid, void** ppvObj )
758 domdoc *This = impl_from_ISupportErrorInfo(iface);
759 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3 *)This, riid, ppvObj);
762 static ULONG WINAPI support_error_AddRef(
763 ISupportErrorInfo *iface )
765 domdoc *This = impl_from_ISupportErrorInfo(iface);
766 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
769 static ULONG WINAPI support_error_Release(
770 ISupportErrorInfo *iface )
772 domdoc *This = impl_from_ISupportErrorInfo(iface);
773 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
776 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
777 ISupportErrorInfo *iface,
780 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
784 static const struct ISupportErrorInfoVtbl support_error_vtbl =
786 support_error_QueryInterface,
787 support_error_AddRef,
788 support_error_Release,
789 support_error_InterfaceSupportsErrorInfo
792 /* IXMLDOMDocument2 interface */
793 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
795 domdoc *This = impl_from_IXMLDOMDocument3( iface );
797 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
801 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
802 IsEqualGUID( riid, &IID_IDispatch ) ||
803 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
804 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
805 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
806 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
810 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
811 IsEqualGUID(&IID_IPersistStreamInit, riid))
813 *ppvObject = &(This->lpvtblIPersistStreamInit);
815 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
817 *ppvObject = &(This->lpvtblIObjectWithSite);
819 else if (IsEqualGUID(&IID_IObjectSafety, riid))
821 *ppvObject = &(This->lpvtblIObjectSafety);
823 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
825 *ppvObject = &This->lpvtblISupportErrorInfo;
827 else if(node_query_interface(&This->node, riid, ppvObject))
829 return *ppvObject ? S_OK : E_NOINTERFACE;
831 else if (IsEqualGUID( riid, &IID_IConnectionPointContainer ))
833 *ppvObject = &This->lpVtblConnectionPointContainer;
835 else if(IsEqualGUID(&IID_IRunnableObject, riid))
837 TRACE("IID_IRunnableObject not supported returning NULL\n");
838 return E_NOINTERFACE;
842 FIXME("interface %s not implemented\n", debugstr_guid(riid));
843 return E_NOINTERFACE;
846 IUnknown_AddRef((IUnknown*)*ppvObject);
852 static ULONG WINAPI domdoc_AddRef(
853 IXMLDOMDocument3 *iface )
855 domdoc *This = impl_from_IXMLDOMDocument3( iface );
856 TRACE("%p\n", This );
857 return InterlockedIncrement( &This->ref );
861 static ULONG WINAPI domdoc_Release(
862 IXMLDOMDocument3 *iface )
864 domdoc *This = impl_from_IXMLDOMDocument3( iface );
867 TRACE("%p\n", This );
869 ref = InterlockedDecrement( &This->ref );
873 detach_bsc(This->bsc);
876 IUnknown_Release( This->site );
877 destroy_xmlnode(&This->node);
878 if(This->schema) IXMLDOMSchemaCollection_Release( This->schema );
879 if (This->stream) IStream_Release(This->stream);
880 HeapFree( GetProcessHeap(), 0, This );
886 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
888 domdoc *This = impl_from_IXMLDOMDocument3( iface );
890 TRACE("(%p)->(%p)\n", This, pctinfo);
897 static HRESULT WINAPI domdoc_GetTypeInfo(
898 IXMLDOMDocument3 *iface,
899 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
901 domdoc *This = impl_from_IXMLDOMDocument3( iface );
904 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
906 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
911 static HRESULT WINAPI domdoc_GetIDsOfNames(
912 IXMLDOMDocument3 *iface,
919 domdoc *This = impl_from_IXMLDOMDocument3( iface );
923 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
926 if(!rgszNames || cNames == 0 || !rgDispId)
929 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
932 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
933 ITypeInfo_Release(typeinfo);
940 static HRESULT WINAPI domdoc_Invoke(
941 IXMLDOMDocument3 *iface,
946 DISPPARAMS* pDispParams,
948 EXCEPINFO* pExcepInfo,
951 domdoc *This = impl_from_IXMLDOMDocument3( iface );
955 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
956 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
958 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
961 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
962 pVarResult, pExcepInfo, puArgErr);
963 ITypeInfo_Release(typeinfo);
970 static HRESULT WINAPI domdoc_get_nodeName(
971 IXMLDOMDocument3 *iface,
974 domdoc *This = impl_from_IXMLDOMDocument3( iface );
976 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
978 TRACE("(%p)->(%p)\n", This, name);
980 return return_bstr(documentW, name);
984 static HRESULT WINAPI domdoc_get_nodeValue(
985 IXMLDOMDocument3 *iface,
988 domdoc *This = impl_from_IXMLDOMDocument3( iface );
990 TRACE("(%p)->(%p)\n", This, value);
995 V_VT(value) = VT_NULL;
996 V_BSTR(value) = NULL; /* tests show that we should do this */
1001 static HRESULT WINAPI domdoc_put_nodeValue(
1002 IXMLDOMDocument3 *iface,
1005 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1006 FIXME("(%p)->(v%d)\n", This, V_VT(&value));
1011 static HRESULT WINAPI domdoc_get_nodeType(
1012 IXMLDOMDocument3 *iface,
1015 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1017 TRACE("(%p)->(%p)\n", This, type);
1019 *type = NODE_DOCUMENT;
1024 static HRESULT WINAPI domdoc_get_parentNode(
1025 IXMLDOMDocument3 *iface,
1026 IXMLDOMNode** parent )
1028 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1030 TRACE("(%p)->(%p)\n", This, parent);
1032 return node_get_parent(&This->node, parent);
1036 static HRESULT WINAPI domdoc_get_childNodes(
1037 IXMLDOMDocument3 *iface,
1038 IXMLDOMNodeList** childList )
1040 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1042 TRACE("(%p)->(%p)\n", This, childList);
1044 return node_get_child_nodes(&This->node, childList);
1048 static HRESULT WINAPI domdoc_get_firstChild(
1049 IXMLDOMDocument3 *iface,
1050 IXMLDOMNode** firstChild )
1052 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1054 TRACE("(%p)->(%p)\n", This, firstChild);
1056 return node_get_first_child(&This->node, firstChild);
1060 static HRESULT WINAPI domdoc_get_lastChild(
1061 IXMLDOMDocument3 *iface,
1062 IXMLDOMNode** lastChild )
1064 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1066 TRACE("(%p)->(%p)\n", This, lastChild);
1068 return node_get_last_child(&This->node, lastChild);
1072 static HRESULT WINAPI domdoc_get_previousSibling(
1073 IXMLDOMDocument3 *iface,
1074 IXMLDOMNode** previousSibling )
1076 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1078 TRACE("(%p)->(%p)\n", This, previousSibling);
1080 return return_null_node(previousSibling);
1084 static HRESULT WINAPI domdoc_get_nextSibling(
1085 IXMLDOMDocument3 *iface,
1086 IXMLDOMNode** nextSibling )
1088 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1090 TRACE("(%p)->(%p)\n", This, nextSibling);
1092 return return_null_node(nextSibling);
1096 static HRESULT WINAPI domdoc_get_attributes(
1097 IXMLDOMDocument3 *iface,
1098 IXMLDOMNamedNodeMap** attributeMap )
1100 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1102 TRACE("(%p)->(%p)\n", This, attributeMap);
1104 return return_null_ptr((void**)attributeMap);
1108 static HRESULT WINAPI domdoc_insertBefore(
1109 IXMLDOMDocument3 *iface,
1110 IXMLDOMNode* newChild,
1112 IXMLDOMNode** outNewChild )
1114 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1116 TRACE("(%p)->(%p x%d %p)\n", This, newChild, V_VT(&refChild), outNewChild);
1118 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1122 static HRESULT WINAPI domdoc_replaceChild(
1123 IXMLDOMDocument3 *iface,
1124 IXMLDOMNode* newChild,
1125 IXMLDOMNode* oldChild,
1126 IXMLDOMNode** outOldChild)
1128 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1130 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1132 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1136 static HRESULT WINAPI domdoc_removeChild(
1137 IXMLDOMDocument3 *iface,
1138 IXMLDOMNode* childNode,
1139 IXMLDOMNode** oldChild)
1141 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1142 return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), childNode, oldChild );
1146 static HRESULT WINAPI domdoc_appendChild(
1147 IXMLDOMDocument3 *iface,
1148 IXMLDOMNode* newChild,
1149 IXMLDOMNode** outNewChild)
1151 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1152 return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newChild, outNewChild );
1156 static HRESULT WINAPI domdoc_hasChildNodes(
1157 IXMLDOMDocument3 *iface,
1158 VARIANT_BOOL* hasChild)
1160 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1161 return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), hasChild );
1165 static HRESULT WINAPI domdoc_get_ownerDocument(
1166 IXMLDOMDocument3 *iface,
1167 IXMLDOMDocument** DOMDocument)
1169 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1170 return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), DOMDocument );
1174 static HRESULT WINAPI domdoc_cloneNode(
1175 IXMLDOMDocument3 *iface,
1177 IXMLDOMNode** outNode)
1179 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1180 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
1181 return node_clone( &This->node, deep, outNode );
1185 static HRESULT WINAPI domdoc_get_nodeTypeString(
1186 IXMLDOMDocument3 *iface,
1189 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1190 return IXMLDOMNode_get_nodeTypeString( IXMLDOMNode_from_impl(&This->node), nodeType );
1194 static HRESULT WINAPI domdoc_get_text(
1195 IXMLDOMDocument3 *iface,
1198 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1199 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), text );
1203 static HRESULT WINAPI domdoc_put_text(
1204 IXMLDOMDocument3 *iface,
1207 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1208 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1213 static HRESULT WINAPI domdoc_get_specified(
1214 IXMLDOMDocument3 *iface,
1215 VARIANT_BOOL* isSpecified )
1217 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1218 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1219 *isSpecified = VARIANT_TRUE;
1224 static HRESULT WINAPI domdoc_get_definition(
1225 IXMLDOMDocument3 *iface,
1226 IXMLDOMNode** definitionNode )
1228 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1229 FIXME("(%p)->(%p)\n", This, definitionNode);
1234 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1235 IXMLDOMDocument3 *iface,
1236 VARIANT* typedValue )
1238 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1239 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
1242 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1243 IXMLDOMDocument3 *iface,
1244 VARIANT typedValue )
1246 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1247 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
1251 static HRESULT WINAPI domdoc_get_dataType(
1252 IXMLDOMDocument3 *iface,
1255 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1256 TRACE("(%p)->(%p)\n", This, typename);
1257 return return_null_var( typename );
1261 static HRESULT WINAPI domdoc_put_dataType(
1262 IXMLDOMDocument3 *iface,
1265 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1266 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
1270 static HRESULT WINAPI domdoc_get_xml(
1271 IXMLDOMDocument3 *iface,
1274 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1276 TRACE("(%p)->(%p)\n", This, p);
1278 return node_get_xml(&This->node, TRUE, TRUE, p);
1282 static HRESULT WINAPI domdoc_transformNode(
1283 IXMLDOMDocument3 *iface,
1284 IXMLDOMNode* styleSheet,
1287 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1288 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), styleSheet, xmlString );
1292 static HRESULT WINAPI domdoc_selectNodes(
1293 IXMLDOMDocument3 *iface,
1295 IXMLDOMNodeList** resultList )
1297 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1298 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), queryString, resultList );
1302 static HRESULT WINAPI domdoc_selectSingleNode(
1303 IXMLDOMDocument3 *iface,
1305 IXMLDOMNode** resultNode )
1307 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1308 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), queryString, resultNode );
1312 static HRESULT WINAPI domdoc_get_parsed(
1313 IXMLDOMDocument3 *iface,
1314 VARIANT_BOOL* isParsed )
1316 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1317 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1318 *isParsed = VARIANT_TRUE;
1323 static HRESULT WINAPI domdoc_get_namespaceURI(
1324 IXMLDOMDocument3 *iface,
1325 BSTR* namespaceURI )
1327 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1328 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), namespaceURI );
1332 static HRESULT WINAPI domdoc_get_prefix(
1333 IXMLDOMDocument3 *iface,
1334 BSTR* prefixString )
1336 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1337 return IXMLDOMNode_get_prefix( IXMLDOMNode_from_impl(&This->node), prefixString );
1341 static HRESULT WINAPI domdoc_get_baseName(
1342 IXMLDOMDocument3 *iface,
1345 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1346 return IXMLDOMNode_get_baseName( IXMLDOMNode_from_impl(&This->node), nameString );
1350 static HRESULT WINAPI domdoc_transformNodeToObject(
1351 IXMLDOMDocument3 *iface,
1352 IXMLDOMNode* stylesheet,
1353 VARIANT outputObject)
1355 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1356 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), stylesheet, outputObject );
1360 static HRESULT WINAPI domdoc_get_doctype(
1361 IXMLDOMDocument3 *iface,
1362 IXMLDOMDocumentType** documentType )
1364 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1365 FIXME("(%p)\n", This);
1370 static HRESULT WINAPI domdoc_get_implementation(
1371 IXMLDOMDocument3 *iface,
1372 IXMLDOMImplementation** impl )
1374 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1376 TRACE("(%p)->(%p)\n", This, impl);
1379 return E_INVALIDARG;
1381 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1386 static HRESULT WINAPI domdoc_get_documentElement(
1387 IXMLDOMDocument3 *iface,
1388 IXMLDOMElement** DOMElement )
1390 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1391 IXMLDOMNode *element_node;
1395 TRACE("(%p)->(%p)\n", This, DOMElement);
1398 return E_INVALIDARG;
1402 root = xmlDocGetRootElement( get_doc(This) );
1406 element_node = create_node( root );
1407 if(!element_node) return S_FALSE;
1409 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1410 IXMLDOMNode_Release(element_node);
1416 static HRESULT WINAPI domdoc_put_documentElement(
1417 IXMLDOMDocument3 *iface,
1418 IXMLDOMElement* DOMElement )
1420 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1421 IXMLDOMNode *elementNode;
1426 TRACE("(%p)->(%p)\n", This, DOMElement);
1428 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1432 xmlNode = get_node_obj( elementNode );
1434 FIXME("elementNode is not our object\n");
1438 if(!xmlNode->node->parent)
1439 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1440 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1442 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1443 IXMLDOMNode_Release( elementNode );
1446 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1452 static HRESULT WINAPI domdoc_createElement(
1453 IXMLDOMDocument3 *iface,
1455 IXMLDOMElement** element )
1457 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1462 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1464 if (!element || !tagname) return E_INVALIDARG;
1466 V_VT(&type) = VT_I1;
1467 V_I1(&type) = NODE_ELEMENT;
1469 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1472 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1473 IXMLDOMNode_Release(node);
1480 static HRESULT WINAPI domdoc_createDocumentFragment(
1481 IXMLDOMDocument3 *iface,
1482 IXMLDOMDocumentFragment** frag )
1484 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1489 TRACE("(%p)->(%p)\n", This, frag);
1491 if (!frag) return E_INVALIDARG;
1495 V_VT(&type) = VT_I1;
1496 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1498 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1501 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1502 IXMLDOMNode_Release(node);
1509 static HRESULT WINAPI domdoc_createTextNode(
1510 IXMLDOMDocument3 *iface,
1512 IXMLDOMText** text )
1514 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1519 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1521 if (!text) return E_INVALIDARG;
1525 V_VT(&type) = VT_I1;
1526 V_I1(&type) = NODE_TEXT;
1528 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1531 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1532 IXMLDOMNode_Release(node);
1533 hr = IXMLDOMText_put_data(*text, data);
1540 static HRESULT WINAPI domdoc_createComment(
1541 IXMLDOMDocument3 *iface,
1543 IXMLDOMComment** comment )
1545 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1550 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1552 if (!comment) return E_INVALIDARG;
1556 V_VT(&type) = VT_I1;
1557 V_I1(&type) = NODE_COMMENT;
1559 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1562 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1563 IXMLDOMNode_Release(node);
1564 hr = IXMLDOMComment_put_data(*comment, data);
1571 static HRESULT WINAPI domdoc_createCDATASection(
1572 IXMLDOMDocument3 *iface,
1574 IXMLDOMCDATASection** cdata )
1576 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1581 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1583 if (!cdata) return E_INVALIDARG;
1587 V_VT(&type) = VT_I1;
1588 V_I1(&type) = NODE_CDATA_SECTION;
1590 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1593 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1594 IXMLDOMNode_Release(node);
1595 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1602 static HRESULT WINAPI domdoc_createProcessingInstruction(
1603 IXMLDOMDocument3 *iface,
1606 IXMLDOMProcessingInstruction** pi )
1608 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1613 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1615 if (!pi) return E_INVALIDARG;
1619 V_VT(&type) = VT_I1;
1620 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1622 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1627 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1628 node_obj = get_node_obj(node);
1629 hr = node_set_content(node_obj, data);
1631 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1632 IXMLDOMNode_Release(node);
1639 static HRESULT WINAPI domdoc_createAttribute(
1640 IXMLDOMDocument3 *iface,
1642 IXMLDOMAttribute** attribute )
1644 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1649 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1651 if (!attribute || !name) return E_INVALIDARG;
1653 V_VT(&type) = VT_I1;
1654 V_I1(&type) = NODE_ATTRIBUTE;
1656 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1659 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1660 IXMLDOMNode_Release(node);
1667 static HRESULT WINAPI domdoc_createEntityReference(
1668 IXMLDOMDocument3 *iface,
1670 IXMLDOMEntityReference** entityref )
1672 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1677 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1679 if (!entityref) return E_INVALIDARG;
1683 V_VT(&type) = VT_I1;
1684 V_I1(&type) = NODE_ENTITY_REFERENCE;
1686 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1689 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1690 IXMLDOMNode_Release(node);
1697 static HRESULT WINAPI domdoc_getElementsByTagName(
1698 IXMLDOMDocument3 *iface,
1700 IXMLDOMNodeList** resultList )
1702 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1705 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagName), resultList);
1707 if (!tagName || !resultList) return E_INVALIDARG;
1709 if (tagName[0] == '*' && tagName[1] == 0)
1711 static const WCHAR formatallW[] = {'/','/','*',0};
1712 hr = queryresult_create((xmlNodePtr)get_doc(This), formatallW, resultList);
1716 static const WCHAR xpathformat[] =
1717 { '/','/','*','[','l','o','c','a','l','-','n','a','m','e','(',')','=','\'' };
1718 static const WCHAR closeW[] = { '\'',']',0 };
1724 length = lstrlenW(tagName);
1726 /* without two WCHARs from format specifier */
1727 ptr = pattern = heap_alloc(sizeof(xpathformat) + length*sizeof(WCHAR) + sizeof(closeW));
1729 memcpy(ptr, xpathformat, sizeof(xpathformat));
1730 ptr += sizeof(xpathformat)/sizeof(WCHAR);
1731 memcpy(ptr, tagName, length*sizeof(WCHAR));
1733 memcpy(ptr, closeW, sizeof(closeW));
1735 hr = queryresult_create((xmlNodePtr)get_doc(This), pattern, resultList);
1742 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1748 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1750 return E_INVALIDARG;
1757 static HRESULT WINAPI domdoc_createNode(
1758 IXMLDOMDocument3 *iface,
1762 IXMLDOMNode** node )
1764 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1765 DOMNodeType node_type;
1767 xmlChar *xml_name, *href;
1770 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1772 if(!node) return E_INVALIDARG;
1774 hr = get_node_type(Type, &node_type);
1775 if(FAILED(hr)) return hr;
1777 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1778 FIXME("nodes with namespaces currently not supported.\n");
1780 TRACE("node_type %d\n", node_type);
1782 /* exit earlier for types that need name */
1786 case NODE_ATTRIBUTE:
1787 case NODE_ENTITY_REFERENCE:
1788 case NODE_PROCESSING_INSTRUCTION:
1789 if (!name || *name == 0) return E_FAIL;
1794 xml_name = xmlChar_from_wchar(name);
1795 /* prevent empty href to be allocated */
1796 href = namespaceURI ? xmlChar_from_wchar(namespaceURI) : NULL;
1802 xmlChar *local, *prefix;
1804 local = xmlSplitQName2(xml_name, &prefix);
1806 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
1808 /* allow to create default namespace xmlns= */
1809 if (local || (href && *href))
1811 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
1812 xmlSetNs(xmlnode, ns);
1820 case NODE_ATTRIBUTE:
1821 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1824 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1826 case NODE_CDATA_SECTION:
1827 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1829 case NODE_ENTITY_REFERENCE:
1830 xmlnode = xmlNewReference(get_doc(This), xml_name);
1832 case NODE_PROCESSING_INSTRUCTION:
1833 #ifdef HAVE_XMLNEWDOCPI
1834 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1836 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1841 xmlnode = xmlNewDocComment(get_doc(This), NULL);
1843 case NODE_DOCUMENT_FRAGMENT:
1844 xmlnode = xmlNewDocFragment(get_doc(This));
1846 /* unsupported types */
1848 case NODE_DOCUMENT_TYPE:
1851 heap_free(xml_name);
1852 return E_INVALIDARG;
1854 FIXME("unhandled node type %d\n", node_type);
1859 *node = create_node(xmlnode);
1860 heap_free(xml_name);
1865 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1866 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1873 static HRESULT WINAPI domdoc_nodeFromID(
1874 IXMLDOMDocument3 *iface,
1876 IXMLDOMNode** node )
1878 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1879 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1883 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1888 xmldoc = doparse(This, ptr, len, NULL);
1890 xmldoc->_private = create_priv();
1891 return attach_xmldoc(This, xmldoc);
1897 static HRESULT doread( domdoc *This, LPWSTR filename )
1902 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1907 detach_bsc(This->bsc);
1913 static HRESULT WINAPI domdoc_load(
1914 IXMLDOMDocument3 *iface,
1916 VARIANT_BOOL* isSuccessful )
1918 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1919 LPWSTR filename = NULL;
1920 HRESULT hr = S_FALSE;
1921 IXMLDOMDocument3 *pNewDoc = NULL;
1922 IStream *pStream = NULL;
1925 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
1927 *isSuccessful = VARIANT_FALSE;
1929 assert( &This->node );
1931 switch( V_VT(&xmlSource) )
1934 filename = V_BSTR(&xmlSource);
1937 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
1942 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
1943 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1944 hr = attach_xmldoc(This, xmldoc);
1947 *isSuccessful = VARIANT_TRUE;
1952 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1955 IPersistStream *pDocStream;
1956 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1959 hr = IPersistStream_Load(pDocStream, pStream);
1960 IStream_Release(pStream);
1963 *isSuccessful = VARIANT_TRUE;
1965 TRACE("Using IStream to load Document\n");
1970 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1975 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1980 /* ISequentialStream */
1981 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1985 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1988 TRACE("filename (%s)\n", debugstr_w(filename));
1992 hr = doread( This, filename );
1995 This->error = E_FAIL;
1998 hr = This->error = S_OK;
1999 *isSuccessful = VARIANT_TRUE;
2003 if(!filename || FAILED(hr)) {
2004 xmldoc = xmlNewDoc(NULL);
2005 xmldoc->_private = create_priv();
2006 hr = attach_xmldoc(This, xmldoc);
2011 TRACE("ret (%d)\n", hr);
2017 static HRESULT WINAPI domdoc_get_readyState(
2018 IXMLDOMDocument3 *iface,
2021 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2022 FIXME("stub! (%p)->(%p)\n", This, value);
2025 return E_INVALIDARG;
2027 *value = READYSTATE_COMPLETE;
2032 static HRESULT WINAPI domdoc_get_parseError(
2033 IXMLDOMDocument3 *iface,
2034 IXMLDOMParseError** errorObj )
2036 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2037 static const WCHAR err[] = {'e','r','r','o','r',0};
2038 BSTR error_string = NULL;
2040 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2043 error_string = SysAllocString(err);
2045 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2046 if(!*errorObj) return E_OUTOFMEMORY;
2051 static HRESULT WINAPI domdoc_get_url(
2052 IXMLDOMDocument3 *iface,
2055 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2056 FIXME("(%p)->(%p)\n", This, urlString);
2061 static HRESULT WINAPI domdoc_get_async(
2062 IXMLDOMDocument3 *iface,
2063 VARIANT_BOOL* isAsync )
2065 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2067 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2068 *isAsync = This->async;
2073 static HRESULT WINAPI domdoc_put_async(
2074 IXMLDOMDocument3 *iface,
2075 VARIANT_BOOL isAsync )
2077 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2079 TRACE("(%p)->(%d)\n", This, isAsync);
2080 This->async = isAsync;
2085 static HRESULT WINAPI domdoc_abort(
2086 IXMLDOMDocument3 *iface )
2088 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2089 FIXME("%p\n", This);
2094 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
2099 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
2100 str = heap_alloc( len );
2103 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
2109 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2110 static HRESULT WINAPI domdoc_loadXML(
2111 IXMLDOMDocument3 *iface,
2113 VARIANT_BOOL* isSuccessful )
2115 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2116 static const xmlChar encoding[] = "UTF-8";
2117 xmlDocPtr xmldoc = NULL;
2118 HRESULT hr = S_FALSE, hr2;
2122 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2124 assert ( &This->node );
2128 *isSuccessful = VARIANT_FALSE;
2130 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
2132 xmldoc = doparse(This, str, len, encoding);
2136 This->error = E_FAIL;
2137 TRACE("failed to parse document\n");
2141 hr = This->error = S_OK;
2142 *isSuccessful = VARIANT_TRUE;
2143 TRACE("parsed document %p\n", xmldoc);
2148 xmldoc = xmlNewDoc(NULL);
2150 xmldoc->_private = create_priv();
2152 hr2 = attach_xmldoc(This, xmldoc);
2159 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2163 if(!WriteFile(ctx, buffer, len, &written, NULL))
2165 WARN("write error\n");
2172 static int XMLCALL domdoc_save_closecallback(void *ctx)
2174 return CloseHandle(ctx) ? 0 : -1;
2177 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2182 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2185 WARN("stream write error: 0x%08x\n", hr);
2192 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2194 IStream_Release((IStream*)ctx);
2198 static HRESULT WINAPI domdoc_save(
2199 IXMLDOMDocument3 *iface,
2200 VARIANT destination )
2202 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2203 xmlSaveCtxtPtr ctx = NULL;
2207 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
2208 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
2210 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
2212 FIXME("Unhandled vt %d\n", V_VT(&destination));
2216 if(V_VT(&destination) == VT_UNKNOWN)
2218 IUnknown *pUnk = V_UNKNOWN(&destination);
2219 IXMLDOMDocument2 *document;
2222 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2225 VARIANT_BOOL success;
2228 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2231 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2235 IXMLDOMDocument3_Release(document);
2239 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2242 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2243 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2247 IStream_Release(stream);
2254 /* save with file path */
2255 HANDLE handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
2256 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2257 if( handle == INVALID_HANDLE_VALUE )
2259 WARN("failed to create file\n");
2263 /* disable top XML declaration */
2264 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2265 handle, NULL, XML_SAVE_NO_DECL);
2268 CloseHandle(handle);
2273 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2274 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2275 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2277 /* will release resources through close callback */
2283 static HRESULT WINAPI domdoc_get_validateOnParse(
2284 IXMLDOMDocument3 *iface,
2285 VARIANT_BOOL* isValidating )
2287 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2288 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2289 *isValidating = This->validating;
2294 static HRESULT WINAPI domdoc_put_validateOnParse(
2295 IXMLDOMDocument3 *iface,
2296 VARIANT_BOOL isValidating )
2298 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2299 TRACE("(%p)->(%d)\n", This, isValidating);
2300 This->validating = isValidating;
2305 static HRESULT WINAPI domdoc_get_resolveExternals(
2306 IXMLDOMDocument3 *iface,
2307 VARIANT_BOOL* isResolving )
2309 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2310 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2311 *isResolving = This->resolving;
2316 static HRESULT WINAPI domdoc_put_resolveExternals(
2317 IXMLDOMDocument3 *iface,
2318 VARIANT_BOOL isResolving )
2320 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2321 TRACE("(%p)->(%d)\n", This, isResolving);
2322 This->resolving = isResolving;
2327 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2328 IXMLDOMDocument3 *iface,
2329 VARIANT_BOOL* isPreserving )
2331 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2332 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->preserving);
2333 *isPreserving = This->preserving;
2338 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2339 IXMLDOMDocument3 *iface,
2340 VARIANT_BOOL isPreserving )
2342 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2343 TRACE("(%p)->(%d)\n", This, isPreserving);
2344 This->preserving = isPreserving;
2349 static HRESULT WINAPI domdoc_put_onReadyStateChange(
2350 IXMLDOMDocument3 *iface,
2351 VARIANT readyStateChangeSink )
2353 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2354 FIXME("%p\n", This);
2359 static HRESULT WINAPI domdoc_put_onDataAvailable(
2360 IXMLDOMDocument3 *iface,
2361 VARIANT onDataAvailableSink )
2363 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2364 FIXME("%p\n", This);
2368 static HRESULT WINAPI domdoc_put_onTransformNode(
2369 IXMLDOMDocument3 *iface,
2370 VARIANT onTransformNodeSink )
2372 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2373 FIXME("%p\n", This);
2377 static HRESULT WINAPI domdoc_get_namespaces(
2378 IXMLDOMDocument3* iface,
2379 IXMLDOMSchemaCollection** schemaCollection )
2381 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2382 FIXME("(%p)->(%p)\n", This, schemaCollection);
2386 static HRESULT WINAPI domdoc_get_schemas(
2387 IXMLDOMDocument3* iface,
2390 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2391 HRESULT hr = S_FALSE;
2392 IXMLDOMSchemaCollection *cur_schema = This->schema;
2394 TRACE("(%p)->(%p)\n", This, var1);
2396 VariantInit(var1); /* Test shows we don't call VariantClear here */
2397 V_VT(var1) = VT_NULL;
2401 hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2403 V_VT(var1) = VT_DISPATCH;
2408 static HRESULT WINAPI domdoc_putref_schemas(
2409 IXMLDOMDocument3* iface,
2412 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2413 HRESULT hr = E_FAIL;
2414 IXMLDOMSchemaCollection *new_schema = NULL;
2416 FIXME("(%p): semi-stub\n", This);
2420 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2424 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2433 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2438 IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
2439 if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
2445 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2449 LIBXML2_CALLBACK_ERR(domdoc_validate, msg, ap);
2453 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2457 LIBXML2_CALLBACK_WARN(domdoc_validate, msg, ap);
2461 static HRESULT WINAPI domdoc_validate(
2462 IXMLDOMDocument3* iface,
2463 IXMLDOMParseError** err)
2465 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2467 xmlValidCtxtPtr vctx;
2469 TRACE("(%p)->(%p)\n", This, err);
2470 domdoc_get_readyState(iface, &state);
2471 if (state != READYSTATE_COMPLETE)
2474 *err = create_parseError(0, NULL, NULL, NULL, 0, 0, 0);
2478 vctx = xmlNewValidCtxt();
2479 vctx->error = validate_error;
2480 vctx->warning = validate_warning;
2482 if (xmlValidateDocument(vctx, get_doc(This)))
2485 *err = create_parseError(0, NULL, NULL, NULL, 0, 0, 0);
2486 xmlFreeValidCtxt(vctx);
2490 FIXME("partial stub!\n");
2492 *err = create_parseError(0xC00CE223, NULL, NULL, NULL, 0, 0, 0);
2493 xmlFreeValidCtxt(vctx);
2497 static HRESULT WINAPI domdoc_setProperty(
2498 IXMLDOMDocument3* iface,
2502 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2504 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2506 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2512 V_VT(&varStr) = VT_EMPTY;
2513 if (V_VT(&var) != VT_BSTR)
2515 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2517 bstr = V_BSTR(&varStr);
2520 bstr = V_BSTR(&var);
2523 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2524 This->properties->XPath = TRUE;
2525 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2526 This->properties->XPath = FALSE;
2530 VariantClear(&varStr);
2533 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2538 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2539 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2540 xmlXPathContextPtr ctx;
2541 struct list *pNsList;
2542 select_ns_entry* pNsEntry = NULL;
2544 V_VT(&varStr) = VT_EMPTY;
2545 if (V_VT(&var) != VT_BSTR)
2547 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2549 bstr = V_BSTR(&varStr);
2552 bstr = V_BSTR(&var);
2556 pNsList = &(This->properties->selectNsList);
2557 clear_selectNsList(pNsList);
2559 nsStr = xmlChar_from_wchar(bstr);
2562 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2564 This->properties->selectNsStr = nsStr;
2565 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2568 ctx = xmlXPathNewContext(This->node.node->doc);
2571 for (; *pTokBegin; pTokBegin = pTokEnd)
2573 if (pNsEntry != NULL)
2574 memset(pNsEntry, 0, sizeof(select_ns_entry));
2576 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2578 while (*pTokBegin == ' ')
2580 pTokEnd = pTokBegin;
2581 while (*pTokEnd != ' ' && *pTokEnd != 0)
2584 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2587 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2588 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2593 if (*pTokBegin == '=')
2595 /*valid for XSLPattern?*/
2596 FIXME("Setting default xmlns not supported - skipping.\n");
2597 pTokBegin = pTokEnd;
2600 else if (*pTokBegin == ':')
2602 pNsEntry->prefix = ++pTokBegin;
2603 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2606 if (pTokInner == pTokEnd)
2609 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2610 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2614 pNsEntry->prefix_end = *pTokInner;
2618 if (pTokEnd-pTokInner > 1 &&
2619 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2620 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2622 pNsEntry->href = ++pTokInner;
2623 pNsEntry->href_end = *(pTokEnd-1);
2625 list_add_tail(pNsList, &pNsEntry->entry);
2626 /*let libxml figure out if they're valid from here ;)*/
2627 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2636 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2637 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2638 list_add_tail(pNsList, &pNsEntry->entry);
2651 heap_free(pNsEntry);
2652 xmlXPathFreeContext(ctx);
2655 VariantClear(&varStr);
2658 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2659 lstrcmpiW(p, PropertyNewParserW) == 0)
2662 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2666 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2670 static HRESULT WINAPI domdoc_getProperty(
2671 IXMLDOMDocument3* iface,
2675 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2677 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2680 return E_INVALIDARG;
2682 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2684 V_VT(var) = VT_BSTR;
2685 V_BSTR(var) = This->properties->XPath ?
2686 SysAllocString(PropValueXPathW) :
2687 SysAllocString(PropValueXSLPatternW);
2688 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2690 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2693 BSTR rebuiltStr, cur;
2694 const xmlChar *nsStr;
2695 struct list *pNsList;
2696 select_ns_entry* pNsEntry;
2698 V_VT(var) = VT_BSTR;
2699 nsStr = This->properties->selectNsStr;
2700 pNsList = &This->properties->selectNsList;
2701 lenA = This->properties->selectNsStr_len;
2702 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
2703 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
2704 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
2706 /* this is fine because all of the chars that end tokens are ASCII*/
2707 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
2709 while (*cur != 0) ++cur;
2710 if (pNsEntry->prefix_end)
2712 *cur = pNsEntry->prefix_end;
2713 while (*cur != 0) ++cur;
2716 if (pNsEntry->href_end)
2718 *cur = pNsEntry->href_end;
2721 V_BSTR(var) = SysAllocString(rebuiltStr);
2722 heap_free(rebuiltStr);
2726 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2730 static HRESULT WINAPI domdoc_validateNode(
2731 IXMLDOMDocument3* iface,
2733 IXMLDOMParseError** error)
2735 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2736 FIXME("(%p)->(%p %p): stub\n", This, node, error);
2740 static HRESULT WINAPI domdoc_importNode(
2741 IXMLDOMDocument3* iface,
2744 IXMLDOMNode** clone)
2746 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2747 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
2751 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
2753 domdoc_QueryInterface,
2756 domdoc_GetTypeInfoCount,
2758 domdoc_GetIDsOfNames,
2760 domdoc_get_nodeName,
2761 domdoc_get_nodeValue,
2762 domdoc_put_nodeValue,
2763 domdoc_get_nodeType,
2764 domdoc_get_parentNode,
2765 domdoc_get_childNodes,
2766 domdoc_get_firstChild,
2767 domdoc_get_lastChild,
2768 domdoc_get_previousSibling,
2769 domdoc_get_nextSibling,
2770 domdoc_get_attributes,
2771 domdoc_insertBefore,
2772 domdoc_replaceChild,
2775 domdoc_hasChildNodes,
2776 domdoc_get_ownerDocument,
2778 domdoc_get_nodeTypeString,
2781 domdoc_get_specified,
2782 domdoc_get_definition,
2783 domdoc_get_nodeTypedValue,
2784 domdoc_put_nodeTypedValue,
2785 domdoc_get_dataType,
2786 domdoc_put_dataType,
2788 domdoc_transformNode,
2790 domdoc_selectSingleNode,
2792 domdoc_get_namespaceURI,
2794 domdoc_get_baseName,
2795 domdoc_transformNodeToObject,
2797 domdoc_get_implementation,
2798 domdoc_get_documentElement,
2799 domdoc_put_documentElement,
2800 domdoc_createElement,
2801 domdoc_createDocumentFragment,
2802 domdoc_createTextNode,
2803 domdoc_createComment,
2804 domdoc_createCDATASection,
2805 domdoc_createProcessingInstruction,
2806 domdoc_createAttribute,
2807 domdoc_createEntityReference,
2808 domdoc_getElementsByTagName,
2812 domdoc_get_readyState,
2813 domdoc_get_parseError,
2820 domdoc_get_validateOnParse,
2821 domdoc_put_validateOnParse,
2822 domdoc_get_resolveExternals,
2823 domdoc_put_resolveExternals,
2824 domdoc_get_preserveWhiteSpace,
2825 domdoc_put_preserveWhiteSpace,
2826 domdoc_put_onReadyStateChange,
2827 domdoc_put_onDataAvailable,
2828 domdoc_put_onTransformNode,
2829 domdoc_get_namespaces,
2831 domdoc_putref_schemas,
2835 domdoc_validateNode,
2839 /* IConnectionPointContainer */
2840 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
2841 REFIID riid, void **ppv)
2843 domdoc *This = impl_from_IConnectionPointContainer(iface);
2844 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)This, riid, ppv);
2847 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
2849 domdoc *This = impl_from_IConnectionPointContainer(iface);
2850 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)This);
2853 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
2855 domdoc *This = impl_from_IConnectionPointContainer(iface);
2856 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)This);
2859 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
2860 IEnumConnectionPoints **ppEnum)
2862 domdoc *This = impl_from_IConnectionPointContainer(iface);
2863 FIXME("(%p)->(%p): stub\n", This, ppEnum);
2867 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
2868 REFIID riid, IConnectionPoint **cp)
2870 domdoc *This = impl_from_IConnectionPointContainer(iface);
2871 ConnectionPoint *iter;
2873 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
2877 for(iter = This->cp_list; iter; iter = iter->next)
2879 if (IsEqualGUID(iter->iid, riid))
2880 *cp = (IConnectionPoint*)&iter->lpVtblConnectionPoint;
2885 IConnectionPoint_AddRef(*cp);
2889 FIXME("unsupported riid %s\n", debugstr_guid(riid));
2890 return CONNECT_E_NOCONNECTION;
2894 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
2896 ConnectionPointContainer_QueryInterface,
2897 ConnectionPointContainer_AddRef,
2898 ConnectionPointContainer_Release,
2899 ConnectionPointContainer_EnumConnectionPoints,
2900 ConnectionPointContainer_FindConnectionPoint
2903 /* IConnectionPoint */
2904 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
2905 REFIID riid, void **ppv)
2907 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2909 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
2913 if (IsEqualGUID(&IID_IUnknown, riid) ||
2914 IsEqualGUID(&IID_IConnectionPoint, riid))
2921 IConnectionPoint_AddRef(iface);
2925 WARN("Unsupported interface %s\n", debugstr_guid(riid));
2926 return E_NOINTERFACE;
2929 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
2931 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2932 return IConnectionPointContainer_AddRef(This->container);
2935 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
2937 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2938 return IConnectionPointContainer_Release(This->container);
2941 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
2943 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2945 TRACE("(%p)->(%p)\n", This, iid);
2947 if (!iid) return E_POINTER;
2953 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
2954 IConnectionPointContainer **container)
2956 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2958 TRACE("(%p)->(%p)\n", This, container);
2960 if (!container) return E_POINTER;
2962 *container = This->container;
2963 IConnectionPointContainer_AddRef(*container);
2967 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
2970 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2971 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
2975 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
2977 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2979 TRACE("(%p)->(%d)\n", This, cookie);
2981 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
2982 return CONNECT_E_NOCONNECTION;
2984 IUnknown_Release(This->sinks[cookie-1].unk);
2985 This->sinks[cookie-1].unk = NULL;
2990 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
2991 IEnumConnections **ppEnum)
2993 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2994 FIXME("(%p)->(%p): stub\n", This, ppEnum);
2998 static const IConnectionPointVtbl ConnectionPointVtbl =
3000 ConnectionPoint_QueryInterface,
3001 ConnectionPoint_AddRef,
3002 ConnectionPoint_Release,
3003 ConnectionPoint_GetConnectionInterface,
3004 ConnectionPoint_GetConnectionPointContainer,
3005 ConnectionPoint_Advise,
3006 ConnectionPoint_Unadvise,
3007 ConnectionPoint_EnumConnections
3010 void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3012 cp->lpVtblConnectionPoint = &ConnectionPointVtbl;
3018 cp->next = doc->cp_list;
3021 cp->container = (IConnectionPointContainer*)&doc->lpVtblConnectionPointContainer;
3024 /* domdoc implementation of IObjectWithSite */
3025 static HRESULT WINAPI
3026 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3028 domdoc *This = impl_from_IObjectWithSite(iface);
3029 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppvObject );
3032 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3034 domdoc *This = impl_from_IObjectWithSite(iface);
3035 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3038 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3040 domdoc *This = impl_from_IObjectWithSite(iface);
3041 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3044 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3046 domdoc *This = impl_from_IObjectWithSite(iface);
3048 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3053 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3056 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3058 domdoc *This = impl_from_IObjectWithSite(iface);
3060 TRACE("(%p)->(%p)\n", iface, punk);
3066 IUnknown_Release( This->site );
3073 IUnknown_AddRef( punk );
3076 IUnknown_Release( This->site );
3083 static const IObjectWithSiteVtbl domdocObjectSite =
3085 domdoc_ObjectWithSite_QueryInterface,
3086 domdoc_ObjectWithSite_AddRef,
3087 domdoc_ObjectWithSite_Release,
3088 domdoc_ObjectWithSite_SetSite,
3089 domdoc_ObjectWithSite_GetSite
3092 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3094 domdoc *This = impl_from_IObjectSafety(iface);
3095 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppv );
3098 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3100 domdoc *This = impl_from_IObjectSafety(iface);
3101 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3104 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3106 domdoc *This = impl_from_IObjectSafety(iface);
3107 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3110 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3112 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3113 DWORD *supported, DWORD *enabled)
3115 domdoc *This = impl_from_IObjectSafety(iface);
3117 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3119 if(!supported || !enabled) return E_POINTER;
3121 *supported = SAFETY_SUPPORTED_OPTIONS;
3122 *enabled = This->safeopt;
3127 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3128 DWORD mask, DWORD enabled)
3130 domdoc *This = impl_from_IObjectSafety(iface);
3131 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3133 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3136 This->safeopt = enabled & mask & SAFETY_SUPPORTED_OPTIONS;
3140 #undef SAFETY_SUPPORTED_OPTIONS
3142 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3143 domdoc_Safety_QueryInterface,
3144 domdoc_Safety_AddRef,
3145 domdoc_Safety_Release,
3146 domdoc_Safety_GetInterfaceSafetyOptions,
3147 domdoc_Safety_SetInterfaceSafetyOptions
3150 static const tid_t domdoc_iface_tids[] = {
3152 IXMLDOMDocument_tid,
3153 IXMLDOMDocument2_tid,
3156 static dispex_static_data_t domdoc_dispex = {
3158 IXMLDOMDocument2_tid,
3163 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3167 doc = heap_alloc( sizeof (*doc) );
3169 return E_OUTOFMEMORY;
3171 doc->lpVtbl = &domdoc_vtbl;
3172 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
3173 doc->lpvtblIObjectWithSite = &domdocObjectSite;
3174 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
3175 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
3176 doc->lpVtblConnectionPointContainer = &ConnectionPointContainerVtbl;
3178 doc->async = VARIANT_TRUE;
3179 doc->validating = 0;
3181 doc->preserving = 0;
3182 doc->properties = properties_from_xmlDocPtr(xmldoc);
3189 doc->cp_list = NULL;
3191 /* events connection points */
3192 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3193 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3194 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3196 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->lpVtbl, &domdoc_dispex);
3198 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
3200 TRACE("returning iface %p\n", *document);
3204 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3209 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
3211 xmldoc = xmlNewDoc(NULL);
3213 return E_OUTOFMEMORY;
3215 xmldoc->_private = create_priv();
3216 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
3218 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3221 free_properties(properties_from_xmlDocPtr(xmldoc));
3222 heap_free(xmldoc->_private);
3230 IUnknown* create_domdoc( xmlNodePtr document )
3235 TRACE("(%p)\n", document);
3237 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3246 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3248 MESSAGE("This program tried to use a DOMDocument object, but\n"
3249 "libxml2 support was not present at compile time.\n");