2 * DOM Document implementation
4 * Copyright 2005 Mike McCormack
5 * Copyright 2010-2011 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
29 # include <libxml/parser.h>
30 # include <libxml/xmlerror.h>
31 # include <libxml/xpathInternals.h>
32 # include <libxml/xmlsave.h>
33 # include <libxml/SAX2.h>
34 # include <libxml/parserInternals.h>
50 #include "wine/debug.h"
52 #include "msxml_private.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
58 /* not defined in older versions */
59 #define XML_SAVE_FORMAT 1
60 #define XML_SAVE_NO_DECL 2
61 #define XML_SAVE_NO_EMPTY 4
62 #define XML_SAVE_NO_XHTML 8
63 #define XML_SAVE_XHTML 16
64 #define XML_SAVE_AS_XML 32
65 #define XML_SAVE_AS_HTML 64
67 static const WCHAR PropertySelectionLanguageW
[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
68 static const WCHAR PropertySelectionNamespacesW
[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
69 static const WCHAR PropertyProhibitDTDW
[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
70 static const WCHAR PropertyNewParserW
[] = {'N','e','w','P','a','r','s','e','r',0};
71 static const WCHAR PropValueXPathW
[] = {'X','P','a','t','h',0};
72 static const WCHAR PropValueXSLPatternW
[] = {'X','S','L','P','a','t','t','e','r','n',0};
73 static const WCHAR PropertyResolveExternalsW
[] = {'R','e','s','o','l','v','e','E','x','t','e','r','n','a','l','s',0};
75 /* Anything that passes the test_get_ownerDocument()
76 * tests can go here (data shared between all instances).
77 * We need to preserve this when reloading a document,
78 * and also need access to it from the libxml backend. */
80 MSXML_VERSION version
;
81 VARIANT_BOOL preserving
;
82 IXMLDOMSchemaCollection2
* schemaCache
;
83 struct list selectNsList
;
84 xmlChar
const* selectNsStr
;
90 typedef struct ConnectionPoint ConnectionPoint
;
91 typedef struct domdoc domdoc
;
93 struct ConnectionPoint
95 IConnectionPoint IConnectionPoint_iface
;
98 ConnectionPoint
*next
;
99 IConnectionPointContainer
*container
;
106 IPropertyNotifySink
*propnotif
;
112 EVENTID_READYSTATECHANGE
= 0,
113 EVENTID_DATAAVAILABLE
,
114 EVENTID_TRANSFORMNODE
,
121 IXMLDOMDocument3 IXMLDOMDocument3_iface
;
122 IPersistStreamInit IPersistStreamInit_iface
;
123 IObjectWithSite IObjectWithSite_iface
;
124 IObjectSafety IObjectSafety_iface
;
125 IConnectionPointContainer IConnectionPointContainer_iface
;
128 VARIANT_BOOL validating
;
129 VARIANT_BOOL resolving
;
130 domdoc_properties
* properties
;
133 /* IObjectWithSite */
139 /* connection list */
140 ConnectionPoint
*cp_list
;
141 ConnectionPoint cp_domdocevents
;
142 ConnectionPoint cp_propnotif
;
143 ConnectionPoint cp_dispatch
;
146 IDispatch
*events
[EVENTID_LAST
];
148 IXMLDOMSchemaCollection2
*namespaces
;
151 static HRESULT
set_doc_event(domdoc
*doc
, eventid_t eid
, const VARIANT
*v
)
159 IUnknown_QueryInterface(V_UNKNOWN(v
), &IID_IDispatch
, (void**)&disp
);
164 disp
= V_DISPATCH(v
);
165 if (disp
) IDispatch_AddRef(disp
);
168 return DISP_E_TYPEMISMATCH
;
171 if (doc
->events
[eid
]) IDispatch_Release(doc
->events
[eid
]);
172 doc
->events
[eid
] = disp
;
177 static inline ConnectionPoint
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
179 return CONTAINING_RECORD(iface
, ConnectionPoint
, IConnectionPoint_iface
);
183 In native windows, the whole lifetime management of XMLDOMNodes is
184 managed automatically using reference counts. Wine emulates that by
185 maintaining a reference count to the document that is increased for
186 each IXMLDOMNode pointer passed out for this document. If all these
187 pointers are gone, the document is unreachable and gets freed, that
188 is, all nodes in the tree of the document get freed.
190 You are able to create nodes that are associated to a document (in
191 fact, in msxml's XMLDOM model, all nodes are associated to a document),
192 but not in the tree of that document, for example using the createFoo
193 functions from IXMLDOMDocument. These nodes do not get cleaned up
194 by libxml, so we have to do it ourselves.
196 To catch these nodes, a list of "orphan nodes" is introduced.
197 It contains pointers to all roots of node trees that are
198 associated with the document without being part of the document
199 tree. All nodes with parent==NULL (except for the document root nodes)
200 should be in the orphan node list of their document. All orphan nodes
201 get freed together with the document itself.
204 typedef struct _xmldoc_priv
{
207 domdoc_properties
* properties
;
210 typedef struct _orphan_entry
{
215 typedef struct _select_ns_entry
{
217 xmlChar
const* prefix
;
223 static inline xmldoc_priv
* priv_from_xmlDocPtr(const xmlDocPtr doc
)
225 return doc
->_private
;
228 static inline domdoc_properties
* properties_from_xmlDocPtr(xmlDocPtr doc
)
230 return priv_from_xmlDocPtr(doc
)->properties
;
233 BOOL
is_xpathmode(const xmlDocPtr doc
)
235 return properties_from_xmlDocPtr(doc
)->XPath
;
238 void set_xpathmode(xmlDocPtr doc
, BOOL xpath
)
240 properties_from_xmlDocPtr(doc
)->XPath
= xpath
;
243 int registerNamespaces(xmlXPathContextPtr ctxt
)
246 const select_ns_entry
* ns
= NULL
;
247 const struct list
* pNsList
= &properties_from_xmlDocPtr(ctxt
->doc
)->selectNsList
;
249 TRACE("(%p)\n", ctxt
);
251 LIST_FOR_EACH_ENTRY( ns
, pNsList
, select_ns_entry
, entry
)
253 xmlXPathRegisterNs(ctxt
, ns
->prefix
, ns
->href
);
260 static inline void clear_selectNsList(struct list
* pNsList
)
262 select_ns_entry
*ns
, *ns2
;
263 LIST_FOR_EACH_ENTRY_SAFE( ns
, ns2
, pNsList
, select_ns_entry
, entry
)
270 static xmldoc_priv
* create_priv(void)
273 priv
= heap_alloc( sizeof (*priv
) );
278 list_init( &priv
->orphans
);
279 priv
->properties
= NULL
;
285 static domdoc_properties
*create_properties(MSXML_VERSION version
)
287 domdoc_properties
*properties
= heap_alloc(sizeof(domdoc_properties
));
289 list_init(&properties
->selectNsList
);
290 properties
->preserving
= VARIANT_FALSE
;
291 properties
->schemaCache
= NULL
;
292 properties
->selectNsStr
= heap_alloc_zero(sizeof(xmlChar
));
293 properties
->selectNsStr_len
= 0;
295 /* properties that are dependent on object versions */
296 properties
->version
= version
;
297 properties
->XPath
= (version
== MSXML4
|| version
== MSXML6
);
300 properties
->url
= NULL
;
305 static domdoc_properties
* copy_properties(domdoc_properties
const* properties
)
307 domdoc_properties
* pcopy
= heap_alloc(sizeof(domdoc_properties
));
308 select_ns_entry
const* ns
= NULL
;
309 select_ns_entry
* new_ns
= NULL
;
310 int len
= (properties
->selectNsStr_len
+1)*sizeof(xmlChar
);
315 pcopy
->version
= properties
->version
;
316 pcopy
->preserving
= properties
->preserving
;
317 pcopy
->schemaCache
= properties
->schemaCache
;
318 if (pcopy
->schemaCache
)
319 IXMLDOMSchemaCollection2_AddRef(pcopy
->schemaCache
);
320 pcopy
->XPath
= properties
->XPath
;
321 pcopy
->selectNsStr_len
= properties
->selectNsStr_len
;
322 list_init( &pcopy
->selectNsList
);
323 pcopy
->selectNsStr
= heap_alloc(len
);
324 memcpy((xmlChar
*)pcopy
->selectNsStr
, properties
->selectNsStr
, len
);
325 offset
= pcopy
->selectNsStr
- properties
->selectNsStr
;
327 LIST_FOR_EACH_ENTRY( ns
, (&properties
->selectNsList
), select_ns_entry
, entry
)
329 new_ns
= heap_alloc(sizeof(select_ns_entry
));
330 memcpy(new_ns
, ns
, sizeof(select_ns_entry
));
331 new_ns
->href
+= offset
;
332 new_ns
->prefix
+= offset
;
333 list_add_tail(&pcopy
->selectNsList
, &new_ns
->entry
);
338 int len
= strlenW(properties
->url
);
340 pcopy
->url
= CoTaskMemAlloc((len
+1)*sizeof(WCHAR
));
341 memcpy(pcopy
->url
, properties
->url
, len
*sizeof(WCHAR
));
351 static void free_properties(domdoc_properties
* properties
)
355 if (properties
->schemaCache
)
356 IXMLDOMSchemaCollection2_Release(properties
->schemaCache
);
357 clear_selectNsList(&properties
->selectNsList
);
358 heap_free((xmlChar
*)properties
->selectNsStr
);
359 CoTaskMemFree(properties
->url
);
360 heap_free(properties
);
364 static void release_namespaces(domdoc
*This
)
366 if (This
->namespaces
)
368 IXMLDOMSchemaCollection2_Release(This
->namespaces
);
369 This
->namespaces
= NULL
;
373 /* links a "<?xml" node as a first child */
374 void xmldoc_link_xmldecl(xmlDocPtr doc
, xmlNodePtr node
)
377 if (doc
->standalone
!= -1) xmlAddPrevSibling( doc
->children
, node
);
380 /* unlinks a first "<?xml" child if it was created */
381 xmlNodePtr
xmldoc_unlink_xmldecl(xmlDocPtr doc
)
383 static const xmlChar xmlA
[] = "xml";
384 xmlNodePtr node
, first_child
;
388 /* xml declaration node could be created automatically after parsing or added
390 first_child
= doc
->children
;
391 if (first_child
&& first_child
->type
== XML_PI_NODE
&& xmlStrEqual(first_child
->name
, xmlA
))
394 xmlUnlinkNode( node
);
402 BOOL
is_preserving_whitespace(xmlNodePtr node
)
404 domdoc_properties
* properties
= NULL
;
405 /* during parsing the xmlDoc._private stuff is not there */
406 if (priv_from_xmlDocPtr(node
->doc
))
407 properties
= properties_from_xmlDocPtr(node
->doc
);
408 return ((properties
&& properties
->preserving
== VARIANT_TRUE
) ||
409 xmlNodeGetSpacePreserve(node
) == 1);
412 static inline BOOL
strn_isspace(xmlChar
const* str
, int len
)
414 for (; str
&& len
> 0 && *str
; ++str
, --len
)
421 static void sax_characters(void *ctx
, const xmlChar
*ch
, int len
)
423 xmlParserCtxtPtr ctxt
;
426 ctxt
= (xmlParserCtxtPtr
) ctx
;
427 This
= (const domdoc
*) ctxt
->_private
;
431 xmlChar cur
= *(ctxt
->input
->cur
);
433 /* Characters are reported with multiple calls, for example each charref is reported with a separate
434 call and then parser appends it to a single text node or creates a new node if not created.
435 It's not possible to tell if it's ignorable data or not just looking at data itself cause it could be
436 space chars that separate charrefs or similar case. We only need to skip leading and trailing spaces,
437 or whole node if it has nothing but space chars, so to detect leading space node->last is checked that
438 contains text node pointer if already created, trailing spaces are detected directly looking at parser input
439 for next '<' opening bracket - similar logic is used by libxml2 itself. Basically 'cur' == '<' means the last
440 chunk of char data, in case it's not the last chunk we check for previously added node type and if it's not
441 a text node it's safe to ignore.
443 Note that during domdoc_loadXML() the xmlDocPtr->_private data is not available. */
445 if (!This
->properties
->preserving
&&
446 !is_preserving_whitespace(ctxt
->node
) &&
447 strn_isspace(ch
, len
) &&
448 (!ctxt
->node
->last
||
449 ((ctxt
->node
->last
&& (cur
== '<' || ctxt
->node
->last
->type
!= XML_TEXT_NODE
))
454 xmlSAX2Characters(ctxt
, ch
, len
);
457 static void LIBXML2_LOG_CALLBACK
sax_error(void* ctx
, char const* msg
, ...)
461 LIBXML2_CALLBACK_ERR(doparse
, msg
, ap
);
465 static void LIBXML2_LOG_CALLBACK
sax_warning(void* ctx
, char const* msg
, ...)
469 LIBXML2_CALLBACK_WARN(doparse
, msg
, ap
);
473 static void sax_serror(void* ctx
, xmlErrorPtr err
)
475 LIBXML2_CALLBACK_SERROR(doparse
, err
);
478 static xmlDocPtr
doparse(domdoc
* This
, char const* ptr
, int len
, xmlCharEncoding encoding
)
480 xmlDocPtr doc
= NULL
;
481 xmlParserCtxtPtr pctx
;
482 static xmlSAXHandler sax_handler
= {
483 xmlSAX2InternalSubset
, /* internalSubset */
484 xmlSAX2IsStandalone
, /* isStandalone */
485 xmlSAX2HasInternalSubset
, /* hasInternalSubset */
486 xmlSAX2HasExternalSubset
, /* hasExternalSubset */
487 xmlSAX2ResolveEntity
, /* resolveEntity */
488 xmlSAX2GetEntity
, /* getEntity */
489 xmlSAX2EntityDecl
, /* entityDecl */
490 xmlSAX2NotationDecl
, /* notationDecl */
491 xmlSAX2AttributeDecl
, /* attributeDecl */
492 xmlSAX2ElementDecl
, /* elementDecl */
493 xmlSAX2UnparsedEntityDecl
, /* unparsedEntityDecl */
494 xmlSAX2SetDocumentLocator
, /* setDocumentLocator */
495 xmlSAX2StartDocument
, /* startDocument */
496 xmlSAX2EndDocument
, /* endDocument */
497 xmlSAX2StartElement
, /* startElement */
498 xmlSAX2EndElement
, /* endElement */
499 xmlSAX2Reference
, /* reference */
500 sax_characters
, /* characters */
501 sax_characters
, /* ignorableWhitespace */
502 xmlSAX2ProcessingInstruction
, /* processingInstruction */
503 xmlSAX2Comment
, /* comment */
504 sax_warning
, /* warning */
505 sax_error
, /* error */
506 sax_error
, /* fatalError */
507 xmlSAX2GetParameterEntity
, /* getParameterEntity */
508 xmlSAX2CDataBlock
, /* cdataBlock */
509 xmlSAX2ExternalSubset
, /* externalSubset */
512 xmlSAX2StartElementNs
, /* startElementNs */
513 xmlSAX2EndElementNs
, /* endElementNs */
514 sax_serror
/* serror */
517 pctx
= xmlCreateMemoryParserCtxt(ptr
, len
);
520 ERR("Failed to create parser context\n");
524 if (pctx
->sax
) xmlFree(pctx
->sax
);
525 pctx
->sax
= &sax_handler
;
526 pctx
->_private
= This
;
529 if (encoding
!= XML_CHAR_ENCODING_NONE
)
530 xmlSwitchEncoding(pctx
, encoding
);
532 xmlParseDocument(pctx
);
534 if (pctx
->wellFormed
)
540 xmlFreeDoc(pctx
->myDoc
);
544 xmlFreeParserCtxt(pctx
);
546 /* TODO: put this in one of the SAX callbacks */
547 /* create first child as a <?xml...?> */
548 if (doc
&& doc
->standalone
!= -1)
552 xmlChar
*xmlbuff
= (xmlChar
*)buff
;
554 node
= xmlNewDocPI( doc
, (xmlChar
*)"xml", NULL
);
556 /* version attribute can't be omitted */
557 sprintf(buff
, "version=\"%s\"", doc
->version
? (char*)doc
->version
: "1.0");
558 xmlNodeAddContent( node
, xmlbuff
);
562 sprintf(buff
, " encoding=\"%s\"", doc
->encoding
);
563 xmlNodeAddContent( node
, xmlbuff
);
566 if (doc
->standalone
!= -2)
568 sprintf(buff
, " standalone=\"%s\"", doc
->standalone
== 0 ? "no" : "yes");
569 xmlNodeAddContent( node
, xmlbuff
);
572 xmldoc_link_xmldecl( doc
, node
);
578 void xmldoc_init(xmlDocPtr doc
, MSXML_VERSION version
)
580 doc
->_private
= create_priv();
581 priv_from_xmlDocPtr(doc
)->properties
= create_properties(version
);
584 LONG
xmldoc_add_refs(xmlDocPtr doc
, LONG refs
)
586 LONG ref
= InterlockedExchangeAdd(&priv_from_xmlDocPtr(doc
)->refs
, refs
) + refs
;
587 TRACE("(%p)->(%d)\n", doc
, ref
);
591 LONG
xmldoc_add_ref(xmlDocPtr doc
)
593 return xmldoc_add_refs(doc
, 1);
596 LONG
xmldoc_release_refs(xmlDocPtr doc
, LONG refs
)
598 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
599 LONG ref
= InterlockedExchangeAdd(&priv
->refs
, -refs
) - refs
;
600 TRACE("(%p)->(%d)\n", doc
, ref
);
603 WARN("negative refcount, expect troubles\n");
607 orphan_entry
*orphan
, *orphan2
;
608 TRACE("freeing docptr %p\n", doc
);
610 LIST_FOR_EACH_ENTRY_SAFE( orphan
, orphan2
, &priv
->orphans
, orphan_entry
, entry
)
612 xmlFreeNode( orphan
->node
);
615 free_properties(priv
->properties
);
616 heap_free(doc
->_private
);
624 LONG
xmldoc_release(xmlDocPtr doc
)
626 return xmldoc_release_refs(doc
, 1);
629 HRESULT
xmldoc_add_orphan(xmlDocPtr doc
, xmlNodePtr node
)
631 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
634 entry
= heap_alloc( sizeof (*entry
) );
636 return E_OUTOFMEMORY
;
639 list_add_head( &priv
->orphans
, &entry
->entry
);
643 HRESULT
xmldoc_remove_orphan(xmlDocPtr doc
, xmlNodePtr node
)
645 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
646 orphan_entry
*entry
, *entry2
;
648 LIST_FOR_EACH_ENTRY_SAFE( entry
, entry2
, &priv
->orphans
, orphan_entry
, entry
)
650 if( entry
->node
== node
)
652 list_remove( &entry
->entry
);
661 static inline xmlDocPtr
get_doc( domdoc
*This
)
663 return This
->node
.node
->doc
;
666 static HRESULT
attach_xmldoc(domdoc
*This
, xmlDocPtr xml
)
668 release_namespaces(This
);
672 priv_from_xmlDocPtr(get_doc(This
))->properties
= NULL
;
673 if (xmldoc_release(get_doc(This
)) != 0)
674 priv_from_xmlDocPtr(get_doc(This
))->properties
=
675 copy_properties(This
->properties
);
678 This
->node
.node
= (xmlNodePtr
) xml
;
682 xmldoc_add_ref(get_doc(This
));
683 priv_from_xmlDocPtr(get_doc(This
))->properties
= This
->properties
;
689 static inline domdoc
*impl_from_IXMLDOMDocument3( IXMLDOMDocument3
*iface
)
691 return CONTAINING_RECORD(iface
, domdoc
, IXMLDOMDocument3_iface
);
694 static inline domdoc
*impl_from_IPersistStreamInit(IPersistStreamInit
*iface
)
696 return CONTAINING_RECORD(iface
, domdoc
, IPersistStreamInit_iface
);
699 static inline domdoc
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
701 return CONTAINING_RECORD(iface
, domdoc
, IObjectWithSite_iface
);
704 static inline domdoc
*impl_from_IObjectSafety(IObjectSafety
*iface
)
706 return CONTAINING_RECORD(iface
, domdoc
, IObjectSafety_iface
);
709 static inline domdoc
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
711 return CONTAINING_RECORD(iface
, domdoc
, IConnectionPointContainer_iface
);
714 /************************************************************************
715 * domdoc implementation of IPersistStream.
717 static HRESULT WINAPI
PersistStreamInit_QueryInterface(
718 IPersistStreamInit
*iface
, REFIID riid
, void **ppvObj
)
720 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
721 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObj
);
724 static ULONG WINAPI
PersistStreamInit_AddRef(
725 IPersistStreamInit
*iface
)
727 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
728 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
731 static ULONG WINAPI
PersistStreamInit_Release(
732 IPersistStreamInit
*iface
)
734 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
735 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
738 static HRESULT WINAPI
PersistStreamInit_GetClassID(
739 IPersistStreamInit
*iface
, CLSID
*classid
)
741 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
742 TRACE("(%p)->(%p)\n", This
, classid
);
747 *classid
= *DOMDocument_version(This
->properties
->version
);
752 static HRESULT WINAPI
PersistStreamInit_IsDirty(
753 IPersistStreamInit
*iface
)
755 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
756 FIXME("(%p): stub!\n", This
);
760 static HRESULT
domdoc_load_from_stream(domdoc
*doc
, ISequentialStream
*stream
)
762 DWORD read
, written
, len
;
763 xmlDocPtr xmldoc
= NULL
;
771 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &hstream
);
777 ISequentialStream_Read(stream
, buf
, sizeof(buf
), &read
);
778 hr
= IStream_Write(hstream
, buf
, read
, &written
);
779 } while(SUCCEEDED(hr
) && written
!= 0 && read
!= 0);
783 ERR("failed to copy stream 0x%08x\n", hr
);
784 IStream_Release(hstream
);
788 hr
= GetHGlobalFromStream(hstream
, &hglobal
);
792 len
= GlobalSize(hglobal
);
793 ptr
= GlobalLock(hglobal
);
795 xmldoc
= doparse(doc
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
796 GlobalUnlock(hglobal
);
800 ERR("Failed to parse xml\n");
804 xmldoc
->_private
= create_priv();
806 return attach_xmldoc(doc
, xmldoc
);
809 static HRESULT WINAPI
PersistStreamInit_Load(IPersistStreamInit
*iface
, IStream
*stream
)
811 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
813 TRACE("(%p)->(%p)\n", This
, stream
);
818 return domdoc_load_from_stream(This
, (ISequentialStream
*)stream
);
821 static HRESULT WINAPI
PersistStreamInit_Save(
822 IPersistStreamInit
*iface
, IStream
*stream
, BOOL clr_dirty
)
824 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
828 TRACE("(%p)->(%p %d)\n", This
, stream
, clr_dirty
);
830 hr
= IXMLDOMDocument3_get_xml(&This
->IXMLDOMDocument3_iface
, &xmlString
);
833 DWORD len
= SysStringLen(xmlString
) * sizeof(WCHAR
);
835 hr
= IStream_Write( stream
, xmlString
, len
, NULL
);
836 SysFreeString(xmlString
);
839 TRACE("ret 0x%08x\n", hr
);
844 static HRESULT WINAPI
PersistStreamInit_GetSizeMax(
845 IPersistStreamInit
*iface
, ULARGE_INTEGER
*pcbSize
)
847 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
848 TRACE("(%p)->(%p)\n", This
, pcbSize
);
852 static HRESULT WINAPI
PersistStreamInit_InitNew(
853 IPersistStreamInit
*iface
)
855 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
856 TRACE("(%p)\n", This
);
860 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable
=
862 PersistStreamInit_QueryInterface
,
863 PersistStreamInit_AddRef
,
864 PersistStreamInit_Release
,
865 PersistStreamInit_GetClassID
,
866 PersistStreamInit_IsDirty
,
867 PersistStreamInit_Load
,
868 PersistStreamInit_Save
,
869 PersistStreamInit_GetSizeMax
,
870 PersistStreamInit_InitNew
873 /* IXMLDOMDocument3 interface */
875 static const tid_t domdoc_se_tids
[] = {
878 IXMLDOMDocument2_tid
,
879 IXMLDOMDocument3_tid
,
883 static HRESULT WINAPI
domdoc_QueryInterface( IXMLDOMDocument3
*iface
, REFIID riid
, void** ppvObject
)
885 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
887 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( riid
), ppvObject
);
891 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
892 IsEqualGUID( riid
, &IID_IDispatch
) ||
893 IsEqualGUID( riid
, &IID_IXMLDOMNode
) ||
894 IsEqualGUID( riid
, &IID_IXMLDOMDocument
) ||
895 IsEqualGUID( riid
, &IID_IXMLDOMDocument2
)||
896 IsEqualGUID( riid
, &IID_IXMLDOMDocument3
))
900 else if (IsEqualGUID(&IID_IPersistStream
, riid
) ||
901 IsEqualGUID(&IID_IPersistStreamInit
, riid
))
903 *ppvObject
= &This
->IPersistStreamInit_iface
;
905 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
907 *ppvObject
= &This
->IObjectWithSite_iface
;
909 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
911 *ppvObject
= &This
->IObjectSafety_iface
;
913 else if( IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
915 return node_create_supporterrorinfo(domdoc_se_tids
, ppvObject
);
917 else if(node_query_interface(&This
->node
, riid
, ppvObject
))
919 return *ppvObject
? S_OK
: E_NOINTERFACE
;
921 else if (IsEqualGUID( riid
, &IID_IConnectionPointContainer
))
923 *ppvObject
= &This
->IConnectionPointContainer_iface
;
927 TRACE("interface %s not implemented\n", debugstr_guid(riid
));
928 return E_NOINTERFACE
;
931 IUnknown_AddRef((IUnknown
*)*ppvObject
);
936 static ULONG WINAPI
domdoc_AddRef( IXMLDOMDocument3
*iface
)
938 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
939 ULONG ref
= InterlockedIncrement( &This
->ref
);
940 TRACE("(%p)->(%d)\n", This
, ref
);
944 static ULONG WINAPI
domdoc_Release( IXMLDOMDocument3
*iface
)
946 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
947 LONG ref
= InterlockedDecrement( &This
->ref
);
949 TRACE("(%p)->(%d)\n", This
, ref
);
956 IUnknown_Release( This
->site
);
957 destroy_xmlnode(&This
->node
);
959 for (eid
= 0; eid
< EVENTID_LAST
; eid
++)
960 if (This
->events
[eid
]) IDispatch_Release(This
->events
[eid
]);
962 release_namespaces(This
);
969 static HRESULT WINAPI
domdoc_GetTypeInfoCount( IXMLDOMDocument3
*iface
, UINT
* pctinfo
)
971 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
972 return IDispatchEx_GetTypeInfoCount(&This
->node
.dispex
.IDispatchEx_iface
, pctinfo
);
975 static HRESULT WINAPI
domdoc_GetTypeInfo(
976 IXMLDOMDocument3
*iface
,
977 UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
979 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
980 return IDispatchEx_GetTypeInfo(&This
->node
.dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
983 static HRESULT WINAPI
domdoc_GetIDsOfNames(
984 IXMLDOMDocument3
*iface
,
991 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
992 return IDispatchEx_GetIDsOfNames(&This
->node
.dispex
.IDispatchEx_iface
,
993 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
996 static HRESULT WINAPI
domdoc_Invoke(
997 IXMLDOMDocument3
*iface
,
1002 DISPPARAMS
* pDispParams
,
1003 VARIANT
* pVarResult
,
1004 EXCEPINFO
* pExcepInfo
,
1007 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1008 return IDispatchEx_Invoke(&This
->node
.dispex
.IDispatchEx_iface
,
1009 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1012 static HRESULT WINAPI
domdoc_get_nodeName(
1013 IXMLDOMDocument3
*iface
,
1016 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1018 static const WCHAR documentW
[] = {'#','d','o','c','u','m','e','n','t',0};
1020 TRACE("(%p)->(%p)\n", This
, name
);
1022 return return_bstr(documentW
, name
);
1026 static HRESULT WINAPI
domdoc_get_nodeValue(
1027 IXMLDOMDocument3
*iface
,
1030 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1032 TRACE("(%p)->(%p)\n", This
, value
);
1035 return E_INVALIDARG
;
1037 V_VT(value
) = VT_NULL
;
1038 V_BSTR(value
) = NULL
; /* tests show that we should do this */
1043 static HRESULT WINAPI
domdoc_put_nodeValue(
1044 IXMLDOMDocument3
*iface
,
1047 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1048 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&value
));
1053 static HRESULT WINAPI
domdoc_get_nodeType(
1054 IXMLDOMDocument3
*iface
,
1057 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1059 TRACE("(%p)->(%p)\n", This
, type
);
1061 *type
= NODE_DOCUMENT
;
1066 static HRESULT WINAPI
domdoc_get_parentNode(
1067 IXMLDOMDocument3
*iface
,
1068 IXMLDOMNode
** parent
)
1070 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1072 TRACE("(%p)->(%p)\n", This
, parent
);
1074 return node_get_parent(&This
->node
, parent
);
1078 static HRESULT WINAPI
domdoc_get_childNodes(
1079 IXMLDOMDocument3
*iface
,
1080 IXMLDOMNodeList
** childList
)
1082 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1084 TRACE("(%p)->(%p)\n", This
, childList
);
1086 return node_get_child_nodes(&This
->node
, childList
);
1090 static HRESULT WINAPI
domdoc_get_firstChild(
1091 IXMLDOMDocument3
*iface
,
1092 IXMLDOMNode
** firstChild
)
1094 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1096 TRACE("(%p)->(%p)\n", This
, firstChild
);
1098 return node_get_first_child(&This
->node
, firstChild
);
1102 static HRESULT WINAPI
domdoc_get_lastChild(
1103 IXMLDOMDocument3
*iface
,
1104 IXMLDOMNode
** lastChild
)
1106 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1108 TRACE("(%p)->(%p)\n", This
, lastChild
);
1110 return node_get_last_child(&This
->node
, lastChild
);
1114 static HRESULT WINAPI
domdoc_get_previousSibling(
1115 IXMLDOMDocument3
*iface
,
1116 IXMLDOMNode
** previousSibling
)
1118 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1120 TRACE("(%p)->(%p)\n", This
, previousSibling
);
1122 return return_null_node(previousSibling
);
1126 static HRESULT WINAPI
domdoc_get_nextSibling(
1127 IXMLDOMDocument3
*iface
,
1128 IXMLDOMNode
** nextSibling
)
1130 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1132 TRACE("(%p)->(%p)\n", This
, nextSibling
);
1134 return return_null_node(nextSibling
);
1138 static HRESULT WINAPI
domdoc_get_attributes(
1139 IXMLDOMDocument3
*iface
,
1140 IXMLDOMNamedNodeMap
** attributeMap
)
1142 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1144 TRACE("(%p)->(%p)\n", This
, attributeMap
);
1146 return return_null_ptr((void**)attributeMap
);
1150 static HRESULT WINAPI
domdoc_insertBefore(
1151 IXMLDOMDocument3
*iface
,
1152 IXMLDOMNode
* newChild
,
1154 IXMLDOMNode
** outNewChild
)
1156 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1160 TRACE("(%p)->(%p %s %p)\n", This
, newChild
, debugstr_variant(&refChild
), outNewChild
);
1162 hr
= IXMLDOMNode_get_nodeType(newChild
, &type
);
1163 if (hr
!= S_OK
) return hr
;
1165 TRACE("new node type %d\n", type
);
1168 case NODE_ATTRIBUTE
:
1170 case NODE_CDATA_SECTION
:
1171 if (outNewChild
) *outNewChild
= NULL
;
1174 return node_insert_before(&This
->node
, newChild
, &refChild
, outNewChild
);
1178 static HRESULT WINAPI
domdoc_replaceChild(
1179 IXMLDOMDocument3
*iface
,
1180 IXMLDOMNode
* newChild
,
1181 IXMLDOMNode
* oldChild
,
1182 IXMLDOMNode
** outOldChild
)
1184 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1186 TRACE("(%p)->(%p %p %p)\n", This
, newChild
, oldChild
, outOldChild
);
1188 return node_replace_child(&This
->node
, newChild
, oldChild
, outOldChild
);
1192 static HRESULT WINAPI
domdoc_removeChild(
1193 IXMLDOMDocument3
*iface
,
1195 IXMLDOMNode
**oldChild
)
1197 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1198 TRACE("(%p)->(%p %p)\n", This
, child
, oldChild
);
1199 return node_remove_child(&This
->node
, child
, oldChild
);
1203 static HRESULT WINAPI
domdoc_appendChild(
1204 IXMLDOMDocument3
*iface
,
1206 IXMLDOMNode
**outChild
)
1208 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1209 TRACE("(%p)->(%p %p)\n", This
, child
, outChild
);
1210 return node_append_child(&This
->node
, child
, outChild
);
1214 static HRESULT WINAPI
domdoc_hasChildNodes(
1215 IXMLDOMDocument3
*iface
,
1218 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1219 TRACE("(%p)->(%p)\n", This
, ret
);
1220 return node_has_childnodes(&This
->node
, ret
);
1224 static HRESULT WINAPI
domdoc_get_ownerDocument(
1225 IXMLDOMDocument3
*iface
,
1226 IXMLDOMDocument
**doc
)
1228 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1229 TRACE("(%p)->(%p)\n", This
, doc
);
1230 return node_get_owner_doc(&This
->node
, doc
);
1234 static HRESULT WINAPI
domdoc_cloneNode(
1235 IXMLDOMDocument3
*iface
,
1237 IXMLDOMNode
** outNode
)
1239 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1240 TRACE("(%p)->(%d %p)\n", This
, deep
, outNode
);
1241 return node_clone( &This
->node
, deep
, outNode
);
1245 static HRESULT WINAPI
domdoc_get_nodeTypeString(
1246 IXMLDOMDocument3
*iface
,
1249 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1250 static const WCHAR documentW
[] = {'d','o','c','u','m','e','n','t',0};
1252 TRACE("(%p)->(%p)\n", This
, p
);
1254 return return_bstr(documentW
, p
);
1258 static HRESULT WINAPI
domdoc_get_text(
1259 IXMLDOMDocument3
*iface
,
1262 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1263 TRACE("(%p)->(%p)\n", This
, p
);
1264 return node_get_text(&This
->node
, p
);
1268 static HRESULT WINAPI
domdoc_put_text(
1269 IXMLDOMDocument3
*iface
,
1272 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1273 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
1278 static HRESULT WINAPI
domdoc_get_specified(
1279 IXMLDOMDocument3
*iface
,
1280 VARIANT_BOOL
* isSpecified
)
1282 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1283 FIXME("(%p)->(%p) stub!\n", This
, isSpecified
);
1284 *isSpecified
= VARIANT_TRUE
;
1289 static HRESULT WINAPI
domdoc_get_definition(
1290 IXMLDOMDocument3
*iface
,
1291 IXMLDOMNode
** definitionNode
)
1293 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1294 FIXME("(%p)->(%p)\n", This
, definitionNode
);
1299 static HRESULT WINAPI
domdoc_get_nodeTypedValue(
1300 IXMLDOMDocument3
*iface
,
1303 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1304 TRACE("(%p)->(%p)\n", This
, v
);
1305 return return_null_var(v
);
1308 static HRESULT WINAPI
domdoc_put_nodeTypedValue(
1309 IXMLDOMDocument3
*iface
,
1310 VARIANT typedValue
)
1312 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1313 FIXME("(%p)->(%s)\n", This
, debugstr_variant(&typedValue
));
1318 static HRESULT WINAPI
domdoc_get_dataType(
1319 IXMLDOMDocument3
*iface
,
1322 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1323 TRACE("(%p)->(%p)\n", This
, typename
);
1324 return return_null_var( typename
);
1328 static HRESULT WINAPI
domdoc_put_dataType(
1329 IXMLDOMDocument3
*iface
,
1332 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1334 FIXME("(%p)->(%s)\n", This
, debugstr_w(dataTypeName
));
1337 return E_INVALIDARG
;
1342 static int XMLCALL
domdoc_get_xml_writecallback(void *ctx
, const char *data
, int len
)
1344 return xmlBufferAdd((xmlBufferPtr
)ctx
, (xmlChar
*)data
, len
) == 0 ? len
: 0;
1347 static HRESULT WINAPI
domdoc_get_xml(
1348 IXMLDOMDocument3
*iface
,
1351 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1352 xmlSaveCtxtPtr ctxt
;
1357 TRACE("(%p)->(%p)\n", This
, p
);
1360 return E_INVALIDARG
;
1364 buf
= xmlBufferCreate();
1366 return E_OUTOFMEMORY
;
1368 options
= XML_SAVE_FORMAT
| XML_SAVE_NO_DECL
;
1369 ctxt
= xmlSaveToIO(domdoc_get_xml_writecallback
, NULL
, buf
, "UTF-8", options
);
1374 return E_OUTOFMEMORY
;
1377 ret
= xmlSaveDoc(ctxt
, get_doc(This
));
1378 /* flushes on close */
1381 TRACE("%ld, len=%d\n", ret
, xmlBufferLength(buf
));
1382 if(ret
!= -1 && xmlBufferLength(buf
) > 0)
1386 content
= bstr_from_xmlChar(xmlBufferContent(buf
));
1387 content
= EnsureCorrectEOL(content
);
1393 *p
= SysAllocStringLen(NULL
, 0);
1398 return *p
? S_OK
: E_OUTOFMEMORY
;
1402 static HRESULT WINAPI
domdoc_transformNode(
1403 IXMLDOMDocument3
*iface
,
1407 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1408 TRACE("(%p)->(%p %p)\n", This
, node
, p
);
1409 return node_transform_node(&This
->node
, node
, p
);
1413 static HRESULT WINAPI
domdoc_selectNodes(
1414 IXMLDOMDocument3
*iface
,
1416 IXMLDOMNodeList
**outList
)
1418 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1419 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outList
);
1420 return node_select_nodes(&This
->node
, p
, outList
);
1424 static HRESULT WINAPI
domdoc_selectSingleNode(
1425 IXMLDOMDocument3
*iface
,
1427 IXMLDOMNode
**outNode
)
1429 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1430 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outNode
);
1431 return node_select_singlenode(&This
->node
, p
, outNode
);
1435 static HRESULT WINAPI
domdoc_get_parsed(
1436 IXMLDOMDocument3
*iface
,
1437 VARIANT_BOOL
* isParsed
)
1439 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1440 FIXME("(%p)->(%p) stub!\n", This
, isParsed
);
1441 *isParsed
= VARIANT_TRUE
;
1445 static HRESULT WINAPI
domdoc_get_namespaceURI(
1446 IXMLDOMDocument3
*iface
,
1447 BSTR
* namespaceURI
)
1449 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1450 TRACE("(%p)->(%p)\n", This
, namespaceURI
);
1451 return return_null_bstr( namespaceURI
);
1454 static HRESULT WINAPI
domdoc_get_prefix(
1455 IXMLDOMDocument3
*iface
,
1458 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1459 TRACE("(%p)->(%p)\n", This
, prefix
);
1460 return return_null_bstr( prefix
);
1464 static HRESULT WINAPI
domdoc_get_baseName(
1465 IXMLDOMDocument3
*iface
,
1468 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1469 TRACE("(%p)->(%p)\n", This
, name
);
1470 return return_null_bstr( name
);
1474 static HRESULT WINAPI
domdoc_transformNodeToObject(
1475 IXMLDOMDocument3
*iface
,
1476 IXMLDOMNode
* stylesheet
,
1477 VARIANT outputObject
)
1479 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1480 FIXME("(%p)->(%p %s)\n", This
, stylesheet
, debugstr_variant(&outputObject
));
1485 static HRESULT WINAPI
domdoc_get_doctype(
1486 IXMLDOMDocument3
*iface
,
1487 IXMLDOMDocumentType
** doctype
)
1489 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1494 TRACE("(%p)->(%p)\n", This
, doctype
);
1496 if (!doctype
) return E_INVALIDARG
;
1500 dtd
= xmlGetIntSubset(get_doc(This
));
1501 if (!dtd
) return S_FALSE
;
1503 node
= create_node((xmlNodePtr
)dtd
);
1504 if (!node
) return S_FALSE
;
1506 hr
= IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentType
, (void**)doctype
);
1507 IXMLDOMNode_Release(node
);
1513 static HRESULT WINAPI
domdoc_get_implementation(
1514 IXMLDOMDocument3
*iface
,
1515 IXMLDOMImplementation
** impl
)
1517 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1519 TRACE("(%p)->(%p)\n", This
, impl
);
1522 return E_INVALIDARG
;
1524 *impl
= (IXMLDOMImplementation
*)create_doc_Implementation();
1529 static HRESULT WINAPI
domdoc_get_documentElement(
1530 IXMLDOMDocument3
*iface
,
1531 IXMLDOMElement
** DOMElement
)
1533 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1534 IXMLDOMNode
*element_node
;
1538 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1541 return E_INVALIDARG
;
1545 root
= xmlDocGetRootElement( get_doc(This
) );
1549 element_node
= create_node( root
);
1550 if(!element_node
) return S_FALSE
;
1552 hr
= IXMLDOMNode_QueryInterface(element_node
, &IID_IXMLDOMElement
, (void**)DOMElement
);
1553 IXMLDOMNode_Release(element_node
);
1559 static HRESULT WINAPI
domdoc_put_documentElement(
1560 IXMLDOMDocument3
*iface
,
1561 IXMLDOMElement
* DOMElement
)
1563 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1564 IXMLDOMNode
*elementNode
;
1571 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1573 hr
= IXMLDOMElement_QueryInterface( DOMElement
, &IID_IXMLDOMNode
, (void**)&elementNode
);
1577 xmlNode
= get_node_obj( elementNode
);
1578 if(!xmlNode
) return E_FAIL
;
1580 if(!xmlNode
->node
->parent
)
1581 if(xmldoc_remove_orphan(xmlNode
->node
->doc
, xmlNode
->node
) != S_OK
)
1582 WARN("%p is not an orphan of %p\n", xmlNode
->node
->doc
, xmlNode
->node
);
1584 old_doc
= xmlNode
->node
->doc
;
1585 if (old_doc
!= get_doc(This
))
1586 refcount
= xmlnode_get_inst_cnt(xmlNode
);
1588 /* old root is still orphaned by its document, update refcount from new root */
1589 if (refcount
) xmldoc_add_refs(get_doc(This
), refcount
);
1590 oldRoot
= xmlDocSetRootElement( get_doc(This
), xmlNode
->node
);
1591 if (refcount
) xmldoc_release_refs(old_doc
, refcount
);
1592 IXMLDOMNode_Release( elementNode
);
1595 xmldoc_add_orphan(oldRoot
->doc
, oldRoot
);
1601 static HRESULT WINAPI
domdoc_createElement(
1602 IXMLDOMDocument3
*iface
,
1604 IXMLDOMElement
** element
)
1606 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1611 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(tagname
), element
);
1613 if (!element
|| !tagname
) return E_INVALIDARG
;
1615 V_VT(&type
) = VT_I1
;
1616 V_I1(&type
) = NODE_ELEMENT
;
1618 hr
= IXMLDOMDocument3_createNode(iface
, type
, tagname
, NULL
, &node
);
1621 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMElement
, (void**)element
);
1622 IXMLDOMNode_Release(node
);
1629 static HRESULT WINAPI
domdoc_createDocumentFragment(
1630 IXMLDOMDocument3
*iface
,
1631 IXMLDOMDocumentFragment
** frag
)
1633 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1638 TRACE("(%p)->(%p)\n", This
, frag
);
1640 if (!frag
) return E_INVALIDARG
;
1644 V_VT(&type
) = VT_I1
;
1645 V_I1(&type
) = NODE_DOCUMENT_FRAGMENT
;
1647 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1650 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentFragment
, (void**)frag
);
1651 IXMLDOMNode_Release(node
);
1658 static HRESULT WINAPI
domdoc_createTextNode(
1659 IXMLDOMDocument3
*iface
,
1661 IXMLDOMText
** text
)
1663 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1668 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), text
);
1670 if (!text
) return E_INVALIDARG
;
1674 V_VT(&type
) = VT_I1
;
1675 V_I1(&type
) = NODE_TEXT
;
1677 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1680 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMText
, (void**)text
);
1681 IXMLDOMNode_Release(node
);
1682 hr
= IXMLDOMText_put_data(*text
, data
);
1689 static HRESULT WINAPI
domdoc_createComment(
1690 IXMLDOMDocument3
*iface
,
1692 IXMLDOMComment
** comment
)
1694 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1699 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), comment
);
1701 if (!comment
) return E_INVALIDARG
;
1705 V_VT(&type
) = VT_I1
;
1706 V_I1(&type
) = NODE_COMMENT
;
1708 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1711 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMComment
, (void**)comment
);
1712 IXMLDOMNode_Release(node
);
1713 hr
= IXMLDOMComment_put_data(*comment
, data
);
1720 static HRESULT WINAPI
domdoc_createCDATASection(
1721 IXMLDOMDocument3
*iface
,
1723 IXMLDOMCDATASection
** cdata
)
1725 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1730 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), cdata
);
1732 if (!cdata
) return E_INVALIDARG
;
1736 V_VT(&type
) = VT_I1
;
1737 V_I1(&type
) = NODE_CDATA_SECTION
;
1739 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1742 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMCDATASection
, (void**)cdata
);
1743 IXMLDOMNode_Release(node
);
1744 hr
= IXMLDOMCDATASection_put_data(*cdata
, data
);
1751 static HRESULT WINAPI
domdoc_createProcessingInstruction(
1752 IXMLDOMDocument3
*iface
,
1755 IXMLDOMProcessingInstruction
** pi
)
1757 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1762 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_w(target
), debugstr_w(data
), pi
);
1764 if (!pi
) return E_INVALIDARG
;
1768 V_VT(&type
) = VT_I1
;
1769 V_I1(&type
) = NODE_PROCESSING_INSTRUCTION
;
1771 hr
= IXMLDOMDocument3_createNode(iface
, type
, target
, NULL
, &node
);
1776 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1777 node_obj
= get_node_obj(node
);
1778 hr
= node_set_content(node_obj
, data
);
1780 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMProcessingInstruction
, (void**)pi
);
1781 IXMLDOMNode_Release(node
);
1788 static HRESULT WINAPI
domdoc_createAttribute(
1789 IXMLDOMDocument3
*iface
,
1791 IXMLDOMAttribute
** attribute
)
1793 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1798 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), attribute
);
1800 if (!attribute
|| !name
) return E_INVALIDARG
;
1802 V_VT(&type
) = VT_I1
;
1803 V_I1(&type
) = NODE_ATTRIBUTE
;
1805 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1808 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMAttribute
, (void**)attribute
);
1809 IXMLDOMNode_Release(node
);
1816 static HRESULT WINAPI
domdoc_createEntityReference(
1817 IXMLDOMDocument3
*iface
,
1819 IXMLDOMEntityReference
** entityref
)
1821 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1826 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), entityref
);
1828 if (!entityref
) return E_INVALIDARG
;
1832 V_VT(&type
) = VT_I1
;
1833 V_I1(&type
) = NODE_ENTITY_REFERENCE
;
1835 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1838 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMEntityReference
, (void**)entityref
);
1839 IXMLDOMNode_Release(node
);
1845 xmlChar
* tagName_to_XPath(const BSTR tagName
)
1847 xmlChar
*query
, *tmp
;
1848 static const xmlChar everything
[] = "/descendant::node()";
1849 static const xmlChar mod_pre
[] = "*[local-name()='";
1850 static const xmlChar mod_post
[] = "']";
1851 static const xmlChar prefix
[] = "descendant::";
1852 const WCHAR
*tokBegin
, *tokEnd
;
1855 /* Special case - empty tagname - means select all nodes,
1856 except document itself. */
1858 return xmlStrdup(everything
);
1860 query
= xmlStrdup(prefix
);
1863 while (tokBegin
&& *tokBegin
)
1868 query
= xmlStrcat(query
, BAD_CAST
"/");
1872 query
= xmlStrcat(query
, BAD_CAST
"*");
1876 query
= xmlStrcat(query
, mod_pre
);
1878 while (*tokEnd
&& *tokEnd
!= '/')
1880 len
= WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, NULL
, 0, NULL
, NULL
);
1881 tmp
= xmlMalloc(len
);
1882 WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, (char*)tmp
, len
, NULL
, NULL
);
1883 query
= xmlStrncat(query
, tmp
, len
);
1886 query
= xmlStrcat(query
, mod_post
);
1893 static HRESULT WINAPI
domdoc_getElementsByTagName(
1894 IXMLDOMDocument3
*iface
,
1896 IXMLDOMNodeList
** resultList
)
1898 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1903 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(tagName
), resultList
);
1905 if (!tagName
|| !resultList
) return E_INVALIDARG
;
1907 XPath
= This
->properties
->XPath
;
1908 This
->properties
->XPath
= TRUE
;
1909 query
= tagName_to_XPath(tagName
);
1910 hr
= create_selection((xmlNodePtr
)get_doc(This
), query
, resultList
);
1912 This
->properties
->XPath
= XPath
;
1917 static HRESULT
get_node_type(VARIANT Type
, DOMNodeType
* type
)
1923 hr
= VariantChangeType(&tmp
, &Type
, 0, VT_I4
);
1925 return E_INVALIDARG
;
1932 static HRESULT WINAPI
domdoc_createNode(
1933 IXMLDOMDocument3
*iface
,
1937 IXMLDOMNode
** node
)
1939 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1940 DOMNodeType node_type
;
1942 xmlChar
*xml_name
, *href
;
1945 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_variant(&Type
), debugstr_w(name
), debugstr_w(namespaceURI
), node
);
1947 if(!node
) return E_INVALIDARG
;
1949 hr
= get_node_type(Type
, &node_type
);
1950 if(FAILED(hr
)) return hr
;
1952 TRACE("node_type %d\n", node_type
);
1954 /* exit earlier for types that need name */
1958 case NODE_ATTRIBUTE
:
1959 case NODE_ENTITY_REFERENCE
:
1960 case NODE_PROCESSING_INSTRUCTION
:
1961 if (!name
|| *name
== 0) return E_FAIL
;
1967 xml_name
= xmlchar_from_wchar(name
);
1968 /* prevent empty href from being allocated */
1969 href
= namespaceURI
? xmlchar_from_wchar(namespaceURI
) : NULL
;
1975 xmlChar
*local
, *prefix
;
1977 local
= xmlSplitQName2(xml_name
, &prefix
);
1979 xmlnode
= xmlNewDocNode(get_doc(This
), NULL
, local
? local
: xml_name
, NULL
);
1981 /* allow creating the default namespace xmlns= */
1982 if (local
|| (href
&& *href
))
1984 xmlNsPtr ns
= xmlNewNs(xmlnode
, href
, prefix
);
1985 xmlSetNs(xmlnode
, ns
);
1993 case NODE_ATTRIBUTE
:
1995 xmlChar
*local
, *prefix
;
1997 local
= xmlSplitQName2(xml_name
, &prefix
);
1999 xmlnode
= (xmlNodePtr
)xmlNewDocProp(get_doc(This
), local
? local
: xml_name
, NULL
);
2001 if (local
|| (href
&& *href
))
2003 /* we need a floating namespace here, it can't be created linked to attribute from
2005 xmlNsPtr ns
= xmlNewNs(NULL
, href
, prefix
);
2006 xmlSetNs(xmlnode
, ns
);
2015 xmlnode
= (xmlNodePtr
)xmlNewDocText(get_doc(This
), NULL
);
2017 case NODE_CDATA_SECTION
:
2018 xmlnode
= xmlNewCDataBlock(get_doc(This
), NULL
, 0);
2020 case NODE_ENTITY_REFERENCE
:
2021 xmlnode
= xmlNewReference(get_doc(This
), xml_name
);
2023 case NODE_PROCESSING_INSTRUCTION
:
2024 #ifdef HAVE_XMLNEWDOCPI
2025 xmlnode
= xmlNewDocPI(get_doc(This
), xml_name
, NULL
);
2027 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2032 xmlnode
= xmlNewDocComment(get_doc(This
), NULL
);
2034 case NODE_DOCUMENT_FRAGMENT
:
2035 xmlnode
= xmlNewDocFragment(get_doc(This
));
2037 /* unsupported types */
2039 case NODE_DOCUMENT_TYPE
:
2042 heap_free(xml_name
);
2043 return E_INVALIDARG
;
2045 FIXME("unhandled node type %d\n", node_type
);
2050 *node
= create_node(xmlnode
);
2051 heap_free(xml_name
);
2056 TRACE("created node (%d, %p, %p)\n", node_type
, *node
, xmlnode
);
2057 xmldoc_add_orphan(xmlnode
->doc
, xmlnode
);
2064 static HRESULT WINAPI
domdoc_nodeFromID(
2065 IXMLDOMDocument3
*iface
,
2067 IXMLDOMNode
** node
)
2069 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2070 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(idString
), node
);
2074 static HRESULT
domdoc_onDataAvailable(void *obj
, char *ptr
, DWORD len
)
2079 xmldoc
= doparse(This
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
2081 xmldoc
->_private
= create_priv();
2082 return attach_xmldoc(This
, xmldoc
);
2088 static HRESULT
domdoc_load_moniker(domdoc
*This
, IMoniker
*mon
)
2093 hr
= bind_url(mon
, domdoc_onDataAvailable
, This
, &bsc
);
2097 return detach_bsc(bsc
);
2100 static HRESULT WINAPI
domdoc_load(
2101 IXMLDOMDocument3
*iface
,
2103 VARIANT_BOOL
* isSuccessful
)
2105 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2106 LPWSTR filename
= NULL
;
2107 HRESULT hr
= S_FALSE
;
2110 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&source
));
2114 *isSuccessful
= VARIANT_FALSE
;
2116 assert( &This
->node
);
2118 switch( V_VT(&source
) )
2121 filename
= V_BSTR(&source
);
2123 case VT_BSTR
|VT_BYREF
:
2124 if (!V_BSTRREF(&source
)) return E_INVALIDARG
;
2125 filename
= *V_BSTRREF(&source
);
2127 case VT_ARRAY
|VT_UI1
:
2129 SAFEARRAY
*psa
= V_ARRAY(&source
);
2132 UINT dim
= SafeArrayGetDim(psa
);
2137 ERR("SAFEARRAY == NULL\n");
2138 hr
= This
->error
= E_INVALIDARG
;
2141 /* Only takes UTF-8 strings.
2142 * NOT NULL-terminated. */
2143 hr
= SafeArrayAccessData(psa
, (void**)&str
);
2147 WARN("failed to access array data, 0x%08x\n", hr
);
2150 SafeArrayGetUBound(psa
, 1, &len
);
2152 if ((xmldoc
= doparse(This
, str
, ++len
, XML_CHAR_ENCODING_UTF8
)))
2154 hr
= This
->error
= S_OK
;
2155 *isSuccessful
= VARIANT_TRUE
;
2156 TRACE("parsed document %p\n", xmldoc
);
2160 This
->error
= E_FAIL
;
2161 TRACE("failed to parse document\n");
2164 SafeArrayUnaccessData(psa
);
2168 xmldoc
->_private
= create_priv();
2169 return attach_xmldoc(This
, xmldoc
);
2173 FIXME("unhandled SAFEARRAY dim: %d\n", dim
);
2174 hr
= This
->error
= E_NOTIMPL
;
2180 ISequentialStream
*stream
= NULL
;
2181 IXMLDOMDocument3
*newdoc
= NULL
;
2183 if (!V_UNKNOWN(&source
)) return E_INVALIDARG
;
2185 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IXMLDOMDocument3
, (void**)&newdoc
);
2190 domdoc
*newDoc
= impl_from_IXMLDOMDocument3( newdoc
);
2192 xmldoc
= xmlCopyDoc(get_doc(newDoc
), 1);
2193 xmldoc
->_private
= create_priv();
2194 hr
= attach_xmldoc(This
, xmldoc
);
2197 *isSuccessful
= VARIANT_TRUE
;
2203 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IStream
, (void**)&stream
);
2205 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_ISequentialStream
, (void**)&stream
);
2209 hr
= domdoc_load_from_stream(This
, stream
);
2211 *isSuccessful
= VARIANT_TRUE
;
2212 ISequentialStream_Release(stream
);
2216 FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr
, V_UNKNOWN(&source
)->lpVtbl
);
2220 FIXME("VT type not supported (%d)\n", V_VT(&source
));
2227 CoTaskMemFree(This
->properties
->url
);
2228 This
->properties
->url
= NULL
;
2230 hr
= create_moniker_from_url( filename
, &mon
);
2231 if ( SUCCEEDED(hr
) )
2233 hr
= domdoc_load_moniker( This
, mon
);
2235 IMoniker_GetDisplayName(mon
, NULL
, NULL
, &This
->properties
->url
);
2236 IMoniker_Release(mon
);
2240 This
->error
= E_FAIL
;
2243 hr
= This
->error
= S_OK
;
2244 *isSuccessful
= VARIANT_TRUE
;
2248 if(!filename
|| FAILED(hr
)) {
2249 xmldoc
= xmlNewDoc(NULL
);
2250 xmldoc
->_private
= create_priv();
2251 hr
= attach_xmldoc(This
, xmldoc
);
2256 TRACE("ret (%d)\n", hr
);
2262 static HRESULT WINAPI
domdoc_get_readyState(
2263 IXMLDOMDocument3
*iface
,
2266 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2267 FIXME("stub! (%p)->(%p)\n", This
, value
);
2270 return E_INVALIDARG
;
2272 *value
= READYSTATE_COMPLETE
;
2277 static HRESULT WINAPI
domdoc_get_parseError(
2278 IXMLDOMDocument3
*iface
,
2279 IXMLDOMParseError
** errorObj
)
2281 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2282 static const WCHAR err
[] = {'e','r','r','o','r',0};
2283 BSTR error_string
= NULL
;
2285 FIXME("(%p)->(%p): creating a dummy parseError\n", iface
, errorObj
);
2288 error_string
= SysAllocString(err
);
2290 *errorObj
= create_parseError(This
->error
, NULL
, error_string
, NULL
, 0, 0, 0);
2291 if(!*errorObj
) return E_OUTOFMEMORY
;
2296 static HRESULT WINAPI
domdoc_get_url(
2297 IXMLDOMDocument3
*iface
,
2300 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2302 TRACE("(%p)->(%p)\n", This
, url
);
2305 return E_INVALIDARG
;
2307 if (This
->properties
->url
)
2309 *url
= SysAllocString(This
->properties
->url
);
2311 return E_OUTOFMEMORY
;
2316 return return_null_bstr(url
);
2320 static HRESULT WINAPI
domdoc_get_async(
2321 IXMLDOMDocument3
*iface
,
2322 VARIANT_BOOL
* isAsync
)
2324 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2326 TRACE("(%p)->(%p: %d)\n", This
, isAsync
, This
->async
);
2327 *isAsync
= This
->async
;
2332 static HRESULT WINAPI
domdoc_put_async(
2333 IXMLDOMDocument3
*iface
,
2334 VARIANT_BOOL isAsync
)
2336 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2338 TRACE("(%p)->(%d)\n", This
, isAsync
);
2339 This
->async
= isAsync
;
2344 static HRESULT WINAPI
domdoc_abort(
2345 IXMLDOMDocument3
*iface
)
2347 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2348 FIXME("%p\n", This
);
2352 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2353 static HRESULT WINAPI
domdoc_loadXML(
2354 IXMLDOMDocument3
*iface
,
2356 VARIANT_BOOL
* isSuccessful
)
2358 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2359 xmlDocPtr xmldoc
= NULL
;
2360 HRESULT hr
= S_FALSE
, hr2
;
2362 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), isSuccessful
);
2364 assert ( &This
->node
);
2368 *isSuccessful
= VARIANT_FALSE
;
2374 /* skip leading spaces if needed */
2375 if (This
->properties
->version
== MSXML_DEFAULT
|| This
->properties
->version
== MSXML26
)
2376 while (*ptr
&& isspaceW(*ptr
)) ptr
++;
2378 xmldoc
= doparse(This
, (char*)ptr
, strlenW(ptr
)*sizeof(WCHAR
), XML_CHAR_ENCODING_UTF16LE
);
2381 This
->error
= E_FAIL
;
2382 TRACE("failed to parse document\n");
2386 hr
= This
->error
= S_OK
;
2387 *isSuccessful
= VARIANT_TRUE
;
2388 TRACE("parsed document %p\n", xmldoc
);
2394 xmldoc
= xmlNewDoc(NULL
);
2395 xmldoc
->_private
= create_priv();
2396 hr2
= attach_xmldoc(This
, xmldoc
);
2403 static int XMLCALL
domdoc_save_writecallback(void *ctx
, const char *buffer
, int len
)
2407 if(!WriteFile(ctx
, buffer
, len
, &written
, NULL
))
2409 WARN("write error\n");
2416 static int XMLCALL
domdoc_save_closecallback(void *ctx
)
2418 return CloseHandle(ctx
) ? 0 : -1;
2421 static int XMLCALL
domdoc_stream_save_writecallback(void *ctx
, const char *buffer
, int len
)
2426 hr
= IStream_Write((IStream
*)ctx
, buffer
, len
, &written
);
2427 TRACE("0x%08x %p %d %u\n", hr
, buffer
, len
, written
);
2430 WARN("stream write error: 0x%08x\n", hr
);
2437 static int XMLCALL
domdoc_stream_save_closecallback(void *ctx
)
2439 IStream_Release((IStream
*)ctx
);
2443 static HRESULT WINAPI
domdoc_save(
2444 IXMLDOMDocument3
*iface
,
2445 VARIANT destination
)
2447 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2448 xmlSaveCtxtPtr ctx
= NULL
;
2452 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&destination
));
2454 switch (V_VT(&destination
))
2458 IUnknown
*pUnk
= V_UNKNOWN(&destination
);
2459 IXMLDOMDocument3
*document
;
2462 ret
= IUnknown_QueryInterface(pUnk
, &IID_IXMLDOMDocument3
, (void**)&document
);
2465 VARIANT_BOOL success
;
2468 ret
= IXMLDOMDocument3_get_xml(iface
, &xml
);
2471 ret
= IXMLDOMDocument3_loadXML(document
, xml
, &success
);
2475 IXMLDOMDocument3_Release(document
);
2479 ret
= IUnknown_QueryInterface(pUnk
, &IID_IStream
, (void**)&stream
);
2482 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2483 ctx
= xmlSaveToIO(domdoc_stream_save_writecallback
,
2484 domdoc_stream_save_closecallback
, stream
, NULL
, options
);
2488 IStream_Release(stream
);
2496 case VT_BSTR
| VT_BYREF
:
2498 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2500 /* save with file path */
2501 HANDLE handle
= CreateFileW( (V_VT(&destination
) & VT_BYREF
)? *V_BSTRREF(&destination
) : V_BSTR(&destination
),
2502 GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2503 if( handle
== INVALID_HANDLE_VALUE
)
2505 WARN("failed to create file\n");
2509 /* disable top XML declaration */
2510 ctx
= xmlSaveToIO(domdoc_save_writecallback
, domdoc_save_closecallback
,
2511 handle
, NULL
, options
);
2514 CloseHandle(handle
);
2521 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination
));
2525 xmldecl
= xmldoc_unlink_xmldecl(get_doc(This
));
2526 if (xmlSaveDoc(ctx
, get_doc(This
)) == -1) ret
= S_FALSE
;
2527 xmldoc_link_xmldecl(get_doc(This
), xmldecl
);
2529 /* will release resources through close callback */
2535 static HRESULT WINAPI
domdoc_get_validateOnParse(
2536 IXMLDOMDocument3
*iface
,
2537 VARIANT_BOOL
* isValidating
)
2539 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2540 TRACE("(%p)->(%p: %d)\n", This
, isValidating
, This
->validating
);
2541 *isValidating
= This
->validating
;
2546 static HRESULT WINAPI
domdoc_put_validateOnParse(
2547 IXMLDOMDocument3
*iface
,
2548 VARIANT_BOOL isValidating
)
2550 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2551 TRACE("(%p)->(%d)\n", This
, isValidating
);
2552 This
->validating
= isValidating
;
2557 static HRESULT WINAPI
domdoc_get_resolveExternals(
2558 IXMLDOMDocument3
*iface
,
2559 VARIANT_BOOL
* isResolving
)
2561 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2562 TRACE("(%p)->(%p: %d)\n", This
, isResolving
, This
->resolving
);
2563 *isResolving
= This
->resolving
;
2568 static HRESULT WINAPI
domdoc_put_resolveExternals(
2569 IXMLDOMDocument3
*iface
,
2570 VARIANT_BOOL isResolving
)
2572 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2573 TRACE("(%p)->(%d)\n", This
, isResolving
);
2574 This
->resolving
= isResolving
;
2579 static HRESULT WINAPI
domdoc_get_preserveWhiteSpace(
2580 IXMLDOMDocument3
*iface
,
2581 VARIANT_BOOL
* isPreserving
)
2583 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2584 TRACE("(%p)->(%p: %d)\n", This
, isPreserving
, This
->properties
->preserving
);
2585 *isPreserving
= This
->properties
->preserving
;
2590 static HRESULT WINAPI
domdoc_put_preserveWhiteSpace(
2591 IXMLDOMDocument3
*iface
,
2592 VARIANT_BOOL isPreserving
)
2594 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2595 TRACE("(%p)->(%d)\n", This
, isPreserving
);
2596 This
->properties
->preserving
= isPreserving
;
2601 static HRESULT WINAPI
domdoc_put_onreadystatechange(
2602 IXMLDOMDocument3
*iface
,
2605 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2607 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&event
));
2608 return set_doc_event(This
, EVENTID_READYSTATECHANGE
, &event
);
2612 static HRESULT WINAPI
domdoc_put_onDataAvailable(IXMLDOMDocument3
*iface
, VARIANT sink
)
2614 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2615 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2619 static HRESULT WINAPI
domdoc_put_onTransformNode(IXMLDOMDocument3
*iface
, VARIANT sink
)
2621 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2622 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2626 static HRESULT WINAPI
domdoc_get_namespaces(
2627 IXMLDOMDocument3
* iface
,
2628 IXMLDOMSchemaCollection
** collection
)
2630 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2633 FIXME("(%p)->(%p): semi-stub\n", This
, collection
);
2635 if (!collection
) return E_POINTER
;
2637 if (!This
->namespaces
)
2639 hr
= SchemaCache_create(This
->properties
->version
, (void**)&This
->namespaces
);
2640 if (hr
!= S_OK
) return hr
;
2642 hr
= cache_from_doc_ns(This
->namespaces
, &This
->node
);
2644 release_namespaces(This
);
2647 if (This
->namespaces
)
2648 return IXMLDOMSchemaCollection2_QueryInterface(This
->namespaces
,
2649 &IID_IXMLDOMSchemaCollection
, (void**)collection
);
2654 static HRESULT WINAPI
domdoc_get_schemas(
2655 IXMLDOMDocument3
* iface
,
2658 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2659 IXMLDOMSchemaCollection2
* cur_schema
= This
->properties
->schemaCache
;
2660 HRESULT hr
= S_FALSE
;
2662 TRACE("(%p)->(%p)\n", This
, schema
);
2664 V_VT(schema
) = VT_NULL
;
2665 /* just to reset pointer part, cause that's what application is expected to use */
2666 V_DISPATCH(schema
) = NULL
;
2670 hr
= IXMLDOMSchemaCollection2_QueryInterface(cur_schema
, &IID_IDispatch
, (void**)&V_DISPATCH(schema
));
2672 V_VT(schema
) = VT_DISPATCH
;
2677 static HRESULT WINAPI
domdoc_putref_schemas(
2678 IXMLDOMDocument3
* iface
,
2681 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2682 HRESULT hr
= E_FAIL
;
2683 IXMLDOMSchemaCollection2
* new_schema
= NULL
;
2685 FIXME("(%p)->(%s): semi-stub\n", This
, debugstr_variant(&schema
));
2686 switch(V_VT(&schema
))
2689 if (V_UNKNOWN(&schema
))
2691 hr
= IUnknown_QueryInterface(V_UNKNOWN(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2696 if (V_DISPATCH(&schema
))
2698 hr
= IDispatch_QueryInterface(V_DISPATCH(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2708 WARN("Can't get schema from vt %x\n", V_VT(&schema
));
2713 IXMLDOMSchemaCollection2
* old_schema
= InterlockedExchangePointer((void**)&This
->properties
->schemaCache
, new_schema
);
2714 if(old_schema
) IXMLDOMSchemaCollection2_Release(old_schema
);
2720 static inline BOOL
is_wellformed(xmlDocPtr doc
)
2722 #ifdef HAVE_XMLDOC_PROPERTIES
2723 return doc
->properties
& XML_DOC_WELLFORMED
;
2725 /* Not a full check, but catches the worst violations */
2729 for (child
= doc
->children
; child
!= NULL
; child
= child
->next
)
2731 switch (child
->type
)
2733 case XML_ELEMENT_NODE
:
2738 case XML_CDATA_SECTION_NODE
:
2750 static void LIBXML2_LOG_CALLBACK
validate_error(void* ctx
, char const* msg
, ...)
2754 LIBXML2_CALLBACK_ERR(domdoc_validateNode
, msg
, ap
);
2758 static void LIBXML2_LOG_CALLBACK
validate_warning(void* ctx
, char const* msg
, ...)
2762 LIBXML2_CALLBACK_WARN(domdoc_validateNode
, msg
, ap
);
2766 static HRESULT WINAPI
domdoc_validateNode(
2767 IXMLDOMDocument3
* iface
,
2769 IXMLDOMParseError
** err
)
2771 domdoc
* This
= impl_from_IXMLDOMDocument3(iface
);
2772 LONG state
, err_code
= 0;
2776 TRACE("(%p)->(%p, %p)\n", This
, node
, err
);
2777 IXMLDOMDocument3_get_readyState(iface
, &state
);
2778 if (state
!= READYSTATE_COMPLETE
)
2781 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2788 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2792 if (!get_node_obj(node
)->node
|| get_node_obj(node
)->node
->doc
!= get_doc(This
))
2795 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2799 if (!is_wellformed(get_doc(This
)))
2801 ERR("doc not well-formed\n");
2803 *err
= create_parseError(E_XML_NOTWF
, NULL
, NULL
, NULL
, 0, 0, 0);
2807 /* DTD validation */
2808 if (get_doc(This
)->intSubset
|| get_doc(This
)->extSubset
)
2810 xmlValidCtxtPtr vctx
= xmlNewValidCtxt();
2811 vctx
->error
= validate_error
;
2812 vctx
->warning
= validate_warning
;
2815 if (!((node
== (IXMLDOMNode
*)iface
)?
2816 xmlValidateDocument(vctx
, get_doc(This
)) :
2817 xmlValidateElement(vctx
, get_doc(This
), get_node_obj(node
)->node
)))
2819 /* TODO: get a real error code here */
2820 TRACE("DTD validation failed\n");
2821 err_code
= E_XML_INVALID
;
2824 xmlFreeValidCtxt(vctx
);
2827 /* Schema validation */
2828 if (hr
== S_OK
&& This
->properties
->schemaCache
!= NULL
)
2831 hr
= SchemaCache_validate_tree(This
->properties
->schemaCache
, get_node_obj(node
)->node
);
2835 /* TODO: get a real error code here */
2838 TRACE("schema validation succeeded\n");
2842 ERR("schema validation failed\n");
2843 err_code
= E_XML_INVALID
;
2848 /* not really OK, just didn't find a schema for the ns */
2855 ERR("no DTD or schema found\n");
2856 err_code
= E_XML_NODTD
;
2861 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2866 static HRESULT WINAPI
domdoc_validate(
2867 IXMLDOMDocument3
* iface
,
2868 IXMLDOMParseError
** err
)
2870 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2871 TRACE("(%p)->(%p)\n", This
, err
);
2872 return IXMLDOMDocument3_validateNode(iface
, (IXMLDOMNode
*)iface
, err
);
2875 static HRESULT WINAPI
domdoc_setProperty(
2876 IXMLDOMDocument3
* iface
,
2880 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2882 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(p
), debugstr_variant(&value
));
2884 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
2890 V_VT(&varStr
) = VT_EMPTY
;
2891 if (V_VT(&value
) != VT_BSTR
)
2893 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2895 bstr
= V_BSTR(&varStr
);
2898 bstr
= V_BSTR(&value
);
2901 if (lstrcmpiW(bstr
, PropValueXPathW
) == 0)
2902 This
->properties
->XPath
= TRUE
;
2903 else if (lstrcmpiW(bstr
, PropValueXSLPatternW
) == 0)
2904 This
->properties
->XPath
= FALSE
;
2908 VariantClear(&varStr
);
2911 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
2913 xmlChar
*nsStr
= (xmlChar
*)This
->properties
->selectNsStr
;
2914 struct list
*pNsList
;
2919 V_VT(&varStr
) = VT_EMPTY
;
2920 if (V_VT(&value
) != VT_BSTR
)
2922 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2924 bstr
= V_BSTR(&varStr
);
2927 bstr
= V_BSTR(&value
);
2931 pNsList
= &(This
->properties
->selectNsList
);
2932 clear_selectNsList(pNsList
);
2934 nsStr
= xmlchar_from_wchar(bstr
);
2936 TRACE("property value: \"%s\"\n", debugstr_w(bstr
));
2938 This
->properties
->selectNsStr
= nsStr
;
2939 This
->properties
->selectNsStr_len
= xmlStrlen(nsStr
);
2942 xmlChar
*pTokBegin
, *pTokEnd
, *pTokInner
;
2943 select_ns_entry
* ns_entry
= NULL
;
2944 xmlXPathContextPtr ctx
;
2946 ctx
= xmlXPathNewContext(This
->node
.node
->doc
);
2949 /* skip leading spaces */
2950 while (*pTokBegin
== ' ' || *pTokBegin
== '\n' ||
2951 *pTokBegin
== '\t' || *pTokBegin
== '\r')
2954 for (; *pTokBegin
; pTokBegin
= pTokEnd
)
2957 memset(ns_entry
, 0, sizeof(select_ns_entry
));
2959 ns_entry
= heap_alloc_zero(sizeof(select_ns_entry
));
2961 while (*pTokBegin
== ' ')
2963 pTokEnd
= pTokBegin
;
2964 while (*pTokEnd
!= ' ' && *pTokEnd
!= 0)
2967 /* so it failed to advance which means we've got some trailing spaces */
2968 if (pTokEnd
== pTokBegin
) break;
2970 if (xmlStrncmp(pTokBegin
, (xmlChar
const*)"xmlns", 5) != 0)
2973 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2974 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2979 if (*pTokBegin
== '=')
2981 /*valid for XSLPattern?*/
2982 FIXME("Setting default xmlns not supported - skipping.\n");
2985 else if (*pTokBegin
== ':')
2987 ns_entry
->prefix
= ++pTokBegin
;
2988 for (pTokInner
= pTokBegin
; pTokInner
!= pTokEnd
&& *pTokInner
!= '='; ++pTokInner
)
2991 if (pTokInner
== pTokEnd
)
2994 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2995 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2999 ns_entry
->prefix_end
= *pTokInner
;
3003 if (pTokEnd
-pTokInner
> 1 &&
3004 ((*pTokInner
== '\'' && *(pTokEnd
-1) == '\'') ||
3005 (*pTokInner
== '"' && *(pTokEnd
-1) == '"')))
3007 ns_entry
->href
= ++pTokInner
;
3008 ns_entry
->href_end
= *(pTokEnd
-1);
3010 list_add_tail(pNsList
, &ns_entry
->entry
);
3011 /*let libxml figure out if they're valid from here ;)*/
3012 if (xmlXPathRegisterNs(ctx
, ns_entry
->prefix
, ns_entry
->href
) != 0)
3021 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3022 debugstr_w(bstr
), debugstr_an((const char*)pTokInner
, pTokEnd
-pTokInner
));
3023 list_add_tail(pNsList
, &ns_entry
->entry
);
3036 heap_free(ns_entry
);
3037 xmlXPathFreeContext(ctx
);
3040 VariantClear(&varStr
);
3043 else if (lstrcmpiW(p
, PropertyProhibitDTDW
) == 0 ||
3044 lstrcmpiW(p
, PropertyNewParserW
) == 0 ||
3045 lstrcmpiW(p
, PropertyResolveExternalsW
) == 0)
3048 FIXME("Ignoring property %s, value %s\n", debugstr_w(p
), debugstr_variant(&value
));
3052 FIXME("Unknown property %s\n", debugstr_w(p
));
3056 static HRESULT WINAPI
domdoc_getProperty(
3057 IXMLDOMDocument3
* iface
,
3061 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3063 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
3066 return E_INVALIDARG
;
3068 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
3070 V_VT(var
) = VT_BSTR
;
3071 V_BSTR(var
) = This
->properties
->XPath
?
3072 SysAllocString(PropValueXPathW
) :
3073 SysAllocString(PropValueXSLPatternW
);
3074 return V_BSTR(var
) ? S_OK
: E_OUTOFMEMORY
;
3076 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3079 BSTR rebuiltStr
, cur
;
3080 const xmlChar
*nsStr
;
3081 struct list
*pNsList
;
3082 select_ns_entry
* pNsEntry
;
3084 V_VT(var
) = VT_BSTR
;
3085 nsStr
= This
->properties
->selectNsStr
;
3086 pNsList
= &This
->properties
->selectNsList
;
3087 lenA
= This
->properties
->selectNsStr_len
;
3088 lenW
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, NULL
, 0);
3089 rebuiltStr
= heap_alloc(lenW
*sizeof(WCHAR
));
3090 MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, rebuiltStr
, lenW
);
3092 /* this is fine because all of the chars that end tokens are ASCII*/
3093 LIST_FOR_EACH_ENTRY(pNsEntry
, pNsList
, select_ns_entry
, entry
)
3095 while (*cur
!= 0) ++cur
;
3096 if (pNsEntry
->prefix_end
)
3098 *cur
= pNsEntry
->prefix_end
;
3099 while (*cur
!= 0) ++cur
;
3102 if (pNsEntry
->href_end
)
3104 *cur
= pNsEntry
->href_end
;
3107 V_BSTR(var
) = SysAllocString(rebuiltStr
);
3108 heap_free(rebuiltStr
);
3112 FIXME("Unknown property %s\n", debugstr_w(p
));
3116 static HRESULT WINAPI
domdoc_importNode(
3117 IXMLDOMDocument3
* iface
,
3120 IXMLDOMNode
** clone
)
3122 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3123 FIXME("(%p)->(%p %d %p): stub\n", This
, node
, deep
, clone
);
3127 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl
=
3129 domdoc_QueryInterface
,
3132 domdoc_GetTypeInfoCount
,
3134 domdoc_GetIDsOfNames
,
3136 domdoc_get_nodeName
,
3137 domdoc_get_nodeValue
,
3138 domdoc_put_nodeValue
,
3139 domdoc_get_nodeType
,
3140 domdoc_get_parentNode
,
3141 domdoc_get_childNodes
,
3142 domdoc_get_firstChild
,
3143 domdoc_get_lastChild
,
3144 domdoc_get_previousSibling
,
3145 domdoc_get_nextSibling
,
3146 domdoc_get_attributes
,
3147 domdoc_insertBefore
,
3148 domdoc_replaceChild
,
3151 domdoc_hasChildNodes
,
3152 domdoc_get_ownerDocument
,
3154 domdoc_get_nodeTypeString
,
3157 domdoc_get_specified
,
3158 domdoc_get_definition
,
3159 domdoc_get_nodeTypedValue
,
3160 domdoc_put_nodeTypedValue
,
3161 domdoc_get_dataType
,
3162 domdoc_put_dataType
,
3164 domdoc_transformNode
,
3166 domdoc_selectSingleNode
,
3168 domdoc_get_namespaceURI
,
3170 domdoc_get_baseName
,
3171 domdoc_transformNodeToObject
,
3173 domdoc_get_implementation
,
3174 domdoc_get_documentElement
,
3175 domdoc_put_documentElement
,
3176 domdoc_createElement
,
3177 domdoc_createDocumentFragment
,
3178 domdoc_createTextNode
,
3179 domdoc_createComment
,
3180 domdoc_createCDATASection
,
3181 domdoc_createProcessingInstruction
,
3182 domdoc_createAttribute
,
3183 domdoc_createEntityReference
,
3184 domdoc_getElementsByTagName
,
3188 domdoc_get_readyState
,
3189 domdoc_get_parseError
,
3196 domdoc_get_validateOnParse
,
3197 domdoc_put_validateOnParse
,
3198 domdoc_get_resolveExternals
,
3199 domdoc_put_resolveExternals
,
3200 domdoc_get_preserveWhiteSpace
,
3201 domdoc_put_preserveWhiteSpace
,
3202 domdoc_put_onreadystatechange
,
3203 domdoc_put_onDataAvailable
,
3204 domdoc_put_onTransformNode
,
3205 domdoc_get_namespaces
,
3207 domdoc_putref_schemas
,
3211 domdoc_validateNode
,
3215 /* IConnectionPointContainer */
3216 static HRESULT WINAPI
ConnectionPointContainer_QueryInterface(IConnectionPointContainer
*iface
,
3217 REFIID riid
, void **ppv
)
3219 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3220 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3223 static ULONG WINAPI
ConnectionPointContainer_AddRef(IConnectionPointContainer
*iface
)
3225 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3226 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3229 static ULONG WINAPI
ConnectionPointContainer_Release(IConnectionPointContainer
*iface
)
3231 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3232 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3235 static HRESULT WINAPI
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer
*iface
,
3236 IEnumConnectionPoints
**ppEnum
)
3238 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3239 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3243 static HRESULT WINAPI
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer
*iface
,
3244 REFIID riid
, IConnectionPoint
**cp
)
3246 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3247 ConnectionPoint
*iter
;
3249 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), cp
);
3253 for(iter
= This
->cp_list
; iter
; iter
= iter
->next
)
3255 if (IsEqualGUID(iter
->iid
, riid
))
3256 *cp
= &iter
->IConnectionPoint_iface
;
3261 IConnectionPoint_AddRef(*cp
);
3265 FIXME("unsupported riid %s\n", debugstr_guid(riid
));
3266 return CONNECT_E_NOCONNECTION
;
3270 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl
=
3272 ConnectionPointContainer_QueryInterface
,
3273 ConnectionPointContainer_AddRef
,
3274 ConnectionPointContainer_Release
,
3275 ConnectionPointContainer_EnumConnectionPoints
,
3276 ConnectionPointContainer_FindConnectionPoint
3279 /* IConnectionPoint */
3280 static HRESULT WINAPI
ConnectionPoint_QueryInterface(IConnectionPoint
*iface
,
3281 REFIID riid
, void **ppv
)
3283 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3285 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
3289 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
3290 IsEqualGUID(&IID_IConnectionPoint
, riid
))
3297 IConnectionPoint_AddRef(iface
);
3301 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
3302 return E_NOINTERFACE
;
3305 static ULONG WINAPI
ConnectionPoint_AddRef(IConnectionPoint
*iface
)
3307 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3308 return IConnectionPointContainer_AddRef(This
->container
);
3311 static ULONG WINAPI
ConnectionPoint_Release(IConnectionPoint
*iface
)
3313 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3314 return IConnectionPointContainer_Release(This
->container
);
3317 static HRESULT WINAPI
ConnectionPoint_GetConnectionInterface(IConnectionPoint
*iface
, IID
*iid
)
3319 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3321 TRACE("(%p)->(%p)\n", This
, iid
);
3323 if (!iid
) return E_POINTER
;
3329 static HRESULT WINAPI
ConnectionPoint_GetConnectionPointContainer(IConnectionPoint
*iface
,
3330 IConnectionPointContainer
**container
)
3332 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3334 TRACE("(%p)->(%p)\n", This
, container
);
3336 if (!container
) return E_POINTER
;
3338 *container
= This
->container
;
3339 IConnectionPointContainer_AddRef(*container
);
3343 static HRESULT WINAPI
ConnectionPoint_Advise(IConnectionPoint
*iface
, IUnknown
*unk_sink
,
3346 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3351 TRACE("(%p)->(%p %p)\n", This
, unk_sink
, cookie
);
3353 hr
= IUnknown_QueryInterface(unk_sink
, This
->iid
, (void**)&sink
);
3354 if(FAILED(hr
) && !IsEqualGUID(&IID_IPropertyNotifySink
, This
->iid
))
3355 hr
= IUnknown_QueryInterface(unk_sink
, &IID_IDispatch
, (void**)&sink
);
3357 return CONNECT_E_CANNOTCONNECT
;
3361 for (i
= 0; i
< This
->sinks_size
; i
++)
3362 if (!This
->sinks
[i
].unk
)
3365 if (i
== This
->sinks_size
)
3366 This
->sinks
= heap_realloc(This
->sinks
,(++This
->sinks_size
)*sizeof(*This
->sinks
));
3370 This
->sinks
= heap_alloc(sizeof(*This
->sinks
));
3371 This
->sinks_size
= 1;
3375 This
->sinks
[i
].unk
= sink
;
3382 static HRESULT WINAPI
ConnectionPoint_Unadvise(IConnectionPoint
*iface
, DWORD cookie
)
3384 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3386 TRACE("(%p)->(%d)\n", This
, cookie
);
3388 if (cookie
== 0 || cookie
> This
->sinks_size
|| !This
->sinks
[cookie
-1].unk
)
3389 return CONNECT_E_NOCONNECTION
;
3391 IUnknown_Release(This
->sinks
[cookie
-1].unk
);
3392 This
->sinks
[cookie
-1].unk
= NULL
;
3397 static HRESULT WINAPI
ConnectionPoint_EnumConnections(IConnectionPoint
*iface
,
3398 IEnumConnections
**ppEnum
)
3400 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3401 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3405 static const IConnectionPointVtbl ConnectionPointVtbl
=
3407 ConnectionPoint_QueryInterface
,
3408 ConnectionPoint_AddRef
,
3409 ConnectionPoint_Release
,
3410 ConnectionPoint_GetConnectionInterface
,
3411 ConnectionPoint_GetConnectionPointContainer
,
3412 ConnectionPoint_Advise
,
3413 ConnectionPoint_Unadvise
,
3414 ConnectionPoint_EnumConnections
3417 static void ConnectionPoint_Init(ConnectionPoint
*cp
, struct domdoc
*doc
, REFIID riid
)
3419 cp
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointVtbl
;
3425 cp
->next
= doc
->cp_list
;
3428 cp
->container
= &doc
->IConnectionPointContainer_iface
;
3431 /* domdoc implementation of IObjectWithSite */
3432 static HRESULT WINAPI
3433 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
3435 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3436 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObject
);
3439 static ULONG WINAPI
domdoc_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
3441 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3442 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3445 static ULONG WINAPI
domdoc_ObjectWithSite_Release( IObjectWithSite
* iface
)
3447 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3448 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3451 static HRESULT WINAPI
domdoc_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
3453 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3455 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
3460 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
3463 static HRESULT WINAPI
domdoc_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
3465 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3467 TRACE("(%p)->(%p)\n", iface
, punk
);
3473 IUnknown_Release( This
->site
);
3480 IUnknown_AddRef( punk
);
3483 IUnknown_Release( This
->site
);
3490 static const IObjectWithSiteVtbl domdocObjectSite
=
3492 domdoc_ObjectWithSite_QueryInterface
,
3493 domdoc_ObjectWithSite_AddRef
,
3494 domdoc_ObjectWithSite_Release
,
3495 domdoc_ObjectWithSite_SetSite
,
3496 domdoc_ObjectWithSite_GetSite
3499 static HRESULT WINAPI
domdoc_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
3501 domdoc
*This
= impl_from_IObjectSafety(iface
);
3502 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3505 static ULONG WINAPI
domdoc_Safety_AddRef(IObjectSafety
*iface
)
3507 domdoc
*This
= impl_from_IObjectSafety(iface
);
3508 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3511 static ULONG WINAPI
domdoc_Safety_Release(IObjectSafety
*iface
)
3513 domdoc
*This
= impl_from_IObjectSafety(iface
);
3514 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3517 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3519 static HRESULT WINAPI
domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3520 DWORD
*supported
, DWORD
*enabled
)
3522 domdoc
*This
= impl_from_IObjectSafety(iface
);
3524 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
3526 if(!supported
|| !enabled
) return E_POINTER
;
3528 *supported
= SAFETY_SUPPORTED_OPTIONS
;
3529 *enabled
= This
->safeopt
;
3534 static HRESULT WINAPI
domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3535 DWORD mask
, DWORD enabled
)
3537 domdoc
*This
= impl_from_IObjectSafety(iface
);
3538 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
3540 if ((mask
& ~SAFETY_SUPPORTED_OPTIONS
) != 0)
3543 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
3548 #undef SAFETY_SUPPORTED_OPTIONS
3550 static const IObjectSafetyVtbl domdocObjectSafetyVtbl
= {
3551 domdoc_Safety_QueryInterface
,
3552 domdoc_Safety_AddRef
,
3553 domdoc_Safety_Release
,
3554 domdoc_Safety_GetInterfaceSafetyOptions
,
3555 domdoc_Safety_SetInterfaceSafetyOptions
3558 static const tid_t domdoc_iface_tids
[] = {
3559 IXMLDOMDocument3_tid
,
3563 static dispex_static_data_t domdoc_dispex
= {
3565 IXMLDOMDocument3_tid
,
3570 HRESULT
get_domdoc_from_xmldoc(xmlDocPtr xmldoc
, IXMLDOMDocument3
**document
)
3574 doc
= heap_alloc( sizeof (*doc
) );
3576 return E_OUTOFMEMORY
;
3578 doc
->IXMLDOMDocument3_iface
.lpVtbl
= &XMLDOMDocument3Vtbl
;
3579 doc
->IPersistStreamInit_iface
.lpVtbl
= &xmldoc_IPersistStreamInit_VTable
;
3580 doc
->IObjectWithSite_iface
.lpVtbl
= &domdocObjectSite
;
3581 doc
->IObjectSafety_iface
.lpVtbl
= &domdocObjectSafetyVtbl
;
3582 doc
->IConnectionPointContainer_iface
.lpVtbl
= &ConnectionPointContainerVtbl
;
3584 doc
->async
= VARIANT_TRUE
;
3585 doc
->validating
= 0;
3587 doc
->properties
= properties_from_xmlDocPtr(xmldoc
);
3591 doc
->cp_list
= NULL
;
3592 doc
->namespaces
= NULL
;
3593 memset(doc
->events
, 0, sizeof(doc
->events
));
3595 /* events connection points */
3596 ConnectionPoint_Init(&doc
->cp_dispatch
, doc
, &IID_IDispatch
);
3597 ConnectionPoint_Init(&doc
->cp_propnotif
, doc
, &IID_IPropertyNotifySink
);
3598 ConnectionPoint_Init(&doc
->cp_domdocevents
, doc
, &DIID_XMLDOMDocumentEvents
);
3600 init_xmlnode(&doc
->node
, (xmlNodePtr
)xmldoc
, (IXMLDOMNode
*)&doc
->IXMLDOMDocument3_iface
,
3603 *document
= &doc
->IXMLDOMDocument3_iface
;
3605 TRACE("returning iface %p\n", *document
);
3609 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3614 TRACE("(%d, %p)\n", version
, ppObj
);
3616 xmldoc
= xmlNewDoc(NULL
);
3618 return E_OUTOFMEMORY
;
3620 xmldoc_init(xmldoc
, version
);
3622 hr
= get_domdoc_from_xmldoc(xmldoc
, (IXMLDOMDocument3
**)ppObj
);
3625 free_properties(properties_from_xmlDocPtr(xmldoc
));
3626 heap_free(xmldoc
->_private
);
3634 IUnknown
* create_domdoc( xmlNodePtr document
)
3639 TRACE("(%p)\n", document
);
3641 hr
= get_domdoc_from_xmldoc((xmlDocPtr
)document
, (IXMLDOMDocument3
**)&pObj
);
3650 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3652 MESSAGE("This program tried to use a DOMDocument object, but\n"
3653 "libxml2 support was not present at compile time.\n");