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,
1336 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1337 TRACE("(%p)->(%p)\n", This, prefix);
1338 return return_null_bstr( prefix );
1342 static HRESULT WINAPI domdoc_get_baseName(
1343 IXMLDOMDocument3 *iface,
1346 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1347 TRACE("(%p)->(%p)\n", This, name);
1348 return return_null_bstr( name );
1352 static HRESULT WINAPI domdoc_transformNodeToObject(
1353 IXMLDOMDocument3 *iface,
1354 IXMLDOMNode* stylesheet,
1355 VARIANT outputObject)
1357 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1358 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), stylesheet, outputObject );
1362 static HRESULT WINAPI domdoc_get_doctype(
1363 IXMLDOMDocument3 *iface,
1364 IXMLDOMDocumentType** documentType )
1366 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1367 FIXME("(%p)\n", This);
1372 static HRESULT WINAPI domdoc_get_implementation(
1373 IXMLDOMDocument3 *iface,
1374 IXMLDOMImplementation** impl )
1376 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1378 TRACE("(%p)->(%p)\n", This, impl);
1381 return E_INVALIDARG;
1383 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1388 static HRESULT WINAPI domdoc_get_documentElement(
1389 IXMLDOMDocument3 *iface,
1390 IXMLDOMElement** DOMElement )
1392 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1393 IXMLDOMNode *element_node;
1397 TRACE("(%p)->(%p)\n", This, DOMElement);
1400 return E_INVALIDARG;
1404 root = xmlDocGetRootElement( get_doc(This) );
1408 element_node = create_node( root );
1409 if(!element_node) return S_FALSE;
1411 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1412 IXMLDOMNode_Release(element_node);
1418 static HRESULT WINAPI domdoc_put_documentElement(
1419 IXMLDOMDocument3 *iface,
1420 IXMLDOMElement* DOMElement )
1422 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1423 IXMLDOMNode *elementNode;
1428 TRACE("(%p)->(%p)\n", This, DOMElement);
1430 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1434 xmlNode = get_node_obj( elementNode );
1436 FIXME("elementNode is not our object\n");
1440 if(!xmlNode->node->parent)
1441 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1442 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1444 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1445 IXMLDOMNode_Release( elementNode );
1448 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1454 static HRESULT WINAPI domdoc_createElement(
1455 IXMLDOMDocument3 *iface,
1457 IXMLDOMElement** element )
1459 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1464 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1466 if (!element || !tagname) return E_INVALIDARG;
1468 V_VT(&type) = VT_I1;
1469 V_I1(&type) = NODE_ELEMENT;
1471 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1474 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1475 IXMLDOMNode_Release(node);
1482 static HRESULT WINAPI domdoc_createDocumentFragment(
1483 IXMLDOMDocument3 *iface,
1484 IXMLDOMDocumentFragment** frag )
1486 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1491 TRACE("(%p)->(%p)\n", This, frag);
1493 if (!frag) return E_INVALIDARG;
1497 V_VT(&type) = VT_I1;
1498 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1500 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1503 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1504 IXMLDOMNode_Release(node);
1511 static HRESULT WINAPI domdoc_createTextNode(
1512 IXMLDOMDocument3 *iface,
1514 IXMLDOMText** text )
1516 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1521 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1523 if (!text) return E_INVALIDARG;
1527 V_VT(&type) = VT_I1;
1528 V_I1(&type) = NODE_TEXT;
1530 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1533 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1534 IXMLDOMNode_Release(node);
1535 hr = IXMLDOMText_put_data(*text, data);
1542 static HRESULT WINAPI domdoc_createComment(
1543 IXMLDOMDocument3 *iface,
1545 IXMLDOMComment** comment )
1547 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1552 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1554 if (!comment) return E_INVALIDARG;
1558 V_VT(&type) = VT_I1;
1559 V_I1(&type) = NODE_COMMENT;
1561 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1564 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1565 IXMLDOMNode_Release(node);
1566 hr = IXMLDOMComment_put_data(*comment, data);
1573 static HRESULT WINAPI domdoc_createCDATASection(
1574 IXMLDOMDocument3 *iface,
1576 IXMLDOMCDATASection** cdata )
1578 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1583 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1585 if (!cdata) return E_INVALIDARG;
1589 V_VT(&type) = VT_I1;
1590 V_I1(&type) = NODE_CDATA_SECTION;
1592 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1595 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1596 IXMLDOMNode_Release(node);
1597 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1604 static HRESULT WINAPI domdoc_createProcessingInstruction(
1605 IXMLDOMDocument3 *iface,
1608 IXMLDOMProcessingInstruction** pi )
1610 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1615 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1617 if (!pi) return E_INVALIDARG;
1621 V_VT(&type) = VT_I1;
1622 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1624 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1629 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1630 node_obj = get_node_obj(node);
1631 hr = node_set_content(node_obj, data);
1633 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1634 IXMLDOMNode_Release(node);
1641 static HRESULT WINAPI domdoc_createAttribute(
1642 IXMLDOMDocument3 *iface,
1644 IXMLDOMAttribute** attribute )
1646 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1651 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1653 if (!attribute || !name) return E_INVALIDARG;
1655 V_VT(&type) = VT_I1;
1656 V_I1(&type) = NODE_ATTRIBUTE;
1658 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1661 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1662 IXMLDOMNode_Release(node);
1669 static HRESULT WINAPI domdoc_createEntityReference(
1670 IXMLDOMDocument3 *iface,
1672 IXMLDOMEntityReference** entityref )
1674 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1679 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1681 if (!entityref) return E_INVALIDARG;
1685 V_VT(&type) = VT_I1;
1686 V_I1(&type) = NODE_ENTITY_REFERENCE;
1688 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1691 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1692 IXMLDOMNode_Release(node);
1699 static HRESULT WINAPI domdoc_getElementsByTagName(
1700 IXMLDOMDocument3 *iface,
1702 IXMLDOMNodeList** resultList )
1704 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1707 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagName), resultList);
1709 if (!tagName || !resultList) return E_INVALIDARG;
1711 if (tagName[0] == '*' && tagName[1] == 0)
1713 static const WCHAR formatallW[] = {'/','/','*',0};
1714 hr = queryresult_create((xmlNodePtr)get_doc(This), formatallW, resultList);
1718 static const WCHAR xpathformat[] =
1719 { '/','/','*','[','l','o','c','a','l','-','n','a','m','e','(',')','=','\'' };
1720 static const WCHAR closeW[] = { '\'',']',0 };
1726 length = lstrlenW(tagName);
1728 /* without two WCHARs from format specifier */
1729 ptr = pattern = heap_alloc(sizeof(xpathformat) + length*sizeof(WCHAR) + sizeof(closeW));
1731 memcpy(ptr, xpathformat, sizeof(xpathformat));
1732 ptr += sizeof(xpathformat)/sizeof(WCHAR);
1733 memcpy(ptr, tagName, length*sizeof(WCHAR));
1735 memcpy(ptr, closeW, sizeof(closeW));
1737 hr = queryresult_create((xmlNodePtr)get_doc(This), pattern, resultList);
1744 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1750 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1752 return E_INVALIDARG;
1759 static HRESULT WINAPI domdoc_createNode(
1760 IXMLDOMDocument3 *iface,
1764 IXMLDOMNode** node )
1766 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1767 DOMNodeType node_type;
1769 xmlChar *xml_name, *href;
1772 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1774 if(!node) return E_INVALIDARG;
1776 hr = get_node_type(Type, &node_type);
1777 if(FAILED(hr)) return hr;
1779 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1780 FIXME("nodes with namespaces currently not supported.\n");
1782 TRACE("node_type %d\n", node_type);
1784 /* exit earlier for types that need name */
1788 case NODE_ATTRIBUTE:
1789 case NODE_ENTITY_REFERENCE:
1790 case NODE_PROCESSING_INSTRUCTION:
1791 if (!name || *name == 0) return E_FAIL;
1796 xml_name = xmlChar_from_wchar(name);
1797 /* prevent empty href to be allocated */
1798 href = namespaceURI ? xmlChar_from_wchar(namespaceURI) : NULL;
1804 xmlChar *local, *prefix;
1806 local = xmlSplitQName2(xml_name, &prefix);
1808 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
1810 /* allow to create default namespace xmlns= */
1811 if (local || (href && *href))
1813 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
1814 xmlSetNs(xmlnode, ns);
1822 case NODE_ATTRIBUTE:
1823 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1826 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1828 case NODE_CDATA_SECTION:
1829 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1831 case NODE_ENTITY_REFERENCE:
1832 xmlnode = xmlNewReference(get_doc(This), xml_name);
1834 case NODE_PROCESSING_INSTRUCTION:
1835 #ifdef HAVE_XMLNEWDOCPI
1836 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1838 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1843 xmlnode = xmlNewDocComment(get_doc(This), NULL);
1845 case NODE_DOCUMENT_FRAGMENT:
1846 xmlnode = xmlNewDocFragment(get_doc(This));
1848 /* unsupported types */
1850 case NODE_DOCUMENT_TYPE:
1853 heap_free(xml_name);
1854 return E_INVALIDARG;
1856 FIXME("unhandled node type %d\n", node_type);
1861 *node = create_node(xmlnode);
1862 heap_free(xml_name);
1867 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1868 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1875 static HRESULT WINAPI domdoc_nodeFromID(
1876 IXMLDOMDocument3 *iface,
1878 IXMLDOMNode** node )
1880 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1881 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1885 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1890 xmldoc = doparse(This, ptr, len, NULL);
1892 xmldoc->_private = create_priv();
1893 return attach_xmldoc(This, xmldoc);
1899 static HRESULT doread( domdoc *This, LPWSTR filename )
1904 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1909 detach_bsc(This->bsc);
1915 static HRESULT WINAPI domdoc_load(
1916 IXMLDOMDocument3 *iface,
1918 VARIANT_BOOL* isSuccessful )
1920 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1921 LPWSTR filename = NULL;
1922 HRESULT hr = S_FALSE;
1923 IXMLDOMDocument3 *pNewDoc = NULL;
1924 IStream *pStream = NULL;
1927 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
1929 *isSuccessful = VARIANT_FALSE;
1931 assert( &This->node );
1933 switch( V_VT(&xmlSource) )
1936 filename = V_BSTR(&xmlSource);
1939 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
1944 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
1945 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1946 hr = attach_xmldoc(This, xmldoc);
1949 *isSuccessful = VARIANT_TRUE;
1954 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1957 IPersistStream *pDocStream;
1958 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1961 hr = IPersistStream_Load(pDocStream, pStream);
1962 IStream_Release(pStream);
1965 *isSuccessful = VARIANT_TRUE;
1967 TRACE("Using IStream to load Document\n");
1972 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1977 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1982 /* ISequentialStream */
1983 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1987 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1990 TRACE("filename (%s)\n", debugstr_w(filename));
1994 hr = doread( This, filename );
1997 This->error = E_FAIL;
2000 hr = This->error = S_OK;
2001 *isSuccessful = VARIANT_TRUE;
2005 if(!filename || FAILED(hr)) {
2006 xmldoc = xmlNewDoc(NULL);
2007 xmldoc->_private = create_priv();
2008 hr = attach_xmldoc(This, xmldoc);
2013 TRACE("ret (%d)\n", hr);
2019 static HRESULT WINAPI domdoc_get_readyState(
2020 IXMLDOMDocument3 *iface,
2023 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2024 FIXME("stub! (%p)->(%p)\n", This, value);
2027 return E_INVALIDARG;
2029 *value = READYSTATE_COMPLETE;
2034 static HRESULT WINAPI domdoc_get_parseError(
2035 IXMLDOMDocument3 *iface,
2036 IXMLDOMParseError** errorObj )
2038 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2039 static const WCHAR err[] = {'e','r','r','o','r',0};
2040 BSTR error_string = NULL;
2042 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2045 error_string = SysAllocString(err);
2047 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2048 if(!*errorObj) return E_OUTOFMEMORY;
2053 static HRESULT WINAPI domdoc_get_url(
2054 IXMLDOMDocument3 *iface,
2057 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2058 FIXME("(%p)->(%p)\n", This, urlString);
2063 static HRESULT WINAPI domdoc_get_async(
2064 IXMLDOMDocument3 *iface,
2065 VARIANT_BOOL* isAsync )
2067 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2069 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2070 *isAsync = This->async;
2075 static HRESULT WINAPI domdoc_put_async(
2076 IXMLDOMDocument3 *iface,
2077 VARIANT_BOOL isAsync )
2079 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2081 TRACE("(%p)->(%d)\n", This, isAsync);
2082 This->async = isAsync;
2087 static HRESULT WINAPI domdoc_abort(
2088 IXMLDOMDocument3 *iface )
2090 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2091 FIXME("%p\n", This);
2096 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
2101 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
2102 str = heap_alloc( len );
2105 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
2111 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2112 static HRESULT WINAPI domdoc_loadXML(
2113 IXMLDOMDocument3 *iface,
2115 VARIANT_BOOL* isSuccessful )
2117 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2118 static const xmlChar encoding[] = "UTF-8";
2119 xmlDocPtr xmldoc = NULL;
2120 HRESULT hr = S_FALSE, hr2;
2124 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2126 assert ( &This->node );
2130 *isSuccessful = VARIANT_FALSE;
2132 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
2134 xmldoc = doparse(This, str, len, encoding);
2138 This->error = E_FAIL;
2139 TRACE("failed to parse document\n");
2143 hr = This->error = S_OK;
2144 *isSuccessful = VARIANT_TRUE;
2145 TRACE("parsed document %p\n", xmldoc);
2150 xmldoc = xmlNewDoc(NULL);
2152 xmldoc->_private = create_priv();
2154 hr2 = attach_xmldoc(This, xmldoc);
2161 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2165 if(!WriteFile(ctx, buffer, len, &written, NULL))
2167 WARN("write error\n");
2174 static int XMLCALL domdoc_save_closecallback(void *ctx)
2176 return CloseHandle(ctx) ? 0 : -1;
2179 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2184 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2187 WARN("stream write error: 0x%08x\n", hr);
2194 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2196 IStream_Release((IStream*)ctx);
2200 static HRESULT WINAPI domdoc_save(
2201 IXMLDOMDocument3 *iface,
2202 VARIANT destination )
2204 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2205 xmlSaveCtxtPtr ctx = NULL;
2209 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
2210 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
2212 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
2214 FIXME("Unhandled vt %d\n", V_VT(&destination));
2218 if(V_VT(&destination) == VT_UNKNOWN)
2220 IUnknown *pUnk = V_UNKNOWN(&destination);
2221 IXMLDOMDocument2 *document;
2224 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2227 VARIANT_BOOL success;
2230 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2233 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2237 IXMLDOMDocument3_Release(document);
2241 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2244 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2245 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2249 IStream_Release(stream);
2256 /* save with file path */
2257 HANDLE handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
2258 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2259 if( handle == INVALID_HANDLE_VALUE )
2261 WARN("failed to create file\n");
2265 /* disable top XML declaration */
2266 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2267 handle, NULL, XML_SAVE_NO_DECL);
2270 CloseHandle(handle);
2275 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2276 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2277 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2279 /* will release resources through close callback */
2285 static HRESULT WINAPI domdoc_get_validateOnParse(
2286 IXMLDOMDocument3 *iface,
2287 VARIANT_BOOL* isValidating )
2289 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2290 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2291 *isValidating = This->validating;
2296 static HRESULT WINAPI domdoc_put_validateOnParse(
2297 IXMLDOMDocument3 *iface,
2298 VARIANT_BOOL isValidating )
2300 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2301 TRACE("(%p)->(%d)\n", This, isValidating);
2302 This->validating = isValidating;
2307 static HRESULT WINAPI domdoc_get_resolveExternals(
2308 IXMLDOMDocument3 *iface,
2309 VARIANT_BOOL* isResolving )
2311 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2312 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2313 *isResolving = This->resolving;
2318 static HRESULT WINAPI domdoc_put_resolveExternals(
2319 IXMLDOMDocument3 *iface,
2320 VARIANT_BOOL isResolving )
2322 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2323 TRACE("(%p)->(%d)\n", This, isResolving);
2324 This->resolving = isResolving;
2329 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2330 IXMLDOMDocument3 *iface,
2331 VARIANT_BOOL* isPreserving )
2333 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2334 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->preserving);
2335 *isPreserving = This->preserving;
2340 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2341 IXMLDOMDocument3 *iface,
2342 VARIANT_BOOL isPreserving )
2344 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2345 TRACE("(%p)->(%d)\n", This, isPreserving);
2346 This->preserving = isPreserving;
2351 static HRESULT WINAPI domdoc_put_onReadyStateChange(
2352 IXMLDOMDocument3 *iface,
2353 VARIANT readyStateChangeSink )
2355 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2356 FIXME("%p\n", This);
2361 static HRESULT WINAPI domdoc_put_onDataAvailable(
2362 IXMLDOMDocument3 *iface,
2363 VARIANT onDataAvailableSink )
2365 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2366 FIXME("%p\n", This);
2370 static HRESULT WINAPI domdoc_put_onTransformNode(
2371 IXMLDOMDocument3 *iface,
2372 VARIANT onTransformNodeSink )
2374 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2375 FIXME("%p\n", This);
2379 static HRESULT WINAPI domdoc_get_namespaces(
2380 IXMLDOMDocument3* iface,
2381 IXMLDOMSchemaCollection** schemaCollection )
2383 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2384 FIXME("(%p)->(%p)\n", This, schemaCollection);
2388 static HRESULT WINAPI domdoc_get_schemas(
2389 IXMLDOMDocument3* iface,
2392 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2393 HRESULT hr = S_FALSE;
2394 IXMLDOMSchemaCollection *cur_schema = This->schema;
2396 TRACE("(%p)->(%p)\n", This, var1);
2398 VariantInit(var1); /* Test shows we don't call VariantClear here */
2399 V_VT(var1) = VT_NULL;
2403 hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2405 V_VT(var1) = VT_DISPATCH;
2410 static HRESULT WINAPI domdoc_putref_schemas(
2411 IXMLDOMDocument3* iface,
2414 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2415 HRESULT hr = E_FAIL;
2416 IXMLDOMSchemaCollection *new_schema = NULL;
2418 FIXME("(%p): semi-stub\n", This);
2422 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2426 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2435 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2440 IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
2441 if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
2447 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2451 LIBXML2_CALLBACK_ERR(domdoc_validate, msg, ap);
2455 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2459 LIBXML2_CALLBACK_WARN(domdoc_validate, msg, ap);
2463 static HRESULT WINAPI domdoc_validate(
2464 IXMLDOMDocument3* iface,
2465 IXMLDOMParseError** err)
2467 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2469 xmlValidCtxtPtr vctx;
2471 TRACE("(%p)->(%p)\n", This, err);
2472 domdoc_get_readyState(iface, &state);
2473 if (state != READYSTATE_COMPLETE)
2476 *err = create_parseError(0, NULL, NULL, NULL, 0, 0, 0);
2480 vctx = xmlNewValidCtxt();
2481 vctx->error = validate_error;
2482 vctx->warning = validate_warning;
2484 if (xmlValidateDocument(vctx, get_doc(This)))
2487 *err = create_parseError(0, NULL, NULL, NULL, 0, 0, 0);
2488 xmlFreeValidCtxt(vctx);
2492 FIXME("partial stub!\n");
2494 *err = create_parseError(0xC00CE223, NULL, NULL, NULL, 0, 0, 0);
2495 xmlFreeValidCtxt(vctx);
2499 static HRESULT WINAPI domdoc_setProperty(
2500 IXMLDOMDocument3* iface,
2504 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2506 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2508 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2514 V_VT(&varStr) = VT_EMPTY;
2515 if (V_VT(&var) != VT_BSTR)
2517 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2519 bstr = V_BSTR(&varStr);
2522 bstr = V_BSTR(&var);
2525 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2526 This->properties->XPath = TRUE;
2527 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2528 This->properties->XPath = FALSE;
2532 VariantClear(&varStr);
2535 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2540 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2541 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2542 xmlXPathContextPtr ctx;
2543 struct list *pNsList;
2544 select_ns_entry* pNsEntry = NULL;
2546 V_VT(&varStr) = VT_EMPTY;
2547 if (V_VT(&var) != VT_BSTR)
2549 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2551 bstr = V_BSTR(&varStr);
2554 bstr = V_BSTR(&var);
2558 pNsList = &(This->properties->selectNsList);
2559 clear_selectNsList(pNsList);
2561 nsStr = xmlChar_from_wchar(bstr);
2564 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2566 This->properties->selectNsStr = nsStr;
2567 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2570 ctx = xmlXPathNewContext(This->node.node->doc);
2573 for (; *pTokBegin; pTokBegin = pTokEnd)
2575 if (pNsEntry != NULL)
2576 memset(pNsEntry, 0, sizeof(select_ns_entry));
2578 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2580 while (*pTokBegin == ' ')
2582 pTokEnd = pTokBegin;
2583 while (*pTokEnd != ' ' && *pTokEnd != 0)
2586 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2589 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2590 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2595 if (*pTokBegin == '=')
2597 /*valid for XSLPattern?*/
2598 FIXME("Setting default xmlns not supported - skipping.\n");
2599 pTokBegin = pTokEnd;
2602 else if (*pTokBegin == ':')
2604 pNsEntry->prefix = ++pTokBegin;
2605 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2608 if (pTokInner == pTokEnd)
2611 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2612 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2616 pNsEntry->prefix_end = *pTokInner;
2620 if (pTokEnd-pTokInner > 1 &&
2621 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2622 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2624 pNsEntry->href = ++pTokInner;
2625 pNsEntry->href_end = *(pTokEnd-1);
2627 list_add_tail(pNsList, &pNsEntry->entry);
2628 /*let libxml figure out if they're valid from here ;)*/
2629 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2638 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2639 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2640 list_add_tail(pNsList, &pNsEntry->entry);
2653 heap_free(pNsEntry);
2654 xmlXPathFreeContext(ctx);
2657 VariantClear(&varStr);
2660 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2661 lstrcmpiW(p, PropertyNewParserW) == 0)
2664 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2668 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2672 static HRESULT WINAPI domdoc_getProperty(
2673 IXMLDOMDocument3* iface,
2677 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2679 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2682 return E_INVALIDARG;
2684 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2686 V_VT(var) = VT_BSTR;
2687 V_BSTR(var) = This->properties->XPath ?
2688 SysAllocString(PropValueXPathW) :
2689 SysAllocString(PropValueXSLPatternW);
2690 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2692 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2695 BSTR rebuiltStr, cur;
2696 const xmlChar *nsStr;
2697 struct list *pNsList;
2698 select_ns_entry* pNsEntry;
2700 V_VT(var) = VT_BSTR;
2701 nsStr = This->properties->selectNsStr;
2702 pNsList = &This->properties->selectNsList;
2703 lenA = This->properties->selectNsStr_len;
2704 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
2705 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
2706 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
2708 /* this is fine because all of the chars that end tokens are ASCII*/
2709 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
2711 while (*cur != 0) ++cur;
2712 if (pNsEntry->prefix_end)
2714 *cur = pNsEntry->prefix_end;
2715 while (*cur != 0) ++cur;
2718 if (pNsEntry->href_end)
2720 *cur = pNsEntry->href_end;
2723 V_BSTR(var) = SysAllocString(rebuiltStr);
2724 heap_free(rebuiltStr);
2728 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2732 static HRESULT WINAPI domdoc_validateNode(
2733 IXMLDOMDocument3* iface,
2735 IXMLDOMParseError** error)
2737 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2738 FIXME("(%p)->(%p %p): stub\n", This, node, error);
2742 static HRESULT WINAPI domdoc_importNode(
2743 IXMLDOMDocument3* iface,
2746 IXMLDOMNode** clone)
2748 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2749 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
2753 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
2755 domdoc_QueryInterface,
2758 domdoc_GetTypeInfoCount,
2760 domdoc_GetIDsOfNames,
2762 domdoc_get_nodeName,
2763 domdoc_get_nodeValue,
2764 domdoc_put_nodeValue,
2765 domdoc_get_nodeType,
2766 domdoc_get_parentNode,
2767 domdoc_get_childNodes,
2768 domdoc_get_firstChild,
2769 domdoc_get_lastChild,
2770 domdoc_get_previousSibling,
2771 domdoc_get_nextSibling,
2772 domdoc_get_attributes,
2773 domdoc_insertBefore,
2774 domdoc_replaceChild,
2777 domdoc_hasChildNodes,
2778 domdoc_get_ownerDocument,
2780 domdoc_get_nodeTypeString,
2783 domdoc_get_specified,
2784 domdoc_get_definition,
2785 domdoc_get_nodeTypedValue,
2786 domdoc_put_nodeTypedValue,
2787 domdoc_get_dataType,
2788 domdoc_put_dataType,
2790 domdoc_transformNode,
2792 domdoc_selectSingleNode,
2794 domdoc_get_namespaceURI,
2796 domdoc_get_baseName,
2797 domdoc_transformNodeToObject,
2799 domdoc_get_implementation,
2800 domdoc_get_documentElement,
2801 domdoc_put_documentElement,
2802 domdoc_createElement,
2803 domdoc_createDocumentFragment,
2804 domdoc_createTextNode,
2805 domdoc_createComment,
2806 domdoc_createCDATASection,
2807 domdoc_createProcessingInstruction,
2808 domdoc_createAttribute,
2809 domdoc_createEntityReference,
2810 domdoc_getElementsByTagName,
2814 domdoc_get_readyState,
2815 domdoc_get_parseError,
2822 domdoc_get_validateOnParse,
2823 domdoc_put_validateOnParse,
2824 domdoc_get_resolveExternals,
2825 domdoc_put_resolveExternals,
2826 domdoc_get_preserveWhiteSpace,
2827 domdoc_put_preserveWhiteSpace,
2828 domdoc_put_onReadyStateChange,
2829 domdoc_put_onDataAvailable,
2830 domdoc_put_onTransformNode,
2831 domdoc_get_namespaces,
2833 domdoc_putref_schemas,
2837 domdoc_validateNode,
2841 /* IConnectionPointContainer */
2842 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
2843 REFIID riid, void **ppv)
2845 domdoc *This = impl_from_IConnectionPointContainer(iface);
2846 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)This, riid, ppv);
2849 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
2851 domdoc *This = impl_from_IConnectionPointContainer(iface);
2852 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)This);
2855 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
2857 domdoc *This = impl_from_IConnectionPointContainer(iface);
2858 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)This);
2861 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
2862 IEnumConnectionPoints **ppEnum)
2864 domdoc *This = impl_from_IConnectionPointContainer(iface);
2865 FIXME("(%p)->(%p): stub\n", This, ppEnum);
2869 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
2870 REFIID riid, IConnectionPoint **cp)
2872 domdoc *This = impl_from_IConnectionPointContainer(iface);
2873 ConnectionPoint *iter;
2875 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
2879 for(iter = This->cp_list; iter; iter = iter->next)
2881 if (IsEqualGUID(iter->iid, riid))
2882 *cp = (IConnectionPoint*)&iter->lpVtblConnectionPoint;
2887 IConnectionPoint_AddRef(*cp);
2891 FIXME("unsupported riid %s\n", debugstr_guid(riid));
2892 return CONNECT_E_NOCONNECTION;
2896 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
2898 ConnectionPointContainer_QueryInterface,
2899 ConnectionPointContainer_AddRef,
2900 ConnectionPointContainer_Release,
2901 ConnectionPointContainer_EnumConnectionPoints,
2902 ConnectionPointContainer_FindConnectionPoint
2905 /* IConnectionPoint */
2906 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
2907 REFIID riid, void **ppv)
2909 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2911 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
2915 if (IsEqualGUID(&IID_IUnknown, riid) ||
2916 IsEqualGUID(&IID_IConnectionPoint, riid))
2923 IConnectionPoint_AddRef(iface);
2927 WARN("Unsupported interface %s\n", debugstr_guid(riid));
2928 return E_NOINTERFACE;
2931 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
2933 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2934 return IConnectionPointContainer_AddRef(This->container);
2937 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
2939 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2940 return IConnectionPointContainer_Release(This->container);
2943 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
2945 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2947 TRACE("(%p)->(%p)\n", This, iid);
2949 if (!iid) return E_POINTER;
2955 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
2956 IConnectionPointContainer **container)
2958 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2960 TRACE("(%p)->(%p)\n", This, container);
2962 if (!container) return E_POINTER;
2964 *container = This->container;
2965 IConnectionPointContainer_AddRef(*container);
2969 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
2972 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2973 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
2977 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
2979 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2981 TRACE("(%p)->(%d)\n", This, cookie);
2983 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
2984 return CONNECT_E_NOCONNECTION;
2986 IUnknown_Release(This->sinks[cookie-1].unk);
2987 This->sinks[cookie-1].unk = NULL;
2992 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
2993 IEnumConnections **ppEnum)
2995 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2996 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3000 static const IConnectionPointVtbl ConnectionPointVtbl =
3002 ConnectionPoint_QueryInterface,
3003 ConnectionPoint_AddRef,
3004 ConnectionPoint_Release,
3005 ConnectionPoint_GetConnectionInterface,
3006 ConnectionPoint_GetConnectionPointContainer,
3007 ConnectionPoint_Advise,
3008 ConnectionPoint_Unadvise,
3009 ConnectionPoint_EnumConnections
3012 void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3014 cp->lpVtblConnectionPoint = &ConnectionPointVtbl;
3020 cp->next = doc->cp_list;
3023 cp->container = (IConnectionPointContainer*)&doc->lpVtblConnectionPointContainer;
3026 /* domdoc implementation of IObjectWithSite */
3027 static HRESULT WINAPI
3028 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3030 domdoc *This = impl_from_IObjectWithSite(iface);
3031 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppvObject );
3034 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3036 domdoc *This = impl_from_IObjectWithSite(iface);
3037 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3040 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3042 domdoc *This = impl_from_IObjectWithSite(iface);
3043 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3046 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3048 domdoc *This = impl_from_IObjectWithSite(iface);
3050 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3055 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3058 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3060 domdoc *This = impl_from_IObjectWithSite(iface);
3062 TRACE("(%p)->(%p)\n", iface, punk);
3068 IUnknown_Release( This->site );
3075 IUnknown_AddRef( punk );
3078 IUnknown_Release( This->site );
3085 static const IObjectWithSiteVtbl domdocObjectSite =
3087 domdoc_ObjectWithSite_QueryInterface,
3088 domdoc_ObjectWithSite_AddRef,
3089 domdoc_ObjectWithSite_Release,
3090 domdoc_ObjectWithSite_SetSite,
3091 domdoc_ObjectWithSite_GetSite
3094 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3096 domdoc *This = impl_from_IObjectSafety(iface);
3097 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppv );
3100 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3102 domdoc *This = impl_from_IObjectSafety(iface);
3103 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3106 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3108 domdoc *This = impl_from_IObjectSafety(iface);
3109 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3112 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3114 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3115 DWORD *supported, DWORD *enabled)
3117 domdoc *This = impl_from_IObjectSafety(iface);
3119 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3121 if(!supported || !enabled) return E_POINTER;
3123 *supported = SAFETY_SUPPORTED_OPTIONS;
3124 *enabled = This->safeopt;
3129 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3130 DWORD mask, DWORD enabled)
3132 domdoc *This = impl_from_IObjectSafety(iface);
3133 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3135 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3138 This->safeopt = enabled & mask & SAFETY_SUPPORTED_OPTIONS;
3142 #undef SAFETY_SUPPORTED_OPTIONS
3144 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3145 domdoc_Safety_QueryInterface,
3146 domdoc_Safety_AddRef,
3147 domdoc_Safety_Release,
3148 domdoc_Safety_GetInterfaceSafetyOptions,
3149 domdoc_Safety_SetInterfaceSafetyOptions
3152 static const tid_t domdoc_iface_tids[] = {
3154 IXMLDOMDocument_tid,
3155 IXMLDOMDocument2_tid,
3158 static dispex_static_data_t domdoc_dispex = {
3160 IXMLDOMDocument2_tid,
3165 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3169 doc = heap_alloc( sizeof (*doc) );
3171 return E_OUTOFMEMORY;
3173 doc->lpVtbl = &domdoc_vtbl;
3174 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
3175 doc->lpvtblIObjectWithSite = &domdocObjectSite;
3176 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
3177 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
3178 doc->lpVtblConnectionPointContainer = &ConnectionPointContainerVtbl;
3180 doc->async = VARIANT_TRUE;
3181 doc->validating = 0;
3183 doc->preserving = 0;
3184 doc->properties = properties_from_xmlDocPtr(xmldoc);
3191 doc->cp_list = NULL;
3193 /* events connection points */
3194 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3195 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3196 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3198 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->lpVtbl, &domdoc_dispex);
3200 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
3202 TRACE("returning iface %p\n", *document);
3206 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3211 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
3213 xmldoc = xmlNewDoc(NULL);
3215 return E_OUTOFMEMORY;
3217 xmldoc->_private = create_priv();
3218 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
3220 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3223 free_properties(properties_from_xmlDocPtr(xmldoc));
3224 heap_free(xmldoc->_private);
3232 IUnknown* create_domdoc( xmlNodePtr document )
3237 TRACE("(%p)\n", document);
3239 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3248 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3250 MESSAGE("This program tried to use a DOMDocument object, but\n"
3251 "libxml2 support was not present at compile time.\n");