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 xmlDocPtr doparse(domdoc* This, char *ptr, int len, xmlChar const* encoding)
361 xmlDocPtr doc = NULL;
362 xmlParserCtxtPtr pctx;
363 static xmlSAXHandler sax_handler = {
364 xmlSAX2InternalSubset, /* internalSubset */
365 xmlSAX2IsStandalone, /* isStandalone */
366 xmlSAX2HasInternalSubset, /* hasInternalSubset */
367 xmlSAX2HasExternalSubset, /* hasExternalSubset */
368 xmlSAX2ResolveEntity, /* resolveEntity */
369 xmlSAX2GetEntity, /* getEntity */
370 xmlSAX2EntityDecl, /* entityDecl */
371 xmlSAX2NotationDecl, /* notationDecl */
372 xmlSAX2AttributeDecl, /* attributeDecl */
373 xmlSAX2ElementDecl, /* elementDecl */
374 xmlSAX2UnparsedEntityDecl, /* unparsedEntityDecl */
375 xmlSAX2SetDocumentLocator, /* setDocumentLocator */
376 xmlSAX2StartDocument, /* startDocument */
377 xmlSAX2EndDocument, /* endDocument */
378 xmlSAX2StartElement, /* startElement */
379 xmlSAX2EndElement, /* endElement */
380 xmlSAX2Reference, /* reference */
381 sax_characters, /* characters */
382 sax_characters, /* ignorableWhitespace */
383 xmlSAX2ProcessingInstruction, /* processingInstruction */
384 xmlSAX2Comment, /* comment */
385 NULL, /* TODO: warning */
386 NULL, /* TODO: error */
387 NULL, /* TODO: fatalError */
388 xmlSAX2GetParameterEntity, /* getParameterEntity */
389 xmlSAX2CDataBlock, /* cdataBlock */
390 xmlSAX2ExternalSubset, /* externalSubset */
393 xmlSAX2StartElementNs, /* startElementNs */
394 xmlSAX2EndElementNs, /* endElementNs */
395 NULL /* TODO: serror */
399 pctx = xmlCreateMemoryParserCtxt(ptr, len);
402 ERR("Failed to create parser context\n");
406 if (pctx->sax) xmlFree(pctx->sax);
407 pctx->sax = &sax_handler;
408 pctx->_private = This;
410 pctx->encoding = xmlStrdup(encoding);
411 xmlParseDocument(pctx);
413 if (pctx->wellFormed)
419 xmlFreeDoc(pctx->myDoc);
423 xmlFreeParserCtxt(pctx);
425 /* TODO: put this in one of the SAX callbacks */
426 /* create first child as a <?xml...?> */
427 if (doc && doc->standalone != -1)
431 xmlChar *xmlbuff = (xmlChar*)buff;
433 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
435 /* version attribute can't be omitted */
436 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
437 xmlNodeAddContent( node, xmlbuff );
441 sprintf(buff, " encoding=\"%s\"", doc->encoding);
442 xmlNodeAddContent( node, xmlbuff );
445 if (doc->standalone != -2)
447 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
448 xmlNodeAddContent( node, xmlbuff );
451 xmldoc_link_xmldecl( doc, node );
457 void xmldoc_init(xmlDocPtr doc, const GUID *clsid)
459 doc->_private = create_priv();
460 priv_from_xmlDocPtr(doc)->properties = create_properties(clsid);
463 LONG xmldoc_add_ref(xmlDocPtr doc)
465 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
466 TRACE("(%p)->(%d)\n", doc, ref);
470 LONG xmldoc_release(xmlDocPtr doc)
472 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
473 LONG ref = InterlockedDecrement(&priv->refs);
474 TRACE("(%p)->(%d)\n", doc, ref);
477 orphan_entry *orphan, *orphan2;
478 TRACE("freeing docptr %p\n", doc);
480 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
482 xmlFreeNode( orphan->node );
485 free_properties(priv->properties);
486 heap_free(doc->_private);
494 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
496 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
499 entry = heap_alloc( sizeof (*entry) );
501 return E_OUTOFMEMORY;
504 list_add_head( &priv->orphans, &entry->entry );
508 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
510 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
511 orphan_entry *entry, *entry2;
513 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
515 if( entry->node == node )
517 list_remove( &entry->entry );
526 static inline xmlDocPtr get_doc( domdoc *This )
528 return (xmlDocPtr)This->node.node;
531 static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
535 priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
536 if (xmldoc_release(get_doc(This)) != 0)
537 priv_from_xmlDocPtr(get_doc(This))->properties =
538 copy_properties(This->properties);
541 This->node.node = (xmlNodePtr) xml;
545 xmldoc_add_ref(get_doc(This));
546 priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
552 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
554 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
557 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
559 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStreamInit));
562 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
564 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
567 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
569 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
572 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
574 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblISupportErrorInfo));
577 static inline domdoc *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
579 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtblConnectionPointContainer));
582 /************************************************************************
583 * domdoc implementation of IPersistStream.
585 static HRESULT WINAPI domdoc_IPersistStreamInit_QueryInterface(
586 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
588 domdoc *this = impl_from_IPersistStreamInit(iface);
589 return IXMLDOMDocument2_QueryInterface((IXMLDOMDocument2 *)this, riid, ppvObj);
592 static ULONG WINAPI domdoc_IPersistStreamInit_AddRef(
593 IPersistStreamInit *iface)
595 domdoc *this = impl_from_IPersistStreamInit(iface);
596 return IXMLDOMDocument2_AddRef((IXMLDOMDocument2 *)this);
599 static ULONG WINAPI domdoc_IPersistStreamInit_Release(
600 IPersistStreamInit *iface)
602 domdoc *this = impl_from_IPersistStreamInit(iface);
603 return IXMLDOMDocument2_Release((IXMLDOMDocument2 *)this);
606 static HRESULT WINAPI domdoc_IPersistStreamInit_GetClassID(
607 IPersistStreamInit *iface, CLSID *classid)
609 TRACE("(%p,%p): stub!\n", iface, classid);
614 *classid = CLSID_DOMDocument2;
619 static HRESULT WINAPI domdoc_IPersistStreamInit_IsDirty(
620 IPersistStreamInit *iface)
622 domdoc *This = impl_from_IPersistStreamInit(iface);
623 FIXME("(%p): stub!\n", This);
627 static HRESULT WINAPI domdoc_IPersistStreamInit_Load(
628 IPersistStreamInit *iface, LPSTREAM pStm)
630 domdoc *This = impl_from_IPersistStreamInit(iface);
633 DWORD read, written, len;
636 xmlDocPtr xmldoc = NULL;
638 TRACE("(%p)->(%p)\n", This, pStm);
643 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
649 IStream_Read(pStm, buf, sizeof(buf), &read);
650 hr = IStream_Write(This->stream, buf, read, &written);
651 } while(SUCCEEDED(hr) && written != 0 && read != 0);
655 ERR("Failed to copy stream\n");
659 hr = GetHGlobalFromStream(This->stream, &hglobal);
663 len = GlobalSize(hglobal);
664 ptr = GlobalLock(hglobal);
666 xmldoc = doparse(This, ptr, len, NULL);
667 GlobalUnlock(hglobal);
671 ERR("Failed to parse xml\n");
675 xmldoc->_private = create_priv();
677 return attach_xmldoc(This, xmldoc);
680 static HRESULT WINAPI domdoc_IPersistStreamInit_Save(
681 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
683 domdoc *This = impl_from_IPersistStreamInit(iface);
687 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
689 hr = IXMLDOMDocument3_get_xml( (IXMLDOMDocument3*)&This->lpVtbl, &xmlString );
692 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
694 hr = IStream_Write( stream, xmlString, len, NULL );
695 SysFreeString(xmlString);
698 TRACE("ret 0x%08x\n", hr);
703 static HRESULT WINAPI domdoc_IPersistStreamInit_GetSizeMax(
704 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
706 domdoc *This = impl_from_IPersistStreamInit(iface);
707 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
711 static HRESULT WINAPI domdoc_IPersistStreamInit_InitNew(
712 IPersistStreamInit *iface)
714 domdoc *This = impl_from_IPersistStreamInit(iface);
715 TRACE("(%p)\n", This);
719 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
721 domdoc_IPersistStreamInit_QueryInterface,
722 domdoc_IPersistStreamInit_AddRef,
723 domdoc_IPersistStreamInit_Release,
724 domdoc_IPersistStreamInit_GetClassID,
725 domdoc_IPersistStreamInit_IsDirty,
726 domdoc_IPersistStreamInit_Load,
727 domdoc_IPersistStreamInit_Save,
728 domdoc_IPersistStreamInit_GetSizeMax,
729 domdoc_IPersistStreamInit_InitNew
732 /* ISupportErrorInfo interface */
733 static HRESULT WINAPI support_error_QueryInterface(
734 ISupportErrorInfo *iface,
735 REFIID riid, void** ppvObj )
737 domdoc *This = impl_from_ISupportErrorInfo(iface);
738 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3 *)This, riid, ppvObj);
741 static ULONG WINAPI support_error_AddRef(
742 ISupportErrorInfo *iface )
744 domdoc *This = impl_from_ISupportErrorInfo(iface);
745 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
748 static ULONG WINAPI support_error_Release(
749 ISupportErrorInfo *iface )
751 domdoc *This = impl_from_ISupportErrorInfo(iface);
752 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
755 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
756 ISupportErrorInfo *iface,
759 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
763 static const struct ISupportErrorInfoVtbl support_error_vtbl =
765 support_error_QueryInterface,
766 support_error_AddRef,
767 support_error_Release,
768 support_error_InterfaceSupportsErrorInfo
771 /* IXMLDOMDocument2 interface */
772 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
774 domdoc *This = impl_from_IXMLDOMDocument3( iface );
776 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
780 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
781 IsEqualGUID( riid, &IID_IDispatch ) ||
782 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
783 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
784 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
785 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
789 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
790 IsEqualGUID(&IID_IPersistStreamInit, riid))
792 *ppvObject = &(This->lpvtblIPersistStreamInit);
794 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
796 *ppvObject = &(This->lpvtblIObjectWithSite);
798 else if (IsEqualGUID(&IID_IObjectSafety, riid))
800 *ppvObject = &(This->lpvtblIObjectSafety);
802 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
804 *ppvObject = &This->lpvtblISupportErrorInfo;
806 else if(node_query_interface(&This->node, riid, ppvObject))
808 return *ppvObject ? S_OK : E_NOINTERFACE;
810 else if (IsEqualGUID( riid, &IID_IConnectionPointContainer ))
812 *ppvObject = &This->lpVtblConnectionPointContainer;
814 else if(IsEqualGUID(&IID_IRunnableObject, riid))
816 TRACE("IID_IRunnableObject not supported returning NULL\n");
817 return E_NOINTERFACE;
821 FIXME("interface %s not implemented\n", debugstr_guid(riid));
822 return E_NOINTERFACE;
825 IUnknown_AddRef((IUnknown*)*ppvObject);
831 static ULONG WINAPI domdoc_AddRef(
832 IXMLDOMDocument3 *iface )
834 domdoc *This = impl_from_IXMLDOMDocument3( iface );
835 TRACE("%p\n", This );
836 return InterlockedIncrement( &This->ref );
840 static ULONG WINAPI domdoc_Release(
841 IXMLDOMDocument3 *iface )
843 domdoc *This = impl_from_IXMLDOMDocument3( iface );
846 TRACE("%p\n", This );
848 ref = InterlockedDecrement( &This->ref );
852 detach_bsc(This->bsc);
855 IUnknown_Release( This->site );
856 destroy_xmlnode(&This->node);
857 if(This->schema) IXMLDOMSchemaCollection_Release( This->schema );
858 if (This->stream) IStream_Release(This->stream);
859 HeapFree( GetProcessHeap(), 0, This );
865 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
867 domdoc *This = impl_from_IXMLDOMDocument3( iface );
869 TRACE("(%p)->(%p)\n", This, pctinfo);
876 static HRESULT WINAPI domdoc_GetTypeInfo(
877 IXMLDOMDocument3 *iface,
878 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
880 domdoc *This = impl_from_IXMLDOMDocument3( iface );
883 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
885 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
890 static HRESULT WINAPI domdoc_GetIDsOfNames(
891 IXMLDOMDocument3 *iface,
898 domdoc *This = impl_from_IXMLDOMDocument3( iface );
902 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
905 if(!rgszNames || cNames == 0 || !rgDispId)
908 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
911 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
912 ITypeInfo_Release(typeinfo);
919 static HRESULT WINAPI domdoc_Invoke(
920 IXMLDOMDocument3 *iface,
925 DISPPARAMS* pDispParams,
927 EXCEPINFO* pExcepInfo,
930 domdoc *This = impl_from_IXMLDOMDocument3( iface );
934 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
935 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
937 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
940 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
941 pVarResult, pExcepInfo, puArgErr);
942 ITypeInfo_Release(typeinfo);
949 static HRESULT WINAPI domdoc_get_nodeName(
950 IXMLDOMDocument3 *iface,
953 domdoc *This = impl_from_IXMLDOMDocument3( iface );
955 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
957 TRACE("(%p)->(%p)\n", This, name);
959 return return_bstr(documentW, name);
963 static HRESULT WINAPI domdoc_get_nodeValue(
964 IXMLDOMDocument3 *iface,
967 domdoc *This = impl_from_IXMLDOMDocument3( iface );
969 TRACE("(%p)->(%p)\n", This, value);
974 V_VT(value) = VT_NULL;
975 V_BSTR(value) = NULL; /* tests show that we should do this */
980 static HRESULT WINAPI domdoc_put_nodeValue(
981 IXMLDOMDocument3 *iface,
984 domdoc *This = impl_from_IXMLDOMDocument3( iface );
985 FIXME("(%p)->(v%d)\n", This, V_VT(&value));
990 static HRESULT WINAPI domdoc_get_nodeType(
991 IXMLDOMDocument3 *iface,
994 domdoc *This = impl_from_IXMLDOMDocument3( iface );
996 TRACE("(%p)->(%p)\n", This, type);
998 *type = NODE_DOCUMENT;
1003 static HRESULT WINAPI domdoc_get_parentNode(
1004 IXMLDOMDocument3 *iface,
1005 IXMLDOMNode** parent )
1007 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1009 TRACE("(%p)->(%p)\n", This, parent);
1011 return node_get_parent(&This->node, parent);
1015 static HRESULT WINAPI domdoc_get_childNodes(
1016 IXMLDOMDocument3 *iface,
1017 IXMLDOMNodeList** childList )
1019 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1021 TRACE("(%p)->(%p)\n", This, childList);
1023 return node_get_child_nodes(&This->node, childList);
1027 static HRESULT WINAPI domdoc_get_firstChild(
1028 IXMLDOMDocument3 *iface,
1029 IXMLDOMNode** firstChild )
1031 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1033 TRACE("(%p)->(%p)\n", This, firstChild);
1035 return node_get_first_child(&This->node, firstChild);
1039 static HRESULT WINAPI domdoc_get_lastChild(
1040 IXMLDOMDocument3 *iface,
1041 IXMLDOMNode** lastChild )
1043 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1045 TRACE("(%p)->(%p)\n", This, lastChild);
1047 return node_get_last_child(&This->node, lastChild);
1051 static HRESULT WINAPI domdoc_get_previousSibling(
1052 IXMLDOMDocument3 *iface,
1053 IXMLDOMNode** previousSibling )
1055 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1057 TRACE("(%p)->(%p)\n", This, previousSibling);
1059 return return_null_node(previousSibling);
1063 static HRESULT WINAPI domdoc_get_nextSibling(
1064 IXMLDOMDocument3 *iface,
1065 IXMLDOMNode** nextSibling )
1067 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1069 TRACE("(%p)->(%p)\n", This, nextSibling);
1071 return return_null_node(nextSibling);
1075 static HRESULT WINAPI domdoc_get_attributes(
1076 IXMLDOMDocument3 *iface,
1077 IXMLDOMNamedNodeMap** attributeMap )
1079 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1081 TRACE("(%p)->(%p)\n", This, attributeMap);
1083 return return_null_ptr((void**)attributeMap);
1087 static HRESULT WINAPI domdoc_insertBefore(
1088 IXMLDOMDocument3 *iface,
1089 IXMLDOMNode* newChild,
1091 IXMLDOMNode** outNewChild )
1093 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1095 TRACE("(%p)->(%p x%d %p)\n", This, newChild, V_VT(&refChild), outNewChild);
1097 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1101 static HRESULT WINAPI domdoc_replaceChild(
1102 IXMLDOMDocument3 *iface,
1103 IXMLDOMNode* newChild,
1104 IXMLDOMNode* oldChild,
1105 IXMLDOMNode** outOldChild)
1107 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1109 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1111 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1115 static HRESULT WINAPI domdoc_removeChild(
1116 IXMLDOMDocument3 *iface,
1117 IXMLDOMNode* childNode,
1118 IXMLDOMNode** oldChild)
1120 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1121 return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), childNode, oldChild );
1125 static HRESULT WINAPI domdoc_appendChild(
1126 IXMLDOMDocument3 *iface,
1127 IXMLDOMNode* newChild,
1128 IXMLDOMNode** outNewChild)
1130 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1131 return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newChild, outNewChild );
1135 static HRESULT WINAPI domdoc_hasChildNodes(
1136 IXMLDOMDocument3 *iface,
1137 VARIANT_BOOL* hasChild)
1139 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1140 return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), hasChild );
1144 static HRESULT WINAPI domdoc_get_ownerDocument(
1145 IXMLDOMDocument3 *iface,
1146 IXMLDOMDocument** DOMDocument)
1148 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1149 return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), DOMDocument );
1153 static HRESULT WINAPI domdoc_cloneNode(
1154 IXMLDOMDocument3 *iface,
1156 IXMLDOMNode** cloneRoot)
1158 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1159 return IXMLDOMNode_cloneNode( IXMLDOMNode_from_impl(&This->node), deep, cloneRoot );
1163 static HRESULT WINAPI domdoc_get_nodeTypeString(
1164 IXMLDOMDocument3 *iface,
1167 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1168 return IXMLDOMNode_get_nodeTypeString( IXMLDOMNode_from_impl(&This->node), nodeType );
1172 static HRESULT WINAPI domdoc_get_text(
1173 IXMLDOMDocument3 *iface,
1176 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1177 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), text );
1181 static HRESULT WINAPI domdoc_put_text(
1182 IXMLDOMDocument3 *iface,
1185 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1186 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1191 static HRESULT WINAPI domdoc_get_specified(
1192 IXMLDOMDocument3 *iface,
1193 VARIANT_BOOL* isSpecified )
1195 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1196 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1197 *isSpecified = VARIANT_TRUE;
1202 static HRESULT WINAPI domdoc_get_definition(
1203 IXMLDOMDocument3 *iface,
1204 IXMLDOMNode** definitionNode )
1206 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1207 FIXME("(%p)->(%p)\n", This, definitionNode);
1212 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1213 IXMLDOMDocument3 *iface,
1214 VARIANT* typedValue )
1216 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1217 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
1220 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1221 IXMLDOMDocument3 *iface,
1222 VARIANT typedValue )
1224 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1225 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
1229 static HRESULT WINAPI domdoc_get_dataType(
1230 IXMLDOMDocument3 *iface,
1233 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1234 TRACE("(%p)->(%p)\n", This, typename);
1235 return return_null_var( typename );
1239 static HRESULT WINAPI domdoc_put_dataType(
1240 IXMLDOMDocument3 *iface,
1243 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1244 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
1248 static HRESULT WINAPI domdoc_get_xml(
1249 IXMLDOMDocument3 *iface,
1252 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1253 return IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), xmlString );
1257 static HRESULT WINAPI domdoc_transformNode(
1258 IXMLDOMDocument3 *iface,
1259 IXMLDOMNode* styleSheet,
1262 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1263 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), styleSheet, xmlString );
1267 static HRESULT WINAPI domdoc_selectNodes(
1268 IXMLDOMDocument3 *iface,
1270 IXMLDOMNodeList** resultList )
1272 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1273 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), queryString, resultList );
1277 static HRESULT WINAPI domdoc_selectSingleNode(
1278 IXMLDOMDocument3 *iface,
1280 IXMLDOMNode** resultNode )
1282 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1283 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), queryString, resultNode );
1287 static HRESULT WINAPI domdoc_get_parsed(
1288 IXMLDOMDocument3 *iface,
1289 VARIANT_BOOL* isParsed )
1291 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1292 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1293 *isParsed = VARIANT_TRUE;
1298 static HRESULT WINAPI domdoc_get_namespaceURI(
1299 IXMLDOMDocument3 *iface,
1300 BSTR* namespaceURI )
1302 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1303 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), namespaceURI );
1307 static HRESULT WINAPI domdoc_get_prefix(
1308 IXMLDOMDocument3 *iface,
1309 BSTR* prefixString )
1311 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1312 return IXMLDOMNode_get_prefix( IXMLDOMNode_from_impl(&This->node), prefixString );
1316 static HRESULT WINAPI domdoc_get_baseName(
1317 IXMLDOMDocument3 *iface,
1320 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1321 return IXMLDOMNode_get_baseName( IXMLDOMNode_from_impl(&This->node), nameString );
1325 static HRESULT WINAPI domdoc_transformNodeToObject(
1326 IXMLDOMDocument3 *iface,
1327 IXMLDOMNode* stylesheet,
1328 VARIANT outputObject)
1330 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1331 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), stylesheet, outputObject );
1335 static HRESULT WINAPI domdoc_get_doctype(
1336 IXMLDOMDocument3 *iface,
1337 IXMLDOMDocumentType** documentType )
1339 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1340 FIXME("(%p)\n", This);
1345 static HRESULT WINAPI domdoc_get_implementation(
1346 IXMLDOMDocument3 *iface,
1347 IXMLDOMImplementation** impl )
1349 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1351 TRACE("(%p)->(%p)\n", This, impl);
1354 return E_INVALIDARG;
1356 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1361 static HRESULT WINAPI domdoc_get_documentElement(
1362 IXMLDOMDocument3 *iface,
1363 IXMLDOMElement** DOMElement )
1365 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1366 IXMLDOMNode *element_node;
1370 TRACE("(%p)->(%p)\n", This, DOMElement);
1373 return E_INVALIDARG;
1377 root = xmlDocGetRootElement( get_doc(This) );
1381 element_node = create_node( root );
1382 if(!element_node) return S_FALSE;
1384 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1385 IXMLDOMNode_Release(element_node);
1391 static HRESULT WINAPI domdoc_put_documentElement(
1392 IXMLDOMDocument3 *iface,
1393 IXMLDOMElement* DOMElement )
1395 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1396 IXMLDOMNode *elementNode;
1401 TRACE("(%p)->(%p)\n", This, DOMElement);
1403 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1407 xmlNode = get_node_obj( elementNode );
1409 FIXME("elementNode is not our object\n");
1413 if(!xmlNode->node->parent)
1414 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1415 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1417 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1418 IXMLDOMNode_Release( elementNode );
1421 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1427 static HRESULT WINAPI domdoc_createElement(
1428 IXMLDOMDocument3 *iface,
1430 IXMLDOMElement** element )
1432 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1437 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1439 if (!element || !tagname) return E_INVALIDARG;
1441 V_VT(&type) = VT_I1;
1442 V_I1(&type) = NODE_ELEMENT;
1444 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1447 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1448 IXMLDOMNode_Release(node);
1455 static HRESULT WINAPI domdoc_createDocumentFragment(
1456 IXMLDOMDocument3 *iface,
1457 IXMLDOMDocumentFragment** frag )
1459 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1464 TRACE("(%p)->(%p)\n", This, frag);
1466 if (!frag) return E_INVALIDARG;
1470 V_VT(&type) = VT_I1;
1471 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1473 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1476 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1477 IXMLDOMNode_Release(node);
1484 static HRESULT WINAPI domdoc_createTextNode(
1485 IXMLDOMDocument3 *iface,
1487 IXMLDOMText** text )
1489 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1494 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1496 if (!text) return E_INVALIDARG;
1500 V_VT(&type) = VT_I1;
1501 V_I1(&type) = NODE_TEXT;
1503 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1506 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1507 IXMLDOMNode_Release(node);
1508 hr = IXMLDOMText_put_data(*text, data);
1515 static HRESULT WINAPI domdoc_createComment(
1516 IXMLDOMDocument3 *iface,
1518 IXMLDOMComment** comment )
1520 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1525 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1527 if (!comment) return E_INVALIDARG;
1531 V_VT(&type) = VT_I1;
1532 V_I1(&type) = NODE_COMMENT;
1534 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1537 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1538 IXMLDOMNode_Release(node);
1539 hr = IXMLDOMComment_put_data(*comment, data);
1546 static HRESULT WINAPI domdoc_createCDATASection(
1547 IXMLDOMDocument3 *iface,
1549 IXMLDOMCDATASection** cdata )
1551 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1556 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1558 if (!cdata) return E_INVALIDARG;
1562 V_VT(&type) = VT_I1;
1563 V_I1(&type) = NODE_CDATA_SECTION;
1565 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1568 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1569 IXMLDOMNode_Release(node);
1570 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1577 static HRESULT WINAPI domdoc_createProcessingInstruction(
1578 IXMLDOMDocument3 *iface,
1581 IXMLDOMProcessingInstruction** pi )
1583 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1588 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1590 if (!pi) return E_INVALIDARG;
1594 V_VT(&type) = VT_I1;
1595 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1597 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1602 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1603 node_obj = get_node_obj(node);
1604 hr = node_set_content(node_obj, data);
1606 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1607 IXMLDOMNode_Release(node);
1614 static HRESULT WINAPI domdoc_createAttribute(
1615 IXMLDOMDocument3 *iface,
1617 IXMLDOMAttribute** attribute )
1619 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1624 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1626 if (!attribute || !name) return E_INVALIDARG;
1628 V_VT(&type) = VT_I1;
1629 V_I1(&type) = NODE_ATTRIBUTE;
1631 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1634 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1635 IXMLDOMNode_Release(node);
1642 static HRESULT WINAPI domdoc_createEntityReference(
1643 IXMLDOMDocument3 *iface,
1645 IXMLDOMEntityReference** entityref )
1647 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1652 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1654 if (!entityref) return E_INVALIDARG;
1658 V_VT(&type) = VT_I1;
1659 V_I1(&type) = NODE_ENTITY_REFERENCE;
1661 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1664 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1665 IXMLDOMNode_Release(node);
1672 static HRESULT WINAPI domdoc_getElementsByTagName(
1673 IXMLDOMDocument3 *iface,
1675 IXMLDOMNodeList** resultList )
1677 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1680 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagName), resultList);
1682 if (!tagName || !resultList) return E_INVALIDARG;
1684 if (tagName[0] == '*' && tagName[1] == 0)
1686 static const WCHAR formatallW[] = {'/','/','*',0};
1687 hr = queryresult_create((xmlNodePtr)get_doc(This), formatallW, resultList);
1691 static const WCHAR xpathformat[] =
1692 { '/','/','*','[','l','o','c','a','l','-','n','a','m','e','(',')','=','\'' };
1693 static const WCHAR closeW[] = { '\'',']',0 };
1699 length = lstrlenW(tagName);
1701 /* without two WCHARs from format specifier */
1702 ptr = pattern = heap_alloc(sizeof(xpathformat) + length*sizeof(WCHAR) + sizeof(closeW));
1704 memcpy(ptr, xpathformat, sizeof(xpathformat));
1705 ptr += sizeof(xpathformat)/sizeof(WCHAR);
1706 memcpy(ptr, tagName, length*sizeof(WCHAR));
1708 memcpy(ptr, closeW, sizeof(closeW));
1710 hr = queryresult_create((xmlNodePtr)get_doc(This), pattern, resultList);
1717 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1723 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1725 return E_INVALIDARG;
1732 static HRESULT WINAPI domdoc_createNode(
1733 IXMLDOMDocument3 *iface,
1737 IXMLDOMNode** node )
1739 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1740 DOMNodeType node_type;
1742 xmlChar *xml_name, *href;
1745 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1747 if(!node) return E_INVALIDARG;
1749 hr = get_node_type(Type, &node_type);
1750 if(FAILED(hr)) return hr;
1752 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1753 FIXME("nodes with namespaces currently not supported.\n");
1755 TRACE("node_type %d\n", node_type);
1757 /* exit earlier for types that need name */
1761 case NODE_ATTRIBUTE:
1762 case NODE_ENTITY_REFERENCE:
1763 case NODE_PROCESSING_INSTRUCTION:
1764 if (!name || *name == 0) return E_FAIL;
1769 xml_name = xmlChar_from_wchar(name);
1770 /* prevent empty href to be allocated */
1771 href = namespaceURI ? xmlChar_from_wchar(namespaceURI) : NULL;
1777 xmlChar *local, *prefix;
1779 local = xmlSplitQName2(xml_name, &prefix);
1781 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
1783 /* allow to create default namespace xmlns= */
1784 if (local || (href && *href))
1786 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
1787 xmlSetNs(xmlnode, ns);
1795 case NODE_ATTRIBUTE:
1796 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1799 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1801 case NODE_CDATA_SECTION:
1802 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1804 case NODE_ENTITY_REFERENCE:
1805 xmlnode = xmlNewReference(get_doc(This), xml_name);
1807 case NODE_PROCESSING_INSTRUCTION:
1808 #ifdef HAVE_XMLNEWDOCPI
1809 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1811 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1816 xmlnode = xmlNewDocComment(get_doc(This), NULL);
1818 case NODE_DOCUMENT_FRAGMENT:
1819 xmlnode = xmlNewDocFragment(get_doc(This));
1821 /* unsupported types */
1823 case NODE_DOCUMENT_TYPE:
1826 heap_free(xml_name);
1827 return E_INVALIDARG;
1829 FIXME("unhandled node type %d\n", node_type);
1834 *node = create_node(xmlnode);
1835 heap_free(xml_name);
1840 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1841 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1848 static HRESULT WINAPI domdoc_nodeFromID(
1849 IXMLDOMDocument3 *iface,
1851 IXMLDOMNode** node )
1853 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1854 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1858 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1863 xmldoc = doparse(This, ptr, len, NULL);
1865 xmldoc->_private = create_priv();
1866 return attach_xmldoc(This, xmldoc);
1872 static HRESULT doread( domdoc *This, LPWSTR filename )
1877 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1882 detach_bsc(This->bsc);
1888 static HRESULT WINAPI domdoc_load(
1889 IXMLDOMDocument3 *iface,
1891 VARIANT_BOOL* isSuccessful )
1893 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1894 LPWSTR filename = NULL;
1895 HRESULT hr = S_FALSE;
1896 IXMLDOMDocument3 *pNewDoc = NULL;
1897 IStream *pStream = NULL;
1900 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
1902 *isSuccessful = VARIANT_FALSE;
1904 assert( &This->node );
1906 switch( V_VT(&xmlSource) )
1909 filename = V_BSTR(&xmlSource);
1912 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
1917 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
1918 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1919 hr = attach_xmldoc(This, xmldoc);
1922 *isSuccessful = VARIANT_TRUE;
1927 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1930 IPersistStream *pDocStream;
1931 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1934 hr = IPersistStream_Load(pDocStream, pStream);
1935 IStream_Release(pStream);
1938 *isSuccessful = VARIANT_TRUE;
1940 TRACE("Using IStream to load Document\n");
1945 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1950 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1955 /* ISequentialStream */
1956 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1960 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1963 TRACE("filename (%s)\n", debugstr_w(filename));
1967 hr = doread( This, filename );
1970 This->error = E_FAIL;
1973 hr = This->error = S_OK;
1974 *isSuccessful = VARIANT_TRUE;
1978 if(!filename || FAILED(hr)) {
1979 xmldoc = xmlNewDoc(NULL);
1980 xmldoc->_private = create_priv();
1981 hr = attach_xmldoc(This, xmldoc);
1986 TRACE("ret (%d)\n", hr);
1992 static HRESULT WINAPI domdoc_get_readyState(
1993 IXMLDOMDocument3 *iface,
1996 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1997 FIXME("stub! (%p)->(%p)\n", This, value);
2000 return E_INVALIDARG;
2002 *value = READYSTATE_COMPLETE;
2007 static HRESULT WINAPI domdoc_get_parseError(
2008 IXMLDOMDocument3 *iface,
2009 IXMLDOMParseError** errorObj )
2011 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2012 static const WCHAR err[] = {'e','r','r','o','r',0};
2013 BSTR error_string = NULL;
2015 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2018 error_string = SysAllocString(err);
2020 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2021 if(!*errorObj) return E_OUTOFMEMORY;
2026 static HRESULT WINAPI domdoc_get_url(
2027 IXMLDOMDocument3 *iface,
2030 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2031 FIXME("(%p)->(%p)\n", This, urlString);
2036 static HRESULT WINAPI domdoc_get_async(
2037 IXMLDOMDocument3 *iface,
2038 VARIANT_BOOL* isAsync )
2040 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2042 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2043 *isAsync = This->async;
2048 static HRESULT WINAPI domdoc_put_async(
2049 IXMLDOMDocument3 *iface,
2050 VARIANT_BOOL isAsync )
2052 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2054 TRACE("(%p)->(%d)\n", This, isAsync);
2055 This->async = isAsync;
2060 static HRESULT WINAPI domdoc_abort(
2061 IXMLDOMDocument3 *iface )
2063 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2064 FIXME("%p\n", This);
2069 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
2074 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
2075 str = heap_alloc( len );
2078 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
2084 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2085 static HRESULT WINAPI domdoc_loadXML(
2086 IXMLDOMDocument3 *iface,
2088 VARIANT_BOOL* isSuccessful )
2090 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2091 static const xmlChar encoding[] = "UTF-8";
2092 xmlDocPtr xmldoc = NULL;
2093 HRESULT hr = S_FALSE, hr2;
2097 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2099 assert ( &This->node );
2103 *isSuccessful = VARIANT_FALSE;
2105 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
2107 xmldoc = doparse(This, str, len, encoding);
2111 This->error = E_FAIL;
2112 TRACE("failed to parse document\n");
2116 hr = This->error = S_OK;
2117 *isSuccessful = VARIANT_TRUE;
2118 TRACE("parsed document %p\n", xmldoc);
2123 xmldoc = xmlNewDoc(NULL);
2125 xmldoc->_private = create_priv();
2127 hr2 = attach_xmldoc(This, xmldoc);
2134 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2138 if(!WriteFile(ctx, buffer, len, &written, NULL))
2140 WARN("write error\n");
2147 static int XMLCALL domdoc_save_closecallback(void *ctx)
2149 return CloseHandle(ctx) ? 0 : -1;
2152 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2157 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2160 WARN("stream write error: 0x%08x\n", hr);
2167 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2169 IStream_Release((IStream*)ctx);
2173 static HRESULT WINAPI domdoc_save(
2174 IXMLDOMDocument3 *iface,
2175 VARIANT destination )
2177 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2178 xmlSaveCtxtPtr ctx = NULL;
2182 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
2183 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
2185 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
2187 FIXME("Unhandled vt %d\n", V_VT(&destination));
2191 if(V_VT(&destination) == VT_UNKNOWN)
2193 IUnknown *pUnk = V_UNKNOWN(&destination);
2194 IXMLDOMDocument2 *document;
2197 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2200 VARIANT_BOOL success;
2203 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2206 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2210 IXMLDOMDocument3_Release(document);
2214 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2217 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2218 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2222 IStream_Release(stream);
2229 /* save with file path */
2230 HANDLE handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
2231 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2232 if( handle == INVALID_HANDLE_VALUE )
2234 WARN("failed to create file\n");
2238 /* disable top XML declaration */
2239 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2240 handle, NULL, XML_SAVE_NO_DECL);
2243 CloseHandle(handle);
2248 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2249 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2250 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2252 /* will release resources through close callback */
2258 static HRESULT WINAPI domdoc_get_validateOnParse(
2259 IXMLDOMDocument3 *iface,
2260 VARIANT_BOOL* isValidating )
2262 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2263 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2264 *isValidating = This->validating;
2269 static HRESULT WINAPI domdoc_put_validateOnParse(
2270 IXMLDOMDocument3 *iface,
2271 VARIANT_BOOL isValidating )
2273 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2274 TRACE("(%p)->(%d)\n", This, isValidating);
2275 This->validating = isValidating;
2280 static HRESULT WINAPI domdoc_get_resolveExternals(
2281 IXMLDOMDocument3 *iface,
2282 VARIANT_BOOL* isResolving )
2284 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2285 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2286 *isResolving = This->resolving;
2291 static HRESULT WINAPI domdoc_put_resolveExternals(
2292 IXMLDOMDocument3 *iface,
2293 VARIANT_BOOL isResolving )
2295 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2296 TRACE("(%p)->(%d)\n", This, isResolving);
2297 This->resolving = isResolving;
2302 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2303 IXMLDOMDocument3 *iface,
2304 VARIANT_BOOL* isPreserving )
2306 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2307 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->preserving);
2308 *isPreserving = This->preserving;
2313 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2314 IXMLDOMDocument3 *iface,
2315 VARIANT_BOOL isPreserving )
2317 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2318 TRACE("(%p)->(%d)\n", This, isPreserving);
2319 This->preserving = isPreserving;
2324 static HRESULT WINAPI domdoc_put_onReadyStateChange(
2325 IXMLDOMDocument3 *iface,
2326 VARIANT readyStateChangeSink )
2328 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2329 FIXME("%p\n", This);
2334 static HRESULT WINAPI domdoc_put_onDataAvailable(
2335 IXMLDOMDocument3 *iface,
2336 VARIANT onDataAvailableSink )
2338 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2339 FIXME("%p\n", This);
2343 static HRESULT WINAPI domdoc_put_onTransformNode(
2344 IXMLDOMDocument3 *iface,
2345 VARIANT onTransformNodeSink )
2347 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2348 FIXME("%p\n", This);
2352 static HRESULT WINAPI domdoc_get_namespaces(
2353 IXMLDOMDocument3* iface,
2354 IXMLDOMSchemaCollection** schemaCollection )
2356 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2357 FIXME("(%p)->(%p)\n", This, schemaCollection);
2361 static HRESULT WINAPI domdoc_get_schemas(
2362 IXMLDOMDocument3* iface,
2365 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2366 HRESULT hr = S_FALSE;
2367 IXMLDOMSchemaCollection *cur_schema = This->schema;
2369 TRACE("(%p)->(%p)\n", This, var1);
2371 VariantInit(var1); /* Test shows we don't call VariantClear here */
2372 V_VT(var1) = VT_NULL;
2376 hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2378 V_VT(var1) = VT_DISPATCH;
2383 static HRESULT WINAPI domdoc_putref_schemas(
2384 IXMLDOMDocument3* iface,
2387 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2388 HRESULT hr = E_FAIL;
2389 IXMLDOMSchemaCollection *new_schema = NULL;
2391 FIXME("(%p): semi-stub\n", This);
2395 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2399 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2408 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2413 IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
2414 if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
2420 static HRESULT WINAPI domdoc_validate(
2421 IXMLDOMDocument3* iface,
2422 IXMLDOMParseError** err)
2424 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2426 xmlValidCtxtPtr vctx;
2428 TRACE("(%p)->(%p)\n", This, err);
2429 domdoc_get_readyState(iface, &state);
2430 if (state != READYSTATE_COMPLETE)
2433 *err = create_parseError(0, NULL, NULL, NULL, 0, 0, 0);
2437 vctx = xmlNewValidCtxt();
2438 vctx->error = NULL; /* TODO: error callback */
2439 vctx->warning = NULL; /* TODO: warning callback */
2441 if (xmlValidateDocument(vctx, get_doc(This)))
2444 *err = create_parseError(0, NULL, NULL, NULL, 0, 0, 0);
2445 xmlFreeValidCtxt(vctx);
2449 FIXME("partial stub!\n");
2451 *err = create_parseError(0xC00CE223, NULL, NULL, NULL, 0, 0, 0);
2452 xmlFreeValidCtxt(vctx);
2456 static HRESULT WINAPI domdoc_setProperty(
2457 IXMLDOMDocument3* iface,
2461 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2463 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2465 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2471 V_VT(&varStr) = VT_EMPTY;
2472 if (V_VT(&var) != VT_BSTR)
2474 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2476 bstr = V_BSTR(&varStr);
2479 bstr = V_BSTR(&var);
2482 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2483 This->properties->XPath = TRUE;
2484 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2485 This->properties->XPath = FALSE;
2489 VariantClear(&varStr);
2492 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2497 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2498 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2499 xmlXPathContextPtr ctx;
2500 struct list *pNsList;
2501 select_ns_entry* pNsEntry = NULL;
2503 V_VT(&varStr) = VT_EMPTY;
2504 if (V_VT(&var) != VT_BSTR)
2506 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2508 bstr = V_BSTR(&varStr);
2511 bstr = V_BSTR(&var);
2515 pNsList = &(This->properties->selectNsList);
2516 clear_selectNsList(pNsList);
2518 nsStr = xmlChar_from_wchar(bstr);
2521 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2523 This->properties->selectNsStr = nsStr;
2524 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2527 ctx = xmlXPathNewContext(This->node.node->doc);
2530 for (; *pTokBegin; pTokBegin = pTokEnd)
2532 if (pNsEntry != NULL)
2533 memset(pNsEntry, 0, sizeof(select_ns_entry));
2535 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2537 while (*pTokBegin == ' ')
2539 pTokEnd = pTokBegin;
2540 while (*pTokEnd != ' ' && *pTokEnd != 0)
2543 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2546 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2547 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2552 if (*pTokBegin == '=')
2554 /*valid for XSLPattern?*/
2555 FIXME("Setting default xmlns not supported - skipping.\n");
2556 pTokBegin = pTokEnd;
2559 else if (*pTokBegin == ':')
2561 pNsEntry->prefix = ++pTokBegin;
2562 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2565 if (pTokInner == pTokEnd)
2568 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2569 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2573 pNsEntry->prefix_end = *pTokInner;
2577 if (pTokEnd-pTokInner > 1 &&
2578 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2579 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2581 pNsEntry->href = ++pTokInner;
2582 pNsEntry->href_end = *(pTokEnd-1);
2584 list_add_tail(pNsList, &pNsEntry->entry);
2585 /*let libxml figure out if they're valid from here ;)*/
2586 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2595 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2596 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2597 list_add_tail(pNsList, &pNsEntry->entry);
2610 heap_free(pNsEntry);
2611 xmlXPathFreeContext(ctx);
2614 VariantClear(&varStr);
2617 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2618 lstrcmpiW(p, PropertyNewParserW) == 0)
2621 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2625 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2629 static HRESULT WINAPI domdoc_getProperty(
2630 IXMLDOMDocument3* iface,
2634 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2636 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2639 return E_INVALIDARG;
2641 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2643 V_VT(var) = VT_BSTR;
2644 V_BSTR(var) = This->properties->XPath ?
2645 SysAllocString(PropValueXPathW) :
2646 SysAllocString(PropValueXSLPatternW);
2647 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2649 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2652 BSTR rebuiltStr, cur;
2653 const xmlChar *nsStr;
2654 struct list *pNsList;
2655 select_ns_entry* pNsEntry;
2657 V_VT(var) = VT_BSTR;
2658 nsStr = This->properties->selectNsStr;
2659 pNsList = &This->properties->selectNsList;
2660 lenA = This->properties->selectNsStr_len;
2661 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
2662 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
2663 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
2665 /* this is fine because all of the chars that end tokens are ASCII*/
2666 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
2668 while (*cur != 0) ++cur;
2669 if (pNsEntry->prefix_end)
2671 *cur = pNsEntry->prefix_end;
2672 while (*cur != 0) ++cur;
2675 if (pNsEntry->href_end)
2677 *cur = pNsEntry->href_end;
2680 V_BSTR(var) = SysAllocString(rebuiltStr);
2681 heap_free(rebuiltStr);
2685 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2689 static HRESULT WINAPI domdoc_validateNode(
2690 IXMLDOMDocument3* iface,
2692 IXMLDOMParseError** error)
2694 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2695 FIXME("(%p)->(%p %p): stub\n", This, node, error);
2699 static HRESULT WINAPI domdoc_importNode(
2700 IXMLDOMDocument3* iface,
2703 IXMLDOMNode** clone)
2705 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2706 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
2710 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
2712 domdoc_QueryInterface,
2715 domdoc_GetTypeInfoCount,
2717 domdoc_GetIDsOfNames,
2719 domdoc_get_nodeName,
2720 domdoc_get_nodeValue,
2721 domdoc_put_nodeValue,
2722 domdoc_get_nodeType,
2723 domdoc_get_parentNode,
2724 domdoc_get_childNodes,
2725 domdoc_get_firstChild,
2726 domdoc_get_lastChild,
2727 domdoc_get_previousSibling,
2728 domdoc_get_nextSibling,
2729 domdoc_get_attributes,
2730 domdoc_insertBefore,
2731 domdoc_replaceChild,
2734 domdoc_hasChildNodes,
2735 domdoc_get_ownerDocument,
2737 domdoc_get_nodeTypeString,
2740 domdoc_get_specified,
2741 domdoc_get_definition,
2742 domdoc_get_nodeTypedValue,
2743 domdoc_put_nodeTypedValue,
2744 domdoc_get_dataType,
2745 domdoc_put_dataType,
2747 domdoc_transformNode,
2749 domdoc_selectSingleNode,
2751 domdoc_get_namespaceURI,
2753 domdoc_get_baseName,
2754 domdoc_transformNodeToObject,
2756 domdoc_get_implementation,
2757 domdoc_get_documentElement,
2758 domdoc_put_documentElement,
2759 domdoc_createElement,
2760 domdoc_createDocumentFragment,
2761 domdoc_createTextNode,
2762 domdoc_createComment,
2763 domdoc_createCDATASection,
2764 domdoc_createProcessingInstruction,
2765 domdoc_createAttribute,
2766 domdoc_createEntityReference,
2767 domdoc_getElementsByTagName,
2771 domdoc_get_readyState,
2772 domdoc_get_parseError,
2779 domdoc_get_validateOnParse,
2780 domdoc_put_validateOnParse,
2781 domdoc_get_resolveExternals,
2782 domdoc_put_resolveExternals,
2783 domdoc_get_preserveWhiteSpace,
2784 domdoc_put_preserveWhiteSpace,
2785 domdoc_put_onReadyStateChange,
2786 domdoc_put_onDataAvailable,
2787 domdoc_put_onTransformNode,
2788 domdoc_get_namespaces,
2790 domdoc_putref_schemas,
2794 domdoc_validateNode,
2798 /* IConnectionPointContainer */
2799 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
2800 REFIID riid, void **ppv)
2802 domdoc *This = impl_from_IConnectionPointContainer(iface);
2803 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)This, riid, ppv);
2806 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
2808 domdoc *This = impl_from_IConnectionPointContainer(iface);
2809 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)This);
2812 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
2814 domdoc *This = impl_from_IConnectionPointContainer(iface);
2815 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)This);
2818 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
2819 IEnumConnectionPoints **ppEnum)
2821 domdoc *This = impl_from_IConnectionPointContainer(iface);
2822 FIXME("(%p)->(%p): stub\n", This, ppEnum);
2826 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
2827 REFIID riid, IConnectionPoint **cp)
2829 domdoc *This = impl_from_IConnectionPointContainer(iface);
2830 ConnectionPoint *iter;
2832 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
2836 for(iter = This->cp_list; iter; iter = iter->next)
2838 if (IsEqualGUID(iter->iid, riid))
2839 *cp = (IConnectionPoint*)&iter->lpVtblConnectionPoint;
2844 IConnectionPoint_AddRef(*cp);
2848 FIXME("unsupported riid %s\n", debugstr_guid(riid));
2849 return CONNECT_E_NOCONNECTION;
2853 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
2855 ConnectionPointContainer_QueryInterface,
2856 ConnectionPointContainer_AddRef,
2857 ConnectionPointContainer_Release,
2858 ConnectionPointContainer_EnumConnectionPoints,
2859 ConnectionPointContainer_FindConnectionPoint
2862 /* IConnectionPoint */
2863 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
2864 REFIID riid, void **ppv)
2866 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2868 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
2872 if (IsEqualGUID(&IID_IUnknown, riid) ||
2873 IsEqualGUID(&IID_IConnectionPoint, riid))
2880 IConnectionPoint_AddRef(iface);
2884 WARN("Unsupported interface %s\n", debugstr_guid(riid));
2885 return E_NOINTERFACE;
2888 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
2890 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2891 return IConnectionPointContainer_AddRef(This->container);
2894 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
2896 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2897 return IConnectionPointContainer_Release(This->container);
2900 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
2902 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2904 TRACE("(%p)->(%p)\n", This, iid);
2906 if (!iid) return E_POINTER;
2912 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
2913 IConnectionPointContainer **container)
2915 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2917 TRACE("(%p)->(%p)\n", This, container);
2919 if (!container) return E_POINTER;
2921 *container = This->container;
2922 IConnectionPointContainer_AddRef(*container);
2926 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
2929 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2930 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
2934 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
2936 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2938 TRACE("(%p)->(%d)\n", This, cookie);
2940 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
2941 return CONNECT_E_NOCONNECTION;
2943 IUnknown_Release(This->sinks[cookie-1].unk);
2944 This->sinks[cookie-1].unk = NULL;
2949 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
2950 IEnumConnections **ppEnum)
2952 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2953 FIXME("(%p)->(%p): stub\n", This, ppEnum);
2957 static const IConnectionPointVtbl ConnectionPointVtbl =
2959 ConnectionPoint_QueryInterface,
2960 ConnectionPoint_AddRef,
2961 ConnectionPoint_Release,
2962 ConnectionPoint_GetConnectionInterface,
2963 ConnectionPoint_GetConnectionPointContainer,
2964 ConnectionPoint_Advise,
2965 ConnectionPoint_Unadvise,
2966 ConnectionPoint_EnumConnections
2969 void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
2971 cp->lpVtblConnectionPoint = &ConnectionPointVtbl;
2977 cp->next = doc->cp_list;
2980 cp->container = (IConnectionPointContainer*)&doc->lpVtblConnectionPointContainer;
2983 /* domdoc implementation of IObjectWithSite */
2984 static HRESULT WINAPI
2985 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
2987 domdoc *This = impl_from_IObjectWithSite(iface);
2988 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppvObject );
2991 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
2993 domdoc *This = impl_from_IObjectWithSite(iface);
2994 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
2997 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
2999 domdoc *This = impl_from_IObjectWithSite(iface);
3000 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3003 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3005 domdoc *This = impl_from_IObjectWithSite(iface);
3007 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3012 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3015 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3017 domdoc *This = impl_from_IObjectWithSite(iface);
3019 TRACE("(%p)->(%p)\n", iface, punk);
3025 IUnknown_Release( This->site );
3032 IUnknown_AddRef( punk );
3035 IUnknown_Release( This->site );
3042 static const IObjectWithSiteVtbl domdocObjectSite =
3044 domdoc_ObjectWithSite_QueryInterface,
3045 domdoc_ObjectWithSite_AddRef,
3046 domdoc_ObjectWithSite_Release,
3047 domdoc_ObjectWithSite_SetSite,
3048 domdoc_ObjectWithSite_GetSite
3051 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3053 domdoc *This = impl_from_IObjectSafety(iface);
3054 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppv );
3057 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3059 domdoc *This = impl_from_IObjectSafety(iface);
3060 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3063 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3065 domdoc *This = impl_from_IObjectSafety(iface);
3066 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3069 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3071 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3072 DWORD *supported, DWORD *enabled)
3074 domdoc *This = impl_from_IObjectSafety(iface);
3076 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3078 if(!supported || !enabled) return E_POINTER;
3080 *supported = SAFETY_SUPPORTED_OPTIONS;
3081 *enabled = This->safeopt;
3086 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3087 DWORD mask, DWORD enabled)
3089 domdoc *This = impl_from_IObjectSafety(iface);
3090 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3092 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3095 This->safeopt = enabled & mask & SAFETY_SUPPORTED_OPTIONS;
3099 #undef SAFETY_SUPPORTED_OPTIONS
3101 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3102 domdoc_Safety_QueryInterface,
3103 domdoc_Safety_AddRef,
3104 domdoc_Safety_Release,
3105 domdoc_Safety_GetInterfaceSafetyOptions,
3106 domdoc_Safety_SetInterfaceSafetyOptions
3109 static const tid_t domdoc_iface_tids[] = {
3111 IXMLDOMDocument_tid,
3112 IXMLDOMDocument2_tid,
3115 static dispex_static_data_t domdoc_dispex = {
3117 IXMLDOMDocument2_tid,
3122 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3126 doc = heap_alloc( sizeof (*doc) );
3128 return E_OUTOFMEMORY;
3130 doc->lpVtbl = &domdoc_vtbl;
3131 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
3132 doc->lpvtblIObjectWithSite = &domdocObjectSite;
3133 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
3134 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
3135 doc->lpVtblConnectionPointContainer = &ConnectionPointContainerVtbl;
3137 doc->async = VARIANT_TRUE;
3138 doc->validating = 0;
3140 doc->preserving = 0;
3141 doc->properties = properties_from_xmlDocPtr(xmldoc);
3148 doc->cp_list = NULL;
3150 /* events connection points */
3151 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3152 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3153 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3155 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->lpVtbl, &domdoc_dispex);
3157 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
3159 TRACE("returning iface %p\n", *document);
3163 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3168 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
3170 xmldoc = xmlNewDoc(NULL);
3172 return E_OUTOFMEMORY;
3174 xmldoc->_private = create_priv();
3175 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
3177 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3180 free_properties(properties_from_xmlDocPtr(xmldoc));
3181 heap_free(xmldoc->_private);
3189 IUnknown* create_domdoc( xmlNodePtr document )
3194 TRACE("(%p)\n", document);
3196 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3205 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3207 MESSAGE("This program tried to use a DOMDocument object, but\n"
3208 "libxml2 support was not present at compile time.\n");