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
23 #define NONAMELESSUNION
30 # include <libxml/parser.h>
31 # include <libxml/xmlerror.h>
32 # include <libxml/xpathInternals.h>
33 # include <libxml/xmlsave.h>
34 # include <libxml/SAX2.h>
35 # include <libxml/parserInternals.h>
51 #include "wine/debug.h"
53 #include "msxml_private.h"
55 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
59 /* not defined in older versions */
60 #define XML_SAVE_FORMAT 1
61 #define XML_SAVE_NO_DECL 2
62 #define XML_SAVE_NO_EMPTY 4
63 #define XML_SAVE_NO_XHTML 8
64 #define XML_SAVE_XHTML 16
65 #define XML_SAVE_AS_XML 32
66 #define XML_SAVE_AS_HTML 64
68 static const WCHAR PropertySelectionLanguageW
[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
69 static const WCHAR PropertySelectionNamespacesW
[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
70 static const WCHAR PropertyProhibitDTDW
[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
71 static const WCHAR PropertyNewParserW
[] = {'N','e','w','P','a','r','s','e','r',0};
72 static const WCHAR PropValueXPathW
[] = {'X','P','a','t','h',0};
73 static const WCHAR PropValueXSLPatternW
[] = {'X','S','L','P','a','t','t','e','r','n',0};
74 static const WCHAR PropertyResolveExternalsW
[] = {'R','e','s','o','l','v','e','E','x','t','e','r','n','a','l','s',0};
76 /* Anything that passes the test_get_ownerDocument()
77 * tests can go here (data shared between all instances).
78 * We need to preserve this when reloading a document,
79 * and also need access to it from the libxml backend. */
81 MSXML_VERSION version
;
82 VARIANT_BOOL preserving
;
83 IXMLDOMSchemaCollection2
* schemaCache
;
84 struct list selectNsList
;
85 xmlChar
const* selectNsStr
;
91 typedef struct ConnectionPoint ConnectionPoint
;
92 typedef struct domdoc domdoc
;
94 struct ConnectionPoint
96 IConnectionPoint IConnectionPoint_iface
;
99 ConnectionPoint
*next
;
100 IConnectionPointContainer
*container
;
107 IPropertyNotifySink
*propnotif
;
113 EVENTID_READYSTATECHANGE
= 0,
114 EVENTID_DATAAVAILABLE
,
115 EVENTID_TRANSFORMNODE
,
122 IXMLDOMDocument3 IXMLDOMDocument3_iface
;
123 IPersistStreamInit IPersistStreamInit_iface
;
124 IObjectWithSite IObjectWithSite_iface
;
125 IObjectSafety IObjectSafety_iface
;
126 IConnectionPointContainer IConnectionPointContainer_iface
;
129 VARIANT_BOOL validating
;
130 VARIANT_BOOL resolving
;
131 domdoc_properties
* properties
;
134 /* IObjectWithSite */
140 /* connection list */
141 ConnectionPoint
*cp_list
;
142 ConnectionPoint cp_domdocevents
;
143 ConnectionPoint cp_propnotif
;
144 ConnectionPoint cp_dispatch
;
147 IDispatch
*events
[EVENTID_LAST
];
149 IXMLDOMSchemaCollection2
*namespaces
;
152 static HRESULT
set_doc_event(domdoc
*doc
, eventid_t eid
, const VARIANT
*v
)
160 IUnknown_QueryInterface(V_UNKNOWN(v
), &IID_IDispatch
, (void**)&disp
);
165 disp
= V_DISPATCH(v
);
166 if (disp
) IDispatch_AddRef(disp
);
169 return DISP_E_TYPEMISMATCH
;
172 if (doc
->events
[eid
]) IDispatch_Release(doc
->events
[eid
]);
173 doc
->events
[eid
] = disp
;
178 static inline ConnectionPoint
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
180 return CONTAINING_RECORD(iface
, ConnectionPoint
, IConnectionPoint_iface
);
184 In native windows, the whole lifetime management of XMLDOMNodes is
185 managed automatically using reference counts. Wine emulates that by
186 maintaining a reference count to the document that is increased for
187 each IXMLDOMNode pointer passed out for this document. If all these
188 pointers are gone, the document is unreachable and gets freed, that
189 is, all nodes in the tree of the document get freed.
191 You are able to create nodes that are associated to a document (in
192 fact, in msxml's XMLDOM model, all nodes are associated to a document),
193 but not in the tree of that document, for example using the createFoo
194 functions from IXMLDOMDocument. These nodes do not get cleaned up
195 by libxml, so we have to do it ourselves.
197 To catch these nodes, a list of "orphan nodes" is introduced.
198 It contains pointers to all roots of node trees that are
199 associated with the document without being part of the document
200 tree. All nodes with parent==NULL (except for the document root nodes)
201 should be in the orphan node list of their document. All orphan nodes
202 get freed together with the document itself.
205 typedef struct _xmldoc_priv
{
208 domdoc_properties
* properties
;
211 typedef struct _orphan_entry
{
216 typedef struct _select_ns_entry
{
218 xmlChar
const* prefix
;
224 static inline xmldoc_priv
* priv_from_xmlDocPtr(const xmlDocPtr doc
)
226 return doc
->_private
;
229 static inline domdoc_properties
* properties_from_xmlDocPtr(xmlDocPtr doc
)
231 return priv_from_xmlDocPtr(doc
)->properties
;
234 BOOL
is_xpathmode(const xmlDocPtr doc
)
236 return properties_from_xmlDocPtr(doc
)->XPath
;
239 void set_xpathmode(xmlDocPtr doc
, BOOL xpath
)
241 properties_from_xmlDocPtr(doc
)->XPath
= xpath
;
244 int registerNamespaces(xmlXPathContextPtr ctxt
)
247 const select_ns_entry
* ns
= NULL
;
248 const struct list
* pNsList
= &properties_from_xmlDocPtr(ctxt
->doc
)->selectNsList
;
250 TRACE("(%p)\n", ctxt
);
252 LIST_FOR_EACH_ENTRY( ns
, pNsList
, select_ns_entry
, entry
)
254 xmlXPathRegisterNs(ctxt
, ns
->prefix
, ns
->href
);
261 static inline void clear_selectNsList(struct list
* pNsList
)
263 select_ns_entry
*ns
, *ns2
;
264 LIST_FOR_EACH_ENTRY_SAFE( ns
, ns2
, pNsList
, select_ns_entry
, entry
)
271 static xmldoc_priv
* create_priv(void)
274 priv
= heap_alloc( sizeof (*priv
) );
279 list_init( &priv
->orphans
);
280 priv
->properties
= NULL
;
286 static domdoc_properties
*create_properties(MSXML_VERSION version
)
288 domdoc_properties
*properties
= heap_alloc(sizeof(domdoc_properties
));
290 list_init(&properties
->selectNsList
);
291 properties
->preserving
= VARIANT_FALSE
;
292 properties
->schemaCache
= NULL
;
293 properties
->selectNsStr
= heap_alloc_zero(sizeof(xmlChar
));
294 properties
->selectNsStr_len
= 0;
296 /* properties that are dependent on object versions */
297 properties
->version
= version
;
298 properties
->XPath
= (version
== MSXML4
|| version
== MSXML6
);
301 properties
->url
= NULL
;
306 static domdoc_properties
* copy_properties(domdoc_properties
const* properties
)
308 domdoc_properties
* pcopy
= heap_alloc(sizeof(domdoc_properties
));
309 select_ns_entry
const* ns
= NULL
;
310 select_ns_entry
* new_ns
= NULL
;
311 int len
= (properties
->selectNsStr_len
+1)*sizeof(xmlChar
);
316 pcopy
->version
= properties
->version
;
317 pcopy
->preserving
= properties
->preserving
;
318 pcopy
->schemaCache
= properties
->schemaCache
;
319 if (pcopy
->schemaCache
)
320 IXMLDOMSchemaCollection2_AddRef(pcopy
->schemaCache
);
321 pcopy
->XPath
= properties
->XPath
;
322 pcopy
->selectNsStr_len
= properties
->selectNsStr_len
;
323 list_init( &pcopy
->selectNsList
);
324 pcopy
->selectNsStr
= heap_alloc(len
);
325 memcpy((xmlChar
*)pcopy
->selectNsStr
, properties
->selectNsStr
, len
);
326 offset
= pcopy
->selectNsStr
- properties
->selectNsStr
;
328 LIST_FOR_EACH_ENTRY( ns
, (&properties
->selectNsList
), select_ns_entry
, entry
)
330 new_ns
= heap_alloc(sizeof(select_ns_entry
));
331 memcpy(new_ns
, ns
, sizeof(select_ns_entry
));
332 new_ns
->href
+= offset
;
333 new_ns
->prefix
+= offset
;
334 list_add_tail(&pcopy
->selectNsList
, &new_ns
->entry
);
339 int len
= strlenW(properties
->url
);
341 pcopy
->url
= CoTaskMemAlloc((len
+1)*sizeof(WCHAR
));
342 memcpy(pcopy
->url
, properties
->url
, len
*sizeof(WCHAR
));
352 static void free_properties(domdoc_properties
* properties
)
356 if (properties
->schemaCache
)
357 IXMLDOMSchemaCollection2_Release(properties
->schemaCache
);
358 clear_selectNsList(&properties
->selectNsList
);
359 heap_free((xmlChar
*)properties
->selectNsStr
);
360 CoTaskMemFree(properties
->url
);
361 heap_free(properties
);
365 static void release_namespaces(domdoc
*This
)
367 if (This
->namespaces
)
369 IXMLDOMSchemaCollection2_Release(This
->namespaces
);
370 This
->namespaces
= NULL
;
374 /* links a "<?xml" node as a first child */
375 void xmldoc_link_xmldecl(xmlDocPtr doc
, xmlNodePtr node
)
378 if (doc
->standalone
!= -1) xmlAddPrevSibling( doc
->children
, node
);
381 /* unlinks a first "<?xml" child if it was created */
382 xmlNodePtr
xmldoc_unlink_xmldecl(xmlDocPtr doc
)
384 static const xmlChar xmlA
[] = "xml";
385 xmlNodePtr node
, first_child
;
389 /* xml declaration node could be created automatically after parsing or added
391 first_child
= doc
->children
;
392 if (first_child
&& first_child
->type
== XML_PI_NODE
&& xmlStrEqual(first_child
->name
, xmlA
))
395 xmlUnlinkNode( node
);
403 BOOL
is_preserving_whitespace(xmlNodePtr node
)
405 domdoc_properties
* properties
= NULL
;
406 /* during parsing the xmlDoc._private stuff is not there */
407 if (priv_from_xmlDocPtr(node
->doc
))
408 properties
= properties_from_xmlDocPtr(node
->doc
);
409 return ((properties
&& properties
->preserving
== VARIANT_TRUE
) ||
410 xmlNodeGetSpacePreserve(node
) == 1);
413 static inline BOOL
strn_isspace(xmlChar
const* str
, int len
)
415 for (; str
&& len
> 0 && *str
; ++str
, --len
)
422 static void sax_characters(void *ctx
, const xmlChar
*ch
, int len
)
424 xmlParserCtxtPtr ctxt
;
427 ctxt
= (xmlParserCtxtPtr
) ctx
;
428 This
= (const domdoc
*) ctxt
->_private
;
432 xmlChar cur
= *(ctxt
->input
->cur
);
434 /* Characters are reported with multiple calls, for example each charref is reported with a separate
435 call and then parser appends it to a single text node or creates a new node if not created.
436 It's not possible to tell if it's ignorable data or not just looking at data itself cause it could be
437 space chars that separate charrefs or similar case. We only need to skip leading and trailing spaces,
438 or whole node if it has nothing but space chars, so to detect leading space node->last is checked that
439 contains text node pointer if already created, trailing spaces are detected directly looking at parser input
440 for next '<' opening bracket - similar logic is used by libxml2 itself. Basically 'cur' == '<' means the last
441 chunk of char data, in case it's not the last chunk we check for previously added node type and if it's not
442 a text node it's safe to ignore.
444 Note that during domdoc_loadXML() the xmlDocPtr->_private data is not available. */
446 if (!This
->properties
->preserving
&&
447 !is_preserving_whitespace(ctxt
->node
) &&
448 strn_isspace(ch
, len
) &&
449 (!ctxt
->node
->last
||
450 ((ctxt
->node
->last
&& (cur
== '<' || ctxt
->node
->last
->type
!= XML_TEXT_NODE
))
455 xmlSAX2Characters(ctxt
, ch
, len
);
458 static void LIBXML2_LOG_CALLBACK
sax_error(void* ctx
, char const* msg
, ...)
462 LIBXML2_CALLBACK_ERR(doparse
, msg
, ap
);
466 static void LIBXML2_LOG_CALLBACK
sax_warning(void* ctx
, char const* msg
, ...)
470 LIBXML2_CALLBACK_WARN(doparse
, msg
, ap
);
474 static void sax_serror(void* ctx
, xmlErrorPtr err
)
476 LIBXML2_CALLBACK_SERROR(doparse
, err
);
479 static xmlDocPtr
doparse(domdoc
* This
, char const* ptr
, int len
, xmlCharEncoding encoding
)
481 xmlDocPtr doc
= NULL
;
482 xmlParserCtxtPtr pctx
;
483 static xmlSAXHandler sax_handler
= {
484 xmlSAX2InternalSubset
, /* internalSubset */
485 xmlSAX2IsStandalone
, /* isStandalone */
486 xmlSAX2HasInternalSubset
, /* hasInternalSubset */
487 xmlSAX2HasExternalSubset
, /* hasExternalSubset */
488 xmlSAX2ResolveEntity
, /* resolveEntity */
489 xmlSAX2GetEntity
, /* getEntity */
490 xmlSAX2EntityDecl
, /* entityDecl */
491 xmlSAX2NotationDecl
, /* notationDecl */
492 xmlSAX2AttributeDecl
, /* attributeDecl */
493 xmlSAX2ElementDecl
, /* elementDecl */
494 xmlSAX2UnparsedEntityDecl
, /* unparsedEntityDecl */
495 xmlSAX2SetDocumentLocator
, /* setDocumentLocator */
496 xmlSAX2StartDocument
, /* startDocument */
497 xmlSAX2EndDocument
, /* endDocument */
498 xmlSAX2StartElement
, /* startElement */
499 xmlSAX2EndElement
, /* endElement */
500 xmlSAX2Reference
, /* reference */
501 sax_characters
, /* characters */
502 sax_characters
, /* ignorableWhitespace */
503 xmlSAX2ProcessingInstruction
, /* processingInstruction */
504 xmlSAX2Comment
, /* comment */
505 sax_warning
, /* warning */
506 sax_error
, /* error */
507 sax_error
, /* fatalError */
508 xmlSAX2GetParameterEntity
, /* getParameterEntity */
509 xmlSAX2CDataBlock
, /* cdataBlock */
510 xmlSAX2ExternalSubset
, /* externalSubset */
513 xmlSAX2StartElementNs
, /* startElementNs */
514 xmlSAX2EndElementNs
, /* endElementNs */
515 sax_serror
/* serror */
518 pctx
= xmlCreateMemoryParserCtxt(ptr
, len
);
521 ERR("Failed to create parser context\n");
525 if (pctx
->sax
) xmlFree(pctx
->sax
);
526 pctx
->sax
= &sax_handler
;
527 pctx
->_private
= This
;
530 if (encoding
!= XML_CHAR_ENCODING_NONE
)
531 xmlSwitchEncoding(pctx
, encoding
);
533 xmlParseDocument(pctx
);
535 if (pctx
->wellFormed
)
541 xmlFreeDoc(pctx
->myDoc
);
545 xmlFreeParserCtxt(pctx
);
547 /* TODO: put this in one of the SAX callbacks */
548 /* create first child as a <?xml...?> */
549 if (doc
&& doc
->standalone
!= -1)
553 xmlChar
*xmlbuff
= (xmlChar
*)buff
;
555 node
= xmlNewDocPI( doc
, (xmlChar
*)"xml", NULL
);
557 /* version attribute can't be omitted */
558 sprintf(buff
, "version=\"%s\"", doc
->version
? (char*)doc
->version
: "1.0");
559 xmlNodeAddContent( node
, xmlbuff
);
563 sprintf(buff
, " encoding=\"%s\"", doc
->encoding
);
564 xmlNodeAddContent( node
, xmlbuff
);
567 if (doc
->standalone
!= -2)
569 sprintf(buff
, " standalone=\"%s\"", doc
->standalone
== 0 ? "no" : "yes");
570 xmlNodeAddContent( node
, xmlbuff
);
573 xmldoc_link_xmldecl( doc
, node
);
579 void xmldoc_init(xmlDocPtr doc
, MSXML_VERSION version
)
581 doc
->_private
= create_priv();
582 priv_from_xmlDocPtr(doc
)->properties
= create_properties(version
);
585 LONG
xmldoc_add_refs(xmlDocPtr doc
, LONG refs
)
587 LONG ref
= InterlockedExchangeAdd(&priv_from_xmlDocPtr(doc
)->refs
, refs
) + refs
;
588 TRACE("(%p)->(%d)\n", doc
, ref
);
592 LONG
xmldoc_add_ref(xmlDocPtr doc
)
594 return xmldoc_add_refs(doc
, 1);
597 LONG
xmldoc_release_refs(xmlDocPtr doc
, LONG refs
)
599 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
600 LONG ref
= InterlockedExchangeAdd(&priv
->refs
, -refs
) - refs
;
601 TRACE("(%p)->(%d)\n", doc
, ref
);
604 WARN("negative refcount, expect troubles\n");
608 orphan_entry
*orphan
, *orphan2
;
609 TRACE("freeing docptr %p\n", doc
);
611 LIST_FOR_EACH_ENTRY_SAFE( orphan
, orphan2
, &priv
->orphans
, orphan_entry
, entry
)
613 xmlFreeNode( orphan
->node
);
616 free_properties(priv
->properties
);
617 heap_free(doc
->_private
);
625 LONG
xmldoc_release(xmlDocPtr doc
)
627 return xmldoc_release_refs(doc
, 1);
630 HRESULT
xmldoc_add_orphan(xmlDocPtr doc
, xmlNodePtr node
)
632 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
635 entry
= heap_alloc( sizeof (*entry
) );
637 return E_OUTOFMEMORY
;
640 list_add_head( &priv
->orphans
, &entry
->entry
);
644 HRESULT
xmldoc_remove_orphan(xmlDocPtr doc
, xmlNodePtr node
)
646 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
647 orphan_entry
*entry
, *entry2
;
649 LIST_FOR_EACH_ENTRY_SAFE( entry
, entry2
, &priv
->orphans
, orphan_entry
, entry
)
651 if( entry
->node
== node
)
653 list_remove( &entry
->entry
);
662 static inline xmlDocPtr
get_doc( domdoc
*This
)
664 return This
->node
.node
->doc
;
667 static HRESULT
attach_xmldoc(domdoc
*This
, xmlDocPtr xml
)
669 release_namespaces(This
);
673 priv_from_xmlDocPtr(get_doc(This
))->properties
= NULL
;
674 if (xmldoc_release(get_doc(This
)) != 0)
675 priv_from_xmlDocPtr(get_doc(This
))->properties
=
676 copy_properties(This
->properties
);
679 This
->node
.node
= (xmlNodePtr
) xml
;
683 xmldoc_add_ref(get_doc(This
));
684 priv_from_xmlDocPtr(get_doc(This
))->properties
= This
->properties
;
690 static inline domdoc
*impl_from_IXMLDOMDocument3( IXMLDOMDocument3
*iface
)
692 return CONTAINING_RECORD(iface
, domdoc
, IXMLDOMDocument3_iface
);
695 static inline domdoc
*impl_from_IPersistStreamInit(IPersistStreamInit
*iface
)
697 return CONTAINING_RECORD(iface
, domdoc
, IPersistStreamInit_iface
);
700 static inline domdoc
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
702 return CONTAINING_RECORD(iface
, domdoc
, IObjectWithSite_iface
);
705 static inline domdoc
*impl_from_IObjectSafety(IObjectSafety
*iface
)
707 return CONTAINING_RECORD(iface
, domdoc
, IObjectSafety_iface
);
710 static inline domdoc
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
712 return CONTAINING_RECORD(iface
, domdoc
, IConnectionPointContainer_iface
);
715 /************************************************************************
716 * domdoc implementation of IPersistStream.
718 static HRESULT WINAPI
PersistStreamInit_QueryInterface(
719 IPersistStreamInit
*iface
, REFIID riid
, void **ppvObj
)
721 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
722 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObj
);
725 static ULONG WINAPI
PersistStreamInit_AddRef(
726 IPersistStreamInit
*iface
)
728 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
729 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
732 static ULONG WINAPI
PersistStreamInit_Release(
733 IPersistStreamInit
*iface
)
735 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
736 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
739 static HRESULT WINAPI
PersistStreamInit_GetClassID(
740 IPersistStreamInit
*iface
, CLSID
*classid
)
742 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
743 TRACE("(%p)->(%p)\n", This
, classid
);
748 *classid
= *DOMDocument_version(This
->properties
->version
);
753 static HRESULT WINAPI
PersistStreamInit_IsDirty(
754 IPersistStreamInit
*iface
)
756 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
757 FIXME("(%p): stub!\n", This
);
761 static HRESULT
domdoc_load_from_stream(domdoc
*doc
, ISequentialStream
*stream
)
763 DWORD read
, written
, len
;
764 xmlDocPtr xmldoc
= NULL
;
772 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &hstream
);
778 ISequentialStream_Read(stream
, buf
, sizeof(buf
), &read
);
779 hr
= IStream_Write(hstream
, buf
, read
, &written
);
780 } while(SUCCEEDED(hr
) && written
!= 0 && read
!= 0);
784 ERR("failed to copy stream 0x%08x\n", hr
);
785 IStream_Release(hstream
);
789 hr
= GetHGlobalFromStream(hstream
, &hglobal
);
793 len
= GlobalSize(hglobal
);
794 ptr
= GlobalLock(hglobal
);
796 xmldoc
= doparse(doc
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
797 GlobalUnlock(hglobal
);
801 ERR("Failed to parse xml\n");
805 xmldoc
->_private
= create_priv();
807 return attach_xmldoc(doc
, xmldoc
);
810 static HRESULT WINAPI
PersistStreamInit_Load(IPersistStreamInit
*iface
, IStream
*stream
)
812 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
814 TRACE("(%p)->(%p)\n", This
, stream
);
819 return domdoc_load_from_stream(This
, (ISequentialStream
*)stream
);
822 static HRESULT WINAPI
PersistStreamInit_Save(
823 IPersistStreamInit
*iface
, IStream
*stream
, BOOL clr_dirty
)
825 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
829 TRACE("(%p)->(%p %d)\n", This
, stream
, clr_dirty
);
831 hr
= IXMLDOMDocument3_get_xml(&This
->IXMLDOMDocument3_iface
, &xmlString
);
834 DWORD len
= SysStringLen(xmlString
) * sizeof(WCHAR
);
836 hr
= IStream_Write( stream
, xmlString
, len
, NULL
);
837 SysFreeString(xmlString
);
840 TRACE("ret 0x%08x\n", hr
);
845 static HRESULT WINAPI
PersistStreamInit_GetSizeMax(
846 IPersistStreamInit
*iface
, ULARGE_INTEGER
*pcbSize
)
848 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
849 TRACE("(%p)->(%p)\n", This
, pcbSize
);
853 static HRESULT WINAPI
PersistStreamInit_InitNew(
854 IPersistStreamInit
*iface
)
856 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
857 TRACE("(%p)\n", This
);
861 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable
=
863 PersistStreamInit_QueryInterface
,
864 PersistStreamInit_AddRef
,
865 PersistStreamInit_Release
,
866 PersistStreamInit_GetClassID
,
867 PersistStreamInit_IsDirty
,
868 PersistStreamInit_Load
,
869 PersistStreamInit_Save
,
870 PersistStreamInit_GetSizeMax
,
871 PersistStreamInit_InitNew
874 /* IXMLDOMDocument3 interface */
876 static const tid_t domdoc_se_tids
[] = {
879 IXMLDOMDocument2_tid
,
880 IXMLDOMDocument3_tid
,
884 static HRESULT WINAPI
domdoc_QueryInterface( IXMLDOMDocument3
*iface
, REFIID riid
, void** ppvObject
)
886 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
888 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( riid
), ppvObject
);
892 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
893 IsEqualGUID( riid
, &IID_IDispatch
) ||
894 IsEqualGUID( riid
, &IID_IXMLDOMNode
) ||
895 IsEqualGUID( riid
, &IID_IXMLDOMDocument
) ||
896 IsEqualGUID( riid
, &IID_IXMLDOMDocument2
)||
897 IsEqualGUID( riid
, &IID_IXMLDOMDocument3
))
901 else if (IsEqualGUID(&IID_IPersistStream
, riid
) ||
902 IsEqualGUID(&IID_IPersistStreamInit
, riid
))
904 *ppvObject
= &This
->IPersistStreamInit_iface
;
906 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
908 *ppvObject
= &This
->IObjectWithSite_iface
;
910 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
912 *ppvObject
= &This
->IObjectSafety_iface
;
914 else if( IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
916 return node_create_supporterrorinfo(domdoc_se_tids
, ppvObject
);
918 else if(node_query_interface(&This
->node
, riid
, ppvObject
))
920 return *ppvObject
? S_OK
: E_NOINTERFACE
;
922 else if (IsEqualGUID( riid
, &IID_IConnectionPointContainer
))
924 *ppvObject
= &This
->IConnectionPointContainer_iface
;
928 TRACE("interface %s not implemented\n", debugstr_guid(riid
));
929 return E_NOINTERFACE
;
932 IUnknown_AddRef((IUnknown
*)*ppvObject
);
937 static ULONG WINAPI
domdoc_AddRef( IXMLDOMDocument3
*iface
)
939 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
940 ULONG ref
= InterlockedIncrement( &This
->ref
);
941 TRACE("(%p)->(%d)\n", This
, ref
);
945 static ULONG WINAPI
domdoc_Release( IXMLDOMDocument3
*iface
)
947 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
948 LONG ref
= InterlockedDecrement( &This
->ref
);
950 TRACE("(%p)->(%d)\n", This
, ref
);
957 IUnknown_Release( This
->site
);
958 destroy_xmlnode(&This
->node
);
960 for (eid
= 0; eid
< EVENTID_LAST
; eid
++)
961 if (This
->events
[eid
]) IDispatch_Release(This
->events
[eid
]);
963 release_namespaces(This
);
970 static HRESULT WINAPI
domdoc_GetTypeInfoCount( IXMLDOMDocument3
*iface
, UINT
* pctinfo
)
972 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
973 return IDispatchEx_GetTypeInfoCount(&This
->node
.dispex
.IDispatchEx_iface
, pctinfo
);
976 static HRESULT WINAPI
domdoc_GetTypeInfo(
977 IXMLDOMDocument3
*iface
,
978 UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
980 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
981 return IDispatchEx_GetTypeInfo(&This
->node
.dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
984 static HRESULT WINAPI
domdoc_GetIDsOfNames(
985 IXMLDOMDocument3
*iface
,
992 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
993 return IDispatchEx_GetIDsOfNames(&This
->node
.dispex
.IDispatchEx_iface
,
994 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
997 static HRESULT WINAPI
domdoc_Invoke(
998 IXMLDOMDocument3
*iface
,
1003 DISPPARAMS
* pDispParams
,
1004 VARIANT
* pVarResult
,
1005 EXCEPINFO
* pExcepInfo
,
1008 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1009 return IDispatchEx_Invoke(&This
->node
.dispex
.IDispatchEx_iface
,
1010 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1013 static HRESULT WINAPI
domdoc_get_nodeName(
1014 IXMLDOMDocument3
*iface
,
1017 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1019 static const WCHAR documentW
[] = {'#','d','o','c','u','m','e','n','t',0};
1021 TRACE("(%p)->(%p)\n", This
, name
);
1023 return return_bstr(documentW
, name
);
1027 static HRESULT WINAPI
domdoc_get_nodeValue(
1028 IXMLDOMDocument3
*iface
,
1031 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1033 TRACE("(%p)->(%p)\n", This
, value
);
1036 return E_INVALIDARG
;
1038 V_VT(value
) = VT_NULL
;
1039 V_BSTR(value
) = NULL
; /* tests show that we should do this */
1044 static HRESULT WINAPI
domdoc_put_nodeValue(
1045 IXMLDOMDocument3
*iface
,
1048 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1049 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&value
));
1054 static HRESULT WINAPI
domdoc_get_nodeType(
1055 IXMLDOMDocument3
*iface
,
1058 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1060 TRACE("(%p)->(%p)\n", This
, type
);
1062 *type
= NODE_DOCUMENT
;
1067 static HRESULT WINAPI
domdoc_get_parentNode(
1068 IXMLDOMDocument3
*iface
,
1069 IXMLDOMNode
** parent
)
1071 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1073 TRACE("(%p)->(%p)\n", This
, parent
);
1075 return node_get_parent(&This
->node
, parent
);
1079 static HRESULT WINAPI
domdoc_get_childNodes(
1080 IXMLDOMDocument3
*iface
,
1081 IXMLDOMNodeList
** childList
)
1083 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1085 TRACE("(%p)->(%p)\n", This
, childList
);
1087 return node_get_child_nodes(&This
->node
, childList
);
1091 static HRESULT WINAPI
domdoc_get_firstChild(
1092 IXMLDOMDocument3
*iface
,
1093 IXMLDOMNode
** firstChild
)
1095 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1097 TRACE("(%p)->(%p)\n", This
, firstChild
);
1099 return node_get_first_child(&This
->node
, firstChild
);
1103 static HRESULT WINAPI
domdoc_get_lastChild(
1104 IXMLDOMDocument3
*iface
,
1105 IXMLDOMNode
** lastChild
)
1107 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1109 TRACE("(%p)->(%p)\n", This
, lastChild
);
1111 return node_get_last_child(&This
->node
, lastChild
);
1115 static HRESULT WINAPI
domdoc_get_previousSibling(
1116 IXMLDOMDocument3
*iface
,
1117 IXMLDOMNode
** previousSibling
)
1119 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1121 TRACE("(%p)->(%p)\n", This
, previousSibling
);
1123 return return_null_node(previousSibling
);
1127 static HRESULT WINAPI
domdoc_get_nextSibling(
1128 IXMLDOMDocument3
*iface
,
1129 IXMLDOMNode
** nextSibling
)
1131 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1133 TRACE("(%p)->(%p)\n", This
, nextSibling
);
1135 return return_null_node(nextSibling
);
1139 static HRESULT WINAPI
domdoc_get_attributes(
1140 IXMLDOMDocument3
*iface
,
1141 IXMLDOMNamedNodeMap
** attributeMap
)
1143 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1145 TRACE("(%p)->(%p)\n", This
, attributeMap
);
1147 return return_null_ptr((void**)attributeMap
);
1151 static HRESULT WINAPI
domdoc_insertBefore(
1152 IXMLDOMDocument3
*iface
,
1153 IXMLDOMNode
* newChild
,
1155 IXMLDOMNode
** outNewChild
)
1157 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1161 TRACE("(%p)->(%p %s %p)\n", This
, newChild
, debugstr_variant(&refChild
), outNewChild
);
1163 hr
= IXMLDOMNode_get_nodeType(newChild
, &type
);
1164 if (hr
!= S_OK
) return hr
;
1166 TRACE("new node type %d\n", type
);
1169 case NODE_ATTRIBUTE
:
1171 case NODE_CDATA_SECTION
:
1172 if (outNewChild
) *outNewChild
= NULL
;
1175 return node_insert_before(&This
->node
, newChild
, &refChild
, outNewChild
);
1179 static HRESULT WINAPI
domdoc_replaceChild(
1180 IXMLDOMDocument3
*iface
,
1181 IXMLDOMNode
* newChild
,
1182 IXMLDOMNode
* oldChild
,
1183 IXMLDOMNode
** outOldChild
)
1185 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1187 TRACE("(%p)->(%p %p %p)\n", This
, newChild
, oldChild
, outOldChild
);
1189 return node_replace_child(&This
->node
, newChild
, oldChild
, outOldChild
);
1193 static HRESULT WINAPI
domdoc_removeChild(
1194 IXMLDOMDocument3
*iface
,
1196 IXMLDOMNode
**oldChild
)
1198 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1199 TRACE("(%p)->(%p %p)\n", This
, child
, oldChild
);
1200 return node_remove_child(&This
->node
, child
, oldChild
);
1204 static HRESULT WINAPI
domdoc_appendChild(
1205 IXMLDOMDocument3
*iface
,
1207 IXMLDOMNode
**outChild
)
1209 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1210 TRACE("(%p)->(%p %p)\n", This
, child
, outChild
);
1211 return node_append_child(&This
->node
, child
, outChild
);
1215 static HRESULT WINAPI
domdoc_hasChildNodes(
1216 IXMLDOMDocument3
*iface
,
1219 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1220 TRACE("(%p)->(%p)\n", This
, ret
);
1221 return node_has_childnodes(&This
->node
, ret
);
1225 static HRESULT WINAPI
domdoc_get_ownerDocument(
1226 IXMLDOMDocument3
*iface
,
1227 IXMLDOMDocument
**doc
)
1229 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1230 TRACE("(%p)->(%p)\n", This
, doc
);
1231 return node_get_owner_doc(&This
->node
, doc
);
1235 static HRESULT WINAPI
domdoc_cloneNode(
1236 IXMLDOMDocument3
*iface
,
1238 IXMLDOMNode
** outNode
)
1240 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1241 TRACE("(%p)->(%d %p)\n", This
, deep
, outNode
);
1242 return node_clone( &This
->node
, deep
, outNode
);
1246 static HRESULT WINAPI
domdoc_get_nodeTypeString(
1247 IXMLDOMDocument3
*iface
,
1250 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1251 static const WCHAR documentW
[] = {'d','o','c','u','m','e','n','t',0};
1253 TRACE("(%p)->(%p)\n", This
, p
);
1255 return return_bstr(documentW
, p
);
1259 static HRESULT WINAPI
domdoc_get_text(
1260 IXMLDOMDocument3
*iface
,
1263 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1264 TRACE("(%p)->(%p)\n", This
, p
);
1265 return node_get_text(&This
->node
, p
);
1269 static HRESULT WINAPI
domdoc_put_text(
1270 IXMLDOMDocument3
*iface
,
1273 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1274 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
1279 static HRESULT WINAPI
domdoc_get_specified(
1280 IXMLDOMDocument3
*iface
,
1281 VARIANT_BOOL
* isSpecified
)
1283 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1284 FIXME("(%p)->(%p) stub!\n", This
, isSpecified
);
1285 *isSpecified
= VARIANT_TRUE
;
1290 static HRESULT WINAPI
domdoc_get_definition(
1291 IXMLDOMDocument3
*iface
,
1292 IXMLDOMNode
** definitionNode
)
1294 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1295 FIXME("(%p)->(%p)\n", This
, definitionNode
);
1300 static HRESULT WINAPI
domdoc_get_nodeTypedValue(
1301 IXMLDOMDocument3
*iface
,
1304 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1305 TRACE("(%p)->(%p)\n", This
, v
);
1306 return return_null_var(v
);
1309 static HRESULT WINAPI
domdoc_put_nodeTypedValue(
1310 IXMLDOMDocument3
*iface
,
1311 VARIANT typedValue
)
1313 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1314 FIXME("(%p)->(%s)\n", This
, debugstr_variant(&typedValue
));
1319 static HRESULT WINAPI
domdoc_get_dataType(
1320 IXMLDOMDocument3
*iface
,
1323 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1324 TRACE("(%p)->(%p)\n", This
, typename
);
1325 return return_null_var( typename
);
1329 static HRESULT WINAPI
domdoc_put_dataType(
1330 IXMLDOMDocument3
*iface
,
1333 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1335 FIXME("(%p)->(%s)\n", This
, debugstr_w(dataTypeName
));
1338 return E_INVALIDARG
;
1343 static int XMLCALL
domdoc_get_xml_writecallback(void *ctx
, const char *data
, int len
)
1345 return xmlBufferAdd((xmlBufferPtr
)ctx
, (xmlChar
*)data
, len
) == 0 ? len
: 0;
1348 static HRESULT WINAPI
domdoc_get_xml(
1349 IXMLDOMDocument3
*iface
,
1352 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1353 xmlSaveCtxtPtr ctxt
;
1358 TRACE("(%p)->(%p)\n", This
, p
);
1361 return E_INVALIDARG
;
1365 buf
= xmlBufferCreate();
1367 return E_OUTOFMEMORY
;
1369 options
= XML_SAVE_FORMAT
| XML_SAVE_NO_DECL
;
1370 ctxt
= xmlSaveToIO(domdoc_get_xml_writecallback
, NULL
, buf
, "UTF-8", options
);
1375 return E_OUTOFMEMORY
;
1378 ret
= xmlSaveDoc(ctxt
, get_doc(This
));
1379 /* flushes on close */
1382 TRACE("%ld, len=%d\n", ret
, xmlBufferLength(buf
));
1383 if(ret
!= -1 && xmlBufferLength(buf
) > 0)
1387 content
= bstr_from_xmlChar(xmlBufferContent(buf
));
1388 content
= EnsureCorrectEOL(content
);
1394 *p
= SysAllocStringLen(NULL
, 0);
1399 return *p
? S_OK
: E_OUTOFMEMORY
;
1403 static HRESULT WINAPI
domdoc_transformNode(
1404 IXMLDOMDocument3
*iface
,
1408 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1409 TRACE("(%p)->(%p %p)\n", This
, node
, p
);
1410 return node_transform_node(&This
->node
, node
, p
);
1414 static HRESULT WINAPI
domdoc_selectNodes(
1415 IXMLDOMDocument3
*iface
,
1417 IXMLDOMNodeList
**outList
)
1419 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1420 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outList
);
1421 return node_select_nodes(&This
->node
, p
, outList
);
1425 static HRESULT WINAPI
domdoc_selectSingleNode(
1426 IXMLDOMDocument3
*iface
,
1428 IXMLDOMNode
**outNode
)
1430 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1431 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outNode
);
1432 return node_select_singlenode(&This
->node
, p
, outNode
);
1436 static HRESULT WINAPI
domdoc_get_parsed(
1437 IXMLDOMDocument3
*iface
,
1438 VARIANT_BOOL
* isParsed
)
1440 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1441 FIXME("(%p)->(%p) stub!\n", This
, isParsed
);
1442 *isParsed
= VARIANT_TRUE
;
1446 static HRESULT WINAPI
domdoc_get_namespaceURI(
1447 IXMLDOMDocument3
*iface
,
1448 BSTR
* namespaceURI
)
1450 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1451 TRACE("(%p)->(%p)\n", This
, namespaceURI
);
1452 return return_null_bstr( namespaceURI
);
1455 static HRESULT WINAPI
domdoc_get_prefix(
1456 IXMLDOMDocument3
*iface
,
1459 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1460 TRACE("(%p)->(%p)\n", This
, prefix
);
1461 return return_null_bstr( prefix
);
1465 static HRESULT WINAPI
domdoc_get_baseName(
1466 IXMLDOMDocument3
*iface
,
1469 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1470 TRACE("(%p)->(%p)\n", This
, name
);
1471 return return_null_bstr( name
);
1475 static HRESULT WINAPI
domdoc_transformNodeToObject(
1476 IXMLDOMDocument3
*iface
,
1477 IXMLDOMNode
* stylesheet
,
1478 VARIANT outputObject
)
1480 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1481 FIXME("(%p)->(%p %s)\n", This
, stylesheet
, debugstr_variant(&outputObject
));
1486 static HRESULT WINAPI
domdoc_get_doctype(
1487 IXMLDOMDocument3
*iface
,
1488 IXMLDOMDocumentType
** doctype
)
1490 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1495 TRACE("(%p)->(%p)\n", This
, doctype
);
1497 if (!doctype
) return E_INVALIDARG
;
1501 dtd
= xmlGetIntSubset(get_doc(This
));
1502 if (!dtd
) return S_FALSE
;
1504 node
= create_node((xmlNodePtr
)dtd
);
1505 if (!node
) return S_FALSE
;
1507 hr
= IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentType
, (void**)doctype
);
1508 IXMLDOMNode_Release(node
);
1514 static HRESULT WINAPI
domdoc_get_implementation(
1515 IXMLDOMDocument3
*iface
,
1516 IXMLDOMImplementation
** impl
)
1518 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1520 TRACE("(%p)->(%p)\n", This
, impl
);
1523 return E_INVALIDARG
;
1525 *impl
= (IXMLDOMImplementation
*)create_doc_Implementation();
1530 static HRESULT WINAPI
domdoc_get_documentElement(
1531 IXMLDOMDocument3
*iface
,
1532 IXMLDOMElement
** DOMElement
)
1534 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1535 IXMLDOMNode
*element_node
;
1539 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1542 return E_INVALIDARG
;
1546 root
= xmlDocGetRootElement( get_doc(This
) );
1550 element_node
= create_node( root
);
1551 if(!element_node
) return S_FALSE
;
1553 hr
= IXMLDOMNode_QueryInterface(element_node
, &IID_IXMLDOMElement
, (void**)DOMElement
);
1554 IXMLDOMNode_Release(element_node
);
1560 static HRESULT WINAPI
domdoc_put_documentElement(
1561 IXMLDOMDocument3
*iface
,
1562 IXMLDOMElement
* DOMElement
)
1564 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1565 IXMLDOMNode
*elementNode
;
1572 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1574 hr
= IXMLDOMElement_QueryInterface( DOMElement
, &IID_IXMLDOMNode
, (void**)&elementNode
);
1578 xmlNode
= get_node_obj( elementNode
);
1579 if(!xmlNode
) return E_FAIL
;
1581 if(!xmlNode
->node
->parent
)
1582 if(xmldoc_remove_orphan(xmlNode
->node
->doc
, xmlNode
->node
) != S_OK
)
1583 WARN("%p is not an orphan of %p\n", xmlNode
->node
->doc
, xmlNode
->node
);
1585 old_doc
= xmlNode
->node
->doc
;
1586 if (old_doc
!= get_doc(This
))
1587 refcount
= xmlnode_get_inst_cnt(xmlNode
);
1589 /* old root is still orphaned by its document, update refcount from new root */
1590 if (refcount
) xmldoc_add_refs(get_doc(This
), refcount
);
1591 oldRoot
= xmlDocSetRootElement( get_doc(This
), xmlNode
->node
);
1592 if (refcount
) xmldoc_release_refs(old_doc
, refcount
);
1593 IXMLDOMNode_Release( elementNode
);
1596 xmldoc_add_orphan(oldRoot
->doc
, oldRoot
);
1602 static HRESULT WINAPI
domdoc_createElement(
1603 IXMLDOMDocument3
*iface
,
1605 IXMLDOMElement
** element
)
1607 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1612 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(tagname
), element
);
1614 if (!element
|| !tagname
) return E_INVALIDARG
;
1616 V_VT(&type
) = VT_I1
;
1617 V_I1(&type
) = NODE_ELEMENT
;
1619 hr
= IXMLDOMDocument3_createNode(iface
, type
, tagname
, NULL
, &node
);
1622 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMElement
, (void**)element
);
1623 IXMLDOMNode_Release(node
);
1630 static HRESULT WINAPI
domdoc_createDocumentFragment(
1631 IXMLDOMDocument3
*iface
,
1632 IXMLDOMDocumentFragment
** frag
)
1634 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1639 TRACE("(%p)->(%p)\n", This
, frag
);
1641 if (!frag
) return E_INVALIDARG
;
1645 V_VT(&type
) = VT_I1
;
1646 V_I1(&type
) = NODE_DOCUMENT_FRAGMENT
;
1648 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1651 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentFragment
, (void**)frag
);
1652 IXMLDOMNode_Release(node
);
1659 static HRESULT WINAPI
domdoc_createTextNode(
1660 IXMLDOMDocument3
*iface
,
1662 IXMLDOMText
** text
)
1664 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1669 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), text
);
1671 if (!text
) return E_INVALIDARG
;
1675 V_VT(&type
) = VT_I1
;
1676 V_I1(&type
) = NODE_TEXT
;
1678 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1681 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMText
, (void**)text
);
1682 IXMLDOMNode_Release(node
);
1683 hr
= IXMLDOMText_put_data(*text
, data
);
1690 static HRESULT WINAPI
domdoc_createComment(
1691 IXMLDOMDocument3
*iface
,
1693 IXMLDOMComment
** comment
)
1695 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1700 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), comment
);
1702 if (!comment
) return E_INVALIDARG
;
1706 V_VT(&type
) = VT_I1
;
1707 V_I1(&type
) = NODE_COMMENT
;
1709 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1712 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMComment
, (void**)comment
);
1713 IXMLDOMNode_Release(node
);
1714 hr
= IXMLDOMComment_put_data(*comment
, data
);
1721 static HRESULT WINAPI
domdoc_createCDATASection(
1722 IXMLDOMDocument3
*iface
,
1724 IXMLDOMCDATASection
** cdata
)
1726 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1731 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), cdata
);
1733 if (!cdata
) return E_INVALIDARG
;
1737 V_VT(&type
) = VT_I1
;
1738 V_I1(&type
) = NODE_CDATA_SECTION
;
1740 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1743 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMCDATASection
, (void**)cdata
);
1744 IXMLDOMNode_Release(node
);
1745 hr
= IXMLDOMCDATASection_put_data(*cdata
, data
);
1752 static HRESULT WINAPI
domdoc_createProcessingInstruction(
1753 IXMLDOMDocument3
*iface
,
1756 IXMLDOMProcessingInstruction
** pi
)
1758 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1763 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_w(target
), debugstr_w(data
), pi
);
1765 if (!pi
) return E_INVALIDARG
;
1769 V_VT(&type
) = VT_I1
;
1770 V_I1(&type
) = NODE_PROCESSING_INSTRUCTION
;
1772 hr
= IXMLDOMDocument3_createNode(iface
, type
, target
, NULL
, &node
);
1777 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1778 node_obj
= get_node_obj(node
);
1779 hr
= node_set_content(node_obj
, data
);
1781 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMProcessingInstruction
, (void**)pi
);
1782 IXMLDOMNode_Release(node
);
1789 static HRESULT WINAPI
domdoc_createAttribute(
1790 IXMLDOMDocument3
*iface
,
1792 IXMLDOMAttribute
** attribute
)
1794 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1799 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), attribute
);
1801 if (!attribute
|| !name
) return E_INVALIDARG
;
1803 V_VT(&type
) = VT_I1
;
1804 V_I1(&type
) = NODE_ATTRIBUTE
;
1806 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1809 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMAttribute
, (void**)attribute
);
1810 IXMLDOMNode_Release(node
);
1817 static HRESULT WINAPI
domdoc_createEntityReference(
1818 IXMLDOMDocument3
*iface
,
1820 IXMLDOMEntityReference
** entityref
)
1822 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1827 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), entityref
);
1829 if (!entityref
) return E_INVALIDARG
;
1833 V_VT(&type
) = VT_I1
;
1834 V_I1(&type
) = NODE_ENTITY_REFERENCE
;
1836 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1839 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMEntityReference
, (void**)entityref
);
1840 IXMLDOMNode_Release(node
);
1846 xmlChar
* tagName_to_XPath(const BSTR tagName
)
1848 xmlChar
*query
, *tmp
;
1849 static const xmlChar everything
[] = "/descendant::node()";
1850 static const xmlChar mod_pre
[] = "*[local-name()='";
1851 static const xmlChar mod_post
[] = "']";
1852 static const xmlChar prefix
[] = "descendant::";
1853 const WCHAR
*tokBegin
, *tokEnd
;
1856 /* Special case - empty tagname - means select all nodes,
1857 except document itself. */
1859 return xmlStrdup(everything
);
1861 query
= xmlStrdup(prefix
);
1864 while (tokBegin
&& *tokBegin
)
1869 query
= xmlStrcat(query
, BAD_CAST
"/");
1873 query
= xmlStrcat(query
, BAD_CAST
"*");
1877 query
= xmlStrcat(query
, mod_pre
);
1879 while (*tokEnd
&& *tokEnd
!= '/')
1881 len
= WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, NULL
, 0, NULL
, NULL
);
1882 tmp
= xmlMalloc(len
);
1883 WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, (char*)tmp
, len
, NULL
, NULL
);
1884 query
= xmlStrncat(query
, tmp
, len
);
1887 query
= xmlStrcat(query
, mod_post
);
1894 static HRESULT WINAPI
domdoc_getElementsByTagName(
1895 IXMLDOMDocument3
*iface
,
1897 IXMLDOMNodeList
** resultList
)
1899 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1904 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(tagName
), resultList
);
1906 if (!tagName
|| !resultList
) return E_INVALIDARG
;
1908 XPath
= This
->properties
->XPath
;
1909 This
->properties
->XPath
= TRUE
;
1910 query
= tagName_to_XPath(tagName
);
1911 hr
= create_selection((xmlNodePtr
)get_doc(This
), query
, resultList
);
1913 This
->properties
->XPath
= XPath
;
1918 static HRESULT
get_node_type(VARIANT Type
, DOMNodeType
* type
)
1924 hr
= VariantChangeType(&tmp
, &Type
, 0, VT_I4
);
1926 return E_INVALIDARG
;
1933 static HRESULT WINAPI
domdoc_createNode(
1934 IXMLDOMDocument3
*iface
,
1938 IXMLDOMNode
** node
)
1940 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1941 DOMNodeType node_type
;
1943 xmlChar
*xml_name
, *href
;
1946 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_variant(&Type
), debugstr_w(name
), debugstr_w(namespaceURI
), node
);
1948 if(!node
) return E_INVALIDARG
;
1950 hr
= get_node_type(Type
, &node_type
);
1951 if(FAILED(hr
)) return hr
;
1953 TRACE("node_type %d\n", node_type
);
1955 /* exit earlier for types that need name */
1959 case NODE_ATTRIBUTE
:
1960 case NODE_ENTITY_REFERENCE
:
1961 case NODE_PROCESSING_INSTRUCTION
:
1962 if (!name
|| *name
== 0) return E_FAIL
;
1968 xml_name
= xmlchar_from_wchar(name
);
1969 /* prevent empty href to be allocated */
1970 href
= namespaceURI
? xmlchar_from_wchar(namespaceURI
) : NULL
;
1976 xmlChar
*local
, *prefix
;
1978 local
= xmlSplitQName2(xml_name
, &prefix
);
1980 xmlnode
= xmlNewDocNode(get_doc(This
), NULL
, local
? local
: xml_name
, NULL
);
1982 /* allow to create default namespace xmlns= */
1983 if (local
|| (href
&& *href
))
1985 xmlNsPtr ns
= xmlNewNs(xmlnode
, href
, prefix
);
1986 xmlSetNs(xmlnode
, ns
);
1994 case NODE_ATTRIBUTE
:
1996 xmlChar
*local
, *prefix
;
1998 local
= xmlSplitQName2(xml_name
, &prefix
);
2000 xmlnode
= (xmlNodePtr
)xmlNewDocProp(get_doc(This
), local
? local
: xml_name
, NULL
);
2002 if (local
|| (href
&& *href
))
2004 /* we need a floating namespace here, it can't be created linked to attribute from
2006 xmlNsPtr ns
= xmlNewNs(NULL
, href
, prefix
);
2007 xmlSetNs(xmlnode
, ns
);
2016 xmlnode
= (xmlNodePtr
)xmlNewDocText(get_doc(This
), NULL
);
2018 case NODE_CDATA_SECTION
:
2019 xmlnode
= xmlNewCDataBlock(get_doc(This
), NULL
, 0);
2021 case NODE_ENTITY_REFERENCE
:
2022 xmlnode
= xmlNewReference(get_doc(This
), xml_name
);
2024 case NODE_PROCESSING_INSTRUCTION
:
2025 #ifdef HAVE_XMLNEWDOCPI
2026 xmlnode
= xmlNewDocPI(get_doc(This
), xml_name
, NULL
);
2028 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2033 xmlnode
= xmlNewDocComment(get_doc(This
), NULL
);
2035 case NODE_DOCUMENT_FRAGMENT
:
2036 xmlnode
= xmlNewDocFragment(get_doc(This
));
2038 /* unsupported types */
2040 case NODE_DOCUMENT_TYPE
:
2043 heap_free(xml_name
);
2044 return E_INVALIDARG
;
2046 FIXME("unhandled node type %d\n", node_type
);
2051 *node
= create_node(xmlnode
);
2052 heap_free(xml_name
);
2057 TRACE("created node (%d, %p, %p)\n", node_type
, *node
, xmlnode
);
2058 xmldoc_add_orphan(xmlnode
->doc
, xmlnode
);
2065 static HRESULT WINAPI
domdoc_nodeFromID(
2066 IXMLDOMDocument3
*iface
,
2068 IXMLDOMNode
** node
)
2070 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2071 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(idString
), node
);
2075 static HRESULT
domdoc_onDataAvailable(void *obj
, char *ptr
, DWORD len
)
2080 xmldoc
= doparse(This
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
2082 xmldoc
->_private
= create_priv();
2083 return attach_xmldoc(This
, xmldoc
);
2089 static HRESULT
domdoc_load_moniker(domdoc
*This
, IMoniker
*mon
)
2094 hr
= bind_url(mon
, domdoc_onDataAvailable
, This
, &bsc
);
2098 return detach_bsc(bsc
);
2101 static HRESULT WINAPI
domdoc_load(
2102 IXMLDOMDocument3
*iface
,
2104 VARIANT_BOOL
* isSuccessful
)
2106 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2107 LPWSTR filename
= NULL
;
2108 HRESULT hr
= S_FALSE
;
2111 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&source
));
2115 *isSuccessful
= VARIANT_FALSE
;
2117 assert( &This
->node
);
2119 switch( V_VT(&source
) )
2122 filename
= V_BSTR(&source
);
2124 case VT_BSTR
|VT_BYREF
:
2125 if (!V_BSTRREF(&source
)) return E_INVALIDARG
;
2126 filename
= *V_BSTRREF(&source
);
2128 case VT_ARRAY
|VT_UI1
:
2130 SAFEARRAY
*psa
= V_ARRAY(&source
);
2133 UINT dim
= SafeArrayGetDim(psa
);
2138 ERR("SAFEARRAY == NULL\n");
2139 hr
= This
->error
= E_INVALIDARG
;
2142 /* Only takes UTF-8 strings.
2143 * NOT NULL-terminated. */
2144 SafeArrayAccessData(psa
, (void**)&str
);
2145 SafeArrayGetUBound(psa
, 1, &len
);
2147 if ((xmldoc
= doparse(This
, str
, ++len
, XML_CHAR_ENCODING_UTF8
)))
2149 hr
= This
->error
= S_OK
;
2150 *isSuccessful
= VARIANT_TRUE
;
2151 TRACE("parsed document %p\n", xmldoc
);
2155 This
->error
= E_FAIL
;
2156 TRACE("failed to parse document\n");
2159 SafeArrayUnaccessData(psa
);
2163 xmldoc
->_private
= create_priv();
2164 return attach_xmldoc(This
, xmldoc
);
2168 FIXME("unhandled SAFEARRAY dim: %d\n", dim
);
2169 hr
= This
->error
= E_NOTIMPL
;
2175 ISequentialStream
*stream
= NULL
;
2176 IXMLDOMDocument3
*newdoc
= NULL
;
2178 if (!V_UNKNOWN(&source
)) return E_INVALIDARG
;
2180 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IXMLDOMDocument3
, (void**)&newdoc
);
2185 domdoc
*newDoc
= impl_from_IXMLDOMDocument3( newdoc
);
2187 xmldoc
= xmlCopyDoc(get_doc(newDoc
), 1);
2188 xmldoc
->_private
= create_priv();
2189 hr
= attach_xmldoc(This
, xmldoc
);
2192 *isSuccessful
= VARIANT_TRUE
;
2198 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IStream
, (void**)&stream
);
2200 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_ISequentialStream
, (void**)&stream
);
2204 hr
= domdoc_load_from_stream(This
, stream
);
2206 *isSuccessful
= VARIANT_TRUE
;
2207 ISequentialStream_Release(stream
);
2211 FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr
, V_UNKNOWN(&source
)->lpVtbl
);
2215 FIXME("VT type not supported (%d)\n", V_VT(&source
));
2222 CoTaskMemFree(This
->properties
->url
);
2223 This
->properties
->url
= NULL
;
2225 hr
= create_moniker_from_url( filename
, &mon
);
2226 if ( SUCCEEDED(hr
) )
2228 hr
= domdoc_load_moniker( This
, mon
);
2230 IMoniker_GetDisplayName(mon
, NULL
, NULL
, &This
->properties
->url
);
2231 IMoniker_Release(mon
);
2235 This
->error
= E_FAIL
;
2238 hr
= This
->error
= S_OK
;
2239 *isSuccessful
= VARIANT_TRUE
;
2243 if(!filename
|| FAILED(hr
)) {
2244 xmldoc
= xmlNewDoc(NULL
);
2245 xmldoc
->_private
= create_priv();
2246 hr
= attach_xmldoc(This
, xmldoc
);
2251 TRACE("ret (%d)\n", hr
);
2257 static HRESULT WINAPI
domdoc_get_readyState(
2258 IXMLDOMDocument3
*iface
,
2261 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2262 FIXME("stub! (%p)->(%p)\n", This
, value
);
2265 return E_INVALIDARG
;
2267 *value
= READYSTATE_COMPLETE
;
2272 static HRESULT WINAPI
domdoc_get_parseError(
2273 IXMLDOMDocument3
*iface
,
2274 IXMLDOMParseError
** errorObj
)
2276 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2277 static const WCHAR err
[] = {'e','r','r','o','r',0};
2278 BSTR error_string
= NULL
;
2280 FIXME("(%p)->(%p): creating a dummy parseError\n", iface
, errorObj
);
2283 error_string
= SysAllocString(err
);
2285 *errorObj
= create_parseError(This
->error
, NULL
, error_string
, NULL
, 0, 0, 0);
2286 if(!*errorObj
) return E_OUTOFMEMORY
;
2291 static HRESULT WINAPI
domdoc_get_url(
2292 IXMLDOMDocument3
*iface
,
2295 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2297 TRACE("(%p)->(%p)\n", This
, url
);
2300 return E_INVALIDARG
;
2302 if (This
->properties
->url
)
2304 *url
= SysAllocString(This
->properties
->url
);
2306 return E_OUTOFMEMORY
;
2311 return return_null_bstr(url
);
2315 static HRESULT WINAPI
domdoc_get_async(
2316 IXMLDOMDocument3
*iface
,
2317 VARIANT_BOOL
* isAsync
)
2319 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2321 TRACE("(%p)->(%p: %d)\n", This
, isAsync
, This
->async
);
2322 *isAsync
= This
->async
;
2327 static HRESULT WINAPI
domdoc_put_async(
2328 IXMLDOMDocument3
*iface
,
2329 VARIANT_BOOL isAsync
)
2331 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2333 TRACE("(%p)->(%d)\n", This
, isAsync
);
2334 This
->async
= isAsync
;
2339 static HRESULT WINAPI
domdoc_abort(
2340 IXMLDOMDocument3
*iface
)
2342 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2343 FIXME("%p\n", This
);
2347 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2348 static HRESULT WINAPI
domdoc_loadXML(
2349 IXMLDOMDocument3
*iface
,
2351 VARIANT_BOOL
* isSuccessful
)
2353 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2354 xmlDocPtr xmldoc
= NULL
;
2355 HRESULT hr
= S_FALSE
, hr2
;
2357 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), isSuccessful
);
2359 assert ( &This
->node
);
2363 *isSuccessful
= VARIANT_FALSE
;
2369 /* skip leading spaces if needed */
2370 if (This
->properties
->version
== MSXML_DEFAULT
|| This
->properties
->version
== MSXML26
)
2371 while (*ptr
&& isspaceW(*ptr
)) ptr
++;
2373 xmldoc
= doparse(This
, (char*)ptr
, strlenW(ptr
)*sizeof(WCHAR
), XML_CHAR_ENCODING_UTF16LE
);
2376 This
->error
= E_FAIL
;
2377 TRACE("failed to parse document\n");
2381 hr
= This
->error
= S_OK
;
2382 *isSuccessful
= VARIANT_TRUE
;
2383 TRACE("parsed document %p\n", xmldoc
);
2389 xmldoc
= xmlNewDoc(NULL
);
2390 xmldoc
->_private
= create_priv();
2391 hr2
= attach_xmldoc(This
, xmldoc
);
2398 static int XMLCALL
domdoc_save_writecallback(void *ctx
, const char *buffer
, int len
)
2402 if(!WriteFile(ctx
, buffer
, len
, &written
, NULL
))
2404 WARN("write error\n");
2411 static int XMLCALL
domdoc_save_closecallback(void *ctx
)
2413 return CloseHandle(ctx
) ? 0 : -1;
2416 static int XMLCALL
domdoc_stream_save_writecallback(void *ctx
, const char *buffer
, int len
)
2421 hr
= IStream_Write((IStream
*)ctx
, buffer
, len
, &written
);
2422 TRACE("0x%08x %p %d %u\n", hr
, buffer
, len
, written
);
2425 WARN("stream write error: 0x%08x\n", hr
);
2432 static int XMLCALL
domdoc_stream_save_closecallback(void *ctx
)
2434 IStream_Release((IStream
*)ctx
);
2438 static HRESULT WINAPI
domdoc_save(
2439 IXMLDOMDocument3
*iface
,
2440 VARIANT destination
)
2442 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2443 xmlSaveCtxtPtr ctx
= NULL
;
2447 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&destination
));
2449 switch (V_VT(&destination
))
2453 IUnknown
*pUnk
= V_UNKNOWN(&destination
);
2454 IXMLDOMDocument3
*document
;
2457 ret
= IUnknown_QueryInterface(pUnk
, &IID_IXMLDOMDocument3
, (void**)&document
);
2460 VARIANT_BOOL success
;
2463 ret
= IXMLDOMDocument3_get_xml(iface
, &xml
);
2466 ret
= IXMLDOMDocument3_loadXML(document
, xml
, &success
);
2470 IXMLDOMDocument3_Release(document
);
2474 ret
= IUnknown_QueryInterface(pUnk
, &IID_IStream
, (void**)&stream
);
2477 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2478 ctx
= xmlSaveToIO(domdoc_stream_save_writecallback
,
2479 domdoc_stream_save_closecallback
, stream
, NULL
, options
);
2483 IStream_Release(stream
);
2491 case VT_BSTR
| VT_BYREF
:
2493 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2495 /* save with file path */
2496 HANDLE handle
= CreateFileW( (V_VT(&destination
) & VT_BYREF
)? *V_BSTRREF(&destination
) : V_BSTR(&destination
),
2497 GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2498 if( handle
== INVALID_HANDLE_VALUE
)
2500 WARN("failed to create file\n");
2504 /* disable top XML declaration */
2505 ctx
= xmlSaveToIO(domdoc_save_writecallback
, domdoc_save_closecallback
,
2506 handle
, NULL
, options
);
2509 CloseHandle(handle
);
2516 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination
));
2520 xmldecl
= xmldoc_unlink_xmldecl(get_doc(This
));
2521 if (xmlSaveDoc(ctx
, get_doc(This
)) == -1) ret
= S_FALSE
;
2522 xmldoc_link_xmldecl(get_doc(This
), xmldecl
);
2524 /* will release resources through close callback */
2530 static HRESULT WINAPI
domdoc_get_validateOnParse(
2531 IXMLDOMDocument3
*iface
,
2532 VARIANT_BOOL
* isValidating
)
2534 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2535 TRACE("(%p)->(%p: %d)\n", This
, isValidating
, This
->validating
);
2536 *isValidating
= This
->validating
;
2541 static HRESULT WINAPI
domdoc_put_validateOnParse(
2542 IXMLDOMDocument3
*iface
,
2543 VARIANT_BOOL isValidating
)
2545 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2546 TRACE("(%p)->(%d)\n", This
, isValidating
);
2547 This
->validating
= isValidating
;
2552 static HRESULT WINAPI
domdoc_get_resolveExternals(
2553 IXMLDOMDocument3
*iface
,
2554 VARIANT_BOOL
* isResolving
)
2556 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2557 TRACE("(%p)->(%p: %d)\n", This
, isResolving
, This
->resolving
);
2558 *isResolving
= This
->resolving
;
2563 static HRESULT WINAPI
domdoc_put_resolveExternals(
2564 IXMLDOMDocument3
*iface
,
2565 VARIANT_BOOL isResolving
)
2567 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2568 TRACE("(%p)->(%d)\n", This
, isResolving
);
2569 This
->resolving
= isResolving
;
2574 static HRESULT WINAPI
domdoc_get_preserveWhiteSpace(
2575 IXMLDOMDocument3
*iface
,
2576 VARIANT_BOOL
* isPreserving
)
2578 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2579 TRACE("(%p)->(%p: %d)\n", This
, isPreserving
, This
->properties
->preserving
);
2580 *isPreserving
= This
->properties
->preserving
;
2585 static HRESULT WINAPI
domdoc_put_preserveWhiteSpace(
2586 IXMLDOMDocument3
*iface
,
2587 VARIANT_BOOL isPreserving
)
2589 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2590 TRACE("(%p)->(%d)\n", This
, isPreserving
);
2591 This
->properties
->preserving
= isPreserving
;
2596 static HRESULT WINAPI
domdoc_put_onreadystatechange(
2597 IXMLDOMDocument3
*iface
,
2600 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2602 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&event
));
2603 return set_doc_event(This
, EVENTID_READYSTATECHANGE
, &event
);
2607 static HRESULT WINAPI
domdoc_put_onDataAvailable(IXMLDOMDocument3
*iface
, VARIANT sink
)
2609 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2610 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2614 static HRESULT WINAPI
domdoc_put_onTransformNode(IXMLDOMDocument3
*iface
, VARIANT sink
)
2616 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2617 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2621 static HRESULT WINAPI
domdoc_get_namespaces(
2622 IXMLDOMDocument3
* iface
,
2623 IXMLDOMSchemaCollection
** collection
)
2625 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2628 FIXME("(%p)->(%p): semi-stub\n", This
, collection
);
2630 if (!collection
) return E_POINTER
;
2632 if (!This
->namespaces
)
2634 hr
= SchemaCache_create(This
->properties
->version
, (void**)&This
->namespaces
);
2635 if (hr
!= S_OK
) return hr
;
2637 hr
= cache_from_doc_ns(This
->namespaces
, &This
->node
);
2639 release_namespaces(This
);
2642 if (This
->namespaces
)
2643 return IXMLDOMSchemaCollection2_QueryInterface(This
->namespaces
,
2644 &IID_IXMLDOMSchemaCollection
, (void**)collection
);
2649 static HRESULT WINAPI
domdoc_get_schemas(
2650 IXMLDOMDocument3
* iface
,
2653 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2654 IXMLDOMSchemaCollection2
* cur_schema
= This
->properties
->schemaCache
;
2655 HRESULT hr
= S_FALSE
;
2657 TRACE("(%p)->(%p)\n", This
, schema
);
2659 V_VT(schema
) = VT_NULL
;
2660 /* just to reset pointer part, cause that's what application is expected to use */
2661 V_DISPATCH(schema
) = NULL
;
2665 hr
= IXMLDOMSchemaCollection2_QueryInterface(cur_schema
, &IID_IDispatch
, (void**)&V_DISPATCH(schema
));
2667 V_VT(schema
) = VT_DISPATCH
;
2672 static HRESULT WINAPI
domdoc_putref_schemas(
2673 IXMLDOMDocument3
* iface
,
2676 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2677 HRESULT hr
= E_FAIL
;
2678 IXMLDOMSchemaCollection2
* new_schema
= NULL
;
2680 FIXME("(%p)->(%s): semi-stub\n", This
, debugstr_variant(&schema
));
2681 switch(V_VT(&schema
))
2684 if (V_UNKNOWN(&schema
))
2686 hr
= IUnknown_QueryInterface(V_UNKNOWN(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2691 if (V_DISPATCH(&schema
))
2693 hr
= IDispatch_QueryInterface(V_DISPATCH(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2703 WARN("Can't get schema from vt %x\n", V_VT(&schema
));
2708 IXMLDOMSchemaCollection2
* old_schema
= InterlockedExchangePointer((void**)&This
->properties
->schemaCache
, new_schema
);
2709 if(old_schema
) IXMLDOMSchemaCollection2_Release(old_schema
);
2715 static inline BOOL
is_wellformed(xmlDocPtr doc
)
2717 #ifdef HAVE_XMLDOC_PROPERTIES
2718 return doc
->properties
& XML_DOC_WELLFORMED
;
2720 /* Not a full check, but catches the worst violations */
2724 for (child
= doc
->children
; child
!= NULL
; child
= child
->next
)
2726 switch (child
->type
)
2728 case XML_ELEMENT_NODE
:
2733 case XML_CDATA_SECTION_NODE
:
2745 static void LIBXML2_LOG_CALLBACK
validate_error(void* ctx
, char const* msg
, ...)
2749 LIBXML2_CALLBACK_ERR(domdoc_validateNode
, msg
, ap
);
2753 static void LIBXML2_LOG_CALLBACK
validate_warning(void* ctx
, char const* msg
, ...)
2757 LIBXML2_CALLBACK_WARN(domdoc_validateNode
, msg
, ap
);
2761 static HRESULT WINAPI
domdoc_validateNode(
2762 IXMLDOMDocument3
* iface
,
2764 IXMLDOMParseError
** err
)
2766 domdoc
* This
= impl_from_IXMLDOMDocument3(iface
);
2767 LONG state
, err_code
= 0;
2771 TRACE("(%p)->(%p, %p)\n", This
, node
, err
);
2772 IXMLDOMDocument3_get_readyState(iface
, &state
);
2773 if (state
!= READYSTATE_COMPLETE
)
2776 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2783 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2787 if (!get_node_obj(node
)->node
|| get_node_obj(node
)->node
->doc
!= get_doc(This
))
2790 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2794 if (!is_wellformed(get_doc(This
)))
2796 ERR("doc not well-formed\n");
2798 *err
= create_parseError(E_XML_NOTWF
, NULL
, NULL
, NULL
, 0, 0, 0);
2802 /* DTD validation */
2803 if (get_doc(This
)->intSubset
|| get_doc(This
)->extSubset
)
2805 xmlValidCtxtPtr vctx
= xmlNewValidCtxt();
2806 vctx
->error
= validate_error
;
2807 vctx
->warning
= validate_warning
;
2810 if (!((node
== (IXMLDOMNode
*)iface
)?
2811 xmlValidateDocument(vctx
, get_doc(This
)) :
2812 xmlValidateElement(vctx
, get_doc(This
), get_node_obj(node
)->node
)))
2814 /* TODO: get a real error code here */
2815 TRACE("DTD validation failed\n");
2816 err_code
= E_XML_INVALID
;
2819 xmlFreeValidCtxt(vctx
);
2822 /* Schema validation */
2823 if (hr
== S_OK
&& This
->properties
->schemaCache
!= NULL
)
2826 hr
= SchemaCache_validate_tree(This
->properties
->schemaCache
, get_node_obj(node
)->node
);
2830 /* TODO: get a real error code here */
2833 TRACE("schema validation succeeded\n");
2837 ERR("schema validation failed\n");
2838 err_code
= E_XML_INVALID
;
2843 /* not really OK, just didn't find a schema for the ns */
2850 ERR("no DTD or schema found\n");
2851 err_code
= E_XML_NODTD
;
2856 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2861 static HRESULT WINAPI
domdoc_validate(
2862 IXMLDOMDocument3
* iface
,
2863 IXMLDOMParseError
** err
)
2865 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2866 TRACE("(%p)->(%p)\n", This
, err
);
2867 return IXMLDOMDocument3_validateNode(iface
, (IXMLDOMNode
*)iface
, err
);
2870 static HRESULT WINAPI
domdoc_setProperty(
2871 IXMLDOMDocument3
* iface
,
2875 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2877 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(p
), debugstr_variant(&value
));
2879 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
2885 V_VT(&varStr
) = VT_EMPTY
;
2886 if (V_VT(&value
) != VT_BSTR
)
2888 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2890 bstr
= V_BSTR(&varStr
);
2893 bstr
= V_BSTR(&value
);
2896 if (lstrcmpiW(bstr
, PropValueXPathW
) == 0)
2897 This
->properties
->XPath
= TRUE
;
2898 else if (lstrcmpiW(bstr
, PropValueXSLPatternW
) == 0)
2899 This
->properties
->XPath
= FALSE
;
2903 VariantClear(&varStr
);
2906 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
2908 xmlChar
*nsStr
= (xmlChar
*)This
->properties
->selectNsStr
;
2909 struct list
*pNsList
;
2914 V_VT(&varStr
) = VT_EMPTY
;
2915 if (V_VT(&value
) != VT_BSTR
)
2917 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2919 bstr
= V_BSTR(&varStr
);
2922 bstr
= V_BSTR(&value
);
2926 pNsList
= &(This
->properties
->selectNsList
);
2927 clear_selectNsList(pNsList
);
2929 nsStr
= xmlchar_from_wchar(bstr
);
2931 TRACE("property value: \"%s\"\n", debugstr_w(bstr
));
2933 This
->properties
->selectNsStr
= nsStr
;
2934 This
->properties
->selectNsStr_len
= xmlStrlen(nsStr
);
2937 xmlChar
*pTokBegin
, *pTokEnd
, *pTokInner
;
2938 select_ns_entry
* ns_entry
= NULL
;
2939 xmlXPathContextPtr ctx
;
2941 ctx
= xmlXPathNewContext(This
->node
.node
->doc
);
2944 /* skip leading spaces */
2945 while (*pTokBegin
== ' ' || *pTokBegin
== '\n' ||
2946 *pTokBegin
== '\t' || *pTokBegin
== '\r')
2949 for (; *pTokBegin
; pTokBegin
= pTokEnd
)
2952 memset(ns_entry
, 0, sizeof(select_ns_entry
));
2954 ns_entry
= heap_alloc_zero(sizeof(select_ns_entry
));
2956 while (*pTokBegin
== ' ')
2958 pTokEnd
= pTokBegin
;
2959 while (*pTokEnd
!= ' ' && *pTokEnd
!= 0)
2962 /* so it failed to advance which means we've got some trailing spaces */
2963 if (pTokEnd
== pTokBegin
) break;
2965 if (xmlStrncmp(pTokBegin
, (xmlChar
const*)"xmlns", 5) != 0)
2968 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2969 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2974 if (*pTokBegin
== '=')
2976 /*valid for XSLPattern?*/
2977 FIXME("Setting default xmlns not supported - skipping.\n");
2980 else if (*pTokBegin
== ':')
2982 ns_entry
->prefix
= ++pTokBegin
;
2983 for (pTokInner
= pTokBegin
; pTokInner
!= pTokEnd
&& *pTokInner
!= '='; ++pTokInner
)
2986 if (pTokInner
== pTokEnd
)
2989 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2990 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2994 ns_entry
->prefix_end
= *pTokInner
;
2998 if (pTokEnd
-pTokInner
> 1 &&
2999 ((*pTokInner
== '\'' && *(pTokEnd
-1) == '\'') ||
3000 (*pTokInner
== '"' && *(pTokEnd
-1) == '"')))
3002 ns_entry
->href
= ++pTokInner
;
3003 ns_entry
->href_end
= *(pTokEnd
-1);
3005 list_add_tail(pNsList
, &ns_entry
->entry
);
3006 /*let libxml figure out if they're valid from here ;)*/
3007 if (xmlXPathRegisterNs(ctx
, ns_entry
->prefix
, ns_entry
->href
) != 0)
3016 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3017 debugstr_w(bstr
), debugstr_an((const char*)pTokInner
, pTokEnd
-pTokInner
));
3018 list_add_tail(pNsList
, &ns_entry
->entry
);
3031 heap_free(ns_entry
);
3032 xmlXPathFreeContext(ctx
);
3035 VariantClear(&varStr
);
3038 else if (lstrcmpiW(p
, PropertyProhibitDTDW
) == 0 ||
3039 lstrcmpiW(p
, PropertyNewParserW
) == 0 ||
3040 lstrcmpiW(p
, PropertyResolveExternalsW
) == 0)
3043 FIXME("Ignoring property %s, value %s\n", debugstr_w(p
), debugstr_variant(&value
));
3047 FIXME("Unknown property %s\n", debugstr_w(p
));
3051 static HRESULT WINAPI
domdoc_getProperty(
3052 IXMLDOMDocument3
* iface
,
3056 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3058 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
3061 return E_INVALIDARG
;
3063 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
3065 V_VT(var
) = VT_BSTR
;
3066 V_BSTR(var
) = This
->properties
->XPath
?
3067 SysAllocString(PropValueXPathW
) :
3068 SysAllocString(PropValueXSLPatternW
);
3069 return V_BSTR(var
) ? S_OK
: E_OUTOFMEMORY
;
3071 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3074 BSTR rebuiltStr
, cur
;
3075 const xmlChar
*nsStr
;
3076 struct list
*pNsList
;
3077 select_ns_entry
* pNsEntry
;
3079 V_VT(var
) = VT_BSTR
;
3080 nsStr
= This
->properties
->selectNsStr
;
3081 pNsList
= &This
->properties
->selectNsList
;
3082 lenA
= This
->properties
->selectNsStr_len
;
3083 lenW
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, NULL
, 0);
3084 rebuiltStr
= heap_alloc(lenW
*sizeof(WCHAR
));
3085 MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, rebuiltStr
, lenW
);
3087 /* this is fine because all of the chars that end tokens are ASCII*/
3088 LIST_FOR_EACH_ENTRY(pNsEntry
, pNsList
, select_ns_entry
, entry
)
3090 while (*cur
!= 0) ++cur
;
3091 if (pNsEntry
->prefix_end
)
3093 *cur
= pNsEntry
->prefix_end
;
3094 while (*cur
!= 0) ++cur
;
3097 if (pNsEntry
->href_end
)
3099 *cur
= pNsEntry
->href_end
;
3102 V_BSTR(var
) = SysAllocString(rebuiltStr
);
3103 heap_free(rebuiltStr
);
3107 FIXME("Unknown property %s\n", debugstr_w(p
));
3111 static HRESULT WINAPI
domdoc_importNode(
3112 IXMLDOMDocument3
* iface
,
3115 IXMLDOMNode
** clone
)
3117 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3118 FIXME("(%p)->(%p %d %p): stub\n", This
, node
, deep
, clone
);
3122 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl
=
3124 domdoc_QueryInterface
,
3127 domdoc_GetTypeInfoCount
,
3129 domdoc_GetIDsOfNames
,
3131 domdoc_get_nodeName
,
3132 domdoc_get_nodeValue
,
3133 domdoc_put_nodeValue
,
3134 domdoc_get_nodeType
,
3135 domdoc_get_parentNode
,
3136 domdoc_get_childNodes
,
3137 domdoc_get_firstChild
,
3138 domdoc_get_lastChild
,
3139 domdoc_get_previousSibling
,
3140 domdoc_get_nextSibling
,
3141 domdoc_get_attributes
,
3142 domdoc_insertBefore
,
3143 domdoc_replaceChild
,
3146 domdoc_hasChildNodes
,
3147 domdoc_get_ownerDocument
,
3149 domdoc_get_nodeTypeString
,
3152 domdoc_get_specified
,
3153 domdoc_get_definition
,
3154 domdoc_get_nodeTypedValue
,
3155 domdoc_put_nodeTypedValue
,
3156 domdoc_get_dataType
,
3157 domdoc_put_dataType
,
3159 domdoc_transformNode
,
3161 domdoc_selectSingleNode
,
3163 domdoc_get_namespaceURI
,
3165 domdoc_get_baseName
,
3166 domdoc_transformNodeToObject
,
3168 domdoc_get_implementation
,
3169 domdoc_get_documentElement
,
3170 domdoc_put_documentElement
,
3171 domdoc_createElement
,
3172 domdoc_createDocumentFragment
,
3173 domdoc_createTextNode
,
3174 domdoc_createComment
,
3175 domdoc_createCDATASection
,
3176 domdoc_createProcessingInstruction
,
3177 domdoc_createAttribute
,
3178 domdoc_createEntityReference
,
3179 domdoc_getElementsByTagName
,
3183 domdoc_get_readyState
,
3184 domdoc_get_parseError
,
3191 domdoc_get_validateOnParse
,
3192 domdoc_put_validateOnParse
,
3193 domdoc_get_resolveExternals
,
3194 domdoc_put_resolveExternals
,
3195 domdoc_get_preserveWhiteSpace
,
3196 domdoc_put_preserveWhiteSpace
,
3197 domdoc_put_onreadystatechange
,
3198 domdoc_put_onDataAvailable
,
3199 domdoc_put_onTransformNode
,
3200 domdoc_get_namespaces
,
3202 domdoc_putref_schemas
,
3206 domdoc_validateNode
,
3210 /* IConnectionPointContainer */
3211 static HRESULT WINAPI
ConnectionPointContainer_QueryInterface(IConnectionPointContainer
*iface
,
3212 REFIID riid
, void **ppv
)
3214 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3215 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3218 static ULONG WINAPI
ConnectionPointContainer_AddRef(IConnectionPointContainer
*iface
)
3220 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3221 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3224 static ULONG WINAPI
ConnectionPointContainer_Release(IConnectionPointContainer
*iface
)
3226 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3227 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3230 static HRESULT WINAPI
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer
*iface
,
3231 IEnumConnectionPoints
**ppEnum
)
3233 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3234 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3238 static HRESULT WINAPI
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer
*iface
,
3239 REFIID riid
, IConnectionPoint
**cp
)
3241 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3242 ConnectionPoint
*iter
;
3244 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), cp
);
3248 for(iter
= This
->cp_list
; iter
; iter
= iter
->next
)
3250 if (IsEqualGUID(iter
->iid
, riid
))
3251 *cp
= &iter
->IConnectionPoint_iface
;
3256 IConnectionPoint_AddRef(*cp
);
3260 FIXME("unsupported riid %s\n", debugstr_guid(riid
));
3261 return CONNECT_E_NOCONNECTION
;
3265 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl
=
3267 ConnectionPointContainer_QueryInterface
,
3268 ConnectionPointContainer_AddRef
,
3269 ConnectionPointContainer_Release
,
3270 ConnectionPointContainer_EnumConnectionPoints
,
3271 ConnectionPointContainer_FindConnectionPoint
3274 /* IConnectionPoint */
3275 static HRESULT WINAPI
ConnectionPoint_QueryInterface(IConnectionPoint
*iface
,
3276 REFIID riid
, void **ppv
)
3278 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3280 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
3284 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
3285 IsEqualGUID(&IID_IConnectionPoint
, riid
))
3292 IConnectionPoint_AddRef(iface
);
3296 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
3297 return E_NOINTERFACE
;
3300 static ULONG WINAPI
ConnectionPoint_AddRef(IConnectionPoint
*iface
)
3302 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3303 return IConnectionPointContainer_AddRef(This
->container
);
3306 static ULONG WINAPI
ConnectionPoint_Release(IConnectionPoint
*iface
)
3308 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3309 return IConnectionPointContainer_Release(This
->container
);
3312 static HRESULT WINAPI
ConnectionPoint_GetConnectionInterface(IConnectionPoint
*iface
, IID
*iid
)
3314 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3316 TRACE("(%p)->(%p)\n", This
, iid
);
3318 if (!iid
) return E_POINTER
;
3324 static HRESULT WINAPI
ConnectionPoint_GetConnectionPointContainer(IConnectionPoint
*iface
,
3325 IConnectionPointContainer
**container
)
3327 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3329 TRACE("(%p)->(%p)\n", This
, container
);
3331 if (!container
) return E_POINTER
;
3333 *container
= This
->container
;
3334 IConnectionPointContainer_AddRef(*container
);
3338 static HRESULT WINAPI
ConnectionPoint_Advise(IConnectionPoint
*iface
, IUnknown
*unk_sink
,
3341 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3346 TRACE("(%p)->(%p %p)\n", This
, unk_sink
, cookie
);
3348 hr
= IUnknown_QueryInterface(unk_sink
, This
->iid
, (void**)&sink
);
3349 if(FAILED(hr
) && !IsEqualGUID(&IID_IPropertyNotifySink
, This
->iid
))
3350 hr
= IUnknown_QueryInterface(unk_sink
, &IID_IDispatch
, (void**)&sink
);
3352 return CONNECT_E_CANNOTCONNECT
;
3356 for (i
= 0; i
< This
->sinks_size
; i
++)
3357 if (!This
->sinks
[i
].unk
)
3360 if (i
== This
->sinks_size
)
3361 This
->sinks
= heap_realloc(This
->sinks
,(++This
->sinks_size
)*sizeof(*This
->sinks
));
3365 This
->sinks
= heap_alloc(sizeof(*This
->sinks
));
3366 This
->sinks_size
= 1;
3370 This
->sinks
[i
].unk
= sink
;
3377 static HRESULT WINAPI
ConnectionPoint_Unadvise(IConnectionPoint
*iface
, DWORD cookie
)
3379 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3381 TRACE("(%p)->(%d)\n", This
, cookie
);
3383 if (cookie
== 0 || cookie
> This
->sinks_size
|| !This
->sinks
[cookie
-1].unk
)
3384 return CONNECT_E_NOCONNECTION
;
3386 IUnknown_Release(This
->sinks
[cookie
-1].unk
);
3387 This
->sinks
[cookie
-1].unk
= NULL
;
3392 static HRESULT WINAPI
ConnectionPoint_EnumConnections(IConnectionPoint
*iface
,
3393 IEnumConnections
**ppEnum
)
3395 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3396 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3400 static const IConnectionPointVtbl ConnectionPointVtbl
=
3402 ConnectionPoint_QueryInterface
,
3403 ConnectionPoint_AddRef
,
3404 ConnectionPoint_Release
,
3405 ConnectionPoint_GetConnectionInterface
,
3406 ConnectionPoint_GetConnectionPointContainer
,
3407 ConnectionPoint_Advise
,
3408 ConnectionPoint_Unadvise
,
3409 ConnectionPoint_EnumConnections
3412 static void ConnectionPoint_Init(ConnectionPoint
*cp
, struct domdoc
*doc
, REFIID riid
)
3414 cp
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointVtbl
;
3420 cp
->next
= doc
->cp_list
;
3423 cp
->container
= &doc
->IConnectionPointContainer_iface
;
3426 /* domdoc implementation of IObjectWithSite */
3427 static HRESULT WINAPI
3428 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
3430 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3431 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObject
);
3434 static ULONG WINAPI
domdoc_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
3436 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3437 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3440 static ULONG WINAPI
domdoc_ObjectWithSite_Release( IObjectWithSite
* iface
)
3442 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3443 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3446 static HRESULT WINAPI
domdoc_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
3448 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3450 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
3455 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
3458 static HRESULT WINAPI
domdoc_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
3460 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3462 TRACE("(%p)->(%p)\n", iface
, punk
);
3468 IUnknown_Release( This
->site
);
3475 IUnknown_AddRef( punk
);
3478 IUnknown_Release( This
->site
);
3485 static const IObjectWithSiteVtbl domdocObjectSite
=
3487 domdoc_ObjectWithSite_QueryInterface
,
3488 domdoc_ObjectWithSite_AddRef
,
3489 domdoc_ObjectWithSite_Release
,
3490 domdoc_ObjectWithSite_SetSite
,
3491 domdoc_ObjectWithSite_GetSite
3494 static HRESULT WINAPI
domdoc_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
3496 domdoc
*This
= impl_from_IObjectSafety(iface
);
3497 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3500 static ULONG WINAPI
domdoc_Safety_AddRef(IObjectSafety
*iface
)
3502 domdoc
*This
= impl_from_IObjectSafety(iface
);
3503 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3506 static ULONG WINAPI
domdoc_Safety_Release(IObjectSafety
*iface
)
3508 domdoc
*This
= impl_from_IObjectSafety(iface
);
3509 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3512 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3514 static HRESULT WINAPI
domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3515 DWORD
*supported
, DWORD
*enabled
)
3517 domdoc
*This
= impl_from_IObjectSafety(iface
);
3519 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
3521 if(!supported
|| !enabled
) return E_POINTER
;
3523 *supported
= SAFETY_SUPPORTED_OPTIONS
;
3524 *enabled
= This
->safeopt
;
3529 static HRESULT WINAPI
domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3530 DWORD mask
, DWORD enabled
)
3532 domdoc
*This
= impl_from_IObjectSafety(iface
);
3533 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
3535 if ((mask
& ~SAFETY_SUPPORTED_OPTIONS
) != 0)
3538 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
3543 #undef SAFETY_SUPPORTED_OPTIONS
3545 static const IObjectSafetyVtbl domdocObjectSafetyVtbl
= {
3546 domdoc_Safety_QueryInterface
,
3547 domdoc_Safety_AddRef
,
3548 domdoc_Safety_Release
,
3549 domdoc_Safety_GetInterfaceSafetyOptions
,
3550 domdoc_Safety_SetInterfaceSafetyOptions
3553 static const tid_t domdoc_iface_tids
[] = {
3554 IXMLDOMDocument3_tid
,
3558 static dispex_static_data_t domdoc_dispex
= {
3560 IXMLDOMDocument3_tid
,
3565 HRESULT
get_domdoc_from_xmldoc(xmlDocPtr xmldoc
, IXMLDOMDocument3
**document
)
3569 doc
= heap_alloc( sizeof (*doc
) );
3571 return E_OUTOFMEMORY
;
3573 doc
->IXMLDOMDocument3_iface
.lpVtbl
= &XMLDOMDocument3Vtbl
;
3574 doc
->IPersistStreamInit_iface
.lpVtbl
= &xmldoc_IPersistStreamInit_VTable
;
3575 doc
->IObjectWithSite_iface
.lpVtbl
= &domdocObjectSite
;
3576 doc
->IObjectSafety_iface
.lpVtbl
= &domdocObjectSafetyVtbl
;
3577 doc
->IConnectionPointContainer_iface
.lpVtbl
= &ConnectionPointContainerVtbl
;
3579 doc
->async
= VARIANT_TRUE
;
3580 doc
->validating
= 0;
3582 doc
->properties
= properties_from_xmlDocPtr(xmldoc
);
3586 doc
->cp_list
= NULL
;
3587 doc
->namespaces
= NULL
;
3588 memset(doc
->events
, 0, sizeof(doc
->events
));
3590 /* events connection points */
3591 ConnectionPoint_Init(&doc
->cp_dispatch
, doc
, &IID_IDispatch
);
3592 ConnectionPoint_Init(&doc
->cp_propnotif
, doc
, &IID_IPropertyNotifySink
);
3593 ConnectionPoint_Init(&doc
->cp_domdocevents
, doc
, &DIID_XMLDOMDocumentEvents
);
3595 init_xmlnode(&doc
->node
, (xmlNodePtr
)xmldoc
, (IXMLDOMNode
*)&doc
->IXMLDOMDocument3_iface
,
3598 *document
= &doc
->IXMLDOMDocument3_iface
;
3600 TRACE("returning iface %p\n", *document
);
3604 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3609 TRACE("(%d, %p)\n", version
, ppObj
);
3611 xmldoc
= xmlNewDoc(NULL
);
3613 return E_OUTOFMEMORY
;
3615 xmldoc_init(xmldoc
, version
);
3617 hr
= get_domdoc_from_xmldoc(xmldoc
, (IXMLDOMDocument3
**)ppObj
);
3620 free_properties(properties_from_xmlDocPtr(xmldoc
));
3621 heap_free(xmldoc
->_private
);
3629 IUnknown
* create_domdoc( xmlNodePtr document
)
3634 TRACE("(%p)\n", document
);
3636 hr
= get_domdoc_from_xmldoc((xmlDocPtr
)document
, (IXMLDOMDocument3
**)&pObj
);
3645 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3647 MESSAGE("This program tried to use a DOMDocument object, but\n"
3648 "libxml2 support was not present at compile time.\n");