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"
52 #include "wine/list.h"
54 #include "msxml_private.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
60 /* not defined in older versions */
61 #define XML_SAVE_FORMAT 1
62 #define XML_SAVE_NO_DECL 2
63 #define XML_SAVE_NO_EMPTY 4
64 #define XML_SAVE_NO_XHTML 8
65 #define XML_SAVE_XHTML 16
66 #define XML_SAVE_AS_XML 32
67 #define XML_SAVE_AS_HTML 64
69 static const WCHAR PropertySelectionLanguageW
[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
70 static const WCHAR PropertySelectionNamespacesW
[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
71 static const WCHAR PropertyProhibitDTDW
[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
72 static const WCHAR PropertyNewParserW
[] = {'N','e','w','P','a','r','s','e','r',0};
73 static const WCHAR PropValueXPathW
[] = {'X','P','a','t','h',0};
74 static const WCHAR PropValueXSLPatternW
[] = {'X','S','L','P','a','t','t','e','r','n',0};
75 static const WCHAR PropertyResolveExternalsW
[] = {'R','e','s','o','l','v','e','E','x','t','e','r','n','a','l','s',0};
77 /* Anything that passes the test_get_ownerDocument()
78 * tests can go here (data shared between all instances).
79 * We need to preserve this when reloading a document,
80 * and also need access to it from the libxml backend. */
82 MSXML_VERSION version
;
83 VARIANT_BOOL preserving
;
84 IXMLDOMSchemaCollection2
* schemaCache
;
85 struct list selectNsList
;
86 xmlChar
const* selectNsStr
;
92 typedef struct ConnectionPoint ConnectionPoint
;
93 typedef struct domdoc domdoc
;
95 struct ConnectionPoint
97 IConnectionPoint IConnectionPoint_iface
;
100 ConnectionPoint
*next
;
101 IConnectionPointContainer
*container
;
108 IPropertyNotifySink
*propnotif
;
114 EVENTID_READYSTATECHANGE
= 0,
115 EVENTID_DATAAVAILABLE
,
116 EVENTID_TRANSFORMNODE
,
123 IXMLDOMDocument3 IXMLDOMDocument3_iface
;
124 IPersistStreamInit IPersistStreamInit_iface
;
125 IObjectWithSite IObjectWithSite_iface
;
126 IObjectSafety IObjectSafety_iface
;
127 IConnectionPointContainer IConnectionPointContainer_iface
;
130 VARIANT_BOOL validating
;
131 VARIANT_BOOL resolving
;
132 domdoc_properties
* properties
;
135 /* IObjectWithSite */
141 /* connection list */
142 ConnectionPoint
*cp_list
;
143 ConnectionPoint cp_domdocevents
;
144 ConnectionPoint cp_propnotif
;
145 ConnectionPoint cp_dispatch
;
148 IDispatch
*events
[EVENTID_LAST
];
150 IXMLDOMSchemaCollection2
*namespaces
;
153 static HRESULT
set_doc_event(domdoc
*doc
, eventid_t eid
, const VARIANT
*v
)
161 IUnknown_QueryInterface(V_UNKNOWN(v
), &IID_IDispatch
, (void**)&disp
);
166 disp
= V_DISPATCH(v
);
167 if (disp
) IDispatch_AddRef(disp
);
170 return DISP_E_TYPEMISMATCH
;
173 if (doc
->events
[eid
]) IDispatch_Release(doc
->events
[eid
]);
174 doc
->events
[eid
] = disp
;
179 static inline ConnectionPoint
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
181 return CONTAINING_RECORD(iface
, ConnectionPoint
, IConnectionPoint_iface
);
185 In native windows, the whole lifetime management of XMLDOMNodes is
186 managed automatically using reference counts. Wine emulates that by
187 maintaining a reference count to the document that is increased for
188 each IXMLDOMNode pointer passed out for this document. If all these
189 pointers are gone, the document is unreachable and gets freed, that
190 is, all nodes in the tree of the document get freed.
192 You are able to create nodes that are associated to a document (in
193 fact, in msxml's XMLDOM model, all nodes are associated to a document),
194 but not in the tree of that document, for example using the createFoo
195 functions from IXMLDOMDocument. These nodes do not get cleaned up
196 by libxml, so we have to do it ourselves.
198 To catch these nodes, a list of "orphan nodes" is introduced.
199 It contains pointers to all roots of node trees that are
200 associated with the document without being part of the document
201 tree. All nodes with parent==NULL (except for the document root nodes)
202 should be in the orphan node list of their document. All orphan nodes
203 get freed together with the document itself.
206 typedef struct _xmldoc_priv
{
209 domdoc_properties
* properties
;
212 typedef struct _orphan_entry
{
217 typedef struct _select_ns_entry
{
219 xmlChar
const* prefix
;
225 static inline xmldoc_priv
* priv_from_xmlDocPtr(const xmlDocPtr doc
)
227 return doc
->_private
;
230 static inline domdoc_properties
* properties_from_xmlDocPtr(xmlDocPtr doc
)
232 return priv_from_xmlDocPtr(doc
)->properties
;
235 BOOL
is_xpathmode(const xmlDocPtr doc
)
237 return properties_from_xmlDocPtr(doc
)->XPath
;
240 void set_xpathmode(xmlDocPtr doc
, BOOL xpath
)
242 properties_from_xmlDocPtr(doc
)->XPath
= xpath
;
245 int registerNamespaces(xmlXPathContextPtr ctxt
)
248 const select_ns_entry
* ns
= NULL
;
249 const struct list
* pNsList
= &properties_from_xmlDocPtr(ctxt
->doc
)->selectNsList
;
251 TRACE("(%p)\n", ctxt
);
253 LIST_FOR_EACH_ENTRY( ns
, pNsList
, select_ns_entry
, entry
)
255 xmlXPathRegisterNs(ctxt
, ns
->prefix
, ns
->href
);
262 static inline void clear_selectNsList(struct list
* pNsList
)
264 select_ns_entry
*ns
, *ns2
;
265 LIST_FOR_EACH_ENTRY_SAFE( ns
, ns2
, pNsList
, select_ns_entry
, entry
)
272 static xmldoc_priv
* create_priv(void)
275 priv
= heap_alloc( sizeof (*priv
) );
280 list_init( &priv
->orphans
);
281 priv
->properties
= NULL
;
287 static domdoc_properties
*create_properties(MSXML_VERSION version
)
289 domdoc_properties
*properties
= heap_alloc(sizeof(domdoc_properties
));
291 list_init(&properties
->selectNsList
);
292 properties
->preserving
= VARIANT_FALSE
;
293 properties
->schemaCache
= NULL
;
294 properties
->selectNsStr
= heap_alloc_zero(sizeof(xmlChar
));
295 properties
->selectNsStr_len
= 0;
297 /* properties that are dependent on object versions */
298 properties
->version
= version
;
299 properties
->XPath
= (version
== MSXML4
|| version
== MSXML6
);
302 properties
->url
= NULL
;
307 static domdoc_properties
* copy_properties(domdoc_properties
const* properties
)
309 domdoc_properties
* pcopy
= heap_alloc(sizeof(domdoc_properties
));
310 select_ns_entry
const* ns
= NULL
;
311 select_ns_entry
* new_ns
= NULL
;
312 int len
= (properties
->selectNsStr_len
+1)*sizeof(xmlChar
);
317 pcopy
->version
= properties
->version
;
318 pcopy
->preserving
= properties
->preserving
;
319 pcopy
->schemaCache
= properties
->schemaCache
;
320 if (pcopy
->schemaCache
)
321 IXMLDOMSchemaCollection2_AddRef(pcopy
->schemaCache
);
322 pcopy
->XPath
= properties
->XPath
;
323 pcopy
->selectNsStr_len
= properties
->selectNsStr_len
;
324 list_init( &pcopy
->selectNsList
);
325 pcopy
->selectNsStr
= heap_alloc(len
);
326 memcpy((xmlChar
*)pcopy
->selectNsStr
, properties
->selectNsStr
, len
);
327 offset
= pcopy
->selectNsStr
- properties
->selectNsStr
;
329 LIST_FOR_EACH_ENTRY( ns
, (&properties
->selectNsList
), select_ns_entry
, entry
)
331 new_ns
= heap_alloc(sizeof(select_ns_entry
));
332 memcpy(new_ns
, ns
, sizeof(select_ns_entry
));
333 new_ns
->href
+= offset
;
334 new_ns
->prefix
+= offset
;
335 list_add_tail(&pcopy
->selectNsList
, &new_ns
->entry
);
340 int len
= strlenW(properties
->url
);
342 pcopy
->url
= CoTaskMemAlloc((len
+1)*sizeof(WCHAR
));
343 memcpy(pcopy
->url
, properties
->url
, len
*sizeof(WCHAR
));
353 static void free_properties(domdoc_properties
* properties
)
357 if (properties
->schemaCache
)
358 IXMLDOMSchemaCollection2_Release(properties
->schemaCache
);
359 clear_selectNsList(&properties
->selectNsList
);
360 heap_free((xmlChar
*)properties
->selectNsStr
);
361 CoTaskMemFree(properties
->url
);
362 heap_free(properties
);
366 static void release_namespaces(domdoc
*This
)
368 if (This
->namespaces
)
370 IXMLDOMSchemaCollection2_Release(This
->namespaces
);
371 This
->namespaces
= NULL
;
375 /* links a "<?xml" node as a first child */
376 void xmldoc_link_xmldecl(xmlDocPtr doc
, xmlNodePtr node
)
379 if (doc
->standalone
!= -1) xmlAddPrevSibling( doc
->children
, node
);
382 /* unlinks a first "<?xml" child if it was created */
383 xmlNodePtr
xmldoc_unlink_xmldecl(xmlDocPtr doc
)
385 static const xmlChar xmlA
[] = "xml";
386 xmlNodePtr node
, first_child
;
390 /* xml declaration node could be created automatically after parsing or added
392 first_child
= doc
->children
;
393 if (first_child
&& first_child
->type
== XML_PI_NODE
&& xmlStrEqual(first_child
->name
, xmlA
))
396 xmlUnlinkNode( node
);
404 BOOL
is_preserving_whitespace(xmlNodePtr node
)
406 domdoc_properties
* properties
= NULL
;
407 /* during parsing the xmlDoc._private stuff is not there */
408 if (priv_from_xmlDocPtr(node
->doc
))
409 properties
= properties_from_xmlDocPtr(node
->doc
);
410 return ((properties
&& properties
->preserving
== VARIANT_TRUE
) ||
411 xmlNodeGetSpacePreserve(node
) == 1);
414 static inline BOOL
strn_isspace(xmlChar
const* str
, int len
)
416 for (; str
&& len
> 0 && *str
; ++str
, --len
)
423 static void sax_characters(void *ctx
, const xmlChar
*ch
, int len
)
425 xmlParserCtxtPtr ctxt
;
428 ctxt
= (xmlParserCtxtPtr
) ctx
;
429 This
= (const domdoc
*) ctxt
->_private
;
433 xmlChar cur
= *(ctxt
->input
->cur
);
435 /* Characters are reported with multiple calls, for example each charref is reported with a separate
436 call and then parser appends it to a single text node or creates a new node if not created.
437 It's not possible to tell if it's ignorable data or not just looking at data itself cause it could be
438 space chars that separate charrefs or similar case. We only need to skip leading and trailing spaces,
439 or whole node if it has nothing but space chars, so to detect leading space node->last is checked that
440 contains text node pointer if already created, trailing spaces are detected directly looking at parser input
441 for next '<' opening bracket - similar logic is used by libxml2 itself. Basically 'cur' == '<' means the last
442 chunk of char data, in case it's not the last chunk we check for previously added node type and if it's not
443 a text node it's safe to ignore.
445 Note that during domdoc_loadXML() the xmlDocPtr->_private data is not available. */
447 if (!This
->properties
->preserving
&&
448 !is_preserving_whitespace(ctxt
->node
) &&
449 strn_isspace(ch
, len
) &&
450 (!ctxt
->node
->last
||
451 ((ctxt
->node
->last
&& (cur
== '<' || ctxt
->node
->last
->type
!= XML_TEXT_NODE
))
456 xmlSAX2Characters(ctxt
, ch
, len
);
459 static void LIBXML2_LOG_CALLBACK
sax_error(void* ctx
, char const* msg
, ...)
463 LIBXML2_CALLBACK_ERR(doparse
, msg
, ap
);
467 static void LIBXML2_LOG_CALLBACK
sax_warning(void* ctx
, char const* msg
, ...)
471 LIBXML2_CALLBACK_WARN(doparse
, msg
, ap
);
475 static void sax_serror(void* ctx
, xmlErrorPtr err
)
477 LIBXML2_CALLBACK_SERROR(doparse
, err
);
480 static xmlDocPtr
doparse(domdoc
* This
, char const* ptr
, int len
, xmlCharEncoding encoding
)
482 xmlDocPtr doc
= NULL
;
483 xmlParserCtxtPtr pctx
;
484 static xmlSAXHandler sax_handler
= {
485 xmlSAX2InternalSubset
, /* internalSubset */
486 xmlSAX2IsStandalone
, /* isStandalone */
487 xmlSAX2HasInternalSubset
, /* hasInternalSubset */
488 xmlSAX2HasExternalSubset
, /* hasExternalSubset */
489 xmlSAX2ResolveEntity
, /* resolveEntity */
490 xmlSAX2GetEntity
, /* getEntity */
491 xmlSAX2EntityDecl
, /* entityDecl */
492 xmlSAX2NotationDecl
, /* notationDecl */
493 xmlSAX2AttributeDecl
, /* attributeDecl */
494 xmlSAX2ElementDecl
, /* elementDecl */
495 xmlSAX2UnparsedEntityDecl
, /* unparsedEntityDecl */
496 xmlSAX2SetDocumentLocator
, /* setDocumentLocator */
497 xmlSAX2StartDocument
, /* startDocument */
498 xmlSAX2EndDocument
, /* endDocument */
499 xmlSAX2StartElement
, /* startElement */
500 xmlSAX2EndElement
, /* endElement */
501 xmlSAX2Reference
, /* reference */
502 sax_characters
, /* characters */
503 sax_characters
, /* ignorableWhitespace */
504 xmlSAX2ProcessingInstruction
, /* processingInstruction */
505 xmlSAX2Comment
, /* comment */
506 sax_warning
, /* warning */
507 sax_error
, /* error */
508 sax_error
, /* fatalError */
509 xmlSAX2GetParameterEntity
, /* getParameterEntity */
510 xmlSAX2CDataBlock
, /* cdataBlock */
511 xmlSAX2ExternalSubset
, /* externalSubset */
514 xmlSAX2StartElementNs
, /* startElementNs */
515 xmlSAX2EndElementNs
, /* endElementNs */
516 sax_serror
/* serror */
519 pctx
= xmlCreateMemoryParserCtxt(ptr
, len
);
522 ERR("Failed to create parser context\n");
526 if (pctx
->sax
) xmlFree(pctx
->sax
);
527 pctx
->sax
= &sax_handler
;
528 pctx
->_private
= This
;
531 if (encoding
!= XML_CHAR_ENCODING_NONE
)
532 xmlSwitchEncoding(pctx
, encoding
);
534 xmlParseDocument(pctx
);
536 if (pctx
->wellFormed
)
542 xmlFreeDoc(pctx
->myDoc
);
546 xmlFreeParserCtxt(pctx
);
548 /* TODO: put this in one of the SAX callbacks */
549 /* create first child as a <?xml...?> */
550 if (doc
&& doc
->standalone
!= -1)
554 xmlChar
*xmlbuff
= (xmlChar
*)buff
;
556 node
= xmlNewDocPI( doc
, (xmlChar
*)"xml", NULL
);
558 /* version attribute can't be omitted */
559 sprintf(buff
, "version=\"%s\"", doc
->version
? (char*)doc
->version
: "1.0");
560 xmlNodeAddContent( node
, xmlbuff
);
564 sprintf(buff
, " encoding=\"%s\"", doc
->encoding
);
565 xmlNodeAddContent( node
, xmlbuff
);
568 if (doc
->standalone
!= -2)
570 sprintf(buff
, " standalone=\"%s\"", doc
->standalone
== 0 ? "no" : "yes");
571 xmlNodeAddContent( node
, xmlbuff
);
574 xmldoc_link_xmldecl( doc
, node
);
580 void xmldoc_init(xmlDocPtr doc
, MSXML_VERSION version
)
582 doc
->_private
= create_priv();
583 priv_from_xmlDocPtr(doc
)->properties
= create_properties(version
);
586 LONG
xmldoc_add_refs(xmlDocPtr doc
, LONG refs
)
588 LONG ref
= InterlockedExchangeAdd(&priv_from_xmlDocPtr(doc
)->refs
, refs
) + refs
;
589 TRACE("(%p)->(%d)\n", doc
, ref
);
593 LONG
xmldoc_add_ref(xmlDocPtr doc
)
595 return xmldoc_add_refs(doc
, 1);
598 LONG
xmldoc_release_refs(xmlDocPtr doc
, LONG refs
)
600 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
601 LONG ref
= InterlockedExchangeAdd(&priv
->refs
, -refs
) - refs
;
602 TRACE("(%p)->(%d)\n", doc
, ref
);
605 WARN("negative refcount, expect troubles\n");
609 orphan_entry
*orphan
, *orphan2
;
610 TRACE("freeing docptr %p\n", doc
);
612 LIST_FOR_EACH_ENTRY_SAFE( orphan
, orphan2
, &priv
->orphans
, orphan_entry
, entry
)
614 xmlFreeNode( orphan
->node
);
617 free_properties(priv
->properties
);
618 heap_free(doc
->_private
);
626 LONG
xmldoc_release(xmlDocPtr doc
)
628 return xmldoc_release_refs(doc
, 1);
631 HRESULT
xmldoc_add_orphan(xmlDocPtr doc
, xmlNodePtr node
)
633 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
636 entry
= heap_alloc( sizeof (*entry
) );
638 return E_OUTOFMEMORY
;
641 list_add_head( &priv
->orphans
, &entry
->entry
);
645 HRESULT
xmldoc_remove_orphan(xmlDocPtr doc
, xmlNodePtr node
)
647 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
648 orphan_entry
*entry
, *entry2
;
650 LIST_FOR_EACH_ENTRY_SAFE( entry
, entry2
, &priv
->orphans
, orphan_entry
, entry
)
652 if( entry
->node
== node
)
654 list_remove( &entry
->entry
);
663 static inline xmlDocPtr
get_doc( domdoc
*This
)
665 return This
->node
.node
->doc
;
668 static HRESULT
attach_xmldoc(domdoc
*This
, xmlDocPtr xml
)
670 release_namespaces(This
);
674 priv_from_xmlDocPtr(get_doc(This
))->properties
= NULL
;
675 if (xmldoc_release(get_doc(This
)) != 0)
676 priv_from_xmlDocPtr(get_doc(This
))->properties
=
677 copy_properties(This
->properties
);
680 This
->node
.node
= (xmlNodePtr
) xml
;
684 xmldoc_add_ref(get_doc(This
));
685 priv_from_xmlDocPtr(get_doc(This
))->properties
= This
->properties
;
691 static inline domdoc
*impl_from_IXMLDOMDocument3( IXMLDOMDocument3
*iface
)
693 return CONTAINING_RECORD(iface
, domdoc
, IXMLDOMDocument3_iface
);
696 static inline domdoc
*impl_from_IPersistStreamInit(IPersistStreamInit
*iface
)
698 return CONTAINING_RECORD(iface
, domdoc
, IPersistStreamInit_iface
);
701 static inline domdoc
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
703 return CONTAINING_RECORD(iface
, domdoc
, IObjectWithSite_iface
);
706 static inline domdoc
*impl_from_IObjectSafety(IObjectSafety
*iface
)
708 return CONTAINING_RECORD(iface
, domdoc
, IObjectSafety_iface
);
711 static inline domdoc
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
713 return CONTAINING_RECORD(iface
, domdoc
, IConnectionPointContainer_iface
);
716 /************************************************************************
717 * domdoc implementation of IPersistStream.
719 static HRESULT WINAPI
PersistStreamInit_QueryInterface(
720 IPersistStreamInit
*iface
, REFIID riid
, void **ppvObj
)
722 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
723 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObj
);
726 static ULONG WINAPI
PersistStreamInit_AddRef(
727 IPersistStreamInit
*iface
)
729 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
730 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
733 static ULONG WINAPI
PersistStreamInit_Release(
734 IPersistStreamInit
*iface
)
736 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
737 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
740 static HRESULT WINAPI
PersistStreamInit_GetClassID(
741 IPersistStreamInit
*iface
, CLSID
*classid
)
743 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
744 TRACE("(%p)->(%p)\n", This
, classid
);
749 *classid
= *DOMDocument_version(This
->properties
->version
);
754 static HRESULT WINAPI
PersistStreamInit_IsDirty(
755 IPersistStreamInit
*iface
)
757 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
758 FIXME("(%p): stub!\n", This
);
762 static HRESULT
domdoc_load_from_stream(domdoc
*doc
, ISequentialStream
*stream
)
764 DWORD read
, written
, len
;
765 xmlDocPtr xmldoc
= NULL
;
773 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &hstream
);
779 ISequentialStream_Read(stream
, buf
, sizeof(buf
), &read
);
780 hr
= IStream_Write(hstream
, buf
, read
, &written
);
781 } while(SUCCEEDED(hr
) && written
!= 0 && read
!= 0);
785 ERR("failed to copy stream 0x%08x\n", hr
);
786 IStream_Release(hstream
);
790 hr
= GetHGlobalFromStream(hstream
, &hglobal
);
794 len
= GlobalSize(hglobal
);
795 ptr
= GlobalLock(hglobal
);
797 xmldoc
= doparse(doc
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
798 GlobalUnlock(hglobal
);
802 ERR("Failed to parse xml\n");
806 xmldoc
->_private
= create_priv();
808 return attach_xmldoc(doc
, xmldoc
);
811 static HRESULT WINAPI
PersistStreamInit_Load(IPersistStreamInit
*iface
, IStream
*stream
)
813 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
815 TRACE("(%p)->(%p)\n", This
, stream
);
820 return domdoc_load_from_stream(This
, (ISequentialStream
*)stream
);
823 static HRESULT WINAPI
PersistStreamInit_Save(
824 IPersistStreamInit
*iface
, IStream
*stream
, BOOL clr_dirty
)
826 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
830 TRACE("(%p)->(%p %d)\n", This
, stream
, clr_dirty
);
832 hr
= IXMLDOMDocument3_get_xml(&This
->IXMLDOMDocument3_iface
, &xmlString
);
835 DWORD len
= SysStringLen(xmlString
) * sizeof(WCHAR
);
837 hr
= IStream_Write( stream
, xmlString
, len
, NULL
);
838 SysFreeString(xmlString
);
841 TRACE("ret 0x%08x\n", hr
);
846 static HRESULT WINAPI
PersistStreamInit_GetSizeMax(
847 IPersistStreamInit
*iface
, ULARGE_INTEGER
*pcbSize
)
849 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
850 TRACE("(%p)->(%p)\n", This
, pcbSize
);
854 static HRESULT WINAPI
PersistStreamInit_InitNew(
855 IPersistStreamInit
*iface
)
857 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
858 TRACE("(%p)\n", This
);
862 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable
=
864 PersistStreamInit_QueryInterface
,
865 PersistStreamInit_AddRef
,
866 PersistStreamInit_Release
,
867 PersistStreamInit_GetClassID
,
868 PersistStreamInit_IsDirty
,
869 PersistStreamInit_Load
,
870 PersistStreamInit_Save
,
871 PersistStreamInit_GetSizeMax
,
872 PersistStreamInit_InitNew
875 /* IXMLDOMDocument3 interface */
877 static const tid_t domdoc_se_tids
[] = {
880 IXMLDOMDocument2_tid
,
881 IXMLDOMDocument3_tid
,
885 static HRESULT WINAPI
domdoc_QueryInterface( IXMLDOMDocument3
*iface
, REFIID riid
, void** ppvObject
)
887 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
889 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( riid
), ppvObject
);
893 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
894 IsEqualGUID( riid
, &IID_IDispatch
) ||
895 IsEqualGUID( riid
, &IID_IXMLDOMNode
) ||
896 IsEqualGUID( riid
, &IID_IXMLDOMDocument
) ||
897 IsEqualGUID( riid
, &IID_IXMLDOMDocument2
)||
898 IsEqualGUID( riid
, &IID_IXMLDOMDocument3
))
902 else if (IsEqualGUID(&IID_IPersistStream
, riid
) ||
903 IsEqualGUID(&IID_IPersistStreamInit
, riid
))
905 *ppvObject
= &This
->IPersistStreamInit_iface
;
907 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
909 *ppvObject
= &This
->IObjectWithSite_iface
;
911 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
913 *ppvObject
= &This
->IObjectSafety_iface
;
915 else if( IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
917 return node_create_supporterrorinfo(domdoc_se_tids
, ppvObject
);
919 else if(node_query_interface(&This
->node
, riid
, ppvObject
))
921 return *ppvObject
? S_OK
: E_NOINTERFACE
;
923 else if (IsEqualGUID( riid
, &IID_IConnectionPointContainer
))
925 *ppvObject
= &This
->IConnectionPointContainer_iface
;
929 TRACE("interface %s not implemented\n", debugstr_guid(riid
));
930 return E_NOINTERFACE
;
933 IUnknown_AddRef((IUnknown
*)*ppvObject
);
938 static ULONG WINAPI
domdoc_AddRef( IXMLDOMDocument3
*iface
)
940 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
941 ULONG ref
= InterlockedIncrement( &This
->ref
);
942 TRACE("(%p)->(%d)\n", This
, ref
);
946 static ULONG WINAPI
domdoc_Release( IXMLDOMDocument3
*iface
)
948 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
949 LONG ref
= InterlockedDecrement( &This
->ref
);
951 TRACE("(%p)->(%d)\n", This
, ref
);
958 IUnknown_Release( This
->site
);
959 destroy_xmlnode(&This
->node
);
961 for (eid
= 0; eid
< EVENTID_LAST
; eid
++)
962 if (This
->events
[eid
]) IDispatch_Release(This
->events
[eid
]);
964 release_namespaces(This
);
971 static HRESULT WINAPI
domdoc_GetTypeInfoCount( IXMLDOMDocument3
*iface
, UINT
* pctinfo
)
973 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
974 return IDispatchEx_GetTypeInfoCount(&This
->node
.dispex
.IDispatchEx_iface
, pctinfo
);
977 static HRESULT WINAPI
domdoc_GetTypeInfo(
978 IXMLDOMDocument3
*iface
,
979 UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
981 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
982 return IDispatchEx_GetTypeInfo(&This
->node
.dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
985 static HRESULT WINAPI
domdoc_GetIDsOfNames(
986 IXMLDOMDocument3
*iface
,
993 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
994 return IDispatchEx_GetIDsOfNames(&This
->node
.dispex
.IDispatchEx_iface
,
995 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
998 static HRESULT WINAPI
domdoc_Invoke(
999 IXMLDOMDocument3
*iface
,
1000 DISPID dispIdMember
,
1004 DISPPARAMS
* pDispParams
,
1005 VARIANT
* pVarResult
,
1006 EXCEPINFO
* pExcepInfo
,
1009 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1010 return IDispatchEx_Invoke(&This
->node
.dispex
.IDispatchEx_iface
,
1011 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1014 static HRESULT WINAPI
domdoc_get_nodeName(
1015 IXMLDOMDocument3
*iface
,
1018 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1020 static const WCHAR documentW
[] = {'#','d','o','c','u','m','e','n','t',0};
1022 TRACE("(%p)->(%p)\n", This
, name
);
1024 return return_bstr(documentW
, name
);
1028 static HRESULT WINAPI
domdoc_get_nodeValue(
1029 IXMLDOMDocument3
*iface
,
1032 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1034 TRACE("(%p)->(%p)\n", This
, value
);
1037 return E_INVALIDARG
;
1039 V_VT(value
) = VT_NULL
;
1040 V_BSTR(value
) = NULL
; /* tests show that we should do this */
1045 static HRESULT WINAPI
domdoc_put_nodeValue(
1046 IXMLDOMDocument3
*iface
,
1049 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1050 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&value
));
1055 static HRESULT WINAPI
domdoc_get_nodeType(
1056 IXMLDOMDocument3
*iface
,
1059 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1061 TRACE("(%p)->(%p)\n", This
, type
);
1063 *type
= NODE_DOCUMENT
;
1068 static HRESULT WINAPI
domdoc_get_parentNode(
1069 IXMLDOMDocument3
*iface
,
1070 IXMLDOMNode
** parent
)
1072 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1074 TRACE("(%p)->(%p)\n", This
, parent
);
1076 return node_get_parent(&This
->node
, parent
);
1080 static HRESULT WINAPI
domdoc_get_childNodes(
1081 IXMLDOMDocument3
*iface
,
1082 IXMLDOMNodeList
** childList
)
1084 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1086 TRACE("(%p)->(%p)\n", This
, childList
);
1088 return node_get_child_nodes(&This
->node
, childList
);
1092 static HRESULT WINAPI
domdoc_get_firstChild(
1093 IXMLDOMDocument3
*iface
,
1094 IXMLDOMNode
** firstChild
)
1096 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1098 TRACE("(%p)->(%p)\n", This
, firstChild
);
1100 return node_get_first_child(&This
->node
, firstChild
);
1104 static HRESULT WINAPI
domdoc_get_lastChild(
1105 IXMLDOMDocument3
*iface
,
1106 IXMLDOMNode
** lastChild
)
1108 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1110 TRACE("(%p)->(%p)\n", This
, lastChild
);
1112 return node_get_last_child(&This
->node
, lastChild
);
1116 static HRESULT WINAPI
domdoc_get_previousSibling(
1117 IXMLDOMDocument3
*iface
,
1118 IXMLDOMNode
** previousSibling
)
1120 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1122 TRACE("(%p)->(%p)\n", This
, previousSibling
);
1124 return return_null_node(previousSibling
);
1128 static HRESULT WINAPI
domdoc_get_nextSibling(
1129 IXMLDOMDocument3
*iface
,
1130 IXMLDOMNode
** nextSibling
)
1132 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1134 TRACE("(%p)->(%p)\n", This
, nextSibling
);
1136 return return_null_node(nextSibling
);
1140 static HRESULT WINAPI
domdoc_get_attributes(
1141 IXMLDOMDocument3
*iface
,
1142 IXMLDOMNamedNodeMap
** attributeMap
)
1144 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1146 TRACE("(%p)->(%p)\n", This
, attributeMap
);
1148 return return_null_ptr((void**)attributeMap
);
1152 static HRESULT WINAPI
domdoc_insertBefore(
1153 IXMLDOMDocument3
*iface
,
1154 IXMLDOMNode
* newChild
,
1156 IXMLDOMNode
** outNewChild
)
1158 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1162 TRACE("(%p)->(%p %s %p)\n", This
, newChild
, debugstr_variant(&refChild
), outNewChild
);
1164 hr
= IXMLDOMNode_get_nodeType(newChild
, &type
);
1165 if (hr
!= S_OK
) return hr
;
1167 TRACE("new node type %d\n", type
);
1170 case NODE_ATTRIBUTE
:
1172 case NODE_CDATA_SECTION
:
1173 if (outNewChild
) *outNewChild
= NULL
;
1176 return node_insert_before(&This
->node
, newChild
, &refChild
, outNewChild
);
1180 static HRESULT WINAPI
domdoc_replaceChild(
1181 IXMLDOMDocument3
*iface
,
1182 IXMLDOMNode
* newChild
,
1183 IXMLDOMNode
* oldChild
,
1184 IXMLDOMNode
** outOldChild
)
1186 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1188 TRACE("(%p)->(%p %p %p)\n", This
, newChild
, oldChild
, outOldChild
);
1190 return node_replace_child(&This
->node
, newChild
, oldChild
, outOldChild
);
1194 static HRESULT WINAPI
domdoc_removeChild(
1195 IXMLDOMDocument3
*iface
,
1197 IXMLDOMNode
**oldChild
)
1199 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1200 TRACE("(%p)->(%p %p)\n", This
, child
, oldChild
);
1201 return node_remove_child(&This
->node
, child
, oldChild
);
1205 static HRESULT WINAPI
domdoc_appendChild(
1206 IXMLDOMDocument3
*iface
,
1208 IXMLDOMNode
**outChild
)
1210 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1211 TRACE("(%p)->(%p %p)\n", This
, child
, outChild
);
1212 return node_append_child(&This
->node
, child
, outChild
);
1216 static HRESULT WINAPI
domdoc_hasChildNodes(
1217 IXMLDOMDocument3
*iface
,
1220 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1221 TRACE("(%p)->(%p)\n", This
, ret
);
1222 return node_has_childnodes(&This
->node
, ret
);
1226 static HRESULT WINAPI
domdoc_get_ownerDocument(
1227 IXMLDOMDocument3
*iface
,
1228 IXMLDOMDocument
**doc
)
1230 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1231 TRACE("(%p)->(%p)\n", This
, doc
);
1232 return node_get_owner_doc(&This
->node
, doc
);
1236 static HRESULT WINAPI
domdoc_cloneNode(
1237 IXMLDOMDocument3
*iface
,
1239 IXMLDOMNode
** outNode
)
1241 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1242 TRACE("(%p)->(%d %p)\n", This
, deep
, outNode
);
1243 return node_clone( &This
->node
, deep
, outNode
);
1247 static HRESULT WINAPI
domdoc_get_nodeTypeString(
1248 IXMLDOMDocument3
*iface
,
1251 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1252 static const WCHAR documentW
[] = {'d','o','c','u','m','e','n','t',0};
1254 TRACE("(%p)->(%p)\n", This
, p
);
1256 return return_bstr(documentW
, p
);
1260 static HRESULT WINAPI
domdoc_get_text(
1261 IXMLDOMDocument3
*iface
,
1264 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1265 TRACE("(%p)->(%p)\n", This
, p
);
1266 return node_get_text(&This
->node
, p
);
1270 static HRESULT WINAPI
domdoc_put_text(
1271 IXMLDOMDocument3
*iface
,
1274 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1275 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
1280 static HRESULT WINAPI
domdoc_get_specified(
1281 IXMLDOMDocument3
*iface
,
1282 VARIANT_BOOL
* isSpecified
)
1284 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1285 FIXME("(%p)->(%p) stub!\n", This
, isSpecified
);
1286 *isSpecified
= VARIANT_TRUE
;
1291 static HRESULT WINAPI
domdoc_get_definition(
1292 IXMLDOMDocument3
*iface
,
1293 IXMLDOMNode
** definitionNode
)
1295 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1296 FIXME("(%p)->(%p)\n", This
, definitionNode
);
1301 static HRESULT WINAPI
domdoc_get_nodeTypedValue(
1302 IXMLDOMDocument3
*iface
,
1305 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1306 TRACE("(%p)->(%p)\n", This
, v
);
1307 return return_null_var(v
);
1310 static HRESULT WINAPI
domdoc_put_nodeTypedValue(
1311 IXMLDOMDocument3
*iface
,
1312 VARIANT typedValue
)
1314 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1315 FIXME("(%p)->(%s)\n", This
, debugstr_variant(&typedValue
));
1320 static HRESULT WINAPI
domdoc_get_dataType(
1321 IXMLDOMDocument3
*iface
,
1324 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1325 TRACE("(%p)->(%p)\n", This
, typename
);
1326 return return_null_var( typename
);
1330 static HRESULT WINAPI
domdoc_put_dataType(
1331 IXMLDOMDocument3
*iface
,
1334 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1336 FIXME("(%p)->(%s)\n", This
, debugstr_w(dataTypeName
));
1339 return E_INVALIDARG
;
1344 static int XMLCALL
domdoc_get_xml_writecallback(void *ctx
, const char *data
, int len
)
1346 return xmlBufferAdd((xmlBufferPtr
)ctx
, (xmlChar
*)data
, len
) == 0 ? len
: 0;
1349 static HRESULT WINAPI
domdoc_get_xml(
1350 IXMLDOMDocument3
*iface
,
1353 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1354 xmlSaveCtxtPtr ctxt
;
1359 TRACE("(%p)->(%p)\n", This
, p
);
1362 return E_INVALIDARG
;
1366 buf
= xmlBufferCreate();
1368 return E_OUTOFMEMORY
;
1370 options
= XML_SAVE_FORMAT
| XML_SAVE_NO_DECL
;
1371 ctxt
= xmlSaveToIO(domdoc_get_xml_writecallback
, NULL
, buf
, "UTF-8", options
);
1376 return E_OUTOFMEMORY
;
1379 ret
= xmlSaveDoc(ctxt
, get_doc(This
));
1380 /* flushes on close */
1383 TRACE("%ld, len=%d\n", ret
, xmlBufferLength(buf
));
1384 if(ret
!= -1 && xmlBufferLength(buf
) > 0)
1388 content
= bstr_from_xmlChar(xmlBufferContent(buf
));
1389 content
= EnsureCorrectEOL(content
);
1395 *p
= SysAllocStringLen(NULL
, 0);
1400 return *p
? S_OK
: E_OUTOFMEMORY
;
1404 static HRESULT WINAPI
domdoc_transformNode(
1405 IXMLDOMDocument3
*iface
,
1409 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1410 TRACE("(%p)->(%p %p)\n", This
, node
, p
);
1411 return node_transform_node(&This
->node
, node
, p
);
1415 static HRESULT WINAPI
domdoc_selectNodes(
1416 IXMLDOMDocument3
*iface
,
1418 IXMLDOMNodeList
**outList
)
1420 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1421 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outList
);
1422 return node_select_nodes(&This
->node
, p
, outList
);
1426 static HRESULT WINAPI
domdoc_selectSingleNode(
1427 IXMLDOMDocument3
*iface
,
1429 IXMLDOMNode
**outNode
)
1431 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1432 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outNode
);
1433 return node_select_singlenode(&This
->node
, p
, outNode
);
1437 static HRESULT WINAPI
domdoc_get_parsed(
1438 IXMLDOMDocument3
*iface
,
1439 VARIANT_BOOL
* isParsed
)
1441 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1442 FIXME("(%p)->(%p) stub!\n", This
, isParsed
);
1443 *isParsed
= VARIANT_TRUE
;
1447 static HRESULT WINAPI
domdoc_get_namespaceURI(
1448 IXMLDOMDocument3
*iface
,
1449 BSTR
* namespaceURI
)
1451 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1452 TRACE("(%p)->(%p)\n", This
, namespaceURI
);
1453 return return_null_bstr( namespaceURI
);
1456 static HRESULT WINAPI
domdoc_get_prefix(
1457 IXMLDOMDocument3
*iface
,
1460 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1461 TRACE("(%p)->(%p)\n", This
, prefix
);
1462 return return_null_bstr( prefix
);
1466 static HRESULT WINAPI
domdoc_get_baseName(
1467 IXMLDOMDocument3
*iface
,
1470 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1471 TRACE("(%p)->(%p)\n", This
, name
);
1472 return return_null_bstr( name
);
1476 static HRESULT WINAPI
domdoc_transformNodeToObject(
1477 IXMLDOMDocument3
*iface
,
1478 IXMLDOMNode
* stylesheet
,
1479 VARIANT outputObject
)
1481 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1482 FIXME("(%p)->(%p %s)\n", This
, stylesheet
, debugstr_variant(&outputObject
));
1487 static HRESULT WINAPI
domdoc_get_doctype(
1488 IXMLDOMDocument3
*iface
,
1489 IXMLDOMDocumentType
** doctype
)
1491 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1496 TRACE("(%p)->(%p)\n", This
, doctype
);
1498 if (!doctype
) return E_INVALIDARG
;
1502 dtd
= xmlGetIntSubset(get_doc(This
));
1503 if (!dtd
) return S_FALSE
;
1505 node
= create_node((xmlNodePtr
)dtd
);
1506 if (!node
) return S_FALSE
;
1508 hr
= IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentType
, (void**)doctype
);
1509 IXMLDOMNode_Release(node
);
1515 static HRESULT WINAPI
domdoc_get_implementation(
1516 IXMLDOMDocument3
*iface
,
1517 IXMLDOMImplementation
** impl
)
1519 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1521 TRACE("(%p)->(%p)\n", This
, impl
);
1524 return E_INVALIDARG
;
1526 *impl
= (IXMLDOMImplementation
*)create_doc_Implementation();
1531 static HRESULT WINAPI
domdoc_get_documentElement(
1532 IXMLDOMDocument3
*iface
,
1533 IXMLDOMElement
** DOMElement
)
1535 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1536 IXMLDOMNode
*element_node
;
1540 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1543 return E_INVALIDARG
;
1547 root
= xmlDocGetRootElement( get_doc(This
) );
1551 element_node
= create_node( root
);
1552 if(!element_node
) return S_FALSE
;
1554 hr
= IXMLDOMNode_QueryInterface(element_node
, &IID_IXMLDOMElement
, (void**)DOMElement
);
1555 IXMLDOMNode_Release(element_node
);
1561 static HRESULT WINAPI
domdoc_put_documentElement(
1562 IXMLDOMDocument3
*iface
,
1563 IXMLDOMElement
* DOMElement
)
1565 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1566 IXMLDOMNode
*elementNode
;
1573 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1575 hr
= IXMLDOMElement_QueryInterface( DOMElement
, &IID_IXMLDOMNode
, (void**)&elementNode
);
1579 xmlNode
= get_node_obj( elementNode
);
1580 if(!xmlNode
) return E_FAIL
;
1582 if(!xmlNode
->node
->parent
)
1583 if(xmldoc_remove_orphan(xmlNode
->node
->doc
, xmlNode
->node
) != S_OK
)
1584 WARN("%p is not an orphan of %p\n", xmlNode
->node
->doc
, xmlNode
->node
);
1586 old_doc
= xmlNode
->node
->doc
;
1587 if (old_doc
!= get_doc(This
))
1588 refcount
= xmlnode_get_inst_cnt(xmlNode
);
1590 /* old root is still orphaned by its document, update refcount from new root */
1591 if (refcount
) xmldoc_add_refs(get_doc(This
), refcount
);
1592 oldRoot
= xmlDocSetRootElement( get_doc(This
), xmlNode
->node
);
1593 if (refcount
) xmldoc_release_refs(old_doc
, refcount
);
1594 IXMLDOMNode_Release( elementNode
);
1597 xmldoc_add_orphan(oldRoot
->doc
, oldRoot
);
1603 static HRESULT WINAPI
domdoc_createElement(
1604 IXMLDOMDocument3
*iface
,
1606 IXMLDOMElement
** element
)
1608 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1613 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(tagname
), element
);
1615 if (!element
|| !tagname
) return E_INVALIDARG
;
1617 V_VT(&type
) = VT_I1
;
1618 V_I1(&type
) = NODE_ELEMENT
;
1620 hr
= IXMLDOMDocument3_createNode(iface
, type
, tagname
, NULL
, &node
);
1623 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMElement
, (void**)element
);
1624 IXMLDOMNode_Release(node
);
1631 static HRESULT WINAPI
domdoc_createDocumentFragment(
1632 IXMLDOMDocument3
*iface
,
1633 IXMLDOMDocumentFragment
** frag
)
1635 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1640 TRACE("(%p)->(%p)\n", This
, frag
);
1642 if (!frag
) return E_INVALIDARG
;
1646 V_VT(&type
) = VT_I1
;
1647 V_I1(&type
) = NODE_DOCUMENT_FRAGMENT
;
1649 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1652 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentFragment
, (void**)frag
);
1653 IXMLDOMNode_Release(node
);
1660 static HRESULT WINAPI
domdoc_createTextNode(
1661 IXMLDOMDocument3
*iface
,
1663 IXMLDOMText
** text
)
1665 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1670 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), text
);
1672 if (!text
) return E_INVALIDARG
;
1676 V_VT(&type
) = VT_I1
;
1677 V_I1(&type
) = NODE_TEXT
;
1679 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1682 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMText
, (void**)text
);
1683 IXMLDOMNode_Release(node
);
1684 hr
= IXMLDOMText_put_data(*text
, data
);
1691 static HRESULT WINAPI
domdoc_createComment(
1692 IXMLDOMDocument3
*iface
,
1694 IXMLDOMComment
** comment
)
1696 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1701 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), comment
);
1703 if (!comment
) return E_INVALIDARG
;
1707 V_VT(&type
) = VT_I1
;
1708 V_I1(&type
) = NODE_COMMENT
;
1710 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1713 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMComment
, (void**)comment
);
1714 IXMLDOMNode_Release(node
);
1715 hr
= IXMLDOMComment_put_data(*comment
, data
);
1722 static HRESULT WINAPI
domdoc_createCDATASection(
1723 IXMLDOMDocument3
*iface
,
1725 IXMLDOMCDATASection
** cdata
)
1727 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1732 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), cdata
);
1734 if (!cdata
) return E_INVALIDARG
;
1738 V_VT(&type
) = VT_I1
;
1739 V_I1(&type
) = NODE_CDATA_SECTION
;
1741 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1744 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMCDATASection
, (void**)cdata
);
1745 IXMLDOMNode_Release(node
);
1746 hr
= IXMLDOMCDATASection_put_data(*cdata
, data
);
1753 static HRESULT WINAPI
domdoc_createProcessingInstruction(
1754 IXMLDOMDocument3
*iface
,
1757 IXMLDOMProcessingInstruction
** pi
)
1759 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1764 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_w(target
), debugstr_w(data
), pi
);
1766 if (!pi
) return E_INVALIDARG
;
1770 V_VT(&type
) = VT_I1
;
1771 V_I1(&type
) = NODE_PROCESSING_INSTRUCTION
;
1773 hr
= IXMLDOMDocument3_createNode(iface
, type
, target
, NULL
, &node
);
1778 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1779 node_obj
= get_node_obj(node
);
1780 hr
= node_set_content(node_obj
, data
);
1782 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMProcessingInstruction
, (void**)pi
);
1783 IXMLDOMNode_Release(node
);
1790 static HRESULT WINAPI
domdoc_createAttribute(
1791 IXMLDOMDocument3
*iface
,
1793 IXMLDOMAttribute
** attribute
)
1795 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1800 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), attribute
);
1802 if (!attribute
|| !name
) return E_INVALIDARG
;
1804 V_VT(&type
) = VT_I1
;
1805 V_I1(&type
) = NODE_ATTRIBUTE
;
1807 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1810 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMAttribute
, (void**)attribute
);
1811 IXMLDOMNode_Release(node
);
1818 static HRESULT WINAPI
domdoc_createEntityReference(
1819 IXMLDOMDocument3
*iface
,
1821 IXMLDOMEntityReference
** entityref
)
1823 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1828 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), entityref
);
1830 if (!entityref
) return E_INVALIDARG
;
1834 V_VT(&type
) = VT_I1
;
1835 V_I1(&type
) = NODE_ENTITY_REFERENCE
;
1837 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1840 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMEntityReference
, (void**)entityref
);
1841 IXMLDOMNode_Release(node
);
1847 xmlChar
* tagName_to_XPath(const BSTR tagName
)
1849 xmlChar
*query
, *tmp
;
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 query
= xmlStrdup(prefix
);
1859 while (tokBegin
&& *tokBegin
)
1864 query
= xmlStrcat(query
, BAD_CAST
"/");
1868 query
= xmlStrcat(query
, BAD_CAST
"*");
1872 query
= xmlStrcat(query
, mod_pre
);
1874 while (*tokEnd
&& *tokEnd
!= '/')
1876 len
= WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, NULL
, 0, NULL
, NULL
);
1877 tmp
= xmlMalloc(len
);
1878 WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, (char*)tmp
, len
, NULL
, NULL
);
1879 query
= xmlStrncat(query
, tmp
, len
);
1882 query
= xmlStrcat(query
, mod_post
);
1889 static HRESULT WINAPI
domdoc_getElementsByTagName(
1890 IXMLDOMDocument3
*iface
,
1892 IXMLDOMNodeList
** resultList
)
1894 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1899 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(tagName
), resultList
);
1901 if (!tagName
|| !resultList
) return E_INVALIDARG
;
1903 XPath
= This
->properties
->XPath
;
1904 This
->properties
->XPath
= TRUE
;
1905 query
= tagName_to_XPath(tagName
);
1906 hr
= create_selection((xmlNodePtr
)get_doc(This
), query
, resultList
);
1908 This
->properties
->XPath
= XPath
;
1913 static HRESULT
get_node_type(VARIANT Type
, DOMNodeType
* type
)
1919 hr
= VariantChangeType(&tmp
, &Type
, 0, VT_I4
);
1921 return E_INVALIDARG
;
1928 static HRESULT WINAPI
domdoc_createNode(
1929 IXMLDOMDocument3
*iface
,
1933 IXMLDOMNode
** node
)
1935 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1936 DOMNodeType node_type
;
1938 xmlChar
*xml_name
, *href
;
1941 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_variant(&Type
), debugstr_w(name
), debugstr_w(namespaceURI
), node
);
1943 if(!node
) return E_INVALIDARG
;
1945 hr
= get_node_type(Type
, &node_type
);
1946 if(FAILED(hr
)) return hr
;
1948 TRACE("node_type %d\n", node_type
);
1950 /* exit earlier for types that need name */
1954 case NODE_ATTRIBUTE
:
1955 case NODE_ENTITY_REFERENCE
:
1956 case NODE_PROCESSING_INSTRUCTION
:
1957 if (!name
|| *name
== 0) return E_FAIL
;
1963 xml_name
= xmlchar_from_wchar(name
);
1964 /* prevent empty href to be allocated */
1965 href
= namespaceURI
? xmlchar_from_wchar(namespaceURI
) : NULL
;
1971 xmlChar
*local
, *prefix
;
1973 local
= xmlSplitQName2(xml_name
, &prefix
);
1975 xmlnode
= xmlNewDocNode(get_doc(This
), NULL
, local
? local
: xml_name
, NULL
);
1977 /* allow to create default namespace xmlns= */
1978 if (local
|| (href
&& *href
))
1980 xmlNsPtr ns
= xmlNewNs(xmlnode
, href
, prefix
);
1981 xmlSetNs(xmlnode
, ns
);
1989 case NODE_ATTRIBUTE
:
1991 xmlChar
*local
, *prefix
;
1993 local
= xmlSplitQName2(xml_name
, &prefix
);
1995 xmlnode
= (xmlNodePtr
)xmlNewDocProp(get_doc(This
), local
? local
: xml_name
, NULL
);
1997 if (local
|| (href
&& *href
))
1999 /* we need a floating namespace here, it can't be created linked to attribute from
2001 xmlNsPtr ns
= xmlNewNs(NULL
, href
, prefix
);
2002 xmlSetNs(xmlnode
, ns
);
2011 xmlnode
= (xmlNodePtr
)xmlNewDocText(get_doc(This
), NULL
);
2013 case NODE_CDATA_SECTION
:
2014 xmlnode
= xmlNewCDataBlock(get_doc(This
), NULL
, 0);
2016 case NODE_ENTITY_REFERENCE
:
2017 xmlnode
= xmlNewReference(get_doc(This
), xml_name
);
2019 case NODE_PROCESSING_INSTRUCTION
:
2020 #ifdef HAVE_XMLNEWDOCPI
2021 xmlnode
= xmlNewDocPI(get_doc(This
), xml_name
, NULL
);
2023 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2028 xmlnode
= xmlNewDocComment(get_doc(This
), NULL
);
2030 case NODE_DOCUMENT_FRAGMENT
:
2031 xmlnode
= xmlNewDocFragment(get_doc(This
));
2033 /* unsupported types */
2035 case NODE_DOCUMENT_TYPE
:
2038 heap_free(xml_name
);
2039 return E_INVALIDARG
;
2041 FIXME("unhandled node type %d\n", node_type
);
2046 *node
= create_node(xmlnode
);
2047 heap_free(xml_name
);
2052 TRACE("created node (%d, %p, %p)\n", node_type
, *node
, xmlnode
);
2053 xmldoc_add_orphan(xmlnode
->doc
, xmlnode
);
2060 static HRESULT WINAPI
domdoc_nodeFromID(
2061 IXMLDOMDocument3
*iface
,
2063 IXMLDOMNode
** node
)
2065 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2066 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(idString
), node
);
2070 static HRESULT
domdoc_onDataAvailable(void *obj
, char *ptr
, DWORD len
)
2075 xmldoc
= doparse(This
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
2077 xmldoc
->_private
= create_priv();
2078 return attach_xmldoc(This
, xmldoc
);
2084 static HRESULT
domdoc_load_moniker(domdoc
*This
, IMoniker
*mon
)
2089 hr
= bind_url(mon
, domdoc_onDataAvailable
, This
, &bsc
);
2093 return detach_bsc(bsc
);
2096 static HRESULT WINAPI
domdoc_load(
2097 IXMLDOMDocument3
*iface
,
2099 VARIANT_BOOL
* isSuccessful
)
2101 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2102 LPWSTR filename
= NULL
;
2103 HRESULT hr
= S_FALSE
;
2106 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&source
));
2110 *isSuccessful
= VARIANT_FALSE
;
2112 assert( &This
->node
);
2114 switch( V_VT(&source
) )
2117 filename
= V_BSTR(&source
);
2119 case VT_BSTR
|VT_BYREF
:
2120 if (!V_BSTRREF(&source
)) return E_INVALIDARG
;
2121 filename
= *V_BSTRREF(&source
);
2123 case VT_ARRAY
|VT_UI1
:
2125 SAFEARRAY
*psa
= V_ARRAY(&source
);
2128 UINT dim
= SafeArrayGetDim(psa
);
2133 ERR("SAFEARRAY == NULL\n");
2134 hr
= This
->error
= E_INVALIDARG
;
2137 /* Only takes UTF-8 strings.
2138 * NOT NULL-terminated. */
2139 SafeArrayAccessData(psa
, (void**)&str
);
2140 SafeArrayGetUBound(psa
, 1, &len
);
2142 if ((xmldoc
= doparse(This
, str
, ++len
, XML_CHAR_ENCODING_UTF8
)))
2144 hr
= This
->error
= S_OK
;
2145 *isSuccessful
= VARIANT_TRUE
;
2146 TRACE("parsed document %p\n", xmldoc
);
2150 This
->error
= E_FAIL
;
2151 TRACE("failed to parse document\n");
2154 SafeArrayUnaccessData(psa
);
2158 xmldoc
->_private
= create_priv();
2159 return attach_xmldoc(This
, xmldoc
);
2163 FIXME("unhandled SAFEARRAY dim: %d\n", dim
);
2164 hr
= This
->error
= E_NOTIMPL
;
2170 ISequentialStream
*stream
= NULL
;
2171 IXMLDOMDocument3
*newdoc
= NULL
;
2173 if (!V_UNKNOWN(&source
)) return E_INVALIDARG
;
2175 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IXMLDOMDocument3
, (void**)&newdoc
);
2180 domdoc
*newDoc
= impl_from_IXMLDOMDocument3( newdoc
);
2182 xmldoc
= xmlCopyDoc(get_doc(newDoc
), 1);
2183 xmldoc
->_private
= create_priv();
2184 hr
= attach_xmldoc(This
, xmldoc
);
2187 *isSuccessful
= VARIANT_TRUE
;
2193 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IStream
, (void**)&stream
);
2195 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_ISequentialStream
, (void**)&stream
);
2199 hr
= domdoc_load_from_stream(This
, stream
);
2201 *isSuccessful
= VARIANT_TRUE
;
2202 ISequentialStream_Release(stream
);
2206 FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr
, V_UNKNOWN(&source
)->lpVtbl
);
2210 FIXME("VT type not supported (%d)\n", V_VT(&source
));
2217 CoTaskMemFree(This
->properties
->url
);
2218 This
->properties
->url
= NULL
;
2220 hr
= create_moniker_from_url( filename
, &mon
);
2221 if ( SUCCEEDED(hr
) )
2223 hr
= domdoc_load_moniker( This
, mon
);
2225 IMoniker_GetDisplayName(mon
, NULL
, NULL
, &This
->properties
->url
);
2226 IMoniker_Release(mon
);
2230 This
->error
= E_FAIL
;
2233 hr
= This
->error
= S_OK
;
2234 *isSuccessful
= VARIANT_TRUE
;
2238 if(!filename
|| FAILED(hr
)) {
2239 xmldoc
= xmlNewDoc(NULL
);
2240 xmldoc
->_private
= create_priv();
2241 hr
= attach_xmldoc(This
, xmldoc
);
2246 TRACE("ret (%d)\n", hr
);
2252 static HRESULT WINAPI
domdoc_get_readyState(
2253 IXMLDOMDocument3
*iface
,
2256 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2257 FIXME("stub! (%p)->(%p)\n", This
, value
);
2260 return E_INVALIDARG
;
2262 *value
= READYSTATE_COMPLETE
;
2267 static HRESULT WINAPI
domdoc_get_parseError(
2268 IXMLDOMDocument3
*iface
,
2269 IXMLDOMParseError
** errorObj
)
2271 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2272 static const WCHAR err
[] = {'e','r','r','o','r',0};
2273 BSTR error_string
= NULL
;
2275 FIXME("(%p)->(%p): creating a dummy parseError\n", iface
, errorObj
);
2278 error_string
= SysAllocString(err
);
2280 *errorObj
= create_parseError(This
->error
, NULL
, error_string
, NULL
, 0, 0, 0);
2281 if(!*errorObj
) return E_OUTOFMEMORY
;
2286 static HRESULT WINAPI
domdoc_get_url(
2287 IXMLDOMDocument3
*iface
,
2290 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2292 TRACE("(%p)->(%p)\n", This
, url
);
2295 return E_INVALIDARG
;
2297 if (This
->properties
->url
)
2299 *url
= SysAllocString(This
->properties
->url
);
2301 return E_OUTOFMEMORY
;
2306 return return_null_bstr(url
);
2310 static HRESULT WINAPI
domdoc_get_async(
2311 IXMLDOMDocument3
*iface
,
2312 VARIANT_BOOL
* isAsync
)
2314 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2316 TRACE("(%p)->(%p: %d)\n", This
, isAsync
, This
->async
);
2317 *isAsync
= This
->async
;
2322 static HRESULT WINAPI
domdoc_put_async(
2323 IXMLDOMDocument3
*iface
,
2324 VARIANT_BOOL isAsync
)
2326 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2328 TRACE("(%p)->(%d)\n", This
, isAsync
);
2329 This
->async
= isAsync
;
2334 static HRESULT WINAPI
domdoc_abort(
2335 IXMLDOMDocument3
*iface
)
2337 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2338 FIXME("%p\n", This
);
2342 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2343 static HRESULT WINAPI
domdoc_loadXML(
2344 IXMLDOMDocument3
*iface
,
2346 VARIANT_BOOL
* isSuccessful
)
2348 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2349 xmlDocPtr xmldoc
= NULL
;
2350 HRESULT hr
= S_FALSE
, hr2
;
2352 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), isSuccessful
);
2354 assert ( &This
->node
);
2358 *isSuccessful
= VARIANT_FALSE
;
2364 /* skip leading spaces if needed */
2365 if (This
->properties
->version
== MSXML_DEFAULT
|| This
->properties
->version
== MSXML26
)
2366 while (*ptr
&& isspaceW(*ptr
)) ptr
++;
2368 xmldoc
= doparse(This
, (char*)ptr
, strlenW(ptr
)*sizeof(WCHAR
), XML_CHAR_ENCODING_UTF16LE
);
2371 This
->error
= E_FAIL
;
2372 TRACE("failed to parse document\n");
2376 hr
= This
->error
= S_OK
;
2377 *isSuccessful
= VARIANT_TRUE
;
2378 TRACE("parsed document %p\n", xmldoc
);
2384 xmldoc
= xmlNewDoc(NULL
);
2385 xmldoc
->_private
= create_priv();
2386 hr2
= attach_xmldoc(This
, xmldoc
);
2393 static int XMLCALL
domdoc_save_writecallback(void *ctx
, const char *buffer
, int len
)
2397 if(!WriteFile(ctx
, buffer
, len
, &written
, NULL
))
2399 WARN("write error\n");
2406 static int XMLCALL
domdoc_save_closecallback(void *ctx
)
2408 return CloseHandle(ctx
) ? 0 : -1;
2411 static int XMLCALL
domdoc_stream_save_writecallback(void *ctx
, const char *buffer
, int len
)
2416 hr
= IStream_Write((IStream
*)ctx
, buffer
, len
, &written
);
2417 TRACE("0x%08x %p %d %u\n", hr
, buffer
, len
, written
);
2420 WARN("stream write error: 0x%08x\n", hr
);
2427 static int XMLCALL
domdoc_stream_save_closecallback(void *ctx
)
2429 IStream_Release((IStream
*)ctx
);
2433 static HRESULT WINAPI
domdoc_save(
2434 IXMLDOMDocument3
*iface
,
2435 VARIANT destination
)
2437 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2438 xmlSaveCtxtPtr ctx
= NULL
;
2442 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&destination
));
2444 switch (V_VT(&destination
))
2448 IUnknown
*pUnk
= V_UNKNOWN(&destination
);
2449 IXMLDOMDocument3
*document
;
2452 ret
= IUnknown_QueryInterface(pUnk
, &IID_IXMLDOMDocument3
, (void**)&document
);
2455 VARIANT_BOOL success
;
2458 ret
= IXMLDOMDocument3_get_xml(iface
, &xml
);
2461 ret
= IXMLDOMDocument3_loadXML(document
, xml
, &success
);
2465 IXMLDOMDocument3_Release(document
);
2469 ret
= IUnknown_QueryInterface(pUnk
, &IID_IStream
, (void**)&stream
);
2472 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2473 ctx
= xmlSaveToIO(domdoc_stream_save_writecallback
,
2474 domdoc_stream_save_closecallback
, stream
, NULL
, options
);
2478 IStream_Release(stream
);
2486 case VT_BSTR
| VT_BYREF
:
2488 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2490 /* save with file path */
2491 HANDLE handle
= CreateFileW( (V_VT(&destination
) & VT_BYREF
)? *V_BSTRREF(&destination
) : V_BSTR(&destination
),
2492 GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2493 if( handle
== INVALID_HANDLE_VALUE
)
2495 WARN("failed to create file\n");
2499 /* disable top XML declaration */
2500 ctx
= xmlSaveToIO(domdoc_save_writecallback
, domdoc_save_closecallback
,
2501 handle
, NULL
, options
);
2504 CloseHandle(handle
);
2511 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination
));
2515 xmldecl
= xmldoc_unlink_xmldecl(get_doc(This
));
2516 if (xmlSaveDoc(ctx
, get_doc(This
)) == -1) ret
= S_FALSE
;
2517 xmldoc_link_xmldecl(get_doc(This
), xmldecl
);
2519 /* will release resources through close callback */
2525 static HRESULT WINAPI
domdoc_get_validateOnParse(
2526 IXMLDOMDocument3
*iface
,
2527 VARIANT_BOOL
* isValidating
)
2529 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2530 TRACE("(%p)->(%p: %d)\n", This
, isValidating
, This
->validating
);
2531 *isValidating
= This
->validating
;
2536 static HRESULT WINAPI
domdoc_put_validateOnParse(
2537 IXMLDOMDocument3
*iface
,
2538 VARIANT_BOOL isValidating
)
2540 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2541 TRACE("(%p)->(%d)\n", This
, isValidating
);
2542 This
->validating
= isValidating
;
2547 static HRESULT WINAPI
domdoc_get_resolveExternals(
2548 IXMLDOMDocument3
*iface
,
2549 VARIANT_BOOL
* isResolving
)
2551 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2552 TRACE("(%p)->(%p: %d)\n", This
, isResolving
, This
->resolving
);
2553 *isResolving
= This
->resolving
;
2558 static HRESULT WINAPI
domdoc_put_resolveExternals(
2559 IXMLDOMDocument3
*iface
,
2560 VARIANT_BOOL isResolving
)
2562 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2563 TRACE("(%p)->(%d)\n", This
, isResolving
);
2564 This
->resolving
= isResolving
;
2569 static HRESULT WINAPI
domdoc_get_preserveWhiteSpace(
2570 IXMLDOMDocument3
*iface
,
2571 VARIANT_BOOL
* isPreserving
)
2573 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2574 TRACE("(%p)->(%p: %d)\n", This
, isPreserving
, This
->properties
->preserving
);
2575 *isPreserving
= This
->properties
->preserving
;
2580 static HRESULT WINAPI
domdoc_put_preserveWhiteSpace(
2581 IXMLDOMDocument3
*iface
,
2582 VARIANT_BOOL isPreserving
)
2584 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2585 TRACE("(%p)->(%d)\n", This
, isPreserving
);
2586 This
->properties
->preserving
= isPreserving
;
2591 static HRESULT WINAPI
domdoc_put_onreadystatechange(
2592 IXMLDOMDocument3
*iface
,
2595 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2597 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&event
));
2598 return set_doc_event(This
, EVENTID_READYSTATECHANGE
, &event
);
2602 static HRESULT WINAPI
domdoc_put_onDataAvailable(IXMLDOMDocument3
*iface
, VARIANT sink
)
2604 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2605 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2609 static HRESULT WINAPI
domdoc_put_onTransformNode(IXMLDOMDocument3
*iface
, VARIANT sink
)
2611 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2612 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2616 static HRESULT WINAPI
domdoc_get_namespaces(
2617 IXMLDOMDocument3
* iface
,
2618 IXMLDOMSchemaCollection
** collection
)
2620 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2623 FIXME("(%p)->(%p): semi-stub\n", This
, collection
);
2625 if (!collection
) return E_POINTER
;
2627 if (!This
->namespaces
)
2629 hr
= SchemaCache_create(This
->properties
->version
, (void**)&This
->namespaces
);
2630 if (hr
!= S_OK
) return hr
;
2632 hr
= cache_from_doc_ns(This
->namespaces
, &This
->node
);
2634 release_namespaces(This
);
2637 if (This
->namespaces
)
2638 return IXMLDOMSchemaCollection2_QueryInterface(This
->namespaces
,
2639 &IID_IXMLDOMSchemaCollection
, (void**)collection
);
2644 static HRESULT WINAPI
domdoc_get_schemas(
2645 IXMLDOMDocument3
* iface
,
2648 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2649 IXMLDOMSchemaCollection2
* cur_schema
= This
->properties
->schemaCache
;
2650 HRESULT hr
= S_FALSE
;
2652 TRACE("(%p)->(%p)\n", This
, schema
);
2654 V_VT(schema
) = VT_NULL
;
2655 /* just to reset pointer part, cause that's what application is expected to use */
2656 V_DISPATCH(schema
) = NULL
;
2660 hr
= IXMLDOMSchemaCollection2_QueryInterface(cur_schema
, &IID_IDispatch
, (void**)&V_DISPATCH(schema
));
2662 V_VT(schema
) = VT_DISPATCH
;
2667 static HRESULT WINAPI
domdoc_putref_schemas(
2668 IXMLDOMDocument3
* iface
,
2671 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2672 HRESULT hr
= E_FAIL
;
2673 IXMLDOMSchemaCollection2
* new_schema
= NULL
;
2675 FIXME("(%p)->(%s): semi-stub\n", This
, debugstr_variant(&schema
));
2676 switch(V_VT(&schema
))
2679 if (V_UNKNOWN(&schema
))
2681 hr
= IUnknown_QueryInterface(V_UNKNOWN(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2686 if (V_DISPATCH(&schema
))
2688 hr
= IDispatch_QueryInterface(V_DISPATCH(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2698 WARN("Can't get schema from vt %x\n", V_VT(&schema
));
2703 IXMLDOMSchemaCollection2
* old_schema
= InterlockedExchangePointer((void**)&This
->properties
->schemaCache
, new_schema
);
2704 if(old_schema
) IXMLDOMSchemaCollection2_Release(old_schema
);
2710 static inline BOOL
is_wellformed(xmlDocPtr doc
)
2712 #ifdef HAVE_XMLDOC_PROPERTIES
2713 return doc
->properties
& XML_DOC_WELLFORMED
;
2715 /* Not a full check, but catches the worst violations */
2719 for (child
= doc
->children
; child
!= NULL
; child
= child
->next
)
2721 switch (child
->type
)
2723 case XML_ELEMENT_NODE
:
2728 case XML_CDATA_SECTION_NODE
:
2740 static void LIBXML2_LOG_CALLBACK
validate_error(void* ctx
, char const* msg
, ...)
2744 LIBXML2_CALLBACK_ERR(domdoc_validateNode
, msg
, ap
);
2748 static void LIBXML2_LOG_CALLBACK
validate_warning(void* ctx
, char const* msg
, ...)
2752 LIBXML2_CALLBACK_WARN(domdoc_validateNode
, msg
, ap
);
2756 static HRESULT WINAPI
domdoc_validateNode(
2757 IXMLDOMDocument3
* iface
,
2759 IXMLDOMParseError
** err
)
2761 domdoc
* This
= impl_from_IXMLDOMDocument3(iface
);
2762 LONG state
, err_code
= 0;
2766 TRACE("(%p)->(%p, %p)\n", This
, node
, err
);
2767 IXMLDOMDocument3_get_readyState(iface
, &state
);
2768 if (state
!= READYSTATE_COMPLETE
)
2771 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2778 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2782 if (!get_node_obj(node
)->node
|| get_node_obj(node
)->node
->doc
!= get_doc(This
))
2785 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2789 if (!is_wellformed(get_doc(This
)))
2791 ERR("doc not well-formed\n");
2793 *err
= create_parseError(E_XML_NOTWF
, NULL
, NULL
, NULL
, 0, 0, 0);
2797 /* DTD validation */
2798 if (get_doc(This
)->intSubset
|| get_doc(This
)->extSubset
)
2800 xmlValidCtxtPtr vctx
= xmlNewValidCtxt();
2801 vctx
->error
= validate_error
;
2802 vctx
->warning
= validate_warning
;
2805 if (!((node
== (IXMLDOMNode
*)iface
)?
2806 xmlValidateDocument(vctx
, get_doc(This
)) :
2807 xmlValidateElement(vctx
, get_doc(This
), get_node_obj(node
)->node
)))
2809 /* TODO: get a real error code here */
2810 TRACE("DTD validation failed\n");
2811 err_code
= E_XML_INVALID
;
2814 xmlFreeValidCtxt(vctx
);
2817 /* Schema validation */
2818 if (hr
== S_OK
&& This
->properties
->schemaCache
!= NULL
)
2821 hr
= SchemaCache_validate_tree(This
->properties
->schemaCache
, get_node_obj(node
)->node
);
2825 /* TODO: get a real error code here */
2828 TRACE("schema validation succeeded\n");
2832 ERR("schema validation failed\n");
2833 err_code
= E_XML_INVALID
;
2838 /* not really OK, just didn't find a schema for the ns */
2845 ERR("no DTD or schema found\n");
2846 err_code
= E_XML_NODTD
;
2851 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2856 static HRESULT WINAPI
domdoc_validate(
2857 IXMLDOMDocument3
* iface
,
2858 IXMLDOMParseError
** err
)
2860 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2861 TRACE("(%p)->(%p)\n", This
, err
);
2862 return IXMLDOMDocument3_validateNode(iface
, (IXMLDOMNode
*)iface
, err
);
2865 static HRESULT WINAPI
domdoc_setProperty(
2866 IXMLDOMDocument3
* iface
,
2870 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2872 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(p
), debugstr_variant(&value
));
2874 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
2880 V_VT(&varStr
) = VT_EMPTY
;
2881 if (V_VT(&value
) != VT_BSTR
)
2883 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2885 bstr
= V_BSTR(&varStr
);
2888 bstr
= V_BSTR(&value
);
2891 if (lstrcmpiW(bstr
, PropValueXPathW
) == 0)
2892 This
->properties
->XPath
= TRUE
;
2893 else if (lstrcmpiW(bstr
, PropValueXSLPatternW
) == 0)
2894 This
->properties
->XPath
= FALSE
;
2898 VariantClear(&varStr
);
2901 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
2903 xmlChar
*nsStr
= (xmlChar
*)This
->properties
->selectNsStr
;
2904 struct list
*pNsList
;
2909 V_VT(&varStr
) = VT_EMPTY
;
2910 if (V_VT(&value
) != VT_BSTR
)
2912 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2914 bstr
= V_BSTR(&varStr
);
2917 bstr
= V_BSTR(&value
);
2921 pNsList
= &(This
->properties
->selectNsList
);
2922 clear_selectNsList(pNsList
);
2924 nsStr
= xmlchar_from_wchar(bstr
);
2926 TRACE("property value: \"%s\"\n", debugstr_w(bstr
));
2928 This
->properties
->selectNsStr
= nsStr
;
2929 This
->properties
->selectNsStr_len
= xmlStrlen(nsStr
);
2932 xmlChar
*pTokBegin
, *pTokEnd
, *pTokInner
;
2933 select_ns_entry
* ns_entry
= NULL
;
2934 xmlXPathContextPtr ctx
;
2936 ctx
= xmlXPathNewContext(This
->node
.node
->doc
);
2939 /* skip leading spaces */
2940 while (*pTokBegin
== ' ' || *pTokBegin
== '\n' ||
2941 *pTokBegin
== '\t' || *pTokBegin
== '\r')
2944 for (; *pTokBegin
; pTokBegin
= pTokEnd
)
2947 memset(ns_entry
, 0, sizeof(select_ns_entry
));
2949 ns_entry
= heap_alloc_zero(sizeof(select_ns_entry
));
2951 while (*pTokBegin
== ' ')
2953 pTokEnd
= pTokBegin
;
2954 while (*pTokEnd
!= ' ' && *pTokEnd
!= 0)
2957 /* so it failed to advance which means we've got some trailing spaces */
2958 if (pTokEnd
== pTokBegin
) break;
2960 if (xmlStrncmp(pTokBegin
, (xmlChar
const*)"xmlns", 5) != 0)
2963 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2964 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2969 if (*pTokBegin
== '=')
2971 /*valid for XSLPattern?*/
2972 FIXME("Setting default xmlns not supported - skipping.\n");
2975 else if (*pTokBegin
== ':')
2977 ns_entry
->prefix
= ++pTokBegin
;
2978 for (pTokInner
= pTokBegin
; pTokInner
!= pTokEnd
&& *pTokInner
!= '='; ++pTokInner
)
2981 if (pTokInner
== pTokEnd
)
2984 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2985 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2989 ns_entry
->prefix_end
= *pTokInner
;
2993 if (pTokEnd
-pTokInner
> 1 &&
2994 ((*pTokInner
== '\'' && *(pTokEnd
-1) == '\'') ||
2995 (*pTokInner
== '"' && *(pTokEnd
-1) == '"')))
2997 ns_entry
->href
= ++pTokInner
;
2998 ns_entry
->href_end
= *(pTokEnd
-1);
3000 list_add_tail(pNsList
, &ns_entry
->entry
);
3001 /*let libxml figure out if they're valid from here ;)*/
3002 if (xmlXPathRegisterNs(ctx
, ns_entry
->prefix
, ns_entry
->href
) != 0)
3011 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3012 debugstr_w(bstr
), debugstr_an((const char*)pTokInner
, pTokEnd
-pTokInner
));
3013 list_add_tail(pNsList
, &ns_entry
->entry
);
3026 heap_free(ns_entry
);
3027 xmlXPathFreeContext(ctx
);
3030 VariantClear(&varStr
);
3033 else if (lstrcmpiW(p
, PropertyProhibitDTDW
) == 0 ||
3034 lstrcmpiW(p
, PropertyNewParserW
) == 0 ||
3035 lstrcmpiW(p
, PropertyResolveExternalsW
) == 0)
3038 FIXME("Ignoring property %s, value %s\n", debugstr_w(p
), debugstr_variant(&value
));
3042 FIXME("Unknown property %s\n", debugstr_w(p
));
3046 static HRESULT WINAPI
domdoc_getProperty(
3047 IXMLDOMDocument3
* iface
,
3051 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3053 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
3056 return E_INVALIDARG
;
3058 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
3060 V_VT(var
) = VT_BSTR
;
3061 V_BSTR(var
) = This
->properties
->XPath
?
3062 SysAllocString(PropValueXPathW
) :
3063 SysAllocString(PropValueXSLPatternW
);
3064 return V_BSTR(var
) ? S_OK
: E_OUTOFMEMORY
;
3066 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3069 BSTR rebuiltStr
, cur
;
3070 const xmlChar
*nsStr
;
3071 struct list
*pNsList
;
3072 select_ns_entry
* pNsEntry
;
3074 V_VT(var
) = VT_BSTR
;
3075 nsStr
= This
->properties
->selectNsStr
;
3076 pNsList
= &This
->properties
->selectNsList
;
3077 lenA
= This
->properties
->selectNsStr_len
;
3078 lenW
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, NULL
, 0);
3079 rebuiltStr
= heap_alloc(lenW
*sizeof(WCHAR
));
3080 MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, rebuiltStr
, lenW
);
3082 /* this is fine because all of the chars that end tokens are ASCII*/
3083 LIST_FOR_EACH_ENTRY(pNsEntry
, pNsList
, select_ns_entry
, entry
)
3085 while (*cur
!= 0) ++cur
;
3086 if (pNsEntry
->prefix_end
)
3088 *cur
= pNsEntry
->prefix_end
;
3089 while (*cur
!= 0) ++cur
;
3092 if (pNsEntry
->href_end
)
3094 *cur
= pNsEntry
->href_end
;
3097 V_BSTR(var
) = SysAllocString(rebuiltStr
);
3098 heap_free(rebuiltStr
);
3102 FIXME("Unknown property %s\n", debugstr_w(p
));
3106 static HRESULT WINAPI
domdoc_importNode(
3107 IXMLDOMDocument3
* iface
,
3110 IXMLDOMNode
** clone
)
3112 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3113 FIXME("(%p)->(%p %d %p): stub\n", This
, node
, deep
, clone
);
3117 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl
=
3119 domdoc_QueryInterface
,
3122 domdoc_GetTypeInfoCount
,
3124 domdoc_GetIDsOfNames
,
3126 domdoc_get_nodeName
,
3127 domdoc_get_nodeValue
,
3128 domdoc_put_nodeValue
,
3129 domdoc_get_nodeType
,
3130 domdoc_get_parentNode
,
3131 domdoc_get_childNodes
,
3132 domdoc_get_firstChild
,
3133 domdoc_get_lastChild
,
3134 domdoc_get_previousSibling
,
3135 domdoc_get_nextSibling
,
3136 domdoc_get_attributes
,
3137 domdoc_insertBefore
,
3138 domdoc_replaceChild
,
3141 domdoc_hasChildNodes
,
3142 domdoc_get_ownerDocument
,
3144 domdoc_get_nodeTypeString
,
3147 domdoc_get_specified
,
3148 domdoc_get_definition
,
3149 domdoc_get_nodeTypedValue
,
3150 domdoc_put_nodeTypedValue
,
3151 domdoc_get_dataType
,
3152 domdoc_put_dataType
,
3154 domdoc_transformNode
,
3156 domdoc_selectSingleNode
,
3158 domdoc_get_namespaceURI
,
3160 domdoc_get_baseName
,
3161 domdoc_transformNodeToObject
,
3163 domdoc_get_implementation
,
3164 domdoc_get_documentElement
,
3165 domdoc_put_documentElement
,
3166 domdoc_createElement
,
3167 domdoc_createDocumentFragment
,
3168 domdoc_createTextNode
,
3169 domdoc_createComment
,
3170 domdoc_createCDATASection
,
3171 domdoc_createProcessingInstruction
,
3172 domdoc_createAttribute
,
3173 domdoc_createEntityReference
,
3174 domdoc_getElementsByTagName
,
3178 domdoc_get_readyState
,
3179 domdoc_get_parseError
,
3186 domdoc_get_validateOnParse
,
3187 domdoc_put_validateOnParse
,
3188 domdoc_get_resolveExternals
,
3189 domdoc_put_resolveExternals
,
3190 domdoc_get_preserveWhiteSpace
,
3191 domdoc_put_preserveWhiteSpace
,
3192 domdoc_put_onreadystatechange
,
3193 domdoc_put_onDataAvailable
,
3194 domdoc_put_onTransformNode
,
3195 domdoc_get_namespaces
,
3197 domdoc_putref_schemas
,
3201 domdoc_validateNode
,
3205 /* IConnectionPointContainer */
3206 static HRESULT WINAPI
ConnectionPointContainer_QueryInterface(IConnectionPointContainer
*iface
,
3207 REFIID riid
, void **ppv
)
3209 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3210 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3213 static ULONG WINAPI
ConnectionPointContainer_AddRef(IConnectionPointContainer
*iface
)
3215 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3216 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3219 static ULONG WINAPI
ConnectionPointContainer_Release(IConnectionPointContainer
*iface
)
3221 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3222 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3225 static HRESULT WINAPI
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer
*iface
,
3226 IEnumConnectionPoints
**ppEnum
)
3228 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3229 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3233 static HRESULT WINAPI
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer
*iface
,
3234 REFIID riid
, IConnectionPoint
**cp
)
3236 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3237 ConnectionPoint
*iter
;
3239 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), cp
);
3243 for(iter
= This
->cp_list
; iter
; iter
= iter
->next
)
3245 if (IsEqualGUID(iter
->iid
, riid
))
3246 *cp
= &iter
->IConnectionPoint_iface
;
3251 IConnectionPoint_AddRef(*cp
);
3255 FIXME("unsupported riid %s\n", debugstr_guid(riid
));
3256 return CONNECT_E_NOCONNECTION
;
3260 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl
=
3262 ConnectionPointContainer_QueryInterface
,
3263 ConnectionPointContainer_AddRef
,
3264 ConnectionPointContainer_Release
,
3265 ConnectionPointContainer_EnumConnectionPoints
,
3266 ConnectionPointContainer_FindConnectionPoint
3269 /* IConnectionPoint */
3270 static HRESULT WINAPI
ConnectionPoint_QueryInterface(IConnectionPoint
*iface
,
3271 REFIID riid
, void **ppv
)
3273 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3275 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
3279 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
3280 IsEqualGUID(&IID_IConnectionPoint
, riid
))
3287 IConnectionPoint_AddRef(iface
);
3291 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
3292 return E_NOINTERFACE
;
3295 static ULONG WINAPI
ConnectionPoint_AddRef(IConnectionPoint
*iface
)
3297 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3298 return IConnectionPointContainer_AddRef(This
->container
);
3301 static ULONG WINAPI
ConnectionPoint_Release(IConnectionPoint
*iface
)
3303 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3304 return IConnectionPointContainer_Release(This
->container
);
3307 static HRESULT WINAPI
ConnectionPoint_GetConnectionInterface(IConnectionPoint
*iface
, IID
*iid
)
3309 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3311 TRACE("(%p)->(%p)\n", This
, iid
);
3313 if (!iid
) return E_POINTER
;
3319 static HRESULT WINAPI
ConnectionPoint_GetConnectionPointContainer(IConnectionPoint
*iface
,
3320 IConnectionPointContainer
**container
)
3322 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3324 TRACE("(%p)->(%p)\n", This
, container
);
3326 if (!container
) return E_POINTER
;
3328 *container
= This
->container
;
3329 IConnectionPointContainer_AddRef(*container
);
3333 static HRESULT WINAPI
ConnectionPoint_Advise(IConnectionPoint
*iface
, IUnknown
*unk_sink
,
3336 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3341 TRACE("(%p)->(%p %p)\n", This
, unk_sink
, cookie
);
3343 hr
= IUnknown_QueryInterface(unk_sink
, This
->iid
, (void**)&sink
);
3344 if(FAILED(hr
) && !IsEqualGUID(&IID_IPropertyNotifySink
, This
->iid
))
3345 hr
= IUnknown_QueryInterface(unk_sink
, &IID_IDispatch
, (void**)&sink
);
3347 return CONNECT_E_CANNOTCONNECT
;
3351 for (i
= 0; i
< This
->sinks_size
; i
++)
3352 if (!This
->sinks
[i
].unk
)
3355 if (i
== This
->sinks_size
)
3356 This
->sinks
= heap_realloc(This
->sinks
,(++This
->sinks_size
)*sizeof(*This
->sinks
));
3360 This
->sinks
= heap_alloc(sizeof(*This
->sinks
));
3361 This
->sinks_size
= 1;
3365 This
->sinks
[i
].unk
= sink
;
3372 static HRESULT WINAPI
ConnectionPoint_Unadvise(IConnectionPoint
*iface
, DWORD cookie
)
3374 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3376 TRACE("(%p)->(%d)\n", This
, cookie
);
3378 if (cookie
== 0 || cookie
> This
->sinks_size
|| !This
->sinks
[cookie
-1].unk
)
3379 return CONNECT_E_NOCONNECTION
;
3381 IUnknown_Release(This
->sinks
[cookie
-1].unk
);
3382 This
->sinks
[cookie
-1].unk
= NULL
;
3387 static HRESULT WINAPI
ConnectionPoint_EnumConnections(IConnectionPoint
*iface
,
3388 IEnumConnections
**ppEnum
)
3390 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3391 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3395 static const IConnectionPointVtbl ConnectionPointVtbl
=
3397 ConnectionPoint_QueryInterface
,
3398 ConnectionPoint_AddRef
,
3399 ConnectionPoint_Release
,
3400 ConnectionPoint_GetConnectionInterface
,
3401 ConnectionPoint_GetConnectionPointContainer
,
3402 ConnectionPoint_Advise
,
3403 ConnectionPoint_Unadvise
,
3404 ConnectionPoint_EnumConnections
3407 static void ConnectionPoint_Init(ConnectionPoint
*cp
, struct domdoc
*doc
, REFIID riid
)
3409 cp
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointVtbl
;
3415 cp
->next
= doc
->cp_list
;
3418 cp
->container
= &doc
->IConnectionPointContainer_iface
;
3421 /* domdoc implementation of IObjectWithSite */
3422 static HRESULT WINAPI
3423 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
3425 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3426 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObject
);
3429 static ULONG WINAPI
domdoc_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
3431 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3432 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3435 static ULONG WINAPI
domdoc_ObjectWithSite_Release( IObjectWithSite
* iface
)
3437 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3438 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3441 static HRESULT WINAPI
domdoc_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
3443 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3445 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
3450 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
3453 static HRESULT WINAPI
domdoc_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
3455 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3457 TRACE("(%p)->(%p)\n", iface
, punk
);
3463 IUnknown_Release( This
->site
);
3470 IUnknown_AddRef( punk
);
3473 IUnknown_Release( This
->site
);
3480 static const IObjectWithSiteVtbl domdocObjectSite
=
3482 domdoc_ObjectWithSite_QueryInterface
,
3483 domdoc_ObjectWithSite_AddRef
,
3484 domdoc_ObjectWithSite_Release
,
3485 domdoc_ObjectWithSite_SetSite
,
3486 domdoc_ObjectWithSite_GetSite
3489 static HRESULT WINAPI
domdoc_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
3491 domdoc
*This
= impl_from_IObjectSafety(iface
);
3492 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3495 static ULONG WINAPI
domdoc_Safety_AddRef(IObjectSafety
*iface
)
3497 domdoc
*This
= impl_from_IObjectSafety(iface
);
3498 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3501 static ULONG WINAPI
domdoc_Safety_Release(IObjectSafety
*iface
)
3503 domdoc
*This
= impl_from_IObjectSafety(iface
);
3504 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3507 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3509 static HRESULT WINAPI
domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3510 DWORD
*supported
, DWORD
*enabled
)
3512 domdoc
*This
= impl_from_IObjectSafety(iface
);
3514 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
3516 if(!supported
|| !enabled
) return E_POINTER
;
3518 *supported
= SAFETY_SUPPORTED_OPTIONS
;
3519 *enabled
= This
->safeopt
;
3524 static HRESULT WINAPI
domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3525 DWORD mask
, DWORD enabled
)
3527 domdoc
*This
= impl_from_IObjectSafety(iface
);
3528 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
3530 if ((mask
& ~SAFETY_SUPPORTED_OPTIONS
) != 0)
3533 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
3538 #undef SAFETY_SUPPORTED_OPTIONS
3540 static const IObjectSafetyVtbl domdocObjectSafetyVtbl
= {
3541 domdoc_Safety_QueryInterface
,
3542 domdoc_Safety_AddRef
,
3543 domdoc_Safety_Release
,
3544 domdoc_Safety_GetInterfaceSafetyOptions
,
3545 domdoc_Safety_SetInterfaceSafetyOptions
3548 static const tid_t domdoc_iface_tids
[] = {
3549 IXMLDOMDocument3_tid
,
3553 static dispex_static_data_t domdoc_dispex
= {
3555 IXMLDOMDocument3_tid
,
3560 HRESULT
get_domdoc_from_xmldoc(xmlDocPtr xmldoc
, IXMLDOMDocument3
**document
)
3564 doc
= heap_alloc( sizeof (*doc
) );
3566 return E_OUTOFMEMORY
;
3568 doc
->IXMLDOMDocument3_iface
.lpVtbl
= &XMLDOMDocument3Vtbl
;
3569 doc
->IPersistStreamInit_iface
.lpVtbl
= &xmldoc_IPersistStreamInit_VTable
;
3570 doc
->IObjectWithSite_iface
.lpVtbl
= &domdocObjectSite
;
3571 doc
->IObjectSafety_iface
.lpVtbl
= &domdocObjectSafetyVtbl
;
3572 doc
->IConnectionPointContainer_iface
.lpVtbl
= &ConnectionPointContainerVtbl
;
3574 doc
->async
= VARIANT_TRUE
;
3575 doc
->validating
= 0;
3577 doc
->properties
= properties_from_xmlDocPtr(xmldoc
);
3581 doc
->cp_list
= NULL
;
3582 doc
->namespaces
= NULL
;
3583 memset(doc
->events
, 0, sizeof(doc
->events
));
3585 /* events connection points */
3586 ConnectionPoint_Init(&doc
->cp_dispatch
, doc
, &IID_IDispatch
);
3587 ConnectionPoint_Init(&doc
->cp_propnotif
, doc
, &IID_IPropertyNotifySink
);
3588 ConnectionPoint_Init(&doc
->cp_domdocevents
, doc
, &DIID_XMLDOMDocumentEvents
);
3590 init_xmlnode(&doc
->node
, (xmlNodePtr
)xmldoc
, (IXMLDOMNode
*)&doc
->IXMLDOMDocument3_iface
,
3593 *document
= &doc
->IXMLDOMDocument3_iface
;
3595 TRACE("returning iface %p\n", *document
);
3599 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3604 TRACE("(%d, %p)\n", version
, ppObj
);
3606 xmldoc
= xmlNewDoc(NULL
);
3608 return E_OUTOFMEMORY
;
3610 xmldoc_init(xmldoc
, version
);
3612 hr
= get_domdoc_from_xmldoc(xmldoc
, (IXMLDOMDocument3
**)ppObj
);
3615 free_properties(properties_from_xmlDocPtr(xmldoc
));
3616 heap_free(xmldoc
->_private
);
3624 IUnknown
* create_domdoc( xmlNodePtr document
)
3629 TRACE("(%p)\n", document
);
3631 hr
= get_domdoc_from_xmldoc((xmlDocPtr
)document
, (IXMLDOMDocument3
**)&pObj
);
3640 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3642 MESSAGE("This program tried to use a DOMDocument object, but\n"
3643 "libxml2 support was not present at compile time.\n");