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 to be 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 to create 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 SafeArrayAccessData(psa
, (void**)&str
);
2144 SafeArrayGetUBound(psa
, 1, &len
);
2146 if ((xmldoc
= doparse(This
, str
, ++len
, XML_CHAR_ENCODING_UTF8
)))
2148 hr
= This
->error
= S_OK
;
2149 *isSuccessful
= VARIANT_TRUE
;
2150 TRACE("parsed document %p\n", xmldoc
);
2154 This
->error
= E_FAIL
;
2155 TRACE("failed to parse document\n");
2158 SafeArrayUnaccessData(psa
);
2162 xmldoc
->_private
= create_priv();
2163 return attach_xmldoc(This
, xmldoc
);
2167 FIXME("unhandled SAFEARRAY dim: %d\n", dim
);
2168 hr
= This
->error
= E_NOTIMPL
;
2174 ISequentialStream
*stream
= NULL
;
2175 IXMLDOMDocument3
*newdoc
= NULL
;
2177 if (!V_UNKNOWN(&source
)) return E_INVALIDARG
;
2179 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IXMLDOMDocument3
, (void**)&newdoc
);
2184 domdoc
*newDoc
= impl_from_IXMLDOMDocument3( newdoc
);
2186 xmldoc
= xmlCopyDoc(get_doc(newDoc
), 1);
2187 xmldoc
->_private
= create_priv();
2188 hr
= attach_xmldoc(This
, xmldoc
);
2191 *isSuccessful
= VARIANT_TRUE
;
2197 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IStream
, (void**)&stream
);
2199 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_ISequentialStream
, (void**)&stream
);
2203 hr
= domdoc_load_from_stream(This
, stream
);
2205 *isSuccessful
= VARIANT_TRUE
;
2206 ISequentialStream_Release(stream
);
2210 FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr
, V_UNKNOWN(&source
)->lpVtbl
);
2214 FIXME("VT type not supported (%d)\n", V_VT(&source
));
2221 CoTaskMemFree(This
->properties
->url
);
2222 This
->properties
->url
= NULL
;
2224 hr
= create_moniker_from_url( filename
, &mon
);
2225 if ( SUCCEEDED(hr
) )
2227 hr
= domdoc_load_moniker( This
, mon
);
2229 IMoniker_GetDisplayName(mon
, NULL
, NULL
, &This
->properties
->url
);
2230 IMoniker_Release(mon
);
2234 This
->error
= E_FAIL
;
2237 hr
= This
->error
= S_OK
;
2238 *isSuccessful
= VARIANT_TRUE
;
2242 if(!filename
|| FAILED(hr
)) {
2243 xmldoc
= xmlNewDoc(NULL
);
2244 xmldoc
->_private
= create_priv();
2245 hr
= attach_xmldoc(This
, xmldoc
);
2250 TRACE("ret (%d)\n", hr
);
2256 static HRESULT WINAPI
domdoc_get_readyState(
2257 IXMLDOMDocument3
*iface
,
2260 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2261 FIXME("stub! (%p)->(%p)\n", This
, value
);
2264 return E_INVALIDARG
;
2266 *value
= READYSTATE_COMPLETE
;
2271 static HRESULT WINAPI
domdoc_get_parseError(
2272 IXMLDOMDocument3
*iface
,
2273 IXMLDOMParseError
** errorObj
)
2275 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2276 static const WCHAR err
[] = {'e','r','r','o','r',0};
2277 BSTR error_string
= NULL
;
2279 FIXME("(%p)->(%p): creating a dummy parseError\n", iface
, errorObj
);
2282 error_string
= SysAllocString(err
);
2284 *errorObj
= create_parseError(This
->error
, NULL
, error_string
, NULL
, 0, 0, 0);
2285 if(!*errorObj
) return E_OUTOFMEMORY
;
2290 static HRESULT WINAPI
domdoc_get_url(
2291 IXMLDOMDocument3
*iface
,
2294 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2296 TRACE("(%p)->(%p)\n", This
, url
);
2299 return E_INVALIDARG
;
2301 if (This
->properties
->url
)
2303 *url
= SysAllocString(This
->properties
->url
);
2305 return E_OUTOFMEMORY
;
2310 return return_null_bstr(url
);
2314 static HRESULT WINAPI
domdoc_get_async(
2315 IXMLDOMDocument3
*iface
,
2316 VARIANT_BOOL
* isAsync
)
2318 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2320 TRACE("(%p)->(%p: %d)\n", This
, isAsync
, This
->async
);
2321 *isAsync
= This
->async
;
2326 static HRESULT WINAPI
domdoc_put_async(
2327 IXMLDOMDocument3
*iface
,
2328 VARIANT_BOOL isAsync
)
2330 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2332 TRACE("(%p)->(%d)\n", This
, isAsync
);
2333 This
->async
= isAsync
;
2338 static HRESULT WINAPI
domdoc_abort(
2339 IXMLDOMDocument3
*iface
)
2341 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2342 FIXME("%p\n", This
);
2346 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2347 static HRESULT WINAPI
domdoc_loadXML(
2348 IXMLDOMDocument3
*iface
,
2350 VARIANT_BOOL
* isSuccessful
)
2352 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2353 xmlDocPtr xmldoc
= NULL
;
2354 HRESULT hr
= S_FALSE
, hr2
;
2356 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), isSuccessful
);
2358 assert ( &This
->node
);
2362 *isSuccessful
= VARIANT_FALSE
;
2368 /* skip leading spaces if needed */
2369 if (This
->properties
->version
== MSXML_DEFAULT
|| This
->properties
->version
== MSXML26
)
2370 while (*ptr
&& isspaceW(*ptr
)) ptr
++;
2372 xmldoc
= doparse(This
, (char*)ptr
, strlenW(ptr
)*sizeof(WCHAR
), XML_CHAR_ENCODING_UTF16LE
);
2375 This
->error
= E_FAIL
;
2376 TRACE("failed to parse document\n");
2380 hr
= This
->error
= S_OK
;
2381 *isSuccessful
= VARIANT_TRUE
;
2382 TRACE("parsed document %p\n", xmldoc
);
2388 xmldoc
= xmlNewDoc(NULL
);
2389 xmldoc
->_private
= create_priv();
2390 hr2
= attach_xmldoc(This
, xmldoc
);
2397 static int XMLCALL
domdoc_save_writecallback(void *ctx
, const char *buffer
, int len
)
2401 if(!WriteFile(ctx
, buffer
, len
, &written
, NULL
))
2403 WARN("write error\n");
2410 static int XMLCALL
domdoc_save_closecallback(void *ctx
)
2412 return CloseHandle(ctx
) ? 0 : -1;
2415 static int XMLCALL
domdoc_stream_save_writecallback(void *ctx
, const char *buffer
, int len
)
2420 hr
= IStream_Write((IStream
*)ctx
, buffer
, len
, &written
);
2421 TRACE("0x%08x %p %d %u\n", hr
, buffer
, len
, written
);
2424 WARN("stream write error: 0x%08x\n", hr
);
2431 static int XMLCALL
domdoc_stream_save_closecallback(void *ctx
)
2433 IStream_Release((IStream
*)ctx
);
2437 static HRESULT WINAPI
domdoc_save(
2438 IXMLDOMDocument3
*iface
,
2439 VARIANT destination
)
2441 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2442 xmlSaveCtxtPtr ctx
= NULL
;
2446 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&destination
));
2448 switch (V_VT(&destination
))
2452 IUnknown
*pUnk
= V_UNKNOWN(&destination
);
2453 IXMLDOMDocument3
*document
;
2456 ret
= IUnknown_QueryInterface(pUnk
, &IID_IXMLDOMDocument3
, (void**)&document
);
2459 VARIANT_BOOL success
;
2462 ret
= IXMLDOMDocument3_get_xml(iface
, &xml
);
2465 ret
= IXMLDOMDocument3_loadXML(document
, xml
, &success
);
2469 IXMLDOMDocument3_Release(document
);
2473 ret
= IUnknown_QueryInterface(pUnk
, &IID_IStream
, (void**)&stream
);
2476 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2477 ctx
= xmlSaveToIO(domdoc_stream_save_writecallback
,
2478 domdoc_stream_save_closecallback
, stream
, NULL
, options
);
2482 IStream_Release(stream
);
2490 case VT_BSTR
| VT_BYREF
:
2492 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2494 /* save with file path */
2495 HANDLE handle
= CreateFileW( (V_VT(&destination
) & VT_BYREF
)? *V_BSTRREF(&destination
) : V_BSTR(&destination
),
2496 GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2497 if( handle
== INVALID_HANDLE_VALUE
)
2499 WARN("failed to create file\n");
2503 /* disable top XML declaration */
2504 ctx
= xmlSaveToIO(domdoc_save_writecallback
, domdoc_save_closecallback
,
2505 handle
, NULL
, options
);
2508 CloseHandle(handle
);
2515 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination
));
2519 xmldecl
= xmldoc_unlink_xmldecl(get_doc(This
));
2520 if (xmlSaveDoc(ctx
, get_doc(This
)) == -1) ret
= S_FALSE
;
2521 xmldoc_link_xmldecl(get_doc(This
), xmldecl
);
2523 /* will release resources through close callback */
2529 static HRESULT WINAPI
domdoc_get_validateOnParse(
2530 IXMLDOMDocument3
*iface
,
2531 VARIANT_BOOL
* isValidating
)
2533 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2534 TRACE("(%p)->(%p: %d)\n", This
, isValidating
, This
->validating
);
2535 *isValidating
= This
->validating
;
2540 static HRESULT WINAPI
domdoc_put_validateOnParse(
2541 IXMLDOMDocument3
*iface
,
2542 VARIANT_BOOL isValidating
)
2544 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2545 TRACE("(%p)->(%d)\n", This
, isValidating
);
2546 This
->validating
= isValidating
;
2551 static HRESULT WINAPI
domdoc_get_resolveExternals(
2552 IXMLDOMDocument3
*iface
,
2553 VARIANT_BOOL
* isResolving
)
2555 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2556 TRACE("(%p)->(%p: %d)\n", This
, isResolving
, This
->resolving
);
2557 *isResolving
= This
->resolving
;
2562 static HRESULT WINAPI
domdoc_put_resolveExternals(
2563 IXMLDOMDocument3
*iface
,
2564 VARIANT_BOOL isResolving
)
2566 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2567 TRACE("(%p)->(%d)\n", This
, isResolving
);
2568 This
->resolving
= isResolving
;
2573 static HRESULT WINAPI
domdoc_get_preserveWhiteSpace(
2574 IXMLDOMDocument3
*iface
,
2575 VARIANT_BOOL
* isPreserving
)
2577 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2578 TRACE("(%p)->(%p: %d)\n", This
, isPreserving
, This
->properties
->preserving
);
2579 *isPreserving
= This
->properties
->preserving
;
2584 static HRESULT WINAPI
domdoc_put_preserveWhiteSpace(
2585 IXMLDOMDocument3
*iface
,
2586 VARIANT_BOOL isPreserving
)
2588 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2589 TRACE("(%p)->(%d)\n", This
, isPreserving
);
2590 This
->properties
->preserving
= isPreserving
;
2595 static HRESULT WINAPI
domdoc_put_onreadystatechange(
2596 IXMLDOMDocument3
*iface
,
2599 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2601 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&event
));
2602 return set_doc_event(This
, EVENTID_READYSTATECHANGE
, &event
);
2606 static HRESULT WINAPI
domdoc_put_onDataAvailable(IXMLDOMDocument3
*iface
, VARIANT sink
)
2608 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2609 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2613 static HRESULT WINAPI
domdoc_put_onTransformNode(IXMLDOMDocument3
*iface
, VARIANT sink
)
2615 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2616 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2620 static HRESULT WINAPI
domdoc_get_namespaces(
2621 IXMLDOMDocument3
* iface
,
2622 IXMLDOMSchemaCollection
** collection
)
2624 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2627 FIXME("(%p)->(%p): semi-stub\n", This
, collection
);
2629 if (!collection
) return E_POINTER
;
2631 if (!This
->namespaces
)
2633 hr
= SchemaCache_create(This
->properties
->version
, (void**)&This
->namespaces
);
2634 if (hr
!= S_OK
) return hr
;
2636 hr
= cache_from_doc_ns(This
->namespaces
, &This
->node
);
2638 release_namespaces(This
);
2641 if (This
->namespaces
)
2642 return IXMLDOMSchemaCollection2_QueryInterface(This
->namespaces
,
2643 &IID_IXMLDOMSchemaCollection
, (void**)collection
);
2648 static HRESULT WINAPI
domdoc_get_schemas(
2649 IXMLDOMDocument3
* iface
,
2652 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2653 IXMLDOMSchemaCollection2
* cur_schema
= This
->properties
->schemaCache
;
2654 HRESULT hr
= S_FALSE
;
2656 TRACE("(%p)->(%p)\n", This
, schema
);
2658 V_VT(schema
) = VT_NULL
;
2659 /* just to reset pointer part, cause that's what application is expected to use */
2660 V_DISPATCH(schema
) = NULL
;
2664 hr
= IXMLDOMSchemaCollection2_QueryInterface(cur_schema
, &IID_IDispatch
, (void**)&V_DISPATCH(schema
));
2666 V_VT(schema
) = VT_DISPATCH
;
2671 static HRESULT WINAPI
domdoc_putref_schemas(
2672 IXMLDOMDocument3
* iface
,
2675 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2676 HRESULT hr
= E_FAIL
;
2677 IXMLDOMSchemaCollection2
* new_schema
= NULL
;
2679 FIXME("(%p)->(%s): semi-stub\n", This
, debugstr_variant(&schema
));
2680 switch(V_VT(&schema
))
2683 if (V_UNKNOWN(&schema
))
2685 hr
= IUnknown_QueryInterface(V_UNKNOWN(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2690 if (V_DISPATCH(&schema
))
2692 hr
= IDispatch_QueryInterface(V_DISPATCH(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2702 WARN("Can't get schema from vt %x\n", V_VT(&schema
));
2707 IXMLDOMSchemaCollection2
* old_schema
= InterlockedExchangePointer((void**)&This
->properties
->schemaCache
, new_schema
);
2708 if(old_schema
) IXMLDOMSchemaCollection2_Release(old_schema
);
2714 static inline BOOL
is_wellformed(xmlDocPtr doc
)
2716 #ifdef HAVE_XMLDOC_PROPERTIES
2717 return doc
->properties
& XML_DOC_WELLFORMED
;
2719 /* Not a full check, but catches the worst violations */
2723 for (child
= doc
->children
; child
!= NULL
; child
= child
->next
)
2725 switch (child
->type
)
2727 case XML_ELEMENT_NODE
:
2732 case XML_CDATA_SECTION_NODE
:
2744 static void LIBXML2_LOG_CALLBACK
validate_error(void* ctx
, char const* msg
, ...)
2748 LIBXML2_CALLBACK_ERR(domdoc_validateNode
, msg
, ap
);
2752 static void LIBXML2_LOG_CALLBACK
validate_warning(void* ctx
, char const* msg
, ...)
2756 LIBXML2_CALLBACK_WARN(domdoc_validateNode
, msg
, ap
);
2760 static HRESULT WINAPI
domdoc_validateNode(
2761 IXMLDOMDocument3
* iface
,
2763 IXMLDOMParseError
** err
)
2765 domdoc
* This
= impl_from_IXMLDOMDocument3(iface
);
2766 LONG state
, err_code
= 0;
2770 TRACE("(%p)->(%p, %p)\n", This
, node
, err
);
2771 IXMLDOMDocument3_get_readyState(iface
, &state
);
2772 if (state
!= READYSTATE_COMPLETE
)
2775 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2782 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2786 if (!get_node_obj(node
)->node
|| get_node_obj(node
)->node
->doc
!= get_doc(This
))
2789 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2793 if (!is_wellformed(get_doc(This
)))
2795 ERR("doc not well-formed\n");
2797 *err
= create_parseError(E_XML_NOTWF
, NULL
, NULL
, NULL
, 0, 0, 0);
2801 /* DTD validation */
2802 if (get_doc(This
)->intSubset
|| get_doc(This
)->extSubset
)
2804 xmlValidCtxtPtr vctx
= xmlNewValidCtxt();
2805 vctx
->error
= validate_error
;
2806 vctx
->warning
= validate_warning
;
2809 if (!((node
== (IXMLDOMNode
*)iface
)?
2810 xmlValidateDocument(vctx
, get_doc(This
)) :
2811 xmlValidateElement(vctx
, get_doc(This
), get_node_obj(node
)->node
)))
2813 /* TODO: get a real error code here */
2814 TRACE("DTD validation failed\n");
2815 err_code
= E_XML_INVALID
;
2818 xmlFreeValidCtxt(vctx
);
2821 /* Schema validation */
2822 if (hr
== S_OK
&& This
->properties
->schemaCache
!= NULL
)
2825 hr
= SchemaCache_validate_tree(This
->properties
->schemaCache
, get_node_obj(node
)->node
);
2829 /* TODO: get a real error code here */
2832 TRACE("schema validation succeeded\n");
2836 ERR("schema validation failed\n");
2837 err_code
= E_XML_INVALID
;
2842 /* not really OK, just didn't find a schema for the ns */
2849 ERR("no DTD or schema found\n");
2850 err_code
= E_XML_NODTD
;
2855 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2860 static HRESULT WINAPI
domdoc_validate(
2861 IXMLDOMDocument3
* iface
,
2862 IXMLDOMParseError
** err
)
2864 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2865 TRACE("(%p)->(%p)\n", This
, err
);
2866 return IXMLDOMDocument3_validateNode(iface
, (IXMLDOMNode
*)iface
, err
);
2869 static HRESULT WINAPI
domdoc_setProperty(
2870 IXMLDOMDocument3
* iface
,
2874 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2876 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(p
), debugstr_variant(&value
));
2878 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
2884 V_VT(&varStr
) = VT_EMPTY
;
2885 if (V_VT(&value
) != VT_BSTR
)
2887 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2889 bstr
= V_BSTR(&varStr
);
2892 bstr
= V_BSTR(&value
);
2895 if (lstrcmpiW(bstr
, PropValueXPathW
) == 0)
2896 This
->properties
->XPath
= TRUE
;
2897 else if (lstrcmpiW(bstr
, PropValueXSLPatternW
) == 0)
2898 This
->properties
->XPath
= FALSE
;
2902 VariantClear(&varStr
);
2905 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
2907 xmlChar
*nsStr
= (xmlChar
*)This
->properties
->selectNsStr
;
2908 struct list
*pNsList
;
2913 V_VT(&varStr
) = VT_EMPTY
;
2914 if (V_VT(&value
) != VT_BSTR
)
2916 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2918 bstr
= V_BSTR(&varStr
);
2921 bstr
= V_BSTR(&value
);
2925 pNsList
= &(This
->properties
->selectNsList
);
2926 clear_selectNsList(pNsList
);
2928 nsStr
= xmlchar_from_wchar(bstr
);
2930 TRACE("property value: \"%s\"\n", debugstr_w(bstr
));
2932 This
->properties
->selectNsStr
= nsStr
;
2933 This
->properties
->selectNsStr_len
= xmlStrlen(nsStr
);
2936 xmlChar
*pTokBegin
, *pTokEnd
, *pTokInner
;
2937 select_ns_entry
* ns_entry
= NULL
;
2938 xmlXPathContextPtr ctx
;
2940 ctx
= xmlXPathNewContext(This
->node
.node
->doc
);
2943 /* skip leading spaces */
2944 while (*pTokBegin
== ' ' || *pTokBegin
== '\n' ||
2945 *pTokBegin
== '\t' || *pTokBegin
== '\r')
2948 for (; *pTokBegin
; pTokBegin
= pTokEnd
)
2951 memset(ns_entry
, 0, sizeof(select_ns_entry
));
2953 ns_entry
= heap_alloc_zero(sizeof(select_ns_entry
));
2955 while (*pTokBegin
== ' ')
2957 pTokEnd
= pTokBegin
;
2958 while (*pTokEnd
!= ' ' && *pTokEnd
!= 0)
2961 /* so it failed to advance which means we've got some trailing spaces */
2962 if (pTokEnd
== pTokBegin
) break;
2964 if (xmlStrncmp(pTokBegin
, (xmlChar
const*)"xmlns", 5) != 0)
2967 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2968 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2973 if (*pTokBegin
== '=')
2975 /*valid for XSLPattern?*/
2976 FIXME("Setting default xmlns not supported - skipping.\n");
2979 else if (*pTokBegin
== ':')
2981 ns_entry
->prefix
= ++pTokBegin
;
2982 for (pTokInner
= pTokBegin
; pTokInner
!= pTokEnd
&& *pTokInner
!= '='; ++pTokInner
)
2985 if (pTokInner
== pTokEnd
)
2988 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2989 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2993 ns_entry
->prefix_end
= *pTokInner
;
2997 if (pTokEnd
-pTokInner
> 1 &&
2998 ((*pTokInner
== '\'' && *(pTokEnd
-1) == '\'') ||
2999 (*pTokInner
== '"' && *(pTokEnd
-1) == '"')))
3001 ns_entry
->href
= ++pTokInner
;
3002 ns_entry
->href_end
= *(pTokEnd
-1);
3004 list_add_tail(pNsList
, &ns_entry
->entry
);
3005 /*let libxml figure out if they're valid from here ;)*/
3006 if (xmlXPathRegisterNs(ctx
, ns_entry
->prefix
, ns_entry
->href
) != 0)
3015 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3016 debugstr_w(bstr
), debugstr_an((const char*)pTokInner
, pTokEnd
-pTokInner
));
3017 list_add_tail(pNsList
, &ns_entry
->entry
);
3030 heap_free(ns_entry
);
3031 xmlXPathFreeContext(ctx
);
3034 VariantClear(&varStr
);
3037 else if (lstrcmpiW(p
, PropertyProhibitDTDW
) == 0 ||
3038 lstrcmpiW(p
, PropertyNewParserW
) == 0 ||
3039 lstrcmpiW(p
, PropertyResolveExternalsW
) == 0)
3042 FIXME("Ignoring property %s, value %s\n", debugstr_w(p
), debugstr_variant(&value
));
3046 FIXME("Unknown property %s\n", debugstr_w(p
));
3050 static HRESULT WINAPI
domdoc_getProperty(
3051 IXMLDOMDocument3
* iface
,
3055 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3057 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
3060 return E_INVALIDARG
;
3062 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
3064 V_VT(var
) = VT_BSTR
;
3065 V_BSTR(var
) = This
->properties
->XPath
?
3066 SysAllocString(PropValueXPathW
) :
3067 SysAllocString(PropValueXSLPatternW
);
3068 return V_BSTR(var
) ? S_OK
: E_OUTOFMEMORY
;
3070 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3073 BSTR rebuiltStr
, cur
;
3074 const xmlChar
*nsStr
;
3075 struct list
*pNsList
;
3076 select_ns_entry
* pNsEntry
;
3078 V_VT(var
) = VT_BSTR
;
3079 nsStr
= This
->properties
->selectNsStr
;
3080 pNsList
= &This
->properties
->selectNsList
;
3081 lenA
= This
->properties
->selectNsStr_len
;
3082 lenW
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, NULL
, 0);
3083 rebuiltStr
= heap_alloc(lenW
*sizeof(WCHAR
));
3084 MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, rebuiltStr
, lenW
);
3086 /* this is fine because all of the chars that end tokens are ASCII*/
3087 LIST_FOR_EACH_ENTRY(pNsEntry
, pNsList
, select_ns_entry
, entry
)
3089 while (*cur
!= 0) ++cur
;
3090 if (pNsEntry
->prefix_end
)
3092 *cur
= pNsEntry
->prefix_end
;
3093 while (*cur
!= 0) ++cur
;
3096 if (pNsEntry
->href_end
)
3098 *cur
= pNsEntry
->href_end
;
3101 V_BSTR(var
) = SysAllocString(rebuiltStr
);
3102 heap_free(rebuiltStr
);
3106 FIXME("Unknown property %s\n", debugstr_w(p
));
3110 static HRESULT WINAPI
domdoc_importNode(
3111 IXMLDOMDocument3
* iface
,
3114 IXMLDOMNode
** clone
)
3116 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3117 FIXME("(%p)->(%p %d %p): stub\n", This
, node
, deep
, clone
);
3121 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl
=
3123 domdoc_QueryInterface
,
3126 domdoc_GetTypeInfoCount
,
3128 domdoc_GetIDsOfNames
,
3130 domdoc_get_nodeName
,
3131 domdoc_get_nodeValue
,
3132 domdoc_put_nodeValue
,
3133 domdoc_get_nodeType
,
3134 domdoc_get_parentNode
,
3135 domdoc_get_childNodes
,
3136 domdoc_get_firstChild
,
3137 domdoc_get_lastChild
,
3138 domdoc_get_previousSibling
,
3139 domdoc_get_nextSibling
,
3140 domdoc_get_attributes
,
3141 domdoc_insertBefore
,
3142 domdoc_replaceChild
,
3145 domdoc_hasChildNodes
,
3146 domdoc_get_ownerDocument
,
3148 domdoc_get_nodeTypeString
,
3151 domdoc_get_specified
,
3152 domdoc_get_definition
,
3153 domdoc_get_nodeTypedValue
,
3154 domdoc_put_nodeTypedValue
,
3155 domdoc_get_dataType
,
3156 domdoc_put_dataType
,
3158 domdoc_transformNode
,
3160 domdoc_selectSingleNode
,
3162 domdoc_get_namespaceURI
,
3164 domdoc_get_baseName
,
3165 domdoc_transformNodeToObject
,
3167 domdoc_get_implementation
,
3168 domdoc_get_documentElement
,
3169 domdoc_put_documentElement
,
3170 domdoc_createElement
,
3171 domdoc_createDocumentFragment
,
3172 domdoc_createTextNode
,
3173 domdoc_createComment
,
3174 domdoc_createCDATASection
,
3175 domdoc_createProcessingInstruction
,
3176 domdoc_createAttribute
,
3177 domdoc_createEntityReference
,
3178 domdoc_getElementsByTagName
,
3182 domdoc_get_readyState
,
3183 domdoc_get_parseError
,
3190 domdoc_get_validateOnParse
,
3191 domdoc_put_validateOnParse
,
3192 domdoc_get_resolveExternals
,
3193 domdoc_put_resolveExternals
,
3194 domdoc_get_preserveWhiteSpace
,
3195 domdoc_put_preserveWhiteSpace
,
3196 domdoc_put_onreadystatechange
,
3197 domdoc_put_onDataAvailable
,
3198 domdoc_put_onTransformNode
,
3199 domdoc_get_namespaces
,
3201 domdoc_putref_schemas
,
3205 domdoc_validateNode
,
3209 /* IConnectionPointContainer */
3210 static HRESULT WINAPI
ConnectionPointContainer_QueryInterface(IConnectionPointContainer
*iface
,
3211 REFIID riid
, void **ppv
)
3213 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3214 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3217 static ULONG WINAPI
ConnectionPointContainer_AddRef(IConnectionPointContainer
*iface
)
3219 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3220 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3223 static ULONG WINAPI
ConnectionPointContainer_Release(IConnectionPointContainer
*iface
)
3225 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3226 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3229 static HRESULT WINAPI
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer
*iface
,
3230 IEnumConnectionPoints
**ppEnum
)
3232 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3233 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3237 static HRESULT WINAPI
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer
*iface
,
3238 REFIID riid
, IConnectionPoint
**cp
)
3240 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3241 ConnectionPoint
*iter
;
3243 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), cp
);
3247 for(iter
= This
->cp_list
; iter
; iter
= iter
->next
)
3249 if (IsEqualGUID(iter
->iid
, riid
))
3250 *cp
= &iter
->IConnectionPoint_iface
;
3255 IConnectionPoint_AddRef(*cp
);
3259 FIXME("unsupported riid %s\n", debugstr_guid(riid
));
3260 return CONNECT_E_NOCONNECTION
;
3264 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl
=
3266 ConnectionPointContainer_QueryInterface
,
3267 ConnectionPointContainer_AddRef
,
3268 ConnectionPointContainer_Release
,
3269 ConnectionPointContainer_EnumConnectionPoints
,
3270 ConnectionPointContainer_FindConnectionPoint
3273 /* IConnectionPoint */
3274 static HRESULT WINAPI
ConnectionPoint_QueryInterface(IConnectionPoint
*iface
,
3275 REFIID riid
, void **ppv
)
3277 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3279 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
3283 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
3284 IsEqualGUID(&IID_IConnectionPoint
, riid
))
3291 IConnectionPoint_AddRef(iface
);
3295 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
3296 return E_NOINTERFACE
;
3299 static ULONG WINAPI
ConnectionPoint_AddRef(IConnectionPoint
*iface
)
3301 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3302 return IConnectionPointContainer_AddRef(This
->container
);
3305 static ULONG WINAPI
ConnectionPoint_Release(IConnectionPoint
*iface
)
3307 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3308 return IConnectionPointContainer_Release(This
->container
);
3311 static HRESULT WINAPI
ConnectionPoint_GetConnectionInterface(IConnectionPoint
*iface
, IID
*iid
)
3313 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3315 TRACE("(%p)->(%p)\n", This
, iid
);
3317 if (!iid
) return E_POINTER
;
3323 static HRESULT WINAPI
ConnectionPoint_GetConnectionPointContainer(IConnectionPoint
*iface
,
3324 IConnectionPointContainer
**container
)
3326 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3328 TRACE("(%p)->(%p)\n", This
, container
);
3330 if (!container
) return E_POINTER
;
3332 *container
= This
->container
;
3333 IConnectionPointContainer_AddRef(*container
);
3337 static HRESULT WINAPI
ConnectionPoint_Advise(IConnectionPoint
*iface
, IUnknown
*unk_sink
,
3340 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3345 TRACE("(%p)->(%p %p)\n", This
, unk_sink
, cookie
);
3347 hr
= IUnknown_QueryInterface(unk_sink
, This
->iid
, (void**)&sink
);
3348 if(FAILED(hr
) && !IsEqualGUID(&IID_IPropertyNotifySink
, This
->iid
))
3349 hr
= IUnknown_QueryInterface(unk_sink
, &IID_IDispatch
, (void**)&sink
);
3351 return CONNECT_E_CANNOTCONNECT
;
3355 for (i
= 0; i
< This
->sinks_size
; i
++)
3356 if (!This
->sinks
[i
].unk
)
3359 if (i
== This
->sinks_size
)
3360 This
->sinks
= heap_realloc(This
->sinks
,(++This
->sinks_size
)*sizeof(*This
->sinks
));
3364 This
->sinks
= heap_alloc(sizeof(*This
->sinks
));
3365 This
->sinks_size
= 1;
3369 This
->sinks
[i
].unk
= sink
;
3376 static HRESULT WINAPI
ConnectionPoint_Unadvise(IConnectionPoint
*iface
, DWORD cookie
)
3378 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3380 TRACE("(%p)->(%d)\n", This
, cookie
);
3382 if (cookie
== 0 || cookie
> This
->sinks_size
|| !This
->sinks
[cookie
-1].unk
)
3383 return CONNECT_E_NOCONNECTION
;
3385 IUnknown_Release(This
->sinks
[cookie
-1].unk
);
3386 This
->sinks
[cookie
-1].unk
= NULL
;
3391 static HRESULT WINAPI
ConnectionPoint_EnumConnections(IConnectionPoint
*iface
,
3392 IEnumConnections
**ppEnum
)
3394 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3395 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3399 static const IConnectionPointVtbl ConnectionPointVtbl
=
3401 ConnectionPoint_QueryInterface
,
3402 ConnectionPoint_AddRef
,
3403 ConnectionPoint_Release
,
3404 ConnectionPoint_GetConnectionInterface
,
3405 ConnectionPoint_GetConnectionPointContainer
,
3406 ConnectionPoint_Advise
,
3407 ConnectionPoint_Unadvise
,
3408 ConnectionPoint_EnumConnections
3411 static void ConnectionPoint_Init(ConnectionPoint
*cp
, struct domdoc
*doc
, REFIID riid
)
3413 cp
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointVtbl
;
3419 cp
->next
= doc
->cp_list
;
3422 cp
->container
= &doc
->IConnectionPointContainer_iface
;
3425 /* domdoc implementation of IObjectWithSite */
3426 static HRESULT WINAPI
3427 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
3429 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3430 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObject
);
3433 static ULONG WINAPI
domdoc_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
3435 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3436 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3439 static ULONG WINAPI
domdoc_ObjectWithSite_Release( IObjectWithSite
* iface
)
3441 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3442 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3445 static HRESULT WINAPI
domdoc_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
3447 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3449 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
3454 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
3457 static HRESULT WINAPI
domdoc_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
3459 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3461 TRACE("(%p)->(%p)\n", iface
, punk
);
3467 IUnknown_Release( This
->site
);
3474 IUnknown_AddRef( punk
);
3477 IUnknown_Release( This
->site
);
3484 static const IObjectWithSiteVtbl domdocObjectSite
=
3486 domdoc_ObjectWithSite_QueryInterface
,
3487 domdoc_ObjectWithSite_AddRef
,
3488 domdoc_ObjectWithSite_Release
,
3489 domdoc_ObjectWithSite_SetSite
,
3490 domdoc_ObjectWithSite_GetSite
3493 static HRESULT WINAPI
domdoc_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
3495 domdoc
*This
= impl_from_IObjectSafety(iface
);
3496 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3499 static ULONG WINAPI
domdoc_Safety_AddRef(IObjectSafety
*iface
)
3501 domdoc
*This
= impl_from_IObjectSafety(iface
);
3502 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3505 static ULONG WINAPI
domdoc_Safety_Release(IObjectSafety
*iface
)
3507 domdoc
*This
= impl_from_IObjectSafety(iface
);
3508 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3511 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3513 static HRESULT WINAPI
domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3514 DWORD
*supported
, DWORD
*enabled
)
3516 domdoc
*This
= impl_from_IObjectSafety(iface
);
3518 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
3520 if(!supported
|| !enabled
) return E_POINTER
;
3522 *supported
= SAFETY_SUPPORTED_OPTIONS
;
3523 *enabled
= This
->safeopt
;
3528 static HRESULT WINAPI
domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3529 DWORD mask
, DWORD enabled
)
3531 domdoc
*This
= impl_from_IObjectSafety(iface
);
3532 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
3534 if ((mask
& ~SAFETY_SUPPORTED_OPTIONS
) != 0)
3537 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
3542 #undef SAFETY_SUPPORTED_OPTIONS
3544 static const IObjectSafetyVtbl domdocObjectSafetyVtbl
= {
3545 domdoc_Safety_QueryInterface
,
3546 domdoc_Safety_AddRef
,
3547 domdoc_Safety_Release
,
3548 domdoc_Safety_GetInterfaceSafetyOptions
,
3549 domdoc_Safety_SetInterfaceSafetyOptions
3552 static const tid_t domdoc_iface_tids
[] = {
3553 IXMLDOMDocument3_tid
,
3557 static dispex_static_data_t domdoc_dispex
= {
3559 IXMLDOMDocument3_tid
,
3564 HRESULT
get_domdoc_from_xmldoc(xmlDocPtr xmldoc
, IXMLDOMDocument3
**document
)
3568 doc
= heap_alloc( sizeof (*doc
) );
3570 return E_OUTOFMEMORY
;
3572 doc
->IXMLDOMDocument3_iface
.lpVtbl
= &XMLDOMDocument3Vtbl
;
3573 doc
->IPersistStreamInit_iface
.lpVtbl
= &xmldoc_IPersistStreamInit_VTable
;
3574 doc
->IObjectWithSite_iface
.lpVtbl
= &domdocObjectSite
;
3575 doc
->IObjectSafety_iface
.lpVtbl
= &domdocObjectSafetyVtbl
;
3576 doc
->IConnectionPointContainer_iface
.lpVtbl
= &ConnectionPointContainerVtbl
;
3578 doc
->async
= VARIANT_TRUE
;
3579 doc
->validating
= 0;
3581 doc
->properties
= properties_from_xmlDocPtr(xmldoc
);
3585 doc
->cp_list
= NULL
;
3586 doc
->namespaces
= NULL
;
3587 memset(doc
->events
, 0, sizeof(doc
->events
));
3589 /* events connection points */
3590 ConnectionPoint_Init(&doc
->cp_dispatch
, doc
, &IID_IDispatch
);
3591 ConnectionPoint_Init(&doc
->cp_propnotif
, doc
, &IID_IPropertyNotifySink
);
3592 ConnectionPoint_Init(&doc
->cp_domdocevents
, doc
, &DIID_XMLDOMDocumentEvents
);
3594 init_xmlnode(&doc
->node
, (xmlNodePtr
)xmldoc
, (IXMLDOMNode
*)&doc
->IXMLDOMDocument3_iface
,
3597 *document
= &doc
->IXMLDOMDocument3_iface
;
3599 TRACE("returning iface %p\n", *document
);
3603 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3608 TRACE("(%d, %p)\n", version
, ppObj
);
3610 xmldoc
= xmlNewDoc(NULL
);
3612 return E_OUTOFMEMORY
;
3614 xmldoc_init(xmldoc
, version
);
3616 hr
= get_domdoc_from_xmldoc(xmldoc
, (IXMLDOMDocument3
**)ppObj
);
3619 free_properties(properties_from_xmlDocPtr(xmldoc
));
3620 heap_free(xmldoc
->_private
);
3628 IUnknown
* create_domdoc( xmlNodePtr document
)
3633 TRACE("(%p)\n", document
);
3635 hr
= get_domdoc_from_xmldoc((xmlDocPtr
)document
, (IXMLDOMDocument3
**)&pObj
);
3644 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3646 MESSAGE("This program tried to use a DOMDocument object, but\n"
3647 "libxml2 support was not present at compile time.\n");