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 mod_pre
[] = "*[local-name()='";
1850 static const xmlChar mod_post
[] = "']";
1851 static const xmlChar prefix
[] = "descendant::";
1852 const WCHAR
*tokBegin
, *tokEnd
;
1855 query
= xmlStrdup(prefix
);
1858 while (tokBegin
&& *tokBegin
)
1863 query
= xmlStrcat(query
, BAD_CAST
"/");
1867 query
= xmlStrcat(query
, BAD_CAST
"*");
1871 query
= xmlStrcat(query
, mod_pre
);
1873 while (*tokEnd
&& *tokEnd
!= '/')
1875 len
= WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, NULL
, 0, NULL
, NULL
);
1876 tmp
= xmlMalloc(len
);
1877 WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, (char*)tmp
, len
, NULL
, NULL
);
1878 query
= xmlStrncat(query
, tmp
, len
);
1881 query
= xmlStrcat(query
, mod_post
);
1888 static HRESULT WINAPI
domdoc_getElementsByTagName(
1889 IXMLDOMDocument3
*iface
,
1891 IXMLDOMNodeList
** resultList
)
1893 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1898 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(tagName
), resultList
);
1900 if (!tagName
|| !resultList
) return E_INVALIDARG
;
1902 XPath
= This
->properties
->XPath
;
1903 This
->properties
->XPath
= TRUE
;
1904 query
= tagName_to_XPath(tagName
);
1905 hr
= create_selection((xmlNodePtr
)get_doc(This
), query
, resultList
);
1907 This
->properties
->XPath
= XPath
;
1912 static HRESULT
get_node_type(VARIANT Type
, DOMNodeType
* type
)
1918 hr
= VariantChangeType(&tmp
, &Type
, 0, VT_I4
);
1920 return E_INVALIDARG
;
1927 static HRESULT WINAPI
domdoc_createNode(
1928 IXMLDOMDocument3
*iface
,
1932 IXMLDOMNode
** node
)
1934 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1935 DOMNodeType node_type
;
1937 xmlChar
*xml_name
, *href
;
1940 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_variant(&Type
), debugstr_w(name
), debugstr_w(namespaceURI
), node
);
1942 if(!node
) return E_INVALIDARG
;
1944 hr
= get_node_type(Type
, &node_type
);
1945 if(FAILED(hr
)) return hr
;
1947 TRACE("node_type %d\n", node_type
);
1949 /* exit earlier for types that need name */
1953 case NODE_ATTRIBUTE
:
1954 case NODE_ENTITY_REFERENCE
:
1955 case NODE_PROCESSING_INSTRUCTION
:
1956 if (!name
|| *name
== 0) return E_FAIL
;
1962 xml_name
= xmlchar_from_wchar(name
);
1963 /* prevent empty href to be allocated */
1964 href
= namespaceURI
? xmlchar_from_wchar(namespaceURI
) : NULL
;
1970 xmlChar
*local
, *prefix
;
1972 local
= xmlSplitQName2(xml_name
, &prefix
);
1974 xmlnode
= xmlNewDocNode(get_doc(This
), NULL
, local
? local
: xml_name
, NULL
);
1976 /* allow to create default namespace xmlns= */
1977 if (local
|| (href
&& *href
))
1979 xmlNsPtr ns
= xmlNewNs(xmlnode
, href
, prefix
);
1980 xmlSetNs(xmlnode
, ns
);
1988 case NODE_ATTRIBUTE
:
1990 xmlChar
*local
, *prefix
;
1992 local
= xmlSplitQName2(xml_name
, &prefix
);
1994 xmlnode
= (xmlNodePtr
)xmlNewDocProp(get_doc(This
), local
? local
: xml_name
, NULL
);
1996 if (local
|| (href
&& *href
))
1998 /* we need a floating namespace here, it can't be created linked to attribute from
2000 xmlNsPtr ns
= xmlNewNs(NULL
, href
, prefix
);
2001 xmlSetNs(xmlnode
, ns
);
2010 xmlnode
= (xmlNodePtr
)xmlNewDocText(get_doc(This
), NULL
);
2012 case NODE_CDATA_SECTION
:
2013 xmlnode
= xmlNewCDataBlock(get_doc(This
), NULL
, 0);
2015 case NODE_ENTITY_REFERENCE
:
2016 xmlnode
= xmlNewReference(get_doc(This
), xml_name
);
2018 case NODE_PROCESSING_INSTRUCTION
:
2019 #ifdef HAVE_XMLNEWDOCPI
2020 xmlnode
= xmlNewDocPI(get_doc(This
), xml_name
, NULL
);
2022 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2027 xmlnode
= xmlNewDocComment(get_doc(This
), NULL
);
2029 case NODE_DOCUMENT_FRAGMENT
:
2030 xmlnode
= xmlNewDocFragment(get_doc(This
));
2032 /* unsupported types */
2034 case NODE_DOCUMENT_TYPE
:
2037 heap_free(xml_name
);
2038 return E_INVALIDARG
;
2040 FIXME("unhandled node type %d\n", node_type
);
2045 *node
= create_node(xmlnode
);
2046 heap_free(xml_name
);
2051 TRACE("created node (%d, %p, %p)\n", node_type
, *node
, xmlnode
);
2052 xmldoc_add_orphan(xmlnode
->doc
, xmlnode
);
2059 static HRESULT WINAPI
domdoc_nodeFromID(
2060 IXMLDOMDocument3
*iface
,
2062 IXMLDOMNode
** node
)
2064 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2065 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(idString
), node
);
2069 static HRESULT
domdoc_onDataAvailable(void *obj
, char *ptr
, DWORD len
)
2074 xmldoc
= doparse(This
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
2076 xmldoc
->_private
= create_priv();
2077 return attach_xmldoc(This
, xmldoc
);
2083 static HRESULT
domdoc_load_moniker(domdoc
*This
, IMoniker
*mon
)
2088 hr
= bind_url(mon
, domdoc_onDataAvailable
, This
, &bsc
);
2092 return detach_bsc(bsc
);
2095 static HRESULT WINAPI
domdoc_load(
2096 IXMLDOMDocument3
*iface
,
2098 VARIANT_BOOL
* isSuccessful
)
2100 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2101 LPWSTR filename
= NULL
;
2102 HRESULT hr
= S_FALSE
;
2105 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&source
));
2109 *isSuccessful
= VARIANT_FALSE
;
2111 assert( &This
->node
);
2113 switch( V_VT(&source
) )
2116 filename
= V_BSTR(&source
);
2118 case VT_BSTR
|VT_BYREF
:
2119 if (!V_BSTRREF(&source
)) return E_INVALIDARG
;
2120 filename
= *V_BSTRREF(&source
);
2122 case VT_ARRAY
|VT_UI1
:
2124 SAFEARRAY
*psa
= V_ARRAY(&source
);
2127 UINT dim
= SafeArrayGetDim(psa
);
2132 ERR("SAFEARRAY == NULL\n");
2133 hr
= This
->error
= E_INVALIDARG
;
2136 /* Only takes UTF-8 strings.
2137 * NOT NULL-terminated. */
2138 SafeArrayAccessData(psa
, (void**)&str
);
2139 SafeArrayGetUBound(psa
, 1, &len
);
2141 if ((xmldoc
= doparse(This
, str
, ++len
, XML_CHAR_ENCODING_UTF8
)))
2143 hr
= This
->error
= S_OK
;
2144 *isSuccessful
= VARIANT_TRUE
;
2145 TRACE("parsed document %p\n", xmldoc
);
2149 This
->error
= E_FAIL
;
2150 TRACE("failed to parse document\n");
2153 SafeArrayUnaccessData(psa
);
2157 xmldoc
->_private
= create_priv();
2158 return attach_xmldoc(This
, xmldoc
);
2162 FIXME("unhandled SAFEARRAY dim: %d\n", dim
);
2163 hr
= This
->error
= E_NOTIMPL
;
2169 ISequentialStream
*stream
= NULL
;
2170 IXMLDOMDocument3
*newdoc
= NULL
;
2172 if (!V_UNKNOWN(&source
)) return E_INVALIDARG
;
2174 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IXMLDOMDocument3
, (void**)&newdoc
);
2179 domdoc
*newDoc
= impl_from_IXMLDOMDocument3( newdoc
);
2181 xmldoc
= xmlCopyDoc(get_doc(newDoc
), 1);
2182 xmldoc
->_private
= create_priv();
2183 hr
= attach_xmldoc(This
, xmldoc
);
2186 *isSuccessful
= VARIANT_TRUE
;
2192 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IStream
, (void**)&stream
);
2194 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_ISequentialStream
, (void**)&stream
);
2198 hr
= domdoc_load_from_stream(This
, stream
);
2200 *isSuccessful
= VARIANT_TRUE
;
2201 ISequentialStream_Release(stream
);
2205 FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr
, V_UNKNOWN(&source
)->lpVtbl
);
2209 FIXME("VT type not supported (%d)\n", V_VT(&source
));
2216 CoTaskMemFree(This
->properties
->url
);
2217 This
->properties
->url
= NULL
;
2219 hr
= create_moniker_from_url( filename
, &mon
);
2220 if ( SUCCEEDED(hr
) )
2222 hr
= domdoc_load_moniker( This
, mon
);
2224 IMoniker_GetDisplayName(mon
, NULL
, NULL
, &This
->properties
->url
);
2225 IMoniker_Release(mon
);
2229 This
->error
= E_FAIL
;
2232 hr
= This
->error
= S_OK
;
2233 *isSuccessful
= VARIANT_TRUE
;
2237 if(!filename
|| FAILED(hr
)) {
2238 xmldoc
= xmlNewDoc(NULL
);
2239 xmldoc
->_private
= create_priv();
2240 hr
= attach_xmldoc(This
, xmldoc
);
2245 TRACE("ret (%d)\n", hr
);
2251 static HRESULT WINAPI
domdoc_get_readyState(
2252 IXMLDOMDocument3
*iface
,
2255 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2256 FIXME("stub! (%p)->(%p)\n", This
, value
);
2259 return E_INVALIDARG
;
2261 *value
= READYSTATE_COMPLETE
;
2266 static HRESULT WINAPI
domdoc_get_parseError(
2267 IXMLDOMDocument3
*iface
,
2268 IXMLDOMParseError
** errorObj
)
2270 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2271 static const WCHAR err
[] = {'e','r','r','o','r',0};
2272 BSTR error_string
= NULL
;
2274 FIXME("(%p)->(%p): creating a dummy parseError\n", iface
, errorObj
);
2277 error_string
= SysAllocString(err
);
2279 *errorObj
= create_parseError(This
->error
, NULL
, error_string
, NULL
, 0, 0, 0);
2280 if(!*errorObj
) return E_OUTOFMEMORY
;
2285 static HRESULT WINAPI
domdoc_get_url(
2286 IXMLDOMDocument3
*iface
,
2289 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2291 TRACE("(%p)->(%p)\n", This
, url
);
2294 return E_INVALIDARG
;
2296 if (This
->properties
->url
)
2298 *url
= SysAllocString(This
->properties
->url
);
2300 return E_OUTOFMEMORY
;
2305 return return_null_bstr(url
);
2309 static HRESULT WINAPI
domdoc_get_async(
2310 IXMLDOMDocument3
*iface
,
2311 VARIANT_BOOL
* isAsync
)
2313 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2315 TRACE("(%p)->(%p: %d)\n", This
, isAsync
, This
->async
);
2316 *isAsync
= This
->async
;
2321 static HRESULT WINAPI
domdoc_put_async(
2322 IXMLDOMDocument3
*iface
,
2323 VARIANT_BOOL isAsync
)
2325 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2327 TRACE("(%p)->(%d)\n", This
, isAsync
);
2328 This
->async
= isAsync
;
2333 static HRESULT WINAPI
domdoc_abort(
2334 IXMLDOMDocument3
*iface
)
2336 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2337 FIXME("%p\n", This
);
2341 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2342 static HRESULT WINAPI
domdoc_loadXML(
2343 IXMLDOMDocument3
*iface
,
2345 VARIANT_BOOL
* isSuccessful
)
2347 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2348 xmlDocPtr xmldoc
= NULL
;
2349 HRESULT hr
= S_FALSE
, hr2
;
2351 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), isSuccessful
);
2353 assert ( &This
->node
);
2357 *isSuccessful
= VARIANT_FALSE
;
2363 /* skip leading spaces if needed */
2364 if (This
->properties
->version
== MSXML_DEFAULT
|| This
->properties
->version
== MSXML26
)
2365 while (*ptr
&& isspaceW(*ptr
)) ptr
++;
2367 xmldoc
= doparse(This
, (char*)ptr
, strlenW(ptr
)*sizeof(WCHAR
), XML_CHAR_ENCODING_UTF16LE
);
2370 This
->error
= E_FAIL
;
2371 TRACE("failed to parse document\n");
2375 hr
= This
->error
= S_OK
;
2376 *isSuccessful
= VARIANT_TRUE
;
2377 TRACE("parsed document %p\n", xmldoc
);
2383 xmldoc
= xmlNewDoc(NULL
);
2384 xmldoc
->_private
= create_priv();
2385 hr2
= attach_xmldoc(This
, xmldoc
);
2392 static int XMLCALL
domdoc_save_writecallback(void *ctx
, const char *buffer
, int len
)
2396 if(!WriteFile(ctx
, buffer
, len
, &written
, NULL
))
2398 WARN("write error\n");
2405 static int XMLCALL
domdoc_save_closecallback(void *ctx
)
2407 return CloseHandle(ctx
) ? 0 : -1;
2410 static int XMLCALL
domdoc_stream_save_writecallback(void *ctx
, const char *buffer
, int len
)
2415 hr
= IStream_Write((IStream
*)ctx
, buffer
, len
, &written
);
2416 TRACE("0x%08x %p %d %u\n", hr
, buffer
, len
, written
);
2419 WARN("stream write error: 0x%08x\n", hr
);
2426 static int XMLCALL
domdoc_stream_save_closecallback(void *ctx
)
2428 IStream_Release((IStream
*)ctx
);
2432 static HRESULT WINAPI
domdoc_save(
2433 IXMLDOMDocument3
*iface
,
2434 VARIANT destination
)
2436 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2437 xmlSaveCtxtPtr ctx
= NULL
;
2441 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&destination
));
2443 switch (V_VT(&destination
))
2447 IUnknown
*pUnk
= V_UNKNOWN(&destination
);
2448 IXMLDOMDocument3
*document
;
2451 ret
= IUnknown_QueryInterface(pUnk
, &IID_IXMLDOMDocument3
, (void**)&document
);
2454 VARIANT_BOOL success
;
2457 ret
= IXMLDOMDocument3_get_xml(iface
, &xml
);
2460 ret
= IXMLDOMDocument3_loadXML(document
, xml
, &success
);
2464 IXMLDOMDocument3_Release(document
);
2468 ret
= IUnknown_QueryInterface(pUnk
, &IID_IStream
, (void**)&stream
);
2471 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2472 ctx
= xmlSaveToIO(domdoc_stream_save_writecallback
,
2473 domdoc_stream_save_closecallback
, stream
, NULL
, options
);
2477 IStream_Release(stream
);
2485 case VT_BSTR
| VT_BYREF
:
2487 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2489 /* save with file path */
2490 HANDLE handle
= CreateFileW( (V_VT(&destination
) & VT_BYREF
)? *V_BSTRREF(&destination
) : V_BSTR(&destination
),
2491 GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2492 if( handle
== INVALID_HANDLE_VALUE
)
2494 WARN("failed to create file\n");
2498 /* disable top XML declaration */
2499 ctx
= xmlSaveToIO(domdoc_save_writecallback
, domdoc_save_closecallback
,
2500 handle
, NULL
, options
);
2503 CloseHandle(handle
);
2510 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination
));
2514 xmldecl
= xmldoc_unlink_xmldecl(get_doc(This
));
2515 if (xmlSaveDoc(ctx
, get_doc(This
)) == -1) ret
= S_FALSE
;
2516 xmldoc_link_xmldecl(get_doc(This
), xmldecl
);
2518 /* will release resources through close callback */
2524 static HRESULT WINAPI
domdoc_get_validateOnParse(
2525 IXMLDOMDocument3
*iface
,
2526 VARIANT_BOOL
* isValidating
)
2528 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2529 TRACE("(%p)->(%p: %d)\n", This
, isValidating
, This
->validating
);
2530 *isValidating
= This
->validating
;
2535 static HRESULT WINAPI
domdoc_put_validateOnParse(
2536 IXMLDOMDocument3
*iface
,
2537 VARIANT_BOOL isValidating
)
2539 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2540 TRACE("(%p)->(%d)\n", This
, isValidating
);
2541 This
->validating
= isValidating
;
2546 static HRESULT WINAPI
domdoc_get_resolveExternals(
2547 IXMLDOMDocument3
*iface
,
2548 VARIANT_BOOL
* isResolving
)
2550 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2551 TRACE("(%p)->(%p: %d)\n", This
, isResolving
, This
->resolving
);
2552 *isResolving
= This
->resolving
;
2557 static HRESULT WINAPI
domdoc_put_resolveExternals(
2558 IXMLDOMDocument3
*iface
,
2559 VARIANT_BOOL isResolving
)
2561 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2562 TRACE("(%p)->(%d)\n", This
, isResolving
);
2563 This
->resolving
= isResolving
;
2568 static HRESULT WINAPI
domdoc_get_preserveWhiteSpace(
2569 IXMLDOMDocument3
*iface
,
2570 VARIANT_BOOL
* isPreserving
)
2572 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2573 TRACE("(%p)->(%p: %d)\n", This
, isPreserving
, This
->properties
->preserving
);
2574 *isPreserving
= This
->properties
->preserving
;
2579 static HRESULT WINAPI
domdoc_put_preserveWhiteSpace(
2580 IXMLDOMDocument3
*iface
,
2581 VARIANT_BOOL isPreserving
)
2583 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2584 TRACE("(%p)->(%d)\n", This
, isPreserving
);
2585 This
->properties
->preserving
= isPreserving
;
2590 static HRESULT WINAPI
domdoc_put_onreadystatechange(
2591 IXMLDOMDocument3
*iface
,
2594 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2596 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&event
));
2597 return set_doc_event(This
, EVENTID_READYSTATECHANGE
, &event
);
2601 static HRESULT WINAPI
domdoc_put_onDataAvailable(IXMLDOMDocument3
*iface
, VARIANT sink
)
2603 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2604 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2608 static HRESULT WINAPI
domdoc_put_onTransformNode(IXMLDOMDocument3
*iface
, VARIANT sink
)
2610 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2611 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2615 static HRESULT WINAPI
domdoc_get_namespaces(
2616 IXMLDOMDocument3
* iface
,
2617 IXMLDOMSchemaCollection
** collection
)
2619 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2622 FIXME("(%p)->(%p): semi-stub\n", This
, collection
);
2624 if (!collection
) return E_POINTER
;
2626 if (!This
->namespaces
)
2628 hr
= SchemaCache_create(This
->properties
->version
, (void**)&This
->namespaces
);
2629 if (hr
!= S_OK
) return hr
;
2631 hr
= cache_from_doc_ns(This
->namespaces
, &This
->node
);
2633 release_namespaces(This
);
2636 if (This
->namespaces
)
2637 return IXMLDOMSchemaCollection2_QueryInterface(This
->namespaces
,
2638 &IID_IXMLDOMSchemaCollection
, (void**)collection
);
2643 static HRESULT WINAPI
domdoc_get_schemas(
2644 IXMLDOMDocument3
* iface
,
2647 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2648 IXMLDOMSchemaCollection2
* cur_schema
= This
->properties
->schemaCache
;
2649 HRESULT hr
= S_FALSE
;
2651 TRACE("(%p)->(%p)\n", This
, schema
);
2653 V_VT(schema
) = VT_NULL
;
2654 /* just to reset pointer part, cause that's what application is expected to use */
2655 V_DISPATCH(schema
) = NULL
;
2659 hr
= IXMLDOMSchemaCollection2_QueryInterface(cur_schema
, &IID_IDispatch
, (void**)&V_DISPATCH(schema
));
2661 V_VT(schema
) = VT_DISPATCH
;
2666 static HRESULT WINAPI
domdoc_putref_schemas(
2667 IXMLDOMDocument3
* iface
,
2670 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2671 HRESULT hr
= E_FAIL
;
2672 IXMLDOMSchemaCollection2
* new_schema
= NULL
;
2674 FIXME("(%p)->(%s): semi-stub\n", This
, debugstr_variant(&schema
));
2675 switch(V_VT(&schema
))
2678 if (V_UNKNOWN(&schema
))
2680 hr
= IUnknown_QueryInterface(V_UNKNOWN(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2685 if (V_DISPATCH(&schema
))
2687 hr
= IDispatch_QueryInterface(V_DISPATCH(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2697 WARN("Can't get schema from vt %x\n", V_VT(&schema
));
2702 IXMLDOMSchemaCollection2
* old_schema
= InterlockedExchangePointer((void**)&This
->properties
->schemaCache
, new_schema
);
2703 if(old_schema
) IXMLDOMSchemaCollection2_Release(old_schema
);
2709 static inline BOOL
is_wellformed(xmlDocPtr doc
)
2711 #ifdef HAVE_XMLDOC_PROPERTIES
2712 return doc
->properties
& XML_DOC_WELLFORMED
;
2714 /* Not a full check, but catches the worst violations */
2718 for (child
= doc
->children
; child
!= NULL
; child
= child
->next
)
2720 switch (child
->type
)
2722 case XML_ELEMENT_NODE
:
2727 case XML_CDATA_SECTION_NODE
:
2739 static void LIBXML2_LOG_CALLBACK
validate_error(void* ctx
, char const* msg
, ...)
2743 LIBXML2_CALLBACK_ERR(domdoc_validateNode
, msg
, ap
);
2747 static void LIBXML2_LOG_CALLBACK
validate_warning(void* ctx
, char const* msg
, ...)
2751 LIBXML2_CALLBACK_WARN(domdoc_validateNode
, msg
, ap
);
2755 static HRESULT WINAPI
domdoc_validateNode(
2756 IXMLDOMDocument3
* iface
,
2758 IXMLDOMParseError
** err
)
2760 domdoc
* This
= impl_from_IXMLDOMDocument3(iface
);
2761 LONG state
, err_code
= 0;
2765 TRACE("(%p)->(%p, %p)\n", This
, node
, err
);
2766 IXMLDOMDocument3_get_readyState(iface
, &state
);
2767 if (state
!= READYSTATE_COMPLETE
)
2770 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2777 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2781 if (!get_node_obj(node
)->node
|| get_node_obj(node
)->node
->doc
!= get_doc(This
))
2784 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2788 if (!is_wellformed(get_doc(This
)))
2790 ERR("doc not well-formed\n");
2792 *err
= create_parseError(E_XML_NOTWF
, NULL
, NULL
, NULL
, 0, 0, 0);
2796 /* DTD validation */
2797 if (get_doc(This
)->intSubset
|| get_doc(This
)->extSubset
)
2799 xmlValidCtxtPtr vctx
= xmlNewValidCtxt();
2800 vctx
->error
= validate_error
;
2801 vctx
->warning
= validate_warning
;
2804 if (!((node
== (IXMLDOMNode
*)iface
)?
2805 xmlValidateDocument(vctx
, get_doc(This
)) :
2806 xmlValidateElement(vctx
, get_doc(This
), get_node_obj(node
)->node
)))
2808 /* TODO: get a real error code here */
2809 TRACE("DTD validation failed\n");
2810 err_code
= E_XML_INVALID
;
2813 xmlFreeValidCtxt(vctx
);
2816 /* Schema validation */
2817 if (hr
== S_OK
&& This
->properties
->schemaCache
!= NULL
)
2820 hr
= SchemaCache_validate_tree(This
->properties
->schemaCache
, get_node_obj(node
)->node
);
2824 /* TODO: get a real error code here */
2827 TRACE("schema validation succeeded\n");
2831 ERR("schema validation failed\n");
2832 err_code
= E_XML_INVALID
;
2837 /* not really OK, just didn't find a schema for the ns */
2844 ERR("no DTD or schema found\n");
2845 err_code
= E_XML_NODTD
;
2850 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2855 static HRESULT WINAPI
domdoc_validate(
2856 IXMLDOMDocument3
* iface
,
2857 IXMLDOMParseError
** err
)
2859 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2860 TRACE("(%p)->(%p)\n", This
, err
);
2861 return IXMLDOMDocument3_validateNode(iface
, (IXMLDOMNode
*)iface
, err
);
2864 static HRESULT WINAPI
domdoc_setProperty(
2865 IXMLDOMDocument3
* iface
,
2869 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2871 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(p
), debugstr_variant(&value
));
2873 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
2879 V_VT(&varStr
) = VT_EMPTY
;
2880 if (V_VT(&value
) != VT_BSTR
)
2882 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2884 bstr
= V_BSTR(&varStr
);
2887 bstr
= V_BSTR(&value
);
2890 if (lstrcmpiW(bstr
, PropValueXPathW
) == 0)
2891 This
->properties
->XPath
= TRUE
;
2892 else if (lstrcmpiW(bstr
, PropValueXSLPatternW
) == 0)
2893 This
->properties
->XPath
= FALSE
;
2897 VariantClear(&varStr
);
2900 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
2902 xmlChar
*nsStr
= (xmlChar
*)This
->properties
->selectNsStr
;
2903 struct list
*pNsList
;
2908 V_VT(&varStr
) = VT_EMPTY
;
2909 if (V_VT(&value
) != VT_BSTR
)
2911 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2913 bstr
= V_BSTR(&varStr
);
2916 bstr
= V_BSTR(&value
);
2920 pNsList
= &(This
->properties
->selectNsList
);
2921 clear_selectNsList(pNsList
);
2923 nsStr
= xmlchar_from_wchar(bstr
);
2925 TRACE("property value: \"%s\"\n", debugstr_w(bstr
));
2927 This
->properties
->selectNsStr
= nsStr
;
2928 This
->properties
->selectNsStr_len
= xmlStrlen(nsStr
);
2931 xmlChar
*pTokBegin
, *pTokEnd
, *pTokInner
;
2932 select_ns_entry
* ns_entry
= NULL
;
2933 xmlXPathContextPtr ctx
;
2935 ctx
= xmlXPathNewContext(This
->node
.node
->doc
);
2938 /* skip leading spaces */
2939 while (*pTokBegin
== ' ' || *pTokBegin
== '\n' ||
2940 *pTokBegin
== '\t' || *pTokBegin
== '\r')
2943 for (; *pTokBegin
; pTokBegin
= pTokEnd
)
2946 memset(ns_entry
, 0, sizeof(select_ns_entry
));
2948 ns_entry
= heap_alloc_zero(sizeof(select_ns_entry
));
2950 while (*pTokBegin
== ' ')
2952 pTokEnd
= pTokBegin
;
2953 while (*pTokEnd
!= ' ' && *pTokEnd
!= 0)
2956 /* so it failed to advance which means we've got some trailing spaces */
2957 if (pTokEnd
== pTokBegin
) break;
2959 if (xmlStrncmp(pTokBegin
, (xmlChar
const*)"xmlns", 5) != 0)
2962 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2963 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2968 if (*pTokBegin
== '=')
2970 /*valid for XSLPattern?*/
2971 FIXME("Setting default xmlns not supported - skipping.\n");
2974 else if (*pTokBegin
== ':')
2976 ns_entry
->prefix
= ++pTokBegin
;
2977 for (pTokInner
= pTokBegin
; pTokInner
!= pTokEnd
&& *pTokInner
!= '='; ++pTokInner
)
2980 if (pTokInner
== pTokEnd
)
2983 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2984 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2988 ns_entry
->prefix_end
= *pTokInner
;
2992 if (pTokEnd
-pTokInner
> 1 &&
2993 ((*pTokInner
== '\'' && *(pTokEnd
-1) == '\'') ||
2994 (*pTokInner
== '"' && *(pTokEnd
-1) == '"')))
2996 ns_entry
->href
= ++pTokInner
;
2997 ns_entry
->href_end
= *(pTokEnd
-1);
2999 list_add_tail(pNsList
, &ns_entry
->entry
);
3000 /*let libxml figure out if they're valid from here ;)*/
3001 if (xmlXPathRegisterNs(ctx
, ns_entry
->prefix
, ns_entry
->href
) != 0)
3010 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3011 debugstr_w(bstr
), debugstr_an((const char*)pTokInner
, pTokEnd
-pTokInner
));
3012 list_add_tail(pNsList
, &ns_entry
->entry
);
3025 heap_free(ns_entry
);
3026 xmlXPathFreeContext(ctx
);
3029 VariantClear(&varStr
);
3032 else if (lstrcmpiW(p
, PropertyProhibitDTDW
) == 0 ||
3033 lstrcmpiW(p
, PropertyNewParserW
) == 0 ||
3034 lstrcmpiW(p
, PropertyResolveExternalsW
) == 0)
3037 FIXME("Ignoring property %s, value %s\n", debugstr_w(p
), debugstr_variant(&value
));
3041 FIXME("Unknown property %s\n", debugstr_w(p
));
3045 static HRESULT WINAPI
domdoc_getProperty(
3046 IXMLDOMDocument3
* iface
,
3050 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3052 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
3055 return E_INVALIDARG
;
3057 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
3059 V_VT(var
) = VT_BSTR
;
3060 V_BSTR(var
) = This
->properties
->XPath
?
3061 SysAllocString(PropValueXPathW
) :
3062 SysAllocString(PropValueXSLPatternW
);
3063 return V_BSTR(var
) ? S_OK
: E_OUTOFMEMORY
;
3065 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3068 BSTR rebuiltStr
, cur
;
3069 const xmlChar
*nsStr
;
3070 struct list
*pNsList
;
3071 select_ns_entry
* pNsEntry
;
3073 V_VT(var
) = VT_BSTR
;
3074 nsStr
= This
->properties
->selectNsStr
;
3075 pNsList
= &This
->properties
->selectNsList
;
3076 lenA
= This
->properties
->selectNsStr_len
;
3077 lenW
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, NULL
, 0);
3078 rebuiltStr
= heap_alloc(lenW
*sizeof(WCHAR
));
3079 MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, rebuiltStr
, lenW
);
3081 /* this is fine because all of the chars that end tokens are ASCII*/
3082 LIST_FOR_EACH_ENTRY(pNsEntry
, pNsList
, select_ns_entry
, entry
)
3084 while (*cur
!= 0) ++cur
;
3085 if (pNsEntry
->prefix_end
)
3087 *cur
= pNsEntry
->prefix_end
;
3088 while (*cur
!= 0) ++cur
;
3091 if (pNsEntry
->href_end
)
3093 *cur
= pNsEntry
->href_end
;
3096 V_BSTR(var
) = SysAllocString(rebuiltStr
);
3097 heap_free(rebuiltStr
);
3101 FIXME("Unknown property %s\n", debugstr_w(p
));
3105 static HRESULT WINAPI
domdoc_importNode(
3106 IXMLDOMDocument3
* iface
,
3109 IXMLDOMNode
** clone
)
3111 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3112 FIXME("(%p)->(%p %d %p): stub\n", This
, node
, deep
, clone
);
3116 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl
=
3118 domdoc_QueryInterface
,
3121 domdoc_GetTypeInfoCount
,
3123 domdoc_GetIDsOfNames
,
3125 domdoc_get_nodeName
,
3126 domdoc_get_nodeValue
,
3127 domdoc_put_nodeValue
,
3128 domdoc_get_nodeType
,
3129 domdoc_get_parentNode
,
3130 domdoc_get_childNodes
,
3131 domdoc_get_firstChild
,
3132 domdoc_get_lastChild
,
3133 domdoc_get_previousSibling
,
3134 domdoc_get_nextSibling
,
3135 domdoc_get_attributes
,
3136 domdoc_insertBefore
,
3137 domdoc_replaceChild
,
3140 domdoc_hasChildNodes
,
3141 domdoc_get_ownerDocument
,
3143 domdoc_get_nodeTypeString
,
3146 domdoc_get_specified
,
3147 domdoc_get_definition
,
3148 domdoc_get_nodeTypedValue
,
3149 domdoc_put_nodeTypedValue
,
3150 domdoc_get_dataType
,
3151 domdoc_put_dataType
,
3153 domdoc_transformNode
,
3155 domdoc_selectSingleNode
,
3157 domdoc_get_namespaceURI
,
3159 domdoc_get_baseName
,
3160 domdoc_transformNodeToObject
,
3162 domdoc_get_implementation
,
3163 domdoc_get_documentElement
,
3164 domdoc_put_documentElement
,
3165 domdoc_createElement
,
3166 domdoc_createDocumentFragment
,
3167 domdoc_createTextNode
,
3168 domdoc_createComment
,
3169 domdoc_createCDATASection
,
3170 domdoc_createProcessingInstruction
,
3171 domdoc_createAttribute
,
3172 domdoc_createEntityReference
,
3173 domdoc_getElementsByTagName
,
3177 domdoc_get_readyState
,
3178 domdoc_get_parseError
,
3185 domdoc_get_validateOnParse
,
3186 domdoc_put_validateOnParse
,
3187 domdoc_get_resolveExternals
,
3188 domdoc_put_resolveExternals
,
3189 domdoc_get_preserveWhiteSpace
,
3190 domdoc_put_preserveWhiteSpace
,
3191 domdoc_put_onreadystatechange
,
3192 domdoc_put_onDataAvailable
,
3193 domdoc_put_onTransformNode
,
3194 domdoc_get_namespaces
,
3196 domdoc_putref_schemas
,
3200 domdoc_validateNode
,
3204 /* IConnectionPointContainer */
3205 static HRESULT WINAPI
ConnectionPointContainer_QueryInterface(IConnectionPointContainer
*iface
,
3206 REFIID riid
, void **ppv
)
3208 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3209 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3212 static ULONG WINAPI
ConnectionPointContainer_AddRef(IConnectionPointContainer
*iface
)
3214 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3215 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3218 static ULONG WINAPI
ConnectionPointContainer_Release(IConnectionPointContainer
*iface
)
3220 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3221 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3224 static HRESULT WINAPI
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer
*iface
,
3225 IEnumConnectionPoints
**ppEnum
)
3227 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3228 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3232 static HRESULT WINAPI
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer
*iface
,
3233 REFIID riid
, IConnectionPoint
**cp
)
3235 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3236 ConnectionPoint
*iter
;
3238 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), cp
);
3242 for(iter
= This
->cp_list
; iter
; iter
= iter
->next
)
3244 if (IsEqualGUID(iter
->iid
, riid
))
3245 *cp
= &iter
->IConnectionPoint_iface
;
3250 IConnectionPoint_AddRef(*cp
);
3254 FIXME("unsupported riid %s\n", debugstr_guid(riid
));
3255 return CONNECT_E_NOCONNECTION
;
3259 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl
=
3261 ConnectionPointContainer_QueryInterface
,
3262 ConnectionPointContainer_AddRef
,
3263 ConnectionPointContainer_Release
,
3264 ConnectionPointContainer_EnumConnectionPoints
,
3265 ConnectionPointContainer_FindConnectionPoint
3268 /* IConnectionPoint */
3269 static HRESULT WINAPI
ConnectionPoint_QueryInterface(IConnectionPoint
*iface
,
3270 REFIID riid
, void **ppv
)
3272 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3274 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
3278 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
3279 IsEqualGUID(&IID_IConnectionPoint
, riid
))
3286 IConnectionPoint_AddRef(iface
);
3290 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
3291 return E_NOINTERFACE
;
3294 static ULONG WINAPI
ConnectionPoint_AddRef(IConnectionPoint
*iface
)
3296 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3297 return IConnectionPointContainer_AddRef(This
->container
);
3300 static ULONG WINAPI
ConnectionPoint_Release(IConnectionPoint
*iface
)
3302 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3303 return IConnectionPointContainer_Release(This
->container
);
3306 static HRESULT WINAPI
ConnectionPoint_GetConnectionInterface(IConnectionPoint
*iface
, IID
*iid
)
3308 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3310 TRACE("(%p)->(%p)\n", This
, iid
);
3312 if (!iid
) return E_POINTER
;
3318 static HRESULT WINAPI
ConnectionPoint_GetConnectionPointContainer(IConnectionPoint
*iface
,
3319 IConnectionPointContainer
**container
)
3321 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3323 TRACE("(%p)->(%p)\n", This
, container
);
3325 if (!container
) return E_POINTER
;
3327 *container
= This
->container
;
3328 IConnectionPointContainer_AddRef(*container
);
3332 static HRESULT WINAPI
ConnectionPoint_Advise(IConnectionPoint
*iface
, IUnknown
*unk_sink
,
3335 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3340 TRACE("(%p)->(%p %p)\n", This
, unk_sink
, cookie
);
3342 hr
= IUnknown_QueryInterface(unk_sink
, This
->iid
, (void**)&sink
);
3343 if(FAILED(hr
) && !IsEqualGUID(&IID_IPropertyNotifySink
, This
->iid
))
3344 hr
= IUnknown_QueryInterface(unk_sink
, &IID_IDispatch
, (void**)&sink
);
3346 return CONNECT_E_CANNOTCONNECT
;
3350 for (i
= 0; i
< This
->sinks_size
; i
++)
3351 if (!This
->sinks
[i
].unk
)
3354 if (i
== This
->sinks_size
)
3355 This
->sinks
= heap_realloc(This
->sinks
,(++This
->sinks_size
)*sizeof(*This
->sinks
));
3359 This
->sinks
= heap_alloc(sizeof(*This
->sinks
));
3360 This
->sinks_size
= 1;
3364 This
->sinks
[i
].unk
= sink
;
3371 static HRESULT WINAPI
ConnectionPoint_Unadvise(IConnectionPoint
*iface
, DWORD cookie
)
3373 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3375 TRACE("(%p)->(%d)\n", This
, cookie
);
3377 if (cookie
== 0 || cookie
> This
->sinks_size
|| !This
->sinks
[cookie
-1].unk
)
3378 return CONNECT_E_NOCONNECTION
;
3380 IUnknown_Release(This
->sinks
[cookie
-1].unk
);
3381 This
->sinks
[cookie
-1].unk
= NULL
;
3386 static HRESULT WINAPI
ConnectionPoint_EnumConnections(IConnectionPoint
*iface
,
3387 IEnumConnections
**ppEnum
)
3389 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3390 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3394 static const IConnectionPointVtbl ConnectionPointVtbl
=
3396 ConnectionPoint_QueryInterface
,
3397 ConnectionPoint_AddRef
,
3398 ConnectionPoint_Release
,
3399 ConnectionPoint_GetConnectionInterface
,
3400 ConnectionPoint_GetConnectionPointContainer
,
3401 ConnectionPoint_Advise
,
3402 ConnectionPoint_Unadvise
,
3403 ConnectionPoint_EnumConnections
3406 static void ConnectionPoint_Init(ConnectionPoint
*cp
, struct domdoc
*doc
, REFIID riid
)
3408 cp
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointVtbl
;
3414 cp
->next
= doc
->cp_list
;
3417 cp
->container
= &doc
->IConnectionPointContainer_iface
;
3420 /* domdoc implementation of IObjectWithSite */
3421 static HRESULT WINAPI
3422 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
3424 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3425 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObject
);
3428 static ULONG WINAPI
domdoc_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
3430 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3431 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3434 static ULONG WINAPI
domdoc_ObjectWithSite_Release( IObjectWithSite
* iface
)
3436 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3437 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3440 static HRESULT WINAPI
domdoc_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
3442 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3444 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
3449 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
3452 static HRESULT WINAPI
domdoc_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
3454 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3456 TRACE("(%p)->(%p)\n", iface
, punk
);
3462 IUnknown_Release( This
->site
);
3469 IUnknown_AddRef( punk
);
3472 IUnknown_Release( This
->site
);
3479 static const IObjectWithSiteVtbl domdocObjectSite
=
3481 domdoc_ObjectWithSite_QueryInterface
,
3482 domdoc_ObjectWithSite_AddRef
,
3483 domdoc_ObjectWithSite_Release
,
3484 domdoc_ObjectWithSite_SetSite
,
3485 domdoc_ObjectWithSite_GetSite
3488 static HRESULT WINAPI
domdoc_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
3490 domdoc
*This
= impl_from_IObjectSafety(iface
);
3491 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3494 static ULONG WINAPI
domdoc_Safety_AddRef(IObjectSafety
*iface
)
3496 domdoc
*This
= impl_from_IObjectSafety(iface
);
3497 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3500 static ULONG WINAPI
domdoc_Safety_Release(IObjectSafety
*iface
)
3502 domdoc
*This
= impl_from_IObjectSafety(iface
);
3503 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3506 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3508 static HRESULT WINAPI
domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3509 DWORD
*supported
, DWORD
*enabled
)
3511 domdoc
*This
= impl_from_IObjectSafety(iface
);
3513 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
3515 if(!supported
|| !enabled
) return E_POINTER
;
3517 *supported
= SAFETY_SUPPORTED_OPTIONS
;
3518 *enabled
= This
->safeopt
;
3523 static HRESULT WINAPI
domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3524 DWORD mask
, DWORD enabled
)
3526 domdoc
*This
= impl_from_IObjectSafety(iface
);
3527 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
3529 if ((mask
& ~SAFETY_SUPPORTED_OPTIONS
) != 0)
3532 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
3537 #undef SAFETY_SUPPORTED_OPTIONS
3539 static const IObjectSafetyVtbl domdocObjectSafetyVtbl
= {
3540 domdoc_Safety_QueryInterface
,
3541 domdoc_Safety_AddRef
,
3542 domdoc_Safety_Release
,
3543 domdoc_Safety_GetInterfaceSafetyOptions
,
3544 domdoc_Safety_SetInterfaceSafetyOptions
3547 static const tid_t domdoc_iface_tids
[] = {
3548 IXMLDOMDocument3_tid
,
3552 static dispex_static_data_t domdoc_dispex
= {
3554 IXMLDOMDocument3_tid
,
3559 HRESULT
get_domdoc_from_xmldoc(xmlDocPtr xmldoc
, IXMLDOMDocument3
**document
)
3563 doc
= heap_alloc( sizeof (*doc
) );
3565 return E_OUTOFMEMORY
;
3567 doc
->IXMLDOMDocument3_iface
.lpVtbl
= &XMLDOMDocument3Vtbl
;
3568 doc
->IPersistStreamInit_iface
.lpVtbl
= &xmldoc_IPersistStreamInit_VTable
;
3569 doc
->IObjectWithSite_iface
.lpVtbl
= &domdocObjectSite
;
3570 doc
->IObjectSafety_iface
.lpVtbl
= &domdocObjectSafetyVtbl
;
3571 doc
->IConnectionPointContainer_iface
.lpVtbl
= &ConnectionPointContainerVtbl
;
3573 doc
->async
= VARIANT_TRUE
;
3574 doc
->validating
= 0;
3576 doc
->properties
= properties_from_xmlDocPtr(xmldoc
);
3580 doc
->cp_list
= NULL
;
3581 doc
->namespaces
= NULL
;
3582 memset(doc
->events
, 0, sizeof(doc
->events
));
3584 /* events connection points */
3585 ConnectionPoint_Init(&doc
->cp_dispatch
, doc
, &IID_IDispatch
);
3586 ConnectionPoint_Init(&doc
->cp_propnotif
, doc
, &IID_IPropertyNotifySink
);
3587 ConnectionPoint_Init(&doc
->cp_domdocevents
, doc
, &DIID_XMLDOMDocumentEvents
);
3589 init_xmlnode(&doc
->node
, (xmlNodePtr
)xmldoc
, (IXMLDOMNode
*)&doc
->IXMLDOMDocument3_iface
,
3592 *document
= &doc
->IXMLDOMDocument3_iface
;
3594 TRACE("returning iface %p\n", *document
);
3598 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3603 TRACE("(%d, %p)\n", version
, ppObj
);
3605 xmldoc
= xmlNewDoc(NULL
);
3607 return E_OUTOFMEMORY
;
3609 xmldoc_init(xmldoc
, version
);
3611 hr
= get_domdoc_from_xmldoc(xmldoc
, (IXMLDOMDocument3
**)ppObj
);
3614 free_properties(properties_from_xmlDocPtr(xmldoc
));
3615 heap_free(xmldoc
->_private
);
3623 IUnknown
* create_domdoc( xmlNodePtr document
)
3628 TRACE("(%p)\n", document
);
3630 hr
= get_domdoc_from_xmldoc((xmlDocPtr
)document
, (IXMLDOMDocument3
**)&pObj
);
3639 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3641 MESSAGE("This program tried to use a DOMDocument object, but\n"
3642 "libxml2 support was not present at compile time.\n");