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 const struct IXMLDOMDocument3Vtbl *lpVtbl;
100 const struct IPersistStreamInitVtbl *lpvtblIPersistStreamInit;
101 const struct IObjectWithSiteVtbl *lpvtblIObjectWithSite;
102 const struct IObjectSafetyVtbl *lpvtblIObjectSafety;
103 const struct ISupportErrorInfoVtbl *lpvtblISupportErrorInfo;
104 const struct IConnectionPointContainerVtbl *lpVtblConnectionPointContainer;
107 VARIANT_BOOL validating;
108 VARIANT_BOOL resolving;
109 VARIANT_BOOL preserving;
110 domdoc_properties* properties;
111 IXMLDOMSchemaCollection *schema;
124 /* connection list */
125 ConnectionPoint *cp_list;
126 ConnectionPoint cp_domdocevents;
127 ConnectionPoint cp_propnotif;
128 ConnectionPoint cp_dispatch;
131 static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface)
133 return (ConnectionPoint *)((char*)iface - FIELD_OFFSET(ConnectionPoint, lpVtblConnectionPoint));
137 In native windows, the whole lifetime management of XMLDOMNodes is
138 managed automatically using reference counts. Wine emulates that by
139 maintaining a reference count to the document that is increased for
140 each IXMLDOMNode pointer passed out for this document. If all these
141 pointers are gone, the document is unreachable and gets freed, that
142 is, all nodes in the tree of the document get freed.
144 You are able to create nodes that are associated to a document (in
145 fact, in msxml's XMLDOM model, all nodes are associated to a document),
146 but not in the tree of that document, for example using the createFoo
147 functions from IXMLDOMDocument. These nodes do not get cleaned up
148 by libxml, so we have to do it ourselves.
150 To catch these nodes, a list of "orphan nodes" is introduced.
151 It contains pointers to all roots of node trees that are
152 associated with the document without being part of the document
153 tree. All nodes with parent==NULL (except for the document root nodes)
154 should be in the orphan node list of their document. All orphan nodes
155 get freed together with the document itself.
158 typedef struct _xmldoc_priv {
161 domdoc_properties* properties;
164 typedef struct _orphan_entry {
169 typedef struct _select_ns_entry {
171 xmlChar const* prefix;
177 static inline xmldoc_priv * priv_from_xmlDocPtr(const xmlDocPtr doc)
179 return doc->_private;
182 static inline domdoc_properties * properties_from_xmlDocPtr(xmlDocPtr doc)
184 return priv_from_xmlDocPtr(doc)->properties;
187 BOOL is_xpathmode(const xmlDocPtr doc)
189 return properties_from_xmlDocPtr(doc)->XPath;
192 int registerNamespaces(xmlXPathContextPtr ctxt)
195 const select_ns_entry* ns = NULL;
196 const struct list* pNsList = &properties_from_xmlDocPtr(ctxt->doc)->selectNsList;
198 TRACE("(%p)\n", ctxt);
200 LIST_FOR_EACH_ENTRY( ns, pNsList, select_ns_entry, entry )
202 xmlXPathRegisterNs(ctxt, ns->prefix, ns->href);
209 static inline void clear_selectNsList(struct list* pNsList)
211 select_ns_entry *ns, *ns2;
212 LIST_FOR_EACH_ENTRY_SAFE( ns, ns2, pNsList, select_ns_entry, entry )
219 static xmldoc_priv * create_priv(void)
222 priv = heap_alloc( sizeof (*priv) );
227 list_init( &priv->orphans );
228 priv->properties = NULL;
234 static domdoc_properties * create_properties(const GUID *clsid)
236 domdoc_properties *properties = heap_alloc(sizeof(domdoc_properties));
238 list_init( &properties->selectNsList );
239 properties->selectNsStr = heap_alloc_zero(sizeof(xmlChar));
240 properties->selectNsStr_len = 0;
241 properties->XPath = FALSE;
243 /* properties that are dependent on object versions */
244 if (IsEqualCLSID( clsid, &CLSID_DOMDocument40 ) ||
245 IsEqualCLSID( clsid, &CLSID_DOMDocument60 ))
247 properties->XPath = TRUE;
253 static domdoc_properties* copy_properties(domdoc_properties const* properties)
255 domdoc_properties* pcopy = heap_alloc(sizeof(domdoc_properties));
256 select_ns_entry const* ns = NULL;
257 select_ns_entry* new_ns = NULL;
258 int len = (properties->selectNsStr_len+1)*sizeof(xmlChar);
263 pcopy->XPath = properties->XPath;
264 pcopy->selectNsStr_len = properties->selectNsStr_len;
265 list_init( &pcopy->selectNsList );
266 pcopy->selectNsStr = heap_alloc(len);
267 memcpy((xmlChar*)pcopy->selectNsStr, properties->selectNsStr, len);
268 offset = pcopy->selectNsStr - properties->selectNsStr;
270 LIST_FOR_EACH_ENTRY( ns, (&properties->selectNsList), select_ns_entry, entry )
272 new_ns = heap_alloc(sizeof(select_ns_entry));
273 memcpy(new_ns, ns, sizeof(select_ns_entry));
274 new_ns->href += offset;
275 new_ns->prefix += offset;
276 list_add_tail(&pcopy->selectNsList, &new_ns->entry);
284 static void free_properties(domdoc_properties* properties)
288 clear_selectNsList(&properties->selectNsList);
289 heap_free((xmlChar*)properties->selectNsStr);
290 heap_free(properties);
294 /* links a "<?xml" node as a first child */
295 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
298 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
301 /* unlinks a first "<?xml" child if it was created */
302 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
308 if (doc->standalone != -1)
310 node = doc->children;
311 xmlUnlinkNode( node );
319 static inline BOOL strn_isspace(xmlChar const* str, int len)
321 for (; str && len > 0 && *str; ++str, --len)
328 static void sax_characters(void *ctx, const xmlChar *ch, int len)
330 xmlParserCtxtPtr pctx;
333 pctx = (xmlParserCtxtPtr) ctx;
334 This = (domdoc const*) pctx->_private;
336 if (!This->preserving)
338 xmlChar* ws = xmlGetNsProp(pctx->node, BAD_CAST "space", XML_XML_NAMESPACE);
339 if ((!ws || xmlStrcmp(ws, BAD_CAST "preserve") != 0) &&
340 strn_isspace(ch, len))
348 xmlSAX2Characters(ctx, ch, len);
351 static xmlDocPtr doparse(domdoc* This, char *ptr, int len, xmlChar const* encoding)
353 xmlDocPtr doc = NULL;
354 xmlParserCtxtPtr pctx;
355 static xmlSAXHandler sax_handler = {
356 xmlSAX2InternalSubset, /* internalSubset */
357 xmlSAX2IsStandalone, /* isStandalone */
358 xmlSAX2HasInternalSubset, /* hasInternalSubset */
359 xmlSAX2HasExternalSubset, /* hasExternalSubset */
360 xmlSAX2ResolveEntity, /* resolveEntity */
361 xmlSAX2GetEntity, /* getEntity */
362 xmlSAX2EntityDecl, /* entityDecl */
363 xmlSAX2NotationDecl, /* notationDecl */
364 xmlSAX2AttributeDecl, /* attributeDecl */
365 xmlSAX2ElementDecl, /* elementDecl */
366 xmlSAX2UnparsedEntityDecl, /* unparsedEntityDecl */
367 xmlSAX2SetDocumentLocator, /* setDocumentLocator */
368 xmlSAX2StartDocument, /* startDocument */
369 xmlSAX2EndDocument, /* endDocument */
370 xmlSAX2StartElement, /* startElement */
371 xmlSAX2EndElement, /* endElement */
372 xmlSAX2Reference, /* reference */
373 sax_characters, /* characters */
374 sax_characters, /* ignorableWhitespace */
375 xmlSAX2ProcessingInstruction, /* processingInstruction */
376 xmlSAX2Comment, /* comment */
377 NULL, /* TODO: warning */
378 NULL, /* TODO: error */
379 NULL, /* TODO: fatalError */
380 xmlSAX2GetParameterEntity, /* getParameterEntity */
381 xmlSAX2CDataBlock, /* cdataBlock */
382 xmlSAX2ExternalSubset, /* externalSubset */
385 xmlSAX2StartElementNs, /* startElementNs */
386 xmlSAX2EndElementNs, /* endElementNs */
387 NULL /* TODO: serror */
391 pctx = xmlCreateMemoryParserCtxt(ptr, len);
394 ERR("Failed to create parser context\n");
398 if (pctx->sax) xmlFree(pctx->sax);
399 pctx->sax = &sax_handler;
400 pctx->_private = This;
402 pctx->encoding = xmlStrdup(encoding);
403 xmlParseDocument(pctx);
405 if (pctx->wellFormed)
411 xmlFreeDoc(pctx->myDoc);
415 xmlFreeParserCtxt(pctx);
417 /* TODO: put this in one of the SAX callbacks */
418 /* create first child as a <?xml...?> */
419 if (doc && doc->standalone != -1)
423 xmlChar *xmlbuff = (xmlChar*)buff;
425 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
427 /* version attribute can't be omitted */
428 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
429 xmlNodeAddContent( node, xmlbuff );
433 sprintf(buff, " encoding=\"%s\"", doc->encoding);
434 xmlNodeAddContent( node, xmlbuff );
437 if (doc->standalone != -2)
439 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
440 xmlNodeAddContent( node, xmlbuff );
443 xmldoc_link_xmldecl( doc, node );
449 void xmldoc_init(xmlDocPtr doc, const GUID *clsid)
451 doc->_private = create_priv();
452 priv_from_xmlDocPtr(doc)->properties = create_properties(clsid);
455 LONG xmldoc_add_ref(xmlDocPtr doc)
457 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
458 TRACE("(%p)->(%d)\n", doc, ref);
462 LONG xmldoc_release(xmlDocPtr doc)
464 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
465 LONG ref = InterlockedDecrement(&priv->refs);
466 TRACE("(%p)->(%d)\n", doc, ref);
469 orphan_entry *orphan, *orphan2;
470 TRACE("freeing docptr %p\n", doc);
472 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
474 xmlFreeNode( orphan->node );
477 free_properties(priv->properties);
478 heap_free(doc->_private);
486 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
488 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
491 entry = heap_alloc( sizeof (*entry) );
493 return E_OUTOFMEMORY;
496 list_add_head( &priv->orphans, &entry->entry );
500 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
502 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
503 orphan_entry *entry, *entry2;
505 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
507 if( entry->node == node )
509 list_remove( &entry->entry );
518 static inline xmlDocPtr get_doc( domdoc *This )
520 return (xmlDocPtr)This->node.node;
523 static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
527 priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
528 if (xmldoc_release(get_doc(This)) != 0)
529 priv_from_xmlDocPtr(get_doc(This))->properties =
530 copy_properties(This->properties);
533 This->node.node = (xmlNodePtr) xml;
537 xmldoc_add_ref(get_doc(This));
538 priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
544 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
546 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
549 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
551 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStreamInit));
554 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
556 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
559 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
561 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
564 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
566 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblISupportErrorInfo));
569 static inline domdoc *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
571 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtblConnectionPointContainer));
574 /************************************************************************
575 * domdoc implementation of IPersistStream.
577 static HRESULT WINAPI domdoc_IPersistStreamInit_QueryInterface(
578 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
580 domdoc *this = impl_from_IPersistStreamInit(iface);
581 return IXMLDOMDocument2_QueryInterface((IXMLDOMDocument2 *)this, riid, ppvObj);
584 static ULONG WINAPI domdoc_IPersistStreamInit_AddRef(
585 IPersistStreamInit *iface)
587 domdoc *this = impl_from_IPersistStreamInit(iface);
588 return IXMLDOMDocument2_AddRef((IXMLDOMDocument2 *)this);
591 static ULONG WINAPI domdoc_IPersistStreamInit_Release(
592 IPersistStreamInit *iface)
594 domdoc *this = impl_from_IPersistStreamInit(iface);
595 return IXMLDOMDocument2_Release((IXMLDOMDocument2 *)this);
598 static HRESULT WINAPI domdoc_IPersistStreamInit_GetClassID(
599 IPersistStreamInit *iface, CLSID *classid)
601 TRACE("(%p,%p): stub!\n", iface, classid);
606 *classid = CLSID_DOMDocument2;
611 static HRESULT WINAPI domdoc_IPersistStreamInit_IsDirty(
612 IPersistStreamInit *iface)
614 domdoc *This = impl_from_IPersistStreamInit(iface);
615 FIXME("(%p): stub!\n", This);
619 static HRESULT WINAPI domdoc_IPersistStreamInit_Load(
620 IPersistStreamInit *iface, LPSTREAM pStm)
622 domdoc *This = impl_from_IPersistStreamInit(iface);
625 DWORD read, written, len;
628 xmlDocPtr xmldoc = NULL;
630 TRACE("(%p)->(%p)\n", This, pStm);
635 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
641 IStream_Read(pStm, buf, sizeof(buf), &read);
642 hr = IStream_Write(This->stream, buf, read, &written);
643 } while(SUCCEEDED(hr) && written != 0 && read != 0);
647 ERR("Failed to copy stream\n");
651 hr = GetHGlobalFromStream(This->stream, &hglobal);
655 len = GlobalSize(hglobal);
656 ptr = GlobalLock(hglobal);
658 xmldoc = doparse(This, ptr, len, NULL);
659 GlobalUnlock(hglobal);
663 ERR("Failed to parse xml\n");
667 xmldoc->_private = create_priv();
669 return attach_xmldoc(This, xmldoc);
672 static HRESULT WINAPI domdoc_IPersistStreamInit_Save(
673 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
675 domdoc *This = impl_from_IPersistStreamInit(iface);
679 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
681 hr = IXMLDOMDocument3_get_xml( (IXMLDOMDocument3*)&This->lpVtbl, &xmlString );
684 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
686 hr = IStream_Write( stream, xmlString, len, NULL );
687 SysFreeString(xmlString);
690 TRACE("ret 0x%08x\n", hr);
695 static HRESULT WINAPI domdoc_IPersistStreamInit_GetSizeMax(
696 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
698 domdoc *This = impl_from_IPersistStreamInit(iface);
699 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
703 static HRESULT WINAPI domdoc_IPersistStreamInit_InitNew(
704 IPersistStreamInit *iface)
706 domdoc *This = impl_from_IPersistStreamInit(iface);
707 TRACE("(%p)\n", This);
711 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
713 domdoc_IPersistStreamInit_QueryInterface,
714 domdoc_IPersistStreamInit_AddRef,
715 domdoc_IPersistStreamInit_Release,
716 domdoc_IPersistStreamInit_GetClassID,
717 domdoc_IPersistStreamInit_IsDirty,
718 domdoc_IPersistStreamInit_Load,
719 domdoc_IPersistStreamInit_Save,
720 domdoc_IPersistStreamInit_GetSizeMax,
721 domdoc_IPersistStreamInit_InitNew
724 /* ISupportErrorInfo interface */
725 static HRESULT WINAPI support_error_QueryInterface(
726 ISupportErrorInfo *iface,
727 REFIID riid, void** ppvObj )
729 domdoc *This = impl_from_ISupportErrorInfo(iface);
730 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3 *)This, riid, ppvObj);
733 static ULONG WINAPI support_error_AddRef(
734 ISupportErrorInfo *iface )
736 domdoc *This = impl_from_ISupportErrorInfo(iface);
737 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
740 static ULONG WINAPI support_error_Release(
741 ISupportErrorInfo *iface )
743 domdoc *This = impl_from_ISupportErrorInfo(iface);
744 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
747 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
748 ISupportErrorInfo *iface,
751 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
755 static const struct ISupportErrorInfoVtbl support_error_vtbl =
757 support_error_QueryInterface,
758 support_error_AddRef,
759 support_error_Release,
760 support_error_InterfaceSupportsErrorInfo
763 /* IXMLDOMDocument2 interface */
764 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
766 domdoc *This = impl_from_IXMLDOMDocument3( iface );
768 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
772 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
773 IsEqualGUID( riid, &IID_IDispatch ) ||
774 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
775 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
776 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
777 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
781 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
782 IsEqualGUID(&IID_IPersistStreamInit, riid))
784 *ppvObject = &(This->lpvtblIPersistStreamInit);
786 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
788 *ppvObject = &(This->lpvtblIObjectWithSite);
790 else if (IsEqualGUID(&IID_IObjectSafety, riid))
792 *ppvObject = &(This->lpvtblIObjectSafety);
794 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
796 *ppvObject = &This->lpvtblISupportErrorInfo;
798 else if(node_query_interface(&This->node, riid, ppvObject))
800 return *ppvObject ? S_OK : E_NOINTERFACE;
802 else if (IsEqualGUID( riid, &IID_IConnectionPointContainer ))
804 *ppvObject = &This->lpVtblConnectionPointContainer;
806 else if(IsEqualGUID(&IID_IRunnableObject, riid))
808 TRACE("IID_IRunnableObject not supported returning NULL\n");
809 return E_NOINTERFACE;
813 FIXME("interface %s not implemented\n", debugstr_guid(riid));
814 return E_NOINTERFACE;
817 IUnknown_AddRef((IUnknown*)*ppvObject);
823 static ULONG WINAPI domdoc_AddRef(
824 IXMLDOMDocument3 *iface )
826 domdoc *This = impl_from_IXMLDOMDocument3( iface );
827 TRACE("%p\n", This );
828 return InterlockedIncrement( &This->ref );
832 static ULONG WINAPI domdoc_Release(
833 IXMLDOMDocument3 *iface )
835 domdoc *This = impl_from_IXMLDOMDocument3( iface );
838 TRACE("%p\n", This );
840 ref = InterlockedDecrement( &This->ref );
844 detach_bsc(This->bsc);
847 IUnknown_Release( This->site );
848 destroy_xmlnode(&This->node);
849 if(This->schema) IXMLDOMSchemaCollection_Release( This->schema );
850 if (This->stream) IStream_Release(This->stream);
851 HeapFree( GetProcessHeap(), 0, This );
857 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
859 domdoc *This = impl_from_IXMLDOMDocument3( iface );
861 TRACE("(%p)->(%p)\n", This, pctinfo);
868 static HRESULT WINAPI domdoc_GetTypeInfo(
869 IXMLDOMDocument3 *iface,
870 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
872 domdoc *This = impl_from_IXMLDOMDocument3( iface );
875 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
877 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
882 static HRESULT WINAPI domdoc_GetIDsOfNames(
883 IXMLDOMDocument3 *iface,
890 domdoc *This = impl_from_IXMLDOMDocument3( iface );
894 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
897 if(!rgszNames || cNames == 0 || !rgDispId)
900 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
903 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
904 ITypeInfo_Release(typeinfo);
911 static HRESULT WINAPI domdoc_Invoke(
912 IXMLDOMDocument3 *iface,
917 DISPPARAMS* pDispParams,
919 EXCEPINFO* pExcepInfo,
922 domdoc *This = impl_from_IXMLDOMDocument3( iface );
926 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
927 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
929 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
932 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
933 pVarResult, pExcepInfo, puArgErr);
934 ITypeInfo_Release(typeinfo);
941 static HRESULT WINAPI domdoc_get_nodeName(
942 IXMLDOMDocument3 *iface,
945 domdoc *This = impl_from_IXMLDOMDocument3( iface );
947 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
949 TRACE("(%p)->(%p)\n", This, name);
951 return return_bstr(documentW, name);
955 static HRESULT WINAPI domdoc_get_nodeValue(
956 IXMLDOMDocument3 *iface,
959 domdoc *This = impl_from_IXMLDOMDocument3( iface );
961 TRACE("(%p)->(%p)\n", This, value);
966 V_VT(value) = VT_NULL;
967 V_BSTR(value) = NULL; /* tests show that we should do this */
972 static HRESULT WINAPI domdoc_put_nodeValue(
973 IXMLDOMDocument3 *iface,
976 domdoc *This = impl_from_IXMLDOMDocument3( iface );
977 FIXME("(%p)->(v%d)\n", This, V_VT(&value));
982 static HRESULT WINAPI domdoc_get_nodeType(
983 IXMLDOMDocument3 *iface,
986 domdoc *This = impl_from_IXMLDOMDocument3( iface );
988 TRACE("(%p)->(%p)\n", This, type);
990 *type = NODE_DOCUMENT;
995 static HRESULT WINAPI domdoc_get_parentNode(
996 IXMLDOMDocument3 *iface,
997 IXMLDOMNode** parent )
999 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1001 TRACE("(%p)->(%p)\n", This, parent);
1003 return node_get_parent(&This->node, parent);
1007 static HRESULT WINAPI domdoc_get_childNodes(
1008 IXMLDOMDocument3 *iface,
1009 IXMLDOMNodeList** childList )
1011 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1013 TRACE("(%p)->(%p)\n", This, childList);
1015 return node_get_child_nodes(&This->node, childList);
1019 static HRESULT WINAPI domdoc_get_firstChild(
1020 IXMLDOMDocument3 *iface,
1021 IXMLDOMNode** firstChild )
1023 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1025 TRACE("(%p)->(%p)\n", This, firstChild);
1027 return node_get_first_child(&This->node, firstChild);
1031 static HRESULT WINAPI domdoc_get_lastChild(
1032 IXMLDOMDocument3 *iface,
1033 IXMLDOMNode** lastChild )
1035 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1037 TRACE("(%p)->(%p)\n", This, lastChild);
1039 return node_get_last_child(&This->node, lastChild);
1043 static HRESULT WINAPI domdoc_get_previousSibling(
1044 IXMLDOMDocument3 *iface,
1045 IXMLDOMNode** previousSibling )
1047 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1049 TRACE("(%p)->(%p)\n", This, previousSibling);
1051 return return_null_node(previousSibling);
1055 static HRESULT WINAPI domdoc_get_nextSibling(
1056 IXMLDOMDocument3 *iface,
1057 IXMLDOMNode** nextSibling )
1059 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1061 TRACE("(%p)->(%p)\n", This, nextSibling);
1063 return return_null_node(nextSibling);
1067 static HRESULT WINAPI domdoc_get_attributes(
1068 IXMLDOMDocument3 *iface,
1069 IXMLDOMNamedNodeMap** attributeMap )
1071 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1073 TRACE("(%p)->(%p)\n", This, attributeMap);
1075 return return_null_ptr((void**)attributeMap);
1079 static HRESULT WINAPI domdoc_insertBefore(
1080 IXMLDOMDocument3 *iface,
1081 IXMLDOMNode* newChild,
1083 IXMLDOMNode** outNewChild )
1085 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1087 TRACE("(%p)->(%p x%d %p)\n", This, newChild, V_VT(&refChild), outNewChild);
1089 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1093 static HRESULT WINAPI domdoc_replaceChild(
1094 IXMLDOMDocument3 *iface,
1095 IXMLDOMNode* newChild,
1096 IXMLDOMNode* oldChild,
1097 IXMLDOMNode** outOldChild)
1099 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1101 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1103 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1107 static HRESULT WINAPI domdoc_removeChild(
1108 IXMLDOMDocument3 *iface,
1109 IXMLDOMNode* childNode,
1110 IXMLDOMNode** oldChild)
1112 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1113 return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), childNode, oldChild );
1117 static HRESULT WINAPI domdoc_appendChild(
1118 IXMLDOMDocument3 *iface,
1119 IXMLDOMNode* newChild,
1120 IXMLDOMNode** outNewChild)
1122 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1123 return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newChild, outNewChild );
1127 static HRESULT WINAPI domdoc_hasChildNodes(
1128 IXMLDOMDocument3 *iface,
1129 VARIANT_BOOL* hasChild)
1131 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1132 return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), hasChild );
1136 static HRESULT WINAPI domdoc_get_ownerDocument(
1137 IXMLDOMDocument3 *iface,
1138 IXMLDOMDocument** DOMDocument)
1140 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1141 return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), DOMDocument );
1145 static HRESULT WINAPI domdoc_cloneNode(
1146 IXMLDOMDocument3 *iface,
1148 IXMLDOMNode** cloneRoot)
1150 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1151 return IXMLDOMNode_cloneNode( IXMLDOMNode_from_impl(&This->node), deep, cloneRoot );
1155 static HRESULT WINAPI domdoc_get_nodeTypeString(
1156 IXMLDOMDocument3 *iface,
1159 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1160 return IXMLDOMNode_get_nodeTypeString( IXMLDOMNode_from_impl(&This->node), nodeType );
1164 static HRESULT WINAPI domdoc_get_text(
1165 IXMLDOMDocument3 *iface,
1168 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1169 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), text );
1173 static HRESULT WINAPI domdoc_put_text(
1174 IXMLDOMDocument3 *iface,
1177 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1178 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1183 static HRESULT WINAPI domdoc_get_specified(
1184 IXMLDOMDocument3 *iface,
1185 VARIANT_BOOL* isSpecified )
1187 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1188 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1189 *isSpecified = VARIANT_TRUE;
1194 static HRESULT WINAPI domdoc_get_definition(
1195 IXMLDOMDocument3 *iface,
1196 IXMLDOMNode** definitionNode )
1198 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1199 FIXME("(%p)->(%p)\n", This, definitionNode);
1201 return IXMLDOMNode_get_definition( IXMLDOMNode_from_impl(&This->node), definitionNode );
1205 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1206 IXMLDOMDocument3 *iface,
1207 VARIANT* typedValue )
1209 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1210 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
1213 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1214 IXMLDOMDocument3 *iface,
1215 VARIANT typedValue )
1217 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1218 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
1222 static HRESULT WINAPI domdoc_get_dataType(
1223 IXMLDOMDocument3 *iface,
1226 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1227 TRACE("(%p)->(%p)\n", This, typename);
1228 return return_null_var( typename );
1232 static HRESULT WINAPI domdoc_put_dataType(
1233 IXMLDOMDocument3 *iface,
1236 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1237 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
1241 static HRESULT WINAPI domdoc_get_xml(
1242 IXMLDOMDocument3 *iface,
1245 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1246 return IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), xmlString );
1250 static HRESULT WINAPI domdoc_transformNode(
1251 IXMLDOMDocument3 *iface,
1252 IXMLDOMNode* styleSheet,
1255 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1256 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), styleSheet, xmlString );
1260 static HRESULT WINAPI domdoc_selectNodes(
1261 IXMLDOMDocument3 *iface,
1263 IXMLDOMNodeList** resultList )
1265 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1266 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), queryString, resultList );
1270 static HRESULT WINAPI domdoc_selectSingleNode(
1271 IXMLDOMDocument3 *iface,
1273 IXMLDOMNode** resultNode )
1275 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1276 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), queryString, resultNode );
1280 static HRESULT WINAPI domdoc_get_parsed(
1281 IXMLDOMDocument3 *iface,
1282 VARIANT_BOOL* isParsed )
1284 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1285 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1286 *isParsed = VARIANT_TRUE;
1288 return IXMLDOMNode_get_parsed( IXMLDOMNode_from_impl(&This->node), isParsed );
1292 static HRESULT WINAPI domdoc_get_namespaceURI(
1293 IXMLDOMDocument3 *iface,
1294 BSTR* namespaceURI )
1296 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1297 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), namespaceURI );
1301 static HRESULT WINAPI domdoc_get_prefix(
1302 IXMLDOMDocument3 *iface,
1303 BSTR* prefixString )
1305 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1306 return IXMLDOMNode_get_prefix( IXMLDOMNode_from_impl(&This->node), prefixString );
1310 static HRESULT WINAPI domdoc_get_baseName(
1311 IXMLDOMDocument3 *iface,
1314 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1315 return IXMLDOMNode_get_baseName( IXMLDOMNode_from_impl(&This->node), nameString );
1319 static HRESULT WINAPI domdoc_transformNodeToObject(
1320 IXMLDOMDocument3 *iface,
1321 IXMLDOMNode* stylesheet,
1322 VARIANT outputObject)
1324 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1325 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), stylesheet, outputObject );
1329 static HRESULT WINAPI domdoc_get_doctype(
1330 IXMLDOMDocument3 *iface,
1331 IXMLDOMDocumentType** documentType )
1333 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1334 FIXME("(%p)\n", This);
1339 static HRESULT WINAPI domdoc_get_implementation(
1340 IXMLDOMDocument3 *iface,
1341 IXMLDOMImplementation** impl )
1343 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1345 TRACE("(%p)->(%p)\n", This, impl);
1348 return E_INVALIDARG;
1350 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1355 static HRESULT WINAPI domdoc_get_documentElement(
1356 IXMLDOMDocument3 *iface,
1357 IXMLDOMElement** DOMElement )
1359 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1360 IXMLDOMNode *element_node;
1364 TRACE("(%p)->(%p)\n", This, DOMElement);
1367 return E_INVALIDARG;
1371 root = xmlDocGetRootElement( get_doc(This) );
1375 element_node = create_node( root );
1376 if(!element_node) return S_FALSE;
1378 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1379 IXMLDOMNode_Release(element_node);
1385 static HRESULT WINAPI domdoc_put_documentElement(
1386 IXMLDOMDocument3 *iface,
1387 IXMLDOMElement* DOMElement )
1389 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1390 IXMLDOMNode *elementNode;
1395 TRACE("(%p)->(%p)\n", This, DOMElement);
1397 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1401 xmlNode = get_node_obj( elementNode );
1403 FIXME("elementNode is not our object\n");
1407 if(!xmlNode->node->parent)
1408 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1409 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1411 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1412 IXMLDOMNode_Release( elementNode );
1415 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1421 static HRESULT WINAPI domdoc_createElement(
1422 IXMLDOMDocument3 *iface,
1424 IXMLDOMElement** element )
1426 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1431 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1433 if (!element || !tagname) return E_INVALIDARG;
1435 V_VT(&type) = VT_I1;
1436 V_I1(&type) = NODE_ELEMENT;
1438 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1441 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1442 IXMLDOMNode_Release(node);
1449 static HRESULT WINAPI domdoc_createDocumentFragment(
1450 IXMLDOMDocument3 *iface,
1451 IXMLDOMDocumentFragment** frag )
1453 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1458 TRACE("(%p)->(%p)\n", This, frag);
1460 if (!frag) return E_INVALIDARG;
1464 V_VT(&type) = VT_I1;
1465 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1467 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1470 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1471 IXMLDOMNode_Release(node);
1478 static HRESULT WINAPI domdoc_createTextNode(
1479 IXMLDOMDocument3 *iface,
1481 IXMLDOMText** text )
1483 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1488 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1490 if (!text) return E_INVALIDARG;
1494 V_VT(&type) = VT_I1;
1495 V_I1(&type) = NODE_TEXT;
1497 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1500 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1501 IXMLDOMNode_Release(node);
1502 hr = IXMLDOMText_put_data(*text, data);
1509 static HRESULT WINAPI domdoc_createComment(
1510 IXMLDOMDocument3 *iface,
1512 IXMLDOMComment** comment )
1514 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1519 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1521 if (!comment) return E_INVALIDARG;
1525 V_VT(&type) = VT_I1;
1526 V_I1(&type) = NODE_COMMENT;
1528 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1531 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1532 IXMLDOMNode_Release(node);
1533 hr = IXMLDOMComment_put_data(*comment, data);
1540 static HRESULT WINAPI domdoc_createCDATASection(
1541 IXMLDOMDocument3 *iface,
1543 IXMLDOMCDATASection** cdata )
1545 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1550 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1552 if (!cdata) return E_INVALIDARG;
1556 V_VT(&type) = VT_I1;
1557 V_I1(&type) = NODE_CDATA_SECTION;
1559 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1562 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1563 IXMLDOMNode_Release(node);
1564 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1571 static HRESULT WINAPI domdoc_createProcessingInstruction(
1572 IXMLDOMDocument3 *iface,
1575 IXMLDOMProcessingInstruction** pi )
1577 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1582 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1584 if (!pi) return E_INVALIDARG;
1588 V_VT(&type) = VT_I1;
1589 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1591 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1597 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1598 node_obj = get_node_obj(node);
1599 V_VT(&v_data) = VT_BSTR;
1600 V_BSTR(&v_data) = data;
1602 hr = node_put_value(node_obj, &v_data);
1604 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1605 IXMLDOMNode_Release(node);
1612 static HRESULT WINAPI domdoc_createAttribute(
1613 IXMLDOMDocument3 *iface,
1615 IXMLDOMAttribute** attribute )
1617 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1622 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1624 if (!attribute || !name) return E_INVALIDARG;
1626 V_VT(&type) = VT_I1;
1627 V_I1(&type) = NODE_ATTRIBUTE;
1629 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1632 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1633 IXMLDOMNode_Release(node);
1640 static HRESULT WINAPI domdoc_createEntityReference(
1641 IXMLDOMDocument3 *iface,
1643 IXMLDOMEntityReference** entityref )
1645 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1650 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1652 if (!entityref) return E_INVALIDARG;
1656 V_VT(&type) = VT_I1;
1657 V_I1(&type) = NODE_ENTITY_REFERENCE;
1659 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1662 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1663 IXMLDOMNode_Release(node);
1670 static HRESULT WINAPI domdoc_getElementsByTagName(
1671 IXMLDOMDocument3 *iface,
1673 IXMLDOMNodeList** resultList )
1675 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1678 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagName), resultList);
1680 if (!tagName || !resultList) return E_INVALIDARG;
1682 if (tagName[0] == '*' && tagName[1] == 0)
1684 static const WCHAR formatallW[] = {'/','/','*',0};
1685 hr = queryresult_create((xmlNodePtr)get_doc(This), formatallW, resultList);
1689 static const WCHAR xpathformat[] =
1690 { '/','/','*','[','l','o','c','a','l','-','n','a','m','e','(',')','=','\'' };
1691 static const WCHAR closeW[] = { '\'',']',0 };
1697 length = lstrlenW(tagName);
1699 /* without two WCHARs from format specifier */
1700 ptr = pattern = heap_alloc(sizeof(xpathformat) + length*sizeof(WCHAR) + sizeof(closeW));
1702 memcpy(ptr, xpathformat, sizeof(xpathformat));
1703 ptr += sizeof(xpathformat)/sizeof(WCHAR);
1704 memcpy(ptr, tagName, length*sizeof(WCHAR));
1706 memcpy(ptr, closeW, sizeof(closeW));
1708 hr = queryresult_create((xmlNodePtr)get_doc(This), pattern, resultList);
1715 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1721 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1723 return E_INVALIDARG;
1730 static HRESULT WINAPI domdoc_createNode(
1731 IXMLDOMDocument3 *iface,
1735 IXMLDOMNode** node )
1737 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1738 DOMNodeType node_type;
1740 xmlChar *xml_name, *href;
1743 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1745 if(!node) return E_INVALIDARG;
1747 hr = get_node_type(Type, &node_type);
1748 if(FAILED(hr)) return hr;
1750 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1751 FIXME("nodes with namespaces currently not supported.\n");
1753 TRACE("node_type %d\n", node_type);
1755 /* exit earlier for types that need name */
1759 case NODE_ATTRIBUTE:
1760 case NODE_ENTITY_REFERENCE:
1761 case NODE_PROCESSING_INSTRUCTION:
1762 if (!name || *name == 0) return E_FAIL;
1767 xml_name = xmlChar_from_wchar(name);
1768 /* prevent empty href to be allocated */
1769 href = namespaceURI ? xmlChar_from_wchar(namespaceURI) : NULL;
1775 xmlChar *local, *prefix;
1777 local = xmlSplitQName2(xml_name, &prefix);
1779 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
1781 /* allow to create default namespace xmlns= */
1782 if (local || (href && *href))
1784 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
1785 xmlSetNs(xmlnode, ns);
1793 case NODE_ATTRIBUTE:
1794 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1797 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1799 case NODE_CDATA_SECTION:
1800 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1802 case NODE_ENTITY_REFERENCE:
1803 xmlnode = xmlNewReference(get_doc(This), xml_name);
1805 case NODE_PROCESSING_INSTRUCTION:
1806 #ifdef HAVE_XMLNEWDOCPI
1807 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1809 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1814 xmlnode = xmlNewDocComment(get_doc(This), NULL);
1816 case NODE_DOCUMENT_FRAGMENT:
1817 xmlnode = xmlNewDocFragment(get_doc(This));
1819 /* unsupported types */
1821 case NODE_DOCUMENT_TYPE:
1824 heap_free(xml_name);
1825 return E_INVALIDARG;
1827 FIXME("unhandled node type %d\n", node_type);
1832 *node = create_node(xmlnode);
1833 heap_free(xml_name);
1838 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1839 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1846 static HRESULT WINAPI domdoc_nodeFromID(
1847 IXMLDOMDocument3 *iface,
1849 IXMLDOMNode** node )
1851 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1852 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1856 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1861 xmldoc = doparse(This, ptr, len, NULL);
1863 xmldoc->_private = create_priv();
1864 return attach_xmldoc(This, xmldoc);
1870 static HRESULT doread( domdoc *This, LPWSTR filename )
1875 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1880 detach_bsc(This->bsc);
1886 static HRESULT WINAPI domdoc_load(
1887 IXMLDOMDocument3 *iface,
1889 VARIANT_BOOL* isSuccessful )
1891 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1892 LPWSTR filename = NULL;
1893 HRESULT hr = S_FALSE;
1894 IXMLDOMDocument3 *pNewDoc = NULL;
1895 IStream *pStream = NULL;
1898 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
1900 *isSuccessful = VARIANT_FALSE;
1902 assert( &This->node );
1904 switch( V_VT(&xmlSource) )
1907 filename = V_BSTR(&xmlSource);
1910 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
1915 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
1916 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1917 hr = attach_xmldoc(This, xmldoc);
1920 *isSuccessful = VARIANT_TRUE;
1925 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1928 IPersistStream *pDocStream;
1929 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1932 hr = IPersistStream_Load(pDocStream, pStream);
1933 IStream_Release(pStream);
1936 *isSuccessful = VARIANT_TRUE;
1938 TRACE("Using IStream to load Document\n");
1943 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1948 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1953 /* ISequentialStream */
1954 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1958 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1961 TRACE("filename (%s)\n", debugstr_w(filename));
1965 hr = doread( This, filename );
1968 This->error = E_FAIL;
1971 hr = This->error = S_OK;
1972 *isSuccessful = VARIANT_TRUE;
1976 if(!filename || FAILED(hr)) {
1977 xmldoc = xmlNewDoc(NULL);
1978 xmldoc->_private = create_priv();
1979 hr = attach_xmldoc(This, xmldoc);
1984 TRACE("ret (%d)\n", hr);
1990 static HRESULT WINAPI domdoc_get_readyState(
1991 IXMLDOMDocument3 *iface,
1994 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1995 FIXME("stub! (%p)->(%p)\n", This, value);
1998 return E_INVALIDARG;
2000 *value = READYSTATE_COMPLETE;
2005 static HRESULT WINAPI domdoc_get_parseError(
2006 IXMLDOMDocument3 *iface,
2007 IXMLDOMParseError** errorObj )
2009 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2010 static const WCHAR err[] = {'e','r','r','o','r',0};
2011 BSTR error_string = NULL;
2013 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2016 error_string = SysAllocString(err);
2018 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2019 if(!*errorObj) return E_OUTOFMEMORY;
2024 static HRESULT WINAPI domdoc_get_url(
2025 IXMLDOMDocument3 *iface,
2028 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2029 FIXME("(%p)->(%p)\n", This, urlString);
2034 static HRESULT WINAPI domdoc_get_async(
2035 IXMLDOMDocument3 *iface,
2036 VARIANT_BOOL* isAsync )
2038 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2040 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2041 *isAsync = This->async;
2046 static HRESULT WINAPI domdoc_put_async(
2047 IXMLDOMDocument3 *iface,
2048 VARIANT_BOOL isAsync )
2050 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2052 TRACE("(%p)->(%d)\n", This, isAsync);
2053 This->async = isAsync;
2058 static HRESULT WINAPI domdoc_abort(
2059 IXMLDOMDocument3 *iface )
2061 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2062 FIXME("%p\n", This);
2067 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
2072 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
2073 str = heap_alloc( len );
2076 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
2082 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2083 static HRESULT WINAPI domdoc_loadXML(
2084 IXMLDOMDocument3 *iface,
2086 VARIANT_BOOL* isSuccessful )
2088 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2089 static const xmlChar encoding[] = "UTF-8";
2090 xmlDocPtr xmldoc = NULL;
2091 HRESULT hr = S_FALSE, hr2;
2095 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2097 assert ( &This->node );
2101 *isSuccessful = VARIANT_FALSE;
2103 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
2105 xmldoc = doparse(This, str, len, encoding);
2109 This->error = E_FAIL;
2110 TRACE("failed to parse document\n");
2114 hr = This->error = S_OK;
2115 *isSuccessful = VARIANT_TRUE;
2116 TRACE("parsed document %p\n", xmldoc);
2121 xmldoc = xmlNewDoc(NULL);
2123 xmldoc->_private = create_priv();
2125 hr2 = attach_xmldoc(This, xmldoc);
2132 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2136 if(!WriteFile(ctx, buffer, len, &written, NULL))
2138 WARN("write error\n");
2145 static int XMLCALL domdoc_save_closecallback(void *ctx)
2147 return CloseHandle(ctx) ? 0 : -1;
2150 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2155 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2158 WARN("stream write error: 0x%08x\n", hr);
2165 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2167 IStream_Release((IStream*)ctx);
2171 static HRESULT WINAPI domdoc_save(
2172 IXMLDOMDocument3 *iface,
2173 VARIANT destination )
2175 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2176 xmlSaveCtxtPtr ctx = NULL;
2180 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
2181 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
2183 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
2185 FIXME("Unhandled vt %d\n", V_VT(&destination));
2189 if(V_VT(&destination) == VT_UNKNOWN)
2191 IUnknown *pUnk = V_UNKNOWN(&destination);
2192 IXMLDOMDocument2 *document;
2195 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2198 VARIANT_BOOL success;
2201 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2204 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2208 IXMLDOMDocument3_Release(document);
2212 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2215 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2216 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2220 IStream_Release(stream);
2227 /* save with file path */
2228 HANDLE handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
2229 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2230 if( handle == INVALID_HANDLE_VALUE )
2232 WARN("failed to create file\n");
2236 /* disable top XML declaration */
2237 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2238 handle, NULL, XML_SAVE_NO_DECL);
2241 CloseHandle(handle);
2246 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2247 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2248 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2250 /* will release resources through close callback */
2256 static HRESULT WINAPI domdoc_get_validateOnParse(
2257 IXMLDOMDocument3 *iface,
2258 VARIANT_BOOL* isValidating )
2260 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2261 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2262 *isValidating = This->validating;
2267 static HRESULT WINAPI domdoc_put_validateOnParse(
2268 IXMLDOMDocument3 *iface,
2269 VARIANT_BOOL isValidating )
2271 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2272 TRACE("(%p)->(%d)\n", This, isValidating);
2273 This->validating = isValidating;
2278 static HRESULT WINAPI domdoc_get_resolveExternals(
2279 IXMLDOMDocument3 *iface,
2280 VARIANT_BOOL* isResolving )
2282 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2283 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2284 *isResolving = This->resolving;
2289 static HRESULT WINAPI domdoc_put_resolveExternals(
2290 IXMLDOMDocument3 *iface,
2291 VARIANT_BOOL isResolving )
2293 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2294 TRACE("(%p)->(%d)\n", This, isResolving);
2295 This->resolving = isResolving;
2300 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2301 IXMLDOMDocument3 *iface,
2302 VARIANT_BOOL* isPreserving )
2304 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2305 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->preserving);
2306 *isPreserving = This->preserving;
2311 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2312 IXMLDOMDocument3 *iface,
2313 VARIANT_BOOL isPreserving )
2315 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2316 TRACE("(%p)->(%d)\n", This, isPreserving);
2317 This->preserving = isPreserving;
2322 static HRESULT WINAPI domdoc_put_onReadyStateChange(
2323 IXMLDOMDocument3 *iface,
2324 VARIANT readyStateChangeSink )
2326 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2327 FIXME("%p\n", This);
2332 static HRESULT WINAPI domdoc_put_onDataAvailable(
2333 IXMLDOMDocument3 *iface,
2334 VARIANT onDataAvailableSink )
2336 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2337 FIXME("%p\n", This);
2341 static HRESULT WINAPI domdoc_put_onTransformNode(
2342 IXMLDOMDocument3 *iface,
2343 VARIANT onTransformNodeSink )
2345 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2346 FIXME("%p\n", This);
2350 static HRESULT WINAPI domdoc_get_namespaces(
2351 IXMLDOMDocument3* iface,
2352 IXMLDOMSchemaCollection** schemaCollection )
2354 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2355 FIXME("(%p)->(%p)\n", This, schemaCollection);
2359 static HRESULT WINAPI domdoc_get_schemas(
2360 IXMLDOMDocument3* iface,
2363 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2364 HRESULT hr = S_FALSE;
2365 IXMLDOMSchemaCollection *cur_schema = This->schema;
2367 TRACE("(%p)->(%p)\n", This, var1);
2369 VariantInit(var1); /* Test shows we don't call VariantClear here */
2370 V_VT(var1) = VT_NULL;
2374 hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2376 V_VT(var1) = VT_DISPATCH;
2381 static HRESULT WINAPI domdoc_putref_schemas(
2382 IXMLDOMDocument3* iface,
2385 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2386 HRESULT hr = E_FAIL;
2387 IXMLDOMSchemaCollection *new_schema = NULL;
2389 FIXME("(%p): semi-stub\n", This);
2393 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2397 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2406 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2411 IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
2412 if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
2418 static HRESULT WINAPI domdoc_validate(
2419 IXMLDOMDocument3* iface,
2420 IXMLDOMParseError** err)
2422 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2424 xmlValidCtxtPtr vctx;
2426 TRACE("(%p)->(%p)\n", This, err);
2427 domdoc_get_readyState(iface, &state);
2428 if (state != READYSTATE_COMPLETE)
2431 *err = create_parseError(0, NULL, NULL, NULL, 0, 0, 0);
2435 vctx = xmlNewValidCtxt();
2436 vctx->error = NULL; /* TODO: error callback */
2437 vctx->warning = NULL; /* TODO: warning callback */
2439 if (xmlValidateDocument(vctx, get_doc(This)))
2442 *err = create_parseError(0, NULL, NULL, NULL, 0, 0, 0);
2443 xmlFreeValidCtxt(vctx);
2447 FIXME("partial stub!\n");
2449 *err = create_parseError(0xC00CE223, NULL, NULL, NULL, 0, 0, 0);
2450 xmlFreeValidCtxt(vctx);
2454 static HRESULT WINAPI domdoc_setProperty(
2455 IXMLDOMDocument3* iface,
2459 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2461 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2463 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2469 V_VT(&varStr) = VT_EMPTY;
2470 if (V_VT(&var) != VT_BSTR)
2472 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2474 bstr = V_BSTR(&varStr);
2477 bstr = V_BSTR(&var);
2480 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2481 This->properties->XPath = TRUE;
2482 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2483 This->properties->XPath = FALSE;
2487 VariantClear(&varStr);
2490 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2495 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2496 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2497 xmlXPathContextPtr ctx;
2498 struct list *pNsList;
2499 select_ns_entry* pNsEntry = NULL;
2501 V_VT(&varStr) = VT_EMPTY;
2502 if (V_VT(&var) != VT_BSTR)
2504 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2506 bstr = V_BSTR(&varStr);
2509 bstr = V_BSTR(&var);
2513 pNsList = &(This->properties->selectNsList);
2514 clear_selectNsList(pNsList);
2516 nsStr = xmlChar_from_wchar(bstr);
2519 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2521 This->properties->selectNsStr = nsStr;
2522 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2525 ctx = xmlXPathNewContext(This->node.node->doc);
2528 for (; *pTokBegin; pTokBegin = pTokEnd)
2530 if (pNsEntry != NULL)
2531 memset(pNsEntry, 0, sizeof(select_ns_entry));
2533 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2535 while (*pTokBegin == ' ')
2537 pTokEnd = pTokBegin;
2538 while (*pTokEnd != ' ' && *pTokEnd != 0)
2541 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2544 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2545 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2550 if (*pTokBegin == '=')
2552 /*valid for XSLPattern?*/
2553 FIXME("Setting default xmlns not supported - skipping.\n");
2554 pTokBegin = pTokEnd;
2557 else if (*pTokBegin == ':')
2559 pNsEntry->prefix = ++pTokBegin;
2560 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2563 if (pTokInner == pTokEnd)
2566 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2567 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2571 pNsEntry->prefix_end = *pTokInner;
2575 if (pTokEnd-pTokInner > 1 &&
2576 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2577 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2579 pNsEntry->href = ++pTokInner;
2580 pNsEntry->href_end = *(pTokEnd-1);
2582 list_add_tail(pNsList, &pNsEntry->entry);
2583 /*let libxml figure out if they're valid from here ;)*/
2584 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2593 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2594 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2595 list_add_tail(pNsList, &pNsEntry->entry);
2608 heap_free(pNsEntry);
2609 xmlXPathFreeContext(ctx);
2612 VariantClear(&varStr);
2615 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2616 lstrcmpiW(p, PropertyNewParserW) == 0)
2619 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2623 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2627 static HRESULT WINAPI domdoc_getProperty(
2628 IXMLDOMDocument3* iface,
2632 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2634 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2637 return E_INVALIDARG;
2639 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2641 V_VT(var) = VT_BSTR;
2642 V_BSTR(var) = This->properties->XPath ?
2643 SysAllocString(PropValueXPathW) :
2644 SysAllocString(PropValueXSLPatternW);
2645 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2647 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2650 BSTR rebuiltStr, cur;
2651 const xmlChar *nsStr;
2652 struct list *pNsList;
2653 select_ns_entry* pNsEntry;
2655 V_VT(var) = VT_BSTR;
2656 nsStr = This->properties->selectNsStr;
2657 pNsList = &This->properties->selectNsList;
2658 lenA = This->properties->selectNsStr_len;
2659 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
2660 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
2661 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
2663 /* this is fine because all of the chars that end tokens are ASCII*/
2664 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
2666 while (*cur != 0) ++cur;
2667 if (pNsEntry->prefix_end)
2669 *cur = pNsEntry->prefix_end;
2670 while (*cur != 0) ++cur;
2673 if (pNsEntry->href_end)
2675 *cur = pNsEntry->href_end;
2678 V_BSTR(var) = SysAllocString(rebuiltStr);
2679 heap_free(rebuiltStr);
2683 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2687 static HRESULT WINAPI domdoc_validateNode(
2688 IXMLDOMDocument3* iface,
2690 IXMLDOMParseError** error)
2692 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2693 FIXME("(%p)->(%p %p): stub\n", This, node, error);
2697 static HRESULT WINAPI domdoc_importNode(
2698 IXMLDOMDocument3* iface,
2701 IXMLDOMNode** clone)
2703 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2704 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
2708 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
2710 domdoc_QueryInterface,
2713 domdoc_GetTypeInfoCount,
2715 domdoc_GetIDsOfNames,
2717 domdoc_get_nodeName,
2718 domdoc_get_nodeValue,
2719 domdoc_put_nodeValue,
2720 domdoc_get_nodeType,
2721 domdoc_get_parentNode,
2722 domdoc_get_childNodes,
2723 domdoc_get_firstChild,
2724 domdoc_get_lastChild,
2725 domdoc_get_previousSibling,
2726 domdoc_get_nextSibling,
2727 domdoc_get_attributes,
2728 domdoc_insertBefore,
2729 domdoc_replaceChild,
2732 domdoc_hasChildNodes,
2733 domdoc_get_ownerDocument,
2735 domdoc_get_nodeTypeString,
2738 domdoc_get_specified,
2739 domdoc_get_definition,
2740 domdoc_get_nodeTypedValue,
2741 domdoc_put_nodeTypedValue,
2742 domdoc_get_dataType,
2743 domdoc_put_dataType,
2745 domdoc_transformNode,
2747 domdoc_selectSingleNode,
2749 domdoc_get_namespaceURI,
2751 domdoc_get_baseName,
2752 domdoc_transformNodeToObject,
2754 domdoc_get_implementation,
2755 domdoc_get_documentElement,
2756 domdoc_put_documentElement,
2757 domdoc_createElement,
2758 domdoc_createDocumentFragment,
2759 domdoc_createTextNode,
2760 domdoc_createComment,
2761 domdoc_createCDATASection,
2762 domdoc_createProcessingInstruction,
2763 domdoc_createAttribute,
2764 domdoc_createEntityReference,
2765 domdoc_getElementsByTagName,
2769 domdoc_get_readyState,
2770 domdoc_get_parseError,
2777 domdoc_get_validateOnParse,
2778 domdoc_put_validateOnParse,
2779 domdoc_get_resolveExternals,
2780 domdoc_put_resolveExternals,
2781 domdoc_get_preserveWhiteSpace,
2782 domdoc_put_preserveWhiteSpace,
2783 domdoc_put_onReadyStateChange,
2784 domdoc_put_onDataAvailable,
2785 domdoc_put_onTransformNode,
2786 domdoc_get_namespaces,
2788 domdoc_putref_schemas,
2792 domdoc_validateNode,
2796 /* IConnectionPointContainer */
2797 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
2798 REFIID riid, void **ppv)
2800 domdoc *This = impl_from_IConnectionPointContainer(iface);
2801 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)This, riid, ppv);
2804 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
2806 domdoc *This = impl_from_IConnectionPointContainer(iface);
2807 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)This);
2810 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
2812 domdoc *This = impl_from_IConnectionPointContainer(iface);
2813 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)This);
2816 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
2817 IEnumConnectionPoints **ppEnum)
2819 domdoc *This = impl_from_IConnectionPointContainer(iface);
2820 FIXME("(%p)->(%p): stub\n", This, ppEnum);
2824 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
2825 REFIID riid, IConnectionPoint **cp)
2827 domdoc *This = impl_from_IConnectionPointContainer(iface);
2828 ConnectionPoint *iter;
2830 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
2834 for(iter = This->cp_list; iter; iter = iter->next)
2836 if (IsEqualGUID(iter->iid, riid))
2837 *cp = (IConnectionPoint*)&iter->lpVtblConnectionPoint;
2842 IConnectionPoint_AddRef(*cp);
2846 FIXME("unsupported riid %s\n", debugstr_guid(riid));
2847 return CONNECT_E_NOCONNECTION;
2851 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
2853 ConnectionPointContainer_QueryInterface,
2854 ConnectionPointContainer_AddRef,
2855 ConnectionPointContainer_Release,
2856 ConnectionPointContainer_EnumConnectionPoints,
2857 ConnectionPointContainer_FindConnectionPoint
2860 /* IConnectionPoint */
2861 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
2862 REFIID riid, void **ppv)
2864 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2866 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
2870 if (IsEqualGUID(&IID_IUnknown, riid) ||
2871 IsEqualGUID(&IID_IConnectionPoint, riid))
2878 IConnectionPoint_AddRef(iface);
2882 WARN("Unsupported interface %s\n", debugstr_guid(riid));
2883 return E_NOINTERFACE;
2886 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
2888 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2889 return IConnectionPointContainer_AddRef(This->container);
2892 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
2894 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2895 return IConnectionPointContainer_Release(This->container);
2898 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
2900 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2902 TRACE("(%p)->(%p)\n", This, iid);
2904 if (!iid) return E_POINTER;
2910 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
2911 IConnectionPointContainer **ppCPC)
2913 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2914 FIXME("(%p)->(%p): stub\n", This, ppCPC);
2918 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
2921 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2922 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
2926 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD dwCookie)
2928 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2929 FIXME("(%p)->(%d): stub\n", This, dwCookie);
2933 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
2934 IEnumConnections **ppEnum)
2936 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2937 FIXME("(%p)->(%p): stub\n", This, ppEnum);
2941 static const IConnectionPointVtbl ConnectionPointVtbl =
2943 ConnectionPoint_QueryInterface,
2944 ConnectionPoint_AddRef,
2945 ConnectionPoint_Release,
2946 ConnectionPoint_GetConnectionInterface,
2947 ConnectionPoint_GetConnectionPointContainer,
2948 ConnectionPoint_Advise,
2949 ConnectionPoint_Unadvise,
2950 ConnectionPoint_EnumConnections
2953 void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
2955 cp->lpVtblConnectionPoint = &ConnectionPointVtbl;
2960 cp->next = doc->cp_list;
2963 cp->container = (IConnectionPointContainer*)&doc->lpVtblConnectionPointContainer;
2966 /* xmldoc implementation of IObjectWithSite */
2967 static HRESULT WINAPI
2968 xmldoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
2970 domdoc *This = impl_from_IObjectWithSite(iface);
2971 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppvObject );
2975 xmldoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
2977 domdoc *This = impl_from_IObjectWithSite(iface);
2978 return IXMLDocument_AddRef((IXMLDocument *)This);
2982 xmldoc_ObjectWithSite_Release( IObjectWithSite* iface )
2984 domdoc *This = impl_from_IObjectWithSite(iface);
2985 return IXMLDocument_Release((IXMLDocument *)This);
2988 static HRESULT WINAPI
2989 xmldoc_GetSite( IObjectWithSite *iface, REFIID iid, void ** ppvSite )
2991 domdoc *This = impl_from_IObjectWithSite(iface);
2993 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
2998 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3001 static HRESULT WINAPI
3002 xmldoc_SetSite( IObjectWithSite *iface, IUnknown *punk )
3004 domdoc *This = impl_from_IObjectWithSite(iface);
3006 TRACE("(%p)->(%p)\n", iface, punk);
3012 IUnknown_Release( This->site );
3019 IUnknown_AddRef( punk );
3022 IUnknown_Release( This->site );
3029 static const IObjectWithSiteVtbl domdocObjectSite =
3031 xmldoc_ObjectWithSite_QueryInterface,
3032 xmldoc_ObjectWithSite_AddRef,
3033 xmldoc_ObjectWithSite_Release,
3038 static HRESULT WINAPI xmldoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3040 domdoc *This = impl_from_IObjectSafety(iface);
3041 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppv );
3044 static ULONG WINAPI xmldoc_Safety_AddRef(IObjectSafety *iface)
3046 domdoc *This = impl_from_IObjectSafety(iface);
3047 return IXMLDocument_AddRef((IXMLDocument *)This);
3050 static ULONG WINAPI xmldoc_Safety_Release(IObjectSafety *iface)
3052 domdoc *This = impl_from_IObjectSafety(iface);
3053 return IXMLDocument_Release((IXMLDocument *)This);
3056 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3058 static HRESULT WINAPI xmldoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3059 DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
3061 domdoc *This = impl_from_IObjectSafety(iface);
3063 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
3065 if(!pdwSupportedOptions || !pdwEnabledOptions)
3068 *pdwSupportedOptions = SAFETY_SUPPORTED_OPTIONS;
3069 *pdwEnabledOptions = This->safeopt;
3074 static HRESULT WINAPI xmldoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3075 DWORD dwOptionSetMask, DWORD dwEnabledOptions)
3077 domdoc *This = impl_from_IObjectSafety(iface);
3078 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
3080 if ((dwOptionSetMask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3083 This->safeopt = dwEnabledOptions & dwOptionSetMask & SAFETY_SUPPORTED_OPTIONS;
3087 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3088 xmldoc_Safety_QueryInterface,
3089 xmldoc_Safety_AddRef,
3090 xmldoc_Safety_Release,
3091 xmldoc_Safety_GetInterfaceSafetyOptions,
3092 xmldoc_Safety_SetInterfaceSafetyOptions
3096 static const tid_t domdoc_iface_tids[] = {
3098 IXMLDOMDocument_tid,
3099 IXMLDOMDocument2_tid,
3102 static dispex_static_data_t domdoc_dispex = {
3104 IXMLDOMDocument2_tid,
3109 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3113 doc = heap_alloc( sizeof (*doc) );
3115 return E_OUTOFMEMORY;
3117 doc->lpVtbl = &domdoc_vtbl;
3118 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
3119 doc->lpvtblIObjectWithSite = &domdocObjectSite;
3120 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
3121 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
3122 doc->lpVtblConnectionPointContainer = &ConnectionPointContainerVtbl;
3124 doc->async = VARIANT_TRUE;
3125 doc->validating = 0;
3127 doc->preserving = 0;
3128 doc->properties = properties_from_xmlDocPtr(xmldoc);
3135 doc->cp_list = NULL;
3137 /* events connection points */
3138 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3139 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3140 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3142 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->lpVtbl, &domdoc_dispex);
3144 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
3146 TRACE("returning iface %p\n", *document);
3150 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3155 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
3157 xmldoc = xmlNewDoc(NULL);
3159 return E_OUTOFMEMORY;
3161 xmldoc->_private = create_priv();
3162 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
3164 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3167 free_properties(properties_from_xmlDocPtr(xmldoc));
3168 heap_free(xmldoc->_private);
3176 IUnknown* create_domdoc( xmlNodePtr document )
3181 TRACE("(%p)\n", document);
3183 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3192 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3194 MESSAGE("This program tried to use a DOMDocument object, but\n"
3195 "libxml2 support was not present at compile time.\n");