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
;
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
;
136 /* IObjectWithSite */
142 /* connection list */
143 ConnectionPoint
*cp_list
;
144 ConnectionPoint cp_domdocevents
;
145 ConnectionPoint cp_propnotif
;
146 ConnectionPoint cp_dispatch
;
149 IDispatch
*events
[EVENTID_LAST
];
151 IXMLDOMSchemaCollection2
*namespaces
;
154 static HRESULT
set_doc_event(domdoc
*doc
, eventid_t eid
, const VARIANT
*v
)
162 IUnknown_QueryInterface(V_UNKNOWN(v
), &IID_IDispatch
, (void**)&disp
);
167 disp
= V_DISPATCH(v
);
168 if (disp
) IDispatch_AddRef(disp
);
171 return DISP_E_TYPEMISMATCH
;
174 if (doc
->events
[eid
]) IDispatch_Release(doc
->events
[eid
]);
175 doc
->events
[eid
] = disp
;
180 static inline ConnectionPoint
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
182 return CONTAINING_RECORD(iface
, ConnectionPoint
, IConnectionPoint_iface
);
186 In native windows, the whole lifetime management of XMLDOMNodes is
187 managed automatically using reference counts. Wine emulates that by
188 maintaining a reference count to the document that is increased for
189 each IXMLDOMNode pointer passed out for this document. If all these
190 pointers are gone, the document is unreachable and gets freed, that
191 is, all nodes in the tree of the document get freed.
193 You are able to create nodes that are associated to a document (in
194 fact, in msxml's XMLDOM model, all nodes are associated to a document),
195 but not in the tree of that document, for example using the createFoo
196 functions from IXMLDOMDocument. These nodes do not get cleaned up
197 by libxml, so we have to do it ourselves.
199 To catch these nodes, a list of "orphan nodes" is introduced.
200 It contains pointers to all roots of node trees that are
201 associated with the document without being part of the document
202 tree. All nodes with parent==NULL (except for the document root nodes)
203 should be in the orphan node list of their document. All orphan nodes
204 get freed together with the document itself.
207 typedef struct _xmldoc_priv
{
210 domdoc_properties
* properties
;
213 typedef struct _orphan_entry
{
218 typedef struct _select_ns_entry
{
220 xmlChar
const* prefix
;
226 static inline xmldoc_priv
* priv_from_xmlDocPtr(const xmlDocPtr doc
)
228 return doc
->_private
;
231 static inline domdoc_properties
* properties_from_xmlDocPtr(xmlDocPtr doc
)
233 return priv_from_xmlDocPtr(doc
)->properties
;
236 BOOL
is_xpathmode(const xmlDocPtr doc
)
238 return properties_from_xmlDocPtr(doc
)->XPath
;
241 void set_xpathmode(xmlDocPtr doc
, BOOL xpath
)
243 properties_from_xmlDocPtr(doc
)->XPath
= xpath
;
246 int registerNamespaces(xmlXPathContextPtr ctxt
)
249 const select_ns_entry
* ns
= NULL
;
250 const struct list
* pNsList
= &properties_from_xmlDocPtr(ctxt
->doc
)->selectNsList
;
252 TRACE("(%p)\n", ctxt
);
254 LIST_FOR_EACH_ENTRY( ns
, pNsList
, select_ns_entry
, entry
)
256 xmlXPathRegisterNs(ctxt
, ns
->prefix
, ns
->href
);
263 static inline void clear_selectNsList(struct list
* pNsList
)
265 select_ns_entry
*ns
, *ns2
;
266 LIST_FOR_EACH_ENTRY_SAFE( ns
, ns2
, pNsList
, select_ns_entry
, entry
)
273 static xmldoc_priv
* create_priv(void)
276 priv
= heap_alloc( sizeof (*priv
) );
281 list_init( &priv
->orphans
);
282 priv
->properties
= NULL
;
288 static domdoc_properties
*create_properties(MSXML_VERSION version
)
290 domdoc_properties
*properties
= heap_alloc(sizeof(domdoc_properties
));
292 list_init(&properties
->selectNsList
);
293 properties
->preserving
= VARIANT_FALSE
;
294 properties
->schemaCache
= NULL
;
295 properties
->selectNsStr
= heap_alloc_zero(sizeof(xmlChar
));
296 properties
->selectNsStr_len
= 0;
298 /* properties that are dependent on object versions */
299 properties
->version
= version
;
300 properties
->XPath
= (version
== MSXML4
|| version
== MSXML6
);
305 static domdoc_properties
* copy_properties(domdoc_properties
const* properties
)
307 domdoc_properties
* pcopy
= heap_alloc(sizeof(domdoc_properties
));
308 select_ns_entry
const* ns
= NULL
;
309 select_ns_entry
* new_ns
= NULL
;
310 int len
= (properties
->selectNsStr_len
+1)*sizeof(xmlChar
);
315 pcopy
->version
= properties
->version
;
316 pcopy
->preserving
= properties
->preserving
;
317 pcopy
->schemaCache
= properties
->schemaCache
;
318 if (pcopy
->schemaCache
)
319 IXMLDOMSchemaCollection2_AddRef(pcopy
->schemaCache
);
320 pcopy
->XPath
= properties
->XPath
;
321 pcopy
->selectNsStr_len
= properties
->selectNsStr_len
;
322 list_init( &pcopy
->selectNsList
);
323 pcopy
->selectNsStr
= heap_alloc(len
);
324 memcpy((xmlChar
*)pcopy
->selectNsStr
, properties
->selectNsStr
, len
);
325 offset
= pcopy
->selectNsStr
- properties
->selectNsStr
;
327 LIST_FOR_EACH_ENTRY( ns
, (&properties
->selectNsList
), select_ns_entry
, entry
)
329 new_ns
= heap_alloc(sizeof(select_ns_entry
));
330 memcpy(new_ns
, ns
, sizeof(select_ns_entry
));
331 new_ns
->href
+= offset
;
332 new_ns
->prefix
+= offset
;
333 list_add_tail(&pcopy
->selectNsList
, &new_ns
->entry
);
341 static void free_properties(domdoc_properties
* properties
)
345 if (properties
->schemaCache
)
346 IXMLDOMSchemaCollection2_Release(properties
->schemaCache
);
347 clear_selectNsList(&properties
->selectNsList
);
348 heap_free((xmlChar
*)properties
->selectNsStr
);
349 heap_free(properties
);
353 static void release_namespaces(domdoc
*This
)
355 if (This
->namespaces
)
357 IXMLDOMSchemaCollection2_Release(This
->namespaces
);
358 This
->namespaces
= NULL
;
362 /* links a "<?xml" node as a first child */
363 void xmldoc_link_xmldecl(xmlDocPtr doc
, xmlNodePtr node
)
366 if (doc
->standalone
!= -1) xmlAddPrevSibling( doc
->children
, node
);
369 /* unlinks a first "<?xml" child if it was created */
370 xmlNodePtr
xmldoc_unlink_xmldecl(xmlDocPtr doc
)
372 static const xmlChar xmlA
[] = "xml";
373 xmlNodePtr node
, first_child
;
377 /* xml declaration node could be created automatically after parsing or added
379 first_child
= doc
->children
;
380 if (first_child
&& first_child
->type
== XML_PI_NODE
&& xmlStrEqual(first_child
->name
, xmlA
))
383 xmlUnlinkNode( node
);
391 BOOL
is_preserving_whitespace(xmlNodePtr node
)
393 domdoc_properties
* properties
= NULL
;
394 /* during parsing the xmlDoc._private stuff is not there */
395 if (priv_from_xmlDocPtr(node
->doc
))
396 properties
= properties_from_xmlDocPtr(node
->doc
);
397 return ((properties
&& properties
->preserving
== VARIANT_TRUE
) ||
398 xmlNodeGetSpacePreserve(node
) == 1);
401 static inline BOOL
strn_isspace(xmlChar
const* str
, int len
)
403 for (; str
&& len
> 0 && *str
; ++str
, --len
)
410 static void sax_characters(void *ctx
, const xmlChar
*ch
, int len
)
412 xmlParserCtxtPtr ctxt
;
415 ctxt
= (xmlParserCtxtPtr
) ctx
;
416 This
= (const domdoc
*) ctxt
->_private
;
420 xmlChar cur
= *(ctxt
->input
->cur
);
422 /* Characters are reported with multiple calls, for example each charref is reported with a separate
423 call and then parser appends it to a single text node or creates a new node if not created.
424 It's not possible to tell if it's ignorable data or not just looking at data itself cause it could be
425 space chars that separate charrefs or similar case. We only need to skip leading and trailing spaces,
426 or whole node if it has nothing but space chars, so to detect leading space node->last is checked that
427 contains text node pointer if already created, trailing spaces are detected directly looking at parser input
428 for next '<' opening bracket - similar logic is used by libxml2 itself. Basically 'cur' == '<' means the last
429 chunk of char data, in case it's not the last chunk we check for previously added node type and if it's not
430 a text node it's safe to ignore.
432 Note that during domdoc_loadXML() the xmlDocPtr->_private data is not available. */
434 if (!This
->properties
->preserving
&&
435 !is_preserving_whitespace(ctxt
->node
) &&
436 strn_isspace(ch
, len
) &&
437 (!ctxt
->node
->last
||
438 ((ctxt
->node
->last
&& (cur
== '<' || ctxt
->node
->last
->type
!= XML_TEXT_NODE
))
443 xmlSAX2Characters(ctxt
, ch
, len
);
446 static void LIBXML2_LOG_CALLBACK
sax_error(void* ctx
, char const* msg
, ...)
450 LIBXML2_CALLBACK_ERR(doparse
, msg
, ap
);
454 static void LIBXML2_LOG_CALLBACK
sax_warning(void* ctx
, char const* msg
, ...)
458 LIBXML2_CALLBACK_WARN(doparse
, msg
, ap
);
462 static void sax_serror(void* ctx
, xmlErrorPtr err
)
464 LIBXML2_CALLBACK_SERROR(doparse
, err
);
467 static xmlDocPtr
doparse(domdoc
* This
, char const* ptr
, int len
, xmlCharEncoding encoding
)
469 xmlDocPtr doc
= NULL
;
470 xmlParserCtxtPtr pctx
;
471 static xmlSAXHandler sax_handler
= {
472 xmlSAX2InternalSubset
, /* internalSubset */
473 xmlSAX2IsStandalone
, /* isStandalone */
474 xmlSAX2HasInternalSubset
, /* hasInternalSubset */
475 xmlSAX2HasExternalSubset
, /* hasExternalSubset */
476 xmlSAX2ResolveEntity
, /* resolveEntity */
477 xmlSAX2GetEntity
, /* getEntity */
478 xmlSAX2EntityDecl
, /* entityDecl */
479 xmlSAX2NotationDecl
, /* notationDecl */
480 xmlSAX2AttributeDecl
, /* attributeDecl */
481 xmlSAX2ElementDecl
, /* elementDecl */
482 xmlSAX2UnparsedEntityDecl
, /* unparsedEntityDecl */
483 xmlSAX2SetDocumentLocator
, /* setDocumentLocator */
484 xmlSAX2StartDocument
, /* startDocument */
485 xmlSAX2EndDocument
, /* endDocument */
486 xmlSAX2StartElement
, /* startElement */
487 xmlSAX2EndElement
, /* endElement */
488 xmlSAX2Reference
, /* reference */
489 sax_characters
, /* characters */
490 sax_characters
, /* ignorableWhitespace */
491 xmlSAX2ProcessingInstruction
, /* processingInstruction */
492 xmlSAX2Comment
, /* comment */
493 sax_warning
, /* warning */
494 sax_error
, /* error */
495 sax_error
, /* fatalError */
496 xmlSAX2GetParameterEntity
, /* getParameterEntity */
497 xmlSAX2CDataBlock
, /* cdataBlock */
498 xmlSAX2ExternalSubset
, /* externalSubset */
501 xmlSAX2StartElementNs
, /* startElementNs */
502 xmlSAX2EndElementNs
, /* endElementNs */
503 sax_serror
/* serror */
506 pctx
= xmlCreateMemoryParserCtxt(ptr
, len
);
509 ERR("Failed to create parser context\n");
513 if (pctx
->sax
) xmlFree(pctx
->sax
);
514 pctx
->sax
= &sax_handler
;
515 pctx
->_private
= This
;
518 if (encoding
!= XML_CHAR_ENCODING_NONE
)
519 xmlSwitchEncoding(pctx
, encoding
);
521 xmlParseDocument(pctx
);
523 if (pctx
->wellFormed
)
529 xmlFreeDoc(pctx
->myDoc
);
533 xmlFreeParserCtxt(pctx
);
535 /* TODO: put this in one of the SAX callbacks */
536 /* create first child as a <?xml...?> */
537 if (doc
&& doc
->standalone
!= -1)
541 xmlChar
*xmlbuff
= (xmlChar
*)buff
;
543 node
= xmlNewDocPI( doc
, (xmlChar
*)"xml", NULL
);
545 /* version attribute can't be omitted */
546 sprintf(buff
, "version=\"%s\"", doc
->version
? (char*)doc
->version
: "1.0");
547 xmlNodeAddContent( node
, xmlbuff
);
551 sprintf(buff
, " encoding=\"%s\"", doc
->encoding
);
552 xmlNodeAddContent( node
, xmlbuff
);
555 if (doc
->standalone
!= -2)
557 sprintf(buff
, " standalone=\"%s\"", doc
->standalone
== 0 ? "no" : "yes");
558 xmlNodeAddContent( node
, xmlbuff
);
561 xmldoc_link_xmldecl( doc
, node
);
567 void xmldoc_init(xmlDocPtr doc
, MSXML_VERSION version
)
569 doc
->_private
= create_priv();
570 priv_from_xmlDocPtr(doc
)->properties
= create_properties(version
);
573 LONG
xmldoc_add_refs(xmlDocPtr doc
, LONG refs
)
575 LONG ref
= InterlockedExchangeAdd(&priv_from_xmlDocPtr(doc
)->refs
, refs
) + refs
;
576 TRACE("(%p)->(%d)\n", doc
, ref
);
580 LONG
xmldoc_add_ref(xmlDocPtr doc
)
582 return xmldoc_add_refs(doc
, 1);
585 LONG
xmldoc_release_refs(xmlDocPtr doc
, LONG refs
)
587 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
588 LONG ref
= InterlockedExchangeAdd(&priv
->refs
, -refs
) - refs
;
589 TRACE("(%p)->(%d)\n", doc
, ref
);
592 WARN("negative refcount, expect troubles\n");
596 orphan_entry
*orphan
, *orphan2
;
597 TRACE("freeing docptr %p\n", doc
);
599 LIST_FOR_EACH_ENTRY_SAFE( orphan
, orphan2
, &priv
->orphans
, orphan_entry
, entry
)
601 xmlFreeNode( orphan
->node
);
604 free_properties(priv
->properties
);
605 heap_free(doc
->_private
);
613 LONG
xmldoc_release(xmlDocPtr doc
)
615 return xmldoc_release_refs(doc
, 1);
618 HRESULT
xmldoc_add_orphan(xmlDocPtr doc
, xmlNodePtr node
)
620 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
623 entry
= heap_alloc( sizeof (*entry
) );
625 return E_OUTOFMEMORY
;
628 list_add_head( &priv
->orphans
, &entry
->entry
);
632 HRESULT
xmldoc_remove_orphan(xmlDocPtr doc
, xmlNodePtr node
)
634 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
635 orphan_entry
*entry
, *entry2
;
637 LIST_FOR_EACH_ENTRY_SAFE( entry
, entry2
, &priv
->orphans
, orphan_entry
, entry
)
639 if( entry
->node
== node
)
641 list_remove( &entry
->entry
);
650 static inline xmlDocPtr
get_doc( domdoc
*This
)
652 return This
->node
.node
->doc
;
655 static HRESULT
attach_xmldoc(domdoc
*This
, xmlDocPtr xml
)
657 release_namespaces(This
);
661 priv_from_xmlDocPtr(get_doc(This
))->properties
= NULL
;
662 if (xmldoc_release(get_doc(This
)) != 0)
663 priv_from_xmlDocPtr(get_doc(This
))->properties
=
664 copy_properties(This
->properties
);
667 This
->node
.node
= (xmlNodePtr
) xml
;
671 xmldoc_add_ref(get_doc(This
));
672 priv_from_xmlDocPtr(get_doc(This
))->properties
= This
->properties
;
678 static inline domdoc
*impl_from_IXMLDOMDocument3( IXMLDOMDocument3
*iface
)
680 return CONTAINING_RECORD(iface
, domdoc
, IXMLDOMDocument3_iface
);
683 static inline domdoc
*impl_from_IPersistStreamInit(IPersistStreamInit
*iface
)
685 return CONTAINING_RECORD(iface
, domdoc
, IPersistStreamInit_iface
);
688 static inline domdoc
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
690 return CONTAINING_RECORD(iface
, domdoc
, IObjectWithSite_iface
);
693 static inline domdoc
*impl_from_IObjectSafety(IObjectSafety
*iface
)
695 return CONTAINING_RECORD(iface
, domdoc
, IObjectSafety_iface
);
698 static inline domdoc
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
700 return CONTAINING_RECORD(iface
, domdoc
, IConnectionPointContainer_iface
);
703 /************************************************************************
704 * domdoc implementation of IPersistStream.
706 static HRESULT WINAPI
PersistStreamInit_QueryInterface(
707 IPersistStreamInit
*iface
, REFIID riid
, void **ppvObj
)
709 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
710 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObj
);
713 static ULONG WINAPI
PersistStreamInit_AddRef(
714 IPersistStreamInit
*iface
)
716 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
717 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
720 static ULONG WINAPI
PersistStreamInit_Release(
721 IPersistStreamInit
*iface
)
723 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
724 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
727 static HRESULT WINAPI
PersistStreamInit_GetClassID(
728 IPersistStreamInit
*iface
, CLSID
*classid
)
730 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
731 TRACE("(%p)->(%p)\n", This
, classid
);
736 *classid
= *DOMDocument_version(This
->properties
->version
);
741 static HRESULT WINAPI
PersistStreamInit_IsDirty(
742 IPersistStreamInit
*iface
)
744 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
745 FIXME("(%p): stub!\n", This
);
749 static HRESULT
domdoc_load_from_stream(domdoc
*doc
, ISequentialStream
*stream
)
751 DWORD read
, written
, len
;
752 xmlDocPtr xmldoc
= NULL
;
760 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &hstream
);
766 ISequentialStream_Read(stream
, buf
, sizeof(buf
), &read
);
767 hr
= IStream_Write(hstream
, buf
, read
, &written
);
768 } while(SUCCEEDED(hr
) && written
!= 0 && read
!= 0);
772 ERR("failed to copy stream 0x%08x\n", hr
);
773 IStream_Release(hstream
);
777 hr
= GetHGlobalFromStream(hstream
, &hglobal
);
781 len
= GlobalSize(hglobal
);
782 ptr
= GlobalLock(hglobal
);
784 xmldoc
= doparse(doc
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
785 GlobalUnlock(hglobal
);
789 ERR("Failed to parse xml\n");
793 xmldoc
->_private
= create_priv();
795 return attach_xmldoc(doc
, xmldoc
);
798 static HRESULT WINAPI
PersistStreamInit_Load(IPersistStreamInit
*iface
, IStream
*stream
)
800 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
802 TRACE("(%p)->(%p)\n", This
, stream
);
807 return domdoc_load_from_stream(This
, (ISequentialStream
*)stream
);
810 static HRESULT WINAPI
PersistStreamInit_Save(
811 IPersistStreamInit
*iface
, IStream
*stream
, BOOL clr_dirty
)
813 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
817 TRACE("(%p)->(%p %d)\n", This
, stream
, clr_dirty
);
819 hr
= IXMLDOMDocument3_get_xml(&This
->IXMLDOMDocument3_iface
, &xmlString
);
822 DWORD len
= SysStringLen(xmlString
) * sizeof(WCHAR
);
824 hr
= IStream_Write( stream
, xmlString
, len
, NULL
);
825 SysFreeString(xmlString
);
828 TRACE("ret 0x%08x\n", hr
);
833 static HRESULT WINAPI
PersistStreamInit_GetSizeMax(
834 IPersistStreamInit
*iface
, ULARGE_INTEGER
*pcbSize
)
836 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
837 TRACE("(%p)->(%p)\n", This
, pcbSize
);
841 static HRESULT WINAPI
PersistStreamInit_InitNew(
842 IPersistStreamInit
*iface
)
844 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
845 TRACE("(%p)\n", This
);
849 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable
=
851 PersistStreamInit_QueryInterface
,
852 PersistStreamInit_AddRef
,
853 PersistStreamInit_Release
,
854 PersistStreamInit_GetClassID
,
855 PersistStreamInit_IsDirty
,
856 PersistStreamInit_Load
,
857 PersistStreamInit_Save
,
858 PersistStreamInit_GetSizeMax
,
859 PersistStreamInit_InitNew
862 /* IXMLDOMDocument3 interface */
864 static const tid_t domdoc_se_tids
[] = {
867 IXMLDOMDocument2_tid
,
868 IXMLDOMDocument3_tid
,
872 static HRESULT WINAPI
domdoc_QueryInterface( IXMLDOMDocument3
*iface
, REFIID riid
, void** ppvObject
)
874 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
876 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( riid
), ppvObject
);
880 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
881 IsEqualGUID( riid
, &IID_IDispatch
) ||
882 IsEqualGUID( riid
, &IID_IXMLDOMNode
) ||
883 IsEqualGUID( riid
, &IID_IXMLDOMDocument
) ||
884 IsEqualGUID( riid
, &IID_IXMLDOMDocument2
)||
885 IsEqualGUID( riid
, &IID_IXMLDOMDocument3
))
889 else if (IsEqualGUID(&IID_IPersistStream
, riid
) ||
890 IsEqualGUID(&IID_IPersistStreamInit
, riid
))
892 *ppvObject
= &This
->IPersistStreamInit_iface
;
894 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
896 *ppvObject
= &This
->IObjectWithSite_iface
;
898 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
900 *ppvObject
= &This
->IObjectSafety_iface
;
902 else if( IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
904 return node_create_supporterrorinfo(domdoc_se_tids
, ppvObject
);
906 else if(node_query_interface(&This
->node
, riid
, ppvObject
))
908 return *ppvObject
? S_OK
: E_NOINTERFACE
;
910 else if (IsEqualGUID( riid
, &IID_IConnectionPointContainer
))
912 *ppvObject
= &This
->IConnectionPointContainer_iface
;
916 TRACE("interface %s not implemented\n", debugstr_guid(riid
));
917 return E_NOINTERFACE
;
920 IUnknown_AddRef((IUnknown
*)*ppvObject
);
925 static ULONG WINAPI
domdoc_AddRef( IXMLDOMDocument3
*iface
)
927 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
928 ULONG ref
= InterlockedIncrement( &This
->ref
);
929 TRACE("(%p)->(%d)\n", This
, ref
);
933 static ULONG WINAPI
domdoc_Release( IXMLDOMDocument3
*iface
)
935 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
936 LONG ref
= InterlockedDecrement( &This
->ref
);
938 TRACE("(%p)->(%d)\n", This
, ref
);
945 IUnknown_Release( This
->site
);
946 destroy_xmlnode(&This
->node
);
948 for (eid
= 0; eid
< EVENTID_LAST
; eid
++)
949 if (This
->events
[eid
]) IDispatch_Release(This
->events
[eid
]);
951 CoTaskMemFree(This
->url
);
952 release_namespaces(This
);
959 static HRESULT WINAPI
domdoc_GetTypeInfoCount( IXMLDOMDocument3
*iface
, UINT
* pctinfo
)
961 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
962 return IDispatchEx_GetTypeInfoCount(&This
->node
.dispex
.IDispatchEx_iface
, pctinfo
);
965 static HRESULT WINAPI
domdoc_GetTypeInfo(
966 IXMLDOMDocument3
*iface
,
967 UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
969 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
970 return IDispatchEx_GetTypeInfo(&This
->node
.dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
973 static HRESULT WINAPI
domdoc_GetIDsOfNames(
974 IXMLDOMDocument3
*iface
,
981 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
982 return IDispatchEx_GetIDsOfNames(&This
->node
.dispex
.IDispatchEx_iface
,
983 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
986 static HRESULT WINAPI
domdoc_Invoke(
987 IXMLDOMDocument3
*iface
,
992 DISPPARAMS
* pDispParams
,
994 EXCEPINFO
* pExcepInfo
,
997 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
998 return IDispatchEx_Invoke(&This
->node
.dispex
.IDispatchEx_iface
,
999 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1002 static HRESULT WINAPI
domdoc_get_nodeName(
1003 IXMLDOMDocument3
*iface
,
1006 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1008 static const WCHAR documentW
[] = {'#','d','o','c','u','m','e','n','t',0};
1010 TRACE("(%p)->(%p)\n", This
, name
);
1012 return return_bstr(documentW
, name
);
1016 static HRESULT WINAPI
domdoc_get_nodeValue(
1017 IXMLDOMDocument3
*iface
,
1020 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1022 TRACE("(%p)->(%p)\n", This
, value
);
1025 return E_INVALIDARG
;
1027 V_VT(value
) = VT_NULL
;
1028 V_BSTR(value
) = NULL
; /* tests show that we should do this */
1033 static HRESULT WINAPI
domdoc_put_nodeValue(
1034 IXMLDOMDocument3
*iface
,
1037 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1038 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&value
));
1043 static HRESULT WINAPI
domdoc_get_nodeType(
1044 IXMLDOMDocument3
*iface
,
1047 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1049 TRACE("(%p)->(%p)\n", This
, type
);
1051 *type
= NODE_DOCUMENT
;
1056 static HRESULT WINAPI
domdoc_get_parentNode(
1057 IXMLDOMDocument3
*iface
,
1058 IXMLDOMNode
** parent
)
1060 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1062 TRACE("(%p)->(%p)\n", This
, parent
);
1064 return node_get_parent(&This
->node
, parent
);
1068 static HRESULT WINAPI
domdoc_get_childNodes(
1069 IXMLDOMDocument3
*iface
,
1070 IXMLDOMNodeList
** childList
)
1072 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1074 TRACE("(%p)->(%p)\n", This
, childList
);
1076 return node_get_child_nodes(&This
->node
, childList
);
1080 static HRESULT WINAPI
domdoc_get_firstChild(
1081 IXMLDOMDocument3
*iface
,
1082 IXMLDOMNode
** firstChild
)
1084 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1086 TRACE("(%p)->(%p)\n", This
, firstChild
);
1088 return node_get_first_child(&This
->node
, firstChild
);
1092 static HRESULT WINAPI
domdoc_get_lastChild(
1093 IXMLDOMDocument3
*iface
,
1094 IXMLDOMNode
** lastChild
)
1096 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1098 TRACE("(%p)->(%p)\n", This
, lastChild
);
1100 return node_get_last_child(&This
->node
, lastChild
);
1104 static HRESULT WINAPI
domdoc_get_previousSibling(
1105 IXMLDOMDocument3
*iface
,
1106 IXMLDOMNode
** previousSibling
)
1108 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1110 TRACE("(%p)->(%p)\n", This
, previousSibling
);
1112 return return_null_node(previousSibling
);
1116 static HRESULT WINAPI
domdoc_get_nextSibling(
1117 IXMLDOMDocument3
*iface
,
1118 IXMLDOMNode
** nextSibling
)
1120 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1122 TRACE("(%p)->(%p)\n", This
, nextSibling
);
1124 return return_null_node(nextSibling
);
1128 static HRESULT WINAPI
domdoc_get_attributes(
1129 IXMLDOMDocument3
*iface
,
1130 IXMLDOMNamedNodeMap
** attributeMap
)
1132 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1134 TRACE("(%p)->(%p)\n", This
, attributeMap
);
1136 return return_null_ptr((void**)attributeMap
);
1140 static HRESULT WINAPI
domdoc_insertBefore(
1141 IXMLDOMDocument3
*iface
,
1142 IXMLDOMNode
* newChild
,
1144 IXMLDOMNode
** outNewChild
)
1146 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1150 TRACE("(%p)->(%p %s %p)\n", This
, newChild
, debugstr_variant(&refChild
), outNewChild
);
1152 hr
= IXMLDOMNode_get_nodeType(newChild
, &type
);
1153 if (hr
!= S_OK
) return hr
;
1155 TRACE("new node type %d\n", type
);
1158 case NODE_ATTRIBUTE
:
1160 case NODE_CDATA_SECTION
:
1161 if (outNewChild
) *outNewChild
= NULL
;
1164 return node_insert_before(&This
->node
, newChild
, &refChild
, outNewChild
);
1168 static HRESULT WINAPI
domdoc_replaceChild(
1169 IXMLDOMDocument3
*iface
,
1170 IXMLDOMNode
* newChild
,
1171 IXMLDOMNode
* oldChild
,
1172 IXMLDOMNode
** outOldChild
)
1174 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1176 TRACE("(%p)->(%p %p %p)\n", This
, newChild
, oldChild
, outOldChild
);
1178 return node_replace_child(&This
->node
, newChild
, oldChild
, outOldChild
);
1182 static HRESULT WINAPI
domdoc_removeChild(
1183 IXMLDOMDocument3
*iface
,
1185 IXMLDOMNode
**oldChild
)
1187 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1188 TRACE("(%p)->(%p %p)\n", This
, child
, oldChild
);
1189 return node_remove_child(&This
->node
, child
, oldChild
);
1193 static HRESULT WINAPI
domdoc_appendChild(
1194 IXMLDOMDocument3
*iface
,
1196 IXMLDOMNode
**outChild
)
1198 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1199 TRACE("(%p)->(%p %p)\n", This
, child
, outChild
);
1200 return node_append_child(&This
->node
, child
, outChild
);
1204 static HRESULT WINAPI
domdoc_hasChildNodes(
1205 IXMLDOMDocument3
*iface
,
1208 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1209 TRACE("(%p)->(%p)\n", This
, ret
);
1210 return node_has_childnodes(&This
->node
, ret
);
1214 static HRESULT WINAPI
domdoc_get_ownerDocument(
1215 IXMLDOMDocument3
*iface
,
1216 IXMLDOMDocument
**doc
)
1218 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1219 TRACE("(%p)->(%p)\n", This
, doc
);
1220 return node_get_owner_doc(&This
->node
, doc
);
1224 static HRESULT WINAPI
domdoc_cloneNode(
1225 IXMLDOMDocument3
*iface
,
1227 IXMLDOMNode
** outNode
)
1229 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1230 TRACE("(%p)->(%d %p)\n", This
, deep
, outNode
);
1231 return node_clone( &This
->node
, deep
, outNode
);
1235 static HRESULT WINAPI
domdoc_get_nodeTypeString(
1236 IXMLDOMDocument3
*iface
,
1239 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1240 static const WCHAR documentW
[] = {'d','o','c','u','m','e','n','t',0};
1242 TRACE("(%p)->(%p)\n", This
, p
);
1244 return return_bstr(documentW
, p
);
1248 static HRESULT WINAPI
domdoc_get_text(
1249 IXMLDOMDocument3
*iface
,
1252 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1253 TRACE("(%p)->(%p)\n", This
, p
);
1254 return node_get_text(&This
->node
, p
);
1258 static HRESULT WINAPI
domdoc_put_text(
1259 IXMLDOMDocument3
*iface
,
1262 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1263 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
1268 static HRESULT WINAPI
domdoc_get_specified(
1269 IXMLDOMDocument3
*iface
,
1270 VARIANT_BOOL
* isSpecified
)
1272 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1273 FIXME("(%p)->(%p) stub!\n", This
, isSpecified
);
1274 *isSpecified
= VARIANT_TRUE
;
1279 static HRESULT WINAPI
domdoc_get_definition(
1280 IXMLDOMDocument3
*iface
,
1281 IXMLDOMNode
** definitionNode
)
1283 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1284 FIXME("(%p)->(%p)\n", This
, definitionNode
);
1289 static HRESULT WINAPI
domdoc_get_nodeTypedValue(
1290 IXMLDOMDocument3
*iface
,
1293 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1294 TRACE("(%p)->(%p)\n", This
, v
);
1295 return return_null_var(v
);
1298 static HRESULT WINAPI
domdoc_put_nodeTypedValue(
1299 IXMLDOMDocument3
*iface
,
1300 VARIANT typedValue
)
1302 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1303 FIXME("(%p)->(%s)\n", This
, debugstr_variant(&typedValue
));
1308 static HRESULT WINAPI
domdoc_get_dataType(
1309 IXMLDOMDocument3
*iface
,
1312 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1313 TRACE("(%p)->(%p)\n", This
, typename
);
1314 return return_null_var( typename
);
1318 static HRESULT WINAPI
domdoc_put_dataType(
1319 IXMLDOMDocument3
*iface
,
1322 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1324 FIXME("(%p)->(%s)\n", This
, debugstr_w(dataTypeName
));
1327 return E_INVALIDARG
;
1332 static int XMLCALL
domdoc_get_xml_writecallback(void *ctx
, const char *data
, int len
)
1334 return xmlBufferAdd((xmlBufferPtr
)ctx
, (xmlChar
*)data
, len
) == 0 ? len
: 0;
1337 static HRESULT WINAPI
domdoc_get_xml(
1338 IXMLDOMDocument3
*iface
,
1341 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1342 xmlSaveCtxtPtr ctxt
;
1347 TRACE("(%p)->(%p)\n", This
, p
);
1350 return E_INVALIDARG
;
1354 buf
= xmlBufferCreate();
1356 return E_OUTOFMEMORY
;
1358 options
= XML_SAVE_FORMAT
| XML_SAVE_NO_DECL
;
1359 ctxt
= xmlSaveToIO(domdoc_get_xml_writecallback
, NULL
, buf
, "UTF-8", options
);
1364 return E_OUTOFMEMORY
;
1367 ret
= xmlSaveDoc(ctxt
, get_doc(This
));
1368 /* flushes on close */
1371 TRACE("%ld, len=%d\n", ret
, xmlBufferLength(buf
));
1372 if(ret
!= -1 && xmlBufferLength(buf
) > 0)
1376 content
= bstr_from_xmlChar(xmlBufferContent(buf
));
1377 content
= EnsureCorrectEOL(content
);
1383 *p
= SysAllocStringLen(NULL
, 0);
1388 return *p
? S_OK
: E_OUTOFMEMORY
;
1392 static HRESULT WINAPI
domdoc_transformNode(
1393 IXMLDOMDocument3
*iface
,
1397 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1398 TRACE("(%p)->(%p %p)\n", This
, node
, p
);
1399 return node_transform_node(&This
->node
, node
, p
);
1403 static HRESULT WINAPI
domdoc_selectNodes(
1404 IXMLDOMDocument3
*iface
,
1406 IXMLDOMNodeList
**outList
)
1408 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1409 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outList
);
1410 return node_select_nodes(&This
->node
, p
, outList
);
1414 static HRESULT WINAPI
domdoc_selectSingleNode(
1415 IXMLDOMDocument3
*iface
,
1417 IXMLDOMNode
**outNode
)
1419 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1420 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outNode
);
1421 return node_select_singlenode(&This
->node
, p
, outNode
);
1425 static HRESULT WINAPI
domdoc_get_parsed(
1426 IXMLDOMDocument3
*iface
,
1427 VARIANT_BOOL
* isParsed
)
1429 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1430 FIXME("(%p)->(%p) stub!\n", This
, isParsed
);
1431 *isParsed
= VARIANT_TRUE
;
1435 static HRESULT WINAPI
domdoc_get_namespaceURI(
1436 IXMLDOMDocument3
*iface
,
1437 BSTR
* namespaceURI
)
1439 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1440 TRACE("(%p)->(%p)\n", This
, namespaceURI
);
1441 return return_null_bstr( namespaceURI
);
1444 static HRESULT WINAPI
domdoc_get_prefix(
1445 IXMLDOMDocument3
*iface
,
1448 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1449 TRACE("(%p)->(%p)\n", This
, prefix
);
1450 return return_null_bstr( prefix
);
1454 static HRESULT WINAPI
domdoc_get_baseName(
1455 IXMLDOMDocument3
*iface
,
1458 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1459 TRACE("(%p)->(%p)\n", This
, name
);
1460 return return_null_bstr( name
);
1464 static HRESULT WINAPI
domdoc_transformNodeToObject(
1465 IXMLDOMDocument3
*iface
,
1466 IXMLDOMNode
* stylesheet
,
1467 VARIANT outputObject
)
1469 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1470 FIXME("(%p)->(%p %s)\n", This
, stylesheet
, debugstr_variant(&outputObject
));
1475 static HRESULT WINAPI
domdoc_get_doctype(
1476 IXMLDOMDocument3
*iface
,
1477 IXMLDOMDocumentType
** doctype
)
1479 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1484 TRACE("(%p)->(%p)\n", This
, doctype
);
1486 if (!doctype
) return E_INVALIDARG
;
1490 dtd
= xmlGetIntSubset(get_doc(This
));
1491 if (!dtd
) return S_FALSE
;
1493 node
= create_node((xmlNodePtr
)dtd
);
1494 if (!node
) return S_FALSE
;
1496 hr
= IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentType
, (void**)doctype
);
1497 IXMLDOMNode_Release(node
);
1503 static HRESULT WINAPI
domdoc_get_implementation(
1504 IXMLDOMDocument3
*iface
,
1505 IXMLDOMImplementation
** impl
)
1507 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1509 TRACE("(%p)->(%p)\n", This
, impl
);
1512 return E_INVALIDARG
;
1514 *impl
= (IXMLDOMImplementation
*)create_doc_Implementation();
1519 static HRESULT WINAPI
domdoc_get_documentElement(
1520 IXMLDOMDocument3
*iface
,
1521 IXMLDOMElement
** DOMElement
)
1523 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1524 IXMLDOMNode
*element_node
;
1528 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1531 return E_INVALIDARG
;
1535 root
= xmlDocGetRootElement( get_doc(This
) );
1539 element_node
= create_node( root
);
1540 if(!element_node
) return S_FALSE
;
1542 hr
= IXMLDOMNode_QueryInterface(element_node
, &IID_IXMLDOMElement
, (void**)DOMElement
);
1543 IXMLDOMNode_Release(element_node
);
1549 static HRESULT WINAPI
domdoc_put_documentElement(
1550 IXMLDOMDocument3
*iface
,
1551 IXMLDOMElement
* DOMElement
)
1553 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1554 IXMLDOMNode
*elementNode
;
1561 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1563 hr
= IXMLDOMElement_QueryInterface( DOMElement
, &IID_IXMLDOMNode
, (void**)&elementNode
);
1567 xmlNode
= get_node_obj( elementNode
);
1568 if(!xmlNode
) return E_FAIL
;
1570 if(!xmlNode
->node
->parent
)
1571 if(xmldoc_remove_orphan(xmlNode
->node
->doc
, xmlNode
->node
) != S_OK
)
1572 WARN("%p is not an orphan of %p\n", xmlNode
->node
->doc
, xmlNode
->node
);
1574 old_doc
= xmlNode
->node
->doc
;
1575 if (old_doc
!= get_doc(This
))
1576 refcount
= xmlnode_get_inst_cnt(xmlNode
);
1578 /* old root is still orphaned by its document, update refcount from new root */
1579 if (refcount
) xmldoc_add_refs(get_doc(This
), refcount
);
1580 oldRoot
= xmlDocSetRootElement( get_doc(This
), xmlNode
->node
);
1581 if (refcount
) xmldoc_release_refs(old_doc
, refcount
);
1582 IXMLDOMNode_Release( elementNode
);
1585 xmldoc_add_orphan(oldRoot
->doc
, oldRoot
);
1591 static HRESULT WINAPI
domdoc_createElement(
1592 IXMLDOMDocument3
*iface
,
1594 IXMLDOMElement
** element
)
1596 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1601 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(tagname
), element
);
1603 if (!element
|| !tagname
) return E_INVALIDARG
;
1605 V_VT(&type
) = VT_I1
;
1606 V_I1(&type
) = NODE_ELEMENT
;
1608 hr
= IXMLDOMDocument3_createNode(iface
, type
, tagname
, NULL
, &node
);
1611 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMElement
, (void**)element
);
1612 IXMLDOMNode_Release(node
);
1619 static HRESULT WINAPI
domdoc_createDocumentFragment(
1620 IXMLDOMDocument3
*iface
,
1621 IXMLDOMDocumentFragment
** frag
)
1623 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1628 TRACE("(%p)->(%p)\n", This
, frag
);
1630 if (!frag
) return E_INVALIDARG
;
1634 V_VT(&type
) = VT_I1
;
1635 V_I1(&type
) = NODE_DOCUMENT_FRAGMENT
;
1637 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1640 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentFragment
, (void**)frag
);
1641 IXMLDOMNode_Release(node
);
1648 static HRESULT WINAPI
domdoc_createTextNode(
1649 IXMLDOMDocument3
*iface
,
1651 IXMLDOMText
** text
)
1653 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1658 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), text
);
1660 if (!text
) return E_INVALIDARG
;
1664 V_VT(&type
) = VT_I1
;
1665 V_I1(&type
) = NODE_TEXT
;
1667 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1670 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMText
, (void**)text
);
1671 IXMLDOMNode_Release(node
);
1672 hr
= IXMLDOMText_put_data(*text
, data
);
1679 static HRESULT WINAPI
domdoc_createComment(
1680 IXMLDOMDocument3
*iface
,
1682 IXMLDOMComment
** comment
)
1684 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1689 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), comment
);
1691 if (!comment
) return E_INVALIDARG
;
1695 V_VT(&type
) = VT_I1
;
1696 V_I1(&type
) = NODE_COMMENT
;
1698 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1701 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMComment
, (void**)comment
);
1702 IXMLDOMNode_Release(node
);
1703 hr
= IXMLDOMComment_put_data(*comment
, data
);
1710 static HRESULT WINAPI
domdoc_createCDATASection(
1711 IXMLDOMDocument3
*iface
,
1713 IXMLDOMCDATASection
** cdata
)
1715 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1720 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), cdata
);
1722 if (!cdata
) return E_INVALIDARG
;
1726 V_VT(&type
) = VT_I1
;
1727 V_I1(&type
) = NODE_CDATA_SECTION
;
1729 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1732 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMCDATASection
, (void**)cdata
);
1733 IXMLDOMNode_Release(node
);
1734 hr
= IXMLDOMCDATASection_put_data(*cdata
, data
);
1741 static HRESULT WINAPI
domdoc_createProcessingInstruction(
1742 IXMLDOMDocument3
*iface
,
1745 IXMLDOMProcessingInstruction
** pi
)
1747 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1752 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_w(target
), debugstr_w(data
), pi
);
1754 if (!pi
) return E_INVALIDARG
;
1758 V_VT(&type
) = VT_I1
;
1759 V_I1(&type
) = NODE_PROCESSING_INSTRUCTION
;
1761 hr
= IXMLDOMDocument3_createNode(iface
, type
, target
, NULL
, &node
);
1766 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1767 node_obj
= get_node_obj(node
);
1768 hr
= node_set_content(node_obj
, data
);
1770 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMProcessingInstruction
, (void**)pi
);
1771 IXMLDOMNode_Release(node
);
1778 static HRESULT WINAPI
domdoc_createAttribute(
1779 IXMLDOMDocument3
*iface
,
1781 IXMLDOMAttribute
** attribute
)
1783 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1788 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), attribute
);
1790 if (!attribute
|| !name
) return E_INVALIDARG
;
1792 V_VT(&type
) = VT_I1
;
1793 V_I1(&type
) = NODE_ATTRIBUTE
;
1795 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1798 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMAttribute
, (void**)attribute
);
1799 IXMLDOMNode_Release(node
);
1806 static HRESULT WINAPI
domdoc_createEntityReference(
1807 IXMLDOMDocument3
*iface
,
1809 IXMLDOMEntityReference
** entityref
)
1811 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1816 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), entityref
);
1818 if (!entityref
) return E_INVALIDARG
;
1822 V_VT(&type
) = VT_I1
;
1823 V_I1(&type
) = NODE_ENTITY_REFERENCE
;
1825 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1828 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMEntityReference
, (void**)entityref
);
1829 IXMLDOMNode_Release(node
);
1835 xmlChar
* tagName_to_XPath(const BSTR tagName
)
1837 xmlChar
*query
, *tmp
;
1838 static const xmlChar mod_pre
[] = "*[local-name()='";
1839 static const xmlChar mod_post
[] = "']";
1840 static const xmlChar prefix
[] = "descendant::";
1841 const WCHAR
*tokBegin
, *tokEnd
;
1844 query
= xmlStrdup(prefix
);
1847 while (tokBegin
&& *tokBegin
)
1852 query
= xmlStrcat(query
, BAD_CAST
"/");
1856 query
= xmlStrcat(query
, BAD_CAST
"*");
1860 query
= xmlStrcat(query
, mod_pre
);
1862 while (*tokEnd
&& *tokEnd
!= '/')
1864 len
= WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, NULL
, 0, NULL
, NULL
);
1865 tmp
= xmlMalloc(len
);
1866 WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, (char*)tmp
, len
, NULL
, NULL
);
1867 query
= xmlStrncat(query
, tmp
, len
);
1870 query
= xmlStrcat(query
, mod_post
);
1877 static HRESULT WINAPI
domdoc_getElementsByTagName(
1878 IXMLDOMDocument3
*iface
,
1880 IXMLDOMNodeList
** resultList
)
1882 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1887 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(tagName
), resultList
);
1889 if (!tagName
|| !resultList
) return E_INVALIDARG
;
1891 XPath
= This
->properties
->XPath
;
1892 This
->properties
->XPath
= TRUE
;
1893 query
= tagName_to_XPath(tagName
);
1894 hr
= create_selection((xmlNodePtr
)get_doc(This
), query
, resultList
);
1896 This
->properties
->XPath
= XPath
;
1901 static HRESULT
get_node_type(VARIANT Type
, DOMNodeType
* type
)
1907 hr
= VariantChangeType(&tmp
, &Type
, 0, VT_I4
);
1909 return E_INVALIDARG
;
1916 static HRESULT WINAPI
domdoc_createNode(
1917 IXMLDOMDocument3
*iface
,
1921 IXMLDOMNode
** node
)
1923 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1924 DOMNodeType node_type
;
1926 xmlChar
*xml_name
, *href
;
1929 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_variant(&Type
), debugstr_w(name
), debugstr_w(namespaceURI
), node
);
1931 if(!node
) return E_INVALIDARG
;
1933 hr
= get_node_type(Type
, &node_type
);
1934 if(FAILED(hr
)) return hr
;
1936 TRACE("node_type %d\n", node_type
);
1938 /* exit earlier for types that need name */
1942 case NODE_ATTRIBUTE
:
1943 case NODE_ENTITY_REFERENCE
:
1944 case NODE_PROCESSING_INSTRUCTION
:
1945 if (!name
|| *name
== 0) return E_FAIL
;
1951 xml_name
= xmlchar_from_wchar(name
);
1952 /* prevent empty href to be allocated */
1953 href
= namespaceURI
? xmlchar_from_wchar(namespaceURI
) : NULL
;
1959 xmlChar
*local
, *prefix
;
1961 local
= xmlSplitQName2(xml_name
, &prefix
);
1963 xmlnode
= xmlNewDocNode(get_doc(This
), NULL
, local
? local
: xml_name
, NULL
);
1965 /* allow to create default namespace xmlns= */
1966 if (local
|| (href
&& *href
))
1968 xmlNsPtr ns
= xmlNewNs(xmlnode
, href
, prefix
);
1969 xmlSetNs(xmlnode
, ns
);
1977 case NODE_ATTRIBUTE
:
1979 xmlChar
*local
, *prefix
;
1981 local
= xmlSplitQName2(xml_name
, &prefix
);
1983 xmlnode
= (xmlNodePtr
)xmlNewDocProp(get_doc(This
), local
? local
: xml_name
, NULL
);
1985 if (local
|| (href
&& *href
))
1987 /* we need a floating namespace here, it can't be created linked to attribute from
1989 xmlNsPtr ns
= xmlNewNs(NULL
, href
, prefix
);
1990 xmlSetNs(xmlnode
, ns
);
1999 xmlnode
= (xmlNodePtr
)xmlNewDocText(get_doc(This
), NULL
);
2001 case NODE_CDATA_SECTION
:
2002 xmlnode
= xmlNewCDataBlock(get_doc(This
), NULL
, 0);
2004 case NODE_ENTITY_REFERENCE
:
2005 xmlnode
= xmlNewReference(get_doc(This
), xml_name
);
2007 case NODE_PROCESSING_INSTRUCTION
:
2008 #ifdef HAVE_XMLNEWDOCPI
2009 xmlnode
= xmlNewDocPI(get_doc(This
), xml_name
, NULL
);
2011 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2016 xmlnode
= xmlNewDocComment(get_doc(This
), NULL
);
2018 case NODE_DOCUMENT_FRAGMENT
:
2019 xmlnode
= xmlNewDocFragment(get_doc(This
));
2021 /* unsupported types */
2023 case NODE_DOCUMENT_TYPE
:
2026 heap_free(xml_name
);
2027 return E_INVALIDARG
;
2029 FIXME("unhandled node type %d\n", node_type
);
2034 *node
= create_node(xmlnode
);
2035 heap_free(xml_name
);
2040 TRACE("created node (%d, %p, %p)\n", node_type
, *node
, xmlnode
);
2041 xmldoc_add_orphan(xmlnode
->doc
, xmlnode
);
2048 static HRESULT WINAPI
domdoc_nodeFromID(
2049 IXMLDOMDocument3
*iface
,
2051 IXMLDOMNode
** node
)
2053 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2054 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(idString
), node
);
2058 static HRESULT
domdoc_onDataAvailable(void *obj
, char *ptr
, DWORD len
)
2063 xmldoc
= doparse(This
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
2065 xmldoc
->_private
= create_priv();
2066 return attach_xmldoc(This
, xmldoc
);
2072 static HRESULT
domdoc_load_moniker(domdoc
*This
, IMoniker
*mon
)
2077 hr
= bind_url(mon
, domdoc_onDataAvailable
, This
, &bsc
);
2081 return detach_bsc(bsc
);
2084 static HRESULT WINAPI
domdoc_load(
2085 IXMLDOMDocument3
*iface
,
2087 VARIANT_BOOL
* isSuccessful
)
2089 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2090 LPWSTR filename
= NULL
;
2091 HRESULT hr
= S_FALSE
;
2094 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&source
));
2098 *isSuccessful
= VARIANT_FALSE
;
2100 assert( &This
->node
);
2102 switch( V_VT(&source
) )
2105 filename
= V_BSTR(&source
);
2107 case VT_BSTR
|VT_BYREF
:
2108 if (!V_BSTRREF(&source
)) return E_INVALIDARG
;
2109 filename
= *V_BSTRREF(&source
);
2111 case VT_ARRAY
|VT_UI1
:
2113 SAFEARRAY
*psa
= V_ARRAY(&source
);
2116 UINT dim
= SafeArrayGetDim(psa
);
2121 ERR("SAFEARRAY == NULL\n");
2122 hr
= This
->error
= E_INVALIDARG
;
2125 /* Only takes UTF-8 strings.
2126 * NOT NULL-terminated. */
2127 SafeArrayAccessData(psa
, (void**)&str
);
2128 SafeArrayGetUBound(psa
, 1, &len
);
2130 if ((xmldoc
= doparse(This
, str
, ++len
, XML_CHAR_ENCODING_UTF8
)))
2132 hr
= This
->error
= S_OK
;
2133 *isSuccessful
= VARIANT_TRUE
;
2134 TRACE("parsed document %p\n", xmldoc
);
2138 This
->error
= E_FAIL
;
2139 TRACE("failed to parse document\n");
2142 SafeArrayUnaccessData(psa
);
2146 xmldoc
->_private
= create_priv();
2147 return attach_xmldoc(This
, xmldoc
);
2151 FIXME("unhandled SAFEARRAY dim: %d\n", dim
);
2152 hr
= This
->error
= E_NOTIMPL
;
2158 ISequentialStream
*stream
= NULL
;
2159 IXMLDOMDocument3
*newdoc
= NULL
;
2161 if (!V_UNKNOWN(&source
)) return E_INVALIDARG
;
2163 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IXMLDOMDocument3
, (void**)&newdoc
);
2168 domdoc
*newDoc
= impl_from_IXMLDOMDocument3( newdoc
);
2170 xmldoc
= xmlCopyDoc(get_doc(newDoc
), 1);
2171 xmldoc
->_private
= create_priv();
2172 hr
= attach_xmldoc(This
, xmldoc
);
2175 *isSuccessful
= VARIANT_TRUE
;
2181 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IStream
, (void**)&stream
);
2183 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_ISequentialStream
, (void**)&stream
);
2187 hr
= domdoc_load_from_stream(This
, stream
);
2189 *isSuccessful
= VARIANT_TRUE
;
2190 ISequentialStream_Release(stream
);
2194 FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr
, V_UNKNOWN(&source
)->lpVtbl
);
2198 FIXME("VT type not supported (%d)\n", V_VT(&source
));
2205 CoTaskMemFree(This
->url
);
2208 hr
= create_moniker_from_url( filename
, &mon
);
2209 if ( SUCCEEDED(hr
) )
2211 hr
= domdoc_load_moniker( This
, mon
);
2213 IMoniker_GetDisplayName(mon
, NULL
, NULL
, &This
->url
);
2214 IMoniker_Release(mon
);
2218 This
->error
= E_FAIL
;
2221 hr
= This
->error
= S_OK
;
2222 *isSuccessful
= VARIANT_TRUE
;
2226 if(!filename
|| FAILED(hr
)) {
2227 xmldoc
= xmlNewDoc(NULL
);
2228 xmldoc
->_private
= create_priv();
2229 hr
= attach_xmldoc(This
, xmldoc
);
2234 TRACE("ret (%d)\n", hr
);
2240 static HRESULT WINAPI
domdoc_get_readyState(
2241 IXMLDOMDocument3
*iface
,
2244 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2245 FIXME("stub! (%p)->(%p)\n", This
, value
);
2248 return E_INVALIDARG
;
2250 *value
= READYSTATE_COMPLETE
;
2255 static HRESULT WINAPI
domdoc_get_parseError(
2256 IXMLDOMDocument3
*iface
,
2257 IXMLDOMParseError
** errorObj
)
2259 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2260 static const WCHAR err
[] = {'e','r','r','o','r',0};
2261 BSTR error_string
= NULL
;
2263 FIXME("(%p)->(%p): creating a dummy parseError\n", iface
, errorObj
);
2266 error_string
= SysAllocString(err
);
2268 *errorObj
= create_parseError(This
->error
, NULL
, error_string
, NULL
, 0, 0, 0);
2269 if(!*errorObj
) return E_OUTOFMEMORY
;
2274 static HRESULT WINAPI
domdoc_get_url(
2275 IXMLDOMDocument3
*iface
,
2278 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2280 TRACE("(%p)->(%p)\n", This
, url
);
2283 return E_INVALIDARG
;
2287 *url
= SysAllocString(This
->url
);
2289 return E_OUTOFMEMORY
;
2294 return return_null_bstr(url
);
2298 static HRESULT WINAPI
domdoc_get_async(
2299 IXMLDOMDocument3
*iface
,
2300 VARIANT_BOOL
* isAsync
)
2302 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2304 TRACE("(%p)->(%p: %d)\n", This
, isAsync
, This
->async
);
2305 *isAsync
= This
->async
;
2310 static HRESULT WINAPI
domdoc_put_async(
2311 IXMLDOMDocument3
*iface
,
2312 VARIANT_BOOL isAsync
)
2314 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2316 TRACE("(%p)->(%d)\n", This
, isAsync
);
2317 This
->async
= isAsync
;
2322 static HRESULT WINAPI
domdoc_abort(
2323 IXMLDOMDocument3
*iface
)
2325 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2326 FIXME("%p\n", This
);
2330 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2331 static HRESULT WINAPI
domdoc_loadXML(
2332 IXMLDOMDocument3
*iface
,
2334 VARIANT_BOOL
* isSuccessful
)
2336 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2337 xmlDocPtr xmldoc
= NULL
;
2338 HRESULT hr
= S_FALSE
, hr2
;
2340 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), isSuccessful
);
2342 assert ( &This
->node
);
2346 *isSuccessful
= VARIANT_FALSE
;
2352 /* skip leading spaces if needed */
2353 if (This
->properties
->version
== MSXML_DEFAULT
|| This
->properties
->version
== MSXML26
)
2354 while (*ptr
&& isspaceW(*ptr
)) ptr
++;
2356 xmldoc
= doparse(This
, (char*)ptr
, strlenW(ptr
)*sizeof(WCHAR
), XML_CHAR_ENCODING_UTF16LE
);
2359 This
->error
= E_FAIL
;
2360 TRACE("failed to parse document\n");
2364 hr
= This
->error
= S_OK
;
2365 *isSuccessful
= VARIANT_TRUE
;
2366 TRACE("parsed document %p\n", xmldoc
);
2372 xmldoc
= xmlNewDoc(NULL
);
2373 xmldoc
->_private
= create_priv();
2374 hr2
= attach_xmldoc(This
, xmldoc
);
2381 static int XMLCALL
domdoc_save_writecallback(void *ctx
, const char *buffer
, int len
)
2385 if(!WriteFile(ctx
, buffer
, len
, &written
, NULL
))
2387 WARN("write error\n");
2394 static int XMLCALL
domdoc_save_closecallback(void *ctx
)
2396 return CloseHandle(ctx
) ? 0 : -1;
2399 static int XMLCALL
domdoc_stream_save_writecallback(void *ctx
, const char *buffer
, int len
)
2404 hr
= IStream_Write((IStream
*)ctx
, buffer
, len
, &written
);
2405 TRACE("0x%08x %p %d %u\n", hr
, buffer
, len
, written
);
2408 WARN("stream write error: 0x%08x\n", hr
);
2415 static int XMLCALL
domdoc_stream_save_closecallback(void *ctx
)
2417 IStream_Release((IStream
*)ctx
);
2421 static HRESULT WINAPI
domdoc_save(
2422 IXMLDOMDocument3
*iface
,
2423 VARIANT destination
)
2425 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2426 xmlSaveCtxtPtr ctx
= NULL
;
2430 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&destination
));
2432 switch (V_VT(&destination
))
2436 IUnknown
*pUnk
= V_UNKNOWN(&destination
);
2437 IXMLDOMDocument3
*document
;
2440 ret
= IUnknown_QueryInterface(pUnk
, &IID_IXMLDOMDocument3
, (void**)&document
);
2443 VARIANT_BOOL success
;
2446 ret
= IXMLDOMDocument3_get_xml(iface
, &xml
);
2449 ret
= IXMLDOMDocument3_loadXML(document
, xml
, &success
);
2453 IXMLDOMDocument3_Release(document
);
2457 ret
= IUnknown_QueryInterface(pUnk
, &IID_IStream
, (void**)&stream
);
2460 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2461 ctx
= xmlSaveToIO(domdoc_stream_save_writecallback
,
2462 domdoc_stream_save_closecallback
, stream
, NULL
, options
);
2466 IStream_Release(stream
);
2474 case VT_BSTR
| VT_BYREF
:
2476 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2478 /* save with file path */
2479 HANDLE handle
= CreateFileW( (V_VT(&destination
) & VT_BYREF
)? *V_BSTRREF(&destination
) : V_BSTR(&destination
),
2480 GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2481 if( handle
== INVALID_HANDLE_VALUE
)
2483 WARN("failed to create file\n");
2487 /* disable top XML declaration */
2488 ctx
= xmlSaveToIO(domdoc_save_writecallback
, domdoc_save_closecallback
,
2489 handle
, NULL
, options
);
2492 CloseHandle(handle
);
2499 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination
));
2503 xmldecl
= xmldoc_unlink_xmldecl(get_doc(This
));
2504 if (xmlSaveDoc(ctx
, get_doc(This
)) == -1) ret
= S_FALSE
;
2505 xmldoc_link_xmldecl(get_doc(This
), xmldecl
);
2507 /* will release resources through close callback */
2513 static HRESULT WINAPI
domdoc_get_validateOnParse(
2514 IXMLDOMDocument3
*iface
,
2515 VARIANT_BOOL
* isValidating
)
2517 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2518 TRACE("(%p)->(%p: %d)\n", This
, isValidating
, This
->validating
);
2519 *isValidating
= This
->validating
;
2524 static HRESULT WINAPI
domdoc_put_validateOnParse(
2525 IXMLDOMDocument3
*iface
,
2526 VARIANT_BOOL isValidating
)
2528 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2529 TRACE("(%p)->(%d)\n", This
, isValidating
);
2530 This
->validating
= isValidating
;
2535 static HRESULT WINAPI
domdoc_get_resolveExternals(
2536 IXMLDOMDocument3
*iface
,
2537 VARIANT_BOOL
* isResolving
)
2539 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2540 TRACE("(%p)->(%p: %d)\n", This
, isResolving
, This
->resolving
);
2541 *isResolving
= This
->resolving
;
2546 static HRESULT WINAPI
domdoc_put_resolveExternals(
2547 IXMLDOMDocument3
*iface
,
2548 VARIANT_BOOL isResolving
)
2550 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2551 TRACE("(%p)->(%d)\n", This
, isResolving
);
2552 This
->resolving
= isResolving
;
2557 static HRESULT WINAPI
domdoc_get_preserveWhiteSpace(
2558 IXMLDOMDocument3
*iface
,
2559 VARIANT_BOOL
* isPreserving
)
2561 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2562 TRACE("(%p)->(%p: %d)\n", This
, isPreserving
, This
->properties
->preserving
);
2563 *isPreserving
= This
->properties
->preserving
;
2568 static HRESULT WINAPI
domdoc_put_preserveWhiteSpace(
2569 IXMLDOMDocument3
*iface
,
2570 VARIANT_BOOL isPreserving
)
2572 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2573 TRACE("(%p)->(%d)\n", This
, isPreserving
);
2574 This
->properties
->preserving
= isPreserving
;
2579 static HRESULT WINAPI
domdoc_put_onreadystatechange(
2580 IXMLDOMDocument3
*iface
,
2583 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2585 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&event
));
2586 return set_doc_event(This
, EVENTID_READYSTATECHANGE
, &event
);
2590 static HRESULT WINAPI
domdoc_put_onDataAvailable(IXMLDOMDocument3
*iface
, VARIANT sink
)
2592 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2593 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2597 static HRESULT WINAPI
domdoc_put_onTransformNode(IXMLDOMDocument3
*iface
, VARIANT sink
)
2599 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2600 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2604 static HRESULT WINAPI
domdoc_get_namespaces(
2605 IXMLDOMDocument3
* iface
,
2606 IXMLDOMSchemaCollection
** collection
)
2608 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2611 FIXME("(%p)->(%p): semi-stub\n", This
, collection
);
2613 if (!collection
) return E_POINTER
;
2615 if (!This
->namespaces
)
2617 hr
= SchemaCache_create(This
->properties
->version
, NULL
, (void**)&This
->namespaces
);
2618 if (hr
!= S_OK
) return hr
;
2620 hr
= cache_from_doc_ns(This
->namespaces
, &This
->node
);
2622 release_namespaces(This
);
2625 if (This
->namespaces
)
2626 return IXMLDOMSchemaCollection2_QueryInterface(This
->namespaces
,
2627 &IID_IXMLDOMSchemaCollection
, (void**)collection
);
2632 static HRESULT WINAPI
domdoc_get_schemas(
2633 IXMLDOMDocument3
* iface
,
2636 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2637 IXMLDOMSchemaCollection2
* cur_schema
= This
->properties
->schemaCache
;
2638 HRESULT hr
= S_FALSE
;
2640 TRACE("(%p)->(%p)\n", This
, schema
);
2642 V_VT(schema
) = VT_NULL
;
2643 /* just to reset pointer part, cause that's what application is expected to use */
2644 V_DISPATCH(schema
) = NULL
;
2648 hr
= IXMLDOMSchemaCollection2_QueryInterface(cur_schema
, &IID_IDispatch
, (void**)&V_DISPATCH(schema
));
2650 V_VT(schema
) = VT_DISPATCH
;
2655 static HRESULT WINAPI
domdoc_putref_schemas(
2656 IXMLDOMDocument3
* iface
,
2659 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2660 HRESULT hr
= E_FAIL
;
2661 IXMLDOMSchemaCollection2
* new_schema
= NULL
;
2663 FIXME("(%p)->(%s): semi-stub\n", This
, debugstr_variant(&schema
));
2664 switch(V_VT(&schema
))
2667 if (V_UNKNOWN(&schema
))
2669 hr
= IUnknown_QueryInterface(V_UNKNOWN(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2674 if (V_DISPATCH(&schema
))
2676 hr
= IDispatch_QueryInterface(V_DISPATCH(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2686 WARN("Can't get schema from vt %x\n", V_VT(&schema
));
2691 IXMLDOMSchemaCollection2
* old_schema
= InterlockedExchangePointer((void**)&This
->properties
->schemaCache
, new_schema
);
2692 if(old_schema
) IXMLDOMSchemaCollection2_Release(old_schema
);
2698 static inline BOOL
is_wellformed(xmlDocPtr doc
)
2700 #ifdef HAVE_XMLDOC_PROPERTIES
2701 return doc
->properties
& XML_DOC_WELLFORMED
;
2703 /* Not a full check, but catches the worst violations */
2707 for (child
= doc
->children
; child
!= NULL
; child
= child
->next
)
2709 switch (child
->type
)
2711 case XML_ELEMENT_NODE
:
2716 case XML_CDATA_SECTION_NODE
:
2728 static void LIBXML2_LOG_CALLBACK
validate_error(void* ctx
, char const* msg
, ...)
2732 LIBXML2_CALLBACK_ERR(domdoc_validateNode
, msg
, ap
);
2736 static void LIBXML2_LOG_CALLBACK
validate_warning(void* ctx
, char const* msg
, ...)
2740 LIBXML2_CALLBACK_WARN(domdoc_validateNode
, msg
, ap
);
2744 static HRESULT WINAPI
domdoc_validateNode(
2745 IXMLDOMDocument3
* iface
,
2747 IXMLDOMParseError
** err
)
2749 domdoc
* This
= impl_from_IXMLDOMDocument3(iface
);
2750 LONG state
, err_code
= 0;
2754 TRACE("(%p)->(%p, %p)\n", This
, node
, err
);
2755 IXMLDOMDocument3_get_readyState(iface
, &state
);
2756 if (state
!= READYSTATE_COMPLETE
)
2759 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2766 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2770 if (!get_node_obj(node
)->node
|| get_node_obj(node
)->node
->doc
!= get_doc(This
))
2773 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2777 if (!is_wellformed(get_doc(This
)))
2779 ERR("doc not well-formed\n");
2781 *err
= create_parseError(E_XML_NOTWF
, NULL
, NULL
, NULL
, 0, 0, 0);
2785 /* DTD validation */
2786 if (get_doc(This
)->intSubset
|| get_doc(This
)->extSubset
)
2788 xmlValidCtxtPtr vctx
= xmlNewValidCtxt();
2789 vctx
->error
= validate_error
;
2790 vctx
->warning
= validate_warning
;
2793 if (!((node
== (IXMLDOMNode
*)iface
)?
2794 xmlValidateDocument(vctx
, get_doc(This
)) :
2795 xmlValidateElement(vctx
, get_doc(This
), get_node_obj(node
)->node
)))
2797 /* TODO: get a real error code here */
2798 TRACE("DTD validation failed\n");
2799 err_code
= E_XML_INVALID
;
2802 xmlFreeValidCtxt(vctx
);
2805 /* Schema validation */
2806 if (hr
== S_OK
&& This
->properties
->schemaCache
!= NULL
)
2809 hr
= SchemaCache_validate_tree(This
->properties
->schemaCache
, get_node_obj(node
)->node
);
2813 /* TODO: get a real error code here */
2816 TRACE("schema validation succeeded\n");
2820 ERR("schema validation failed\n");
2821 err_code
= E_XML_INVALID
;
2826 /* not really OK, just didn't find a schema for the ns */
2833 ERR("no DTD or schema found\n");
2834 err_code
= E_XML_NODTD
;
2839 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2844 static HRESULT WINAPI
domdoc_validate(
2845 IXMLDOMDocument3
* iface
,
2846 IXMLDOMParseError
** err
)
2848 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2849 TRACE("(%p)->(%p)\n", This
, err
);
2850 return IXMLDOMDocument3_validateNode(iface
, (IXMLDOMNode
*)iface
, err
);
2853 static HRESULT WINAPI
domdoc_setProperty(
2854 IXMLDOMDocument3
* iface
,
2858 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2860 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(p
), debugstr_variant(&value
));
2862 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
2868 V_VT(&varStr
) = VT_EMPTY
;
2869 if (V_VT(&value
) != VT_BSTR
)
2871 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2873 bstr
= V_BSTR(&varStr
);
2876 bstr
= V_BSTR(&value
);
2879 if (lstrcmpiW(bstr
, PropValueXPathW
) == 0)
2880 This
->properties
->XPath
= TRUE
;
2881 else if (lstrcmpiW(bstr
, PropValueXSLPatternW
) == 0)
2882 This
->properties
->XPath
= FALSE
;
2886 VariantClear(&varStr
);
2889 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
2891 xmlChar
*nsStr
= (xmlChar
*)This
->properties
->selectNsStr
;
2892 struct list
*pNsList
;
2897 V_VT(&varStr
) = VT_EMPTY
;
2898 if (V_VT(&value
) != VT_BSTR
)
2900 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2902 bstr
= V_BSTR(&varStr
);
2905 bstr
= V_BSTR(&value
);
2909 pNsList
= &(This
->properties
->selectNsList
);
2910 clear_selectNsList(pNsList
);
2912 nsStr
= xmlchar_from_wchar(bstr
);
2914 TRACE("property value: \"%s\"\n", debugstr_w(bstr
));
2916 This
->properties
->selectNsStr
= nsStr
;
2917 This
->properties
->selectNsStr_len
= xmlStrlen(nsStr
);
2920 xmlChar
*pTokBegin
, *pTokEnd
, *pTokInner
;
2921 select_ns_entry
* ns_entry
= NULL
;
2922 xmlXPathContextPtr ctx
;
2924 ctx
= xmlXPathNewContext(This
->node
.node
->doc
);
2927 /* skip leading spaces */
2928 while (*pTokBegin
== ' ' || *pTokBegin
== '\n' ||
2929 *pTokBegin
== '\t' || *pTokBegin
== '\r')
2932 for (; *pTokBegin
; pTokBegin
= pTokEnd
)
2935 memset(ns_entry
, 0, sizeof(select_ns_entry
));
2937 ns_entry
= heap_alloc_zero(sizeof(select_ns_entry
));
2939 while (*pTokBegin
== ' ')
2941 pTokEnd
= pTokBegin
;
2942 while (*pTokEnd
!= ' ' && *pTokEnd
!= 0)
2945 /* so it failed to advance which means we've got some trailing spaces */
2946 if (pTokEnd
== pTokBegin
) break;
2948 if (xmlStrncmp(pTokBegin
, (xmlChar
const*)"xmlns", 5) != 0)
2951 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2952 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2957 if (*pTokBegin
== '=')
2959 /*valid for XSLPattern?*/
2960 FIXME("Setting default xmlns not supported - skipping.\n");
2963 else if (*pTokBegin
== ':')
2965 ns_entry
->prefix
= ++pTokBegin
;
2966 for (pTokInner
= pTokBegin
; pTokInner
!= pTokEnd
&& *pTokInner
!= '='; ++pTokInner
)
2969 if (pTokInner
== pTokEnd
)
2972 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2973 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2977 ns_entry
->prefix_end
= *pTokInner
;
2981 if (pTokEnd
-pTokInner
> 1 &&
2982 ((*pTokInner
== '\'' && *(pTokEnd
-1) == '\'') ||
2983 (*pTokInner
== '"' && *(pTokEnd
-1) == '"')))
2985 ns_entry
->href
= ++pTokInner
;
2986 ns_entry
->href_end
= *(pTokEnd
-1);
2988 list_add_tail(pNsList
, &ns_entry
->entry
);
2989 /*let libxml figure out if they're valid from here ;)*/
2990 if (xmlXPathRegisterNs(ctx
, ns_entry
->prefix
, ns_entry
->href
) != 0)
2999 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3000 debugstr_w(bstr
), debugstr_an((const char*)pTokInner
, pTokEnd
-pTokInner
));
3001 list_add_tail(pNsList
, &ns_entry
->entry
);
3014 heap_free(ns_entry
);
3015 xmlXPathFreeContext(ctx
);
3018 VariantClear(&varStr
);
3021 else if (lstrcmpiW(p
, PropertyProhibitDTDW
) == 0 ||
3022 lstrcmpiW(p
, PropertyNewParserW
) == 0 ||
3023 lstrcmpiW(p
, PropertyResolveExternalsW
) == 0)
3026 FIXME("Ignoring property %s, value %s\n", debugstr_w(p
), debugstr_variant(&value
));
3030 FIXME("Unknown property %s\n", debugstr_w(p
));
3034 static HRESULT WINAPI
domdoc_getProperty(
3035 IXMLDOMDocument3
* iface
,
3039 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3041 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
3044 return E_INVALIDARG
;
3046 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
3048 V_VT(var
) = VT_BSTR
;
3049 V_BSTR(var
) = This
->properties
->XPath
?
3050 SysAllocString(PropValueXPathW
) :
3051 SysAllocString(PropValueXSLPatternW
);
3052 return V_BSTR(var
) ? S_OK
: E_OUTOFMEMORY
;
3054 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3057 BSTR rebuiltStr
, cur
;
3058 const xmlChar
*nsStr
;
3059 struct list
*pNsList
;
3060 select_ns_entry
* pNsEntry
;
3062 V_VT(var
) = VT_BSTR
;
3063 nsStr
= This
->properties
->selectNsStr
;
3064 pNsList
= &This
->properties
->selectNsList
;
3065 lenA
= This
->properties
->selectNsStr_len
;
3066 lenW
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, NULL
, 0);
3067 rebuiltStr
= heap_alloc(lenW
*sizeof(WCHAR
));
3068 MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, rebuiltStr
, lenW
);
3070 /* this is fine because all of the chars that end tokens are ASCII*/
3071 LIST_FOR_EACH_ENTRY(pNsEntry
, pNsList
, select_ns_entry
, entry
)
3073 while (*cur
!= 0) ++cur
;
3074 if (pNsEntry
->prefix_end
)
3076 *cur
= pNsEntry
->prefix_end
;
3077 while (*cur
!= 0) ++cur
;
3080 if (pNsEntry
->href_end
)
3082 *cur
= pNsEntry
->href_end
;
3085 V_BSTR(var
) = SysAllocString(rebuiltStr
);
3086 heap_free(rebuiltStr
);
3090 FIXME("Unknown property %s\n", debugstr_w(p
));
3094 static HRESULT WINAPI
domdoc_importNode(
3095 IXMLDOMDocument3
* iface
,
3098 IXMLDOMNode
** clone
)
3100 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3101 FIXME("(%p)->(%p %d %p): stub\n", This
, node
, deep
, clone
);
3105 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl
=
3107 domdoc_QueryInterface
,
3110 domdoc_GetTypeInfoCount
,
3112 domdoc_GetIDsOfNames
,
3114 domdoc_get_nodeName
,
3115 domdoc_get_nodeValue
,
3116 domdoc_put_nodeValue
,
3117 domdoc_get_nodeType
,
3118 domdoc_get_parentNode
,
3119 domdoc_get_childNodes
,
3120 domdoc_get_firstChild
,
3121 domdoc_get_lastChild
,
3122 domdoc_get_previousSibling
,
3123 domdoc_get_nextSibling
,
3124 domdoc_get_attributes
,
3125 domdoc_insertBefore
,
3126 domdoc_replaceChild
,
3129 domdoc_hasChildNodes
,
3130 domdoc_get_ownerDocument
,
3132 domdoc_get_nodeTypeString
,
3135 domdoc_get_specified
,
3136 domdoc_get_definition
,
3137 domdoc_get_nodeTypedValue
,
3138 domdoc_put_nodeTypedValue
,
3139 domdoc_get_dataType
,
3140 domdoc_put_dataType
,
3142 domdoc_transformNode
,
3144 domdoc_selectSingleNode
,
3146 domdoc_get_namespaceURI
,
3148 domdoc_get_baseName
,
3149 domdoc_transformNodeToObject
,
3151 domdoc_get_implementation
,
3152 domdoc_get_documentElement
,
3153 domdoc_put_documentElement
,
3154 domdoc_createElement
,
3155 domdoc_createDocumentFragment
,
3156 domdoc_createTextNode
,
3157 domdoc_createComment
,
3158 domdoc_createCDATASection
,
3159 domdoc_createProcessingInstruction
,
3160 domdoc_createAttribute
,
3161 domdoc_createEntityReference
,
3162 domdoc_getElementsByTagName
,
3166 domdoc_get_readyState
,
3167 domdoc_get_parseError
,
3174 domdoc_get_validateOnParse
,
3175 domdoc_put_validateOnParse
,
3176 domdoc_get_resolveExternals
,
3177 domdoc_put_resolveExternals
,
3178 domdoc_get_preserveWhiteSpace
,
3179 domdoc_put_preserveWhiteSpace
,
3180 domdoc_put_onreadystatechange
,
3181 domdoc_put_onDataAvailable
,
3182 domdoc_put_onTransformNode
,
3183 domdoc_get_namespaces
,
3185 domdoc_putref_schemas
,
3189 domdoc_validateNode
,
3193 /* IConnectionPointContainer */
3194 static HRESULT WINAPI
ConnectionPointContainer_QueryInterface(IConnectionPointContainer
*iface
,
3195 REFIID riid
, void **ppv
)
3197 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3198 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3201 static ULONG WINAPI
ConnectionPointContainer_AddRef(IConnectionPointContainer
*iface
)
3203 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3204 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3207 static ULONG WINAPI
ConnectionPointContainer_Release(IConnectionPointContainer
*iface
)
3209 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3210 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3213 static HRESULT WINAPI
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer
*iface
,
3214 IEnumConnectionPoints
**ppEnum
)
3216 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3217 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3221 static HRESULT WINAPI
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer
*iface
,
3222 REFIID riid
, IConnectionPoint
**cp
)
3224 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3225 ConnectionPoint
*iter
;
3227 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), cp
);
3231 for(iter
= This
->cp_list
; iter
; iter
= iter
->next
)
3233 if (IsEqualGUID(iter
->iid
, riid
))
3234 *cp
= &iter
->IConnectionPoint_iface
;
3239 IConnectionPoint_AddRef(*cp
);
3243 FIXME("unsupported riid %s\n", debugstr_guid(riid
));
3244 return CONNECT_E_NOCONNECTION
;
3248 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl
=
3250 ConnectionPointContainer_QueryInterface
,
3251 ConnectionPointContainer_AddRef
,
3252 ConnectionPointContainer_Release
,
3253 ConnectionPointContainer_EnumConnectionPoints
,
3254 ConnectionPointContainer_FindConnectionPoint
3257 /* IConnectionPoint */
3258 static HRESULT WINAPI
ConnectionPoint_QueryInterface(IConnectionPoint
*iface
,
3259 REFIID riid
, void **ppv
)
3261 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3263 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
3267 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
3268 IsEqualGUID(&IID_IConnectionPoint
, riid
))
3275 IConnectionPoint_AddRef(iface
);
3279 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
3280 return E_NOINTERFACE
;
3283 static ULONG WINAPI
ConnectionPoint_AddRef(IConnectionPoint
*iface
)
3285 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3286 return IConnectionPointContainer_AddRef(This
->container
);
3289 static ULONG WINAPI
ConnectionPoint_Release(IConnectionPoint
*iface
)
3291 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3292 return IConnectionPointContainer_Release(This
->container
);
3295 static HRESULT WINAPI
ConnectionPoint_GetConnectionInterface(IConnectionPoint
*iface
, IID
*iid
)
3297 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3299 TRACE("(%p)->(%p)\n", This
, iid
);
3301 if (!iid
) return E_POINTER
;
3307 static HRESULT WINAPI
ConnectionPoint_GetConnectionPointContainer(IConnectionPoint
*iface
,
3308 IConnectionPointContainer
**container
)
3310 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3312 TRACE("(%p)->(%p)\n", This
, container
);
3314 if (!container
) return E_POINTER
;
3316 *container
= This
->container
;
3317 IConnectionPointContainer_AddRef(*container
);
3321 static HRESULT WINAPI
ConnectionPoint_Advise(IConnectionPoint
*iface
, IUnknown
*unk_sink
,
3324 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3329 TRACE("(%p)->(%p %p)\n", This
, unk_sink
, cookie
);
3331 hr
= IUnknown_QueryInterface(unk_sink
, This
->iid
, (void**)&sink
);
3332 if(FAILED(hr
) && !IsEqualGUID(&IID_IPropertyNotifySink
, This
->iid
))
3333 hr
= IUnknown_QueryInterface(unk_sink
, &IID_IDispatch
, (void**)&sink
);
3335 return CONNECT_E_CANNOTCONNECT
;
3339 for (i
= 0; i
< This
->sinks_size
; i
++)
3340 if (!This
->sinks
[i
].unk
)
3343 if (i
== This
->sinks_size
)
3344 This
->sinks
= heap_realloc(This
->sinks
,(++This
->sinks_size
)*sizeof(*This
->sinks
));
3348 This
->sinks
= heap_alloc(sizeof(*This
->sinks
));
3349 This
->sinks_size
= 1;
3353 This
->sinks
[i
].unk
= sink
;
3360 static HRESULT WINAPI
ConnectionPoint_Unadvise(IConnectionPoint
*iface
, DWORD cookie
)
3362 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3364 TRACE("(%p)->(%d)\n", This
, cookie
);
3366 if (cookie
== 0 || cookie
> This
->sinks_size
|| !This
->sinks
[cookie
-1].unk
)
3367 return CONNECT_E_NOCONNECTION
;
3369 IUnknown_Release(This
->sinks
[cookie
-1].unk
);
3370 This
->sinks
[cookie
-1].unk
= NULL
;
3375 static HRESULT WINAPI
ConnectionPoint_EnumConnections(IConnectionPoint
*iface
,
3376 IEnumConnections
**ppEnum
)
3378 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3379 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3383 static const IConnectionPointVtbl ConnectionPointVtbl
=
3385 ConnectionPoint_QueryInterface
,
3386 ConnectionPoint_AddRef
,
3387 ConnectionPoint_Release
,
3388 ConnectionPoint_GetConnectionInterface
,
3389 ConnectionPoint_GetConnectionPointContainer
,
3390 ConnectionPoint_Advise
,
3391 ConnectionPoint_Unadvise
,
3392 ConnectionPoint_EnumConnections
3395 static void ConnectionPoint_Init(ConnectionPoint
*cp
, struct domdoc
*doc
, REFIID riid
)
3397 cp
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointVtbl
;
3403 cp
->next
= doc
->cp_list
;
3406 cp
->container
= &doc
->IConnectionPointContainer_iface
;
3409 /* domdoc implementation of IObjectWithSite */
3410 static HRESULT WINAPI
3411 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
3413 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3414 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObject
);
3417 static ULONG WINAPI
domdoc_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
3419 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3420 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3423 static ULONG WINAPI
domdoc_ObjectWithSite_Release( IObjectWithSite
* iface
)
3425 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3426 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3429 static HRESULT WINAPI
domdoc_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
3431 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3433 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
3438 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
3441 static HRESULT WINAPI
domdoc_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
3443 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3445 TRACE("(%p)->(%p)\n", iface
, punk
);
3451 IUnknown_Release( This
->site
);
3458 IUnknown_AddRef( punk
);
3461 IUnknown_Release( This
->site
);
3468 static const IObjectWithSiteVtbl domdocObjectSite
=
3470 domdoc_ObjectWithSite_QueryInterface
,
3471 domdoc_ObjectWithSite_AddRef
,
3472 domdoc_ObjectWithSite_Release
,
3473 domdoc_ObjectWithSite_SetSite
,
3474 domdoc_ObjectWithSite_GetSite
3477 static HRESULT WINAPI
domdoc_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
3479 domdoc
*This
= impl_from_IObjectSafety(iface
);
3480 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3483 static ULONG WINAPI
domdoc_Safety_AddRef(IObjectSafety
*iface
)
3485 domdoc
*This
= impl_from_IObjectSafety(iface
);
3486 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3489 static ULONG WINAPI
domdoc_Safety_Release(IObjectSafety
*iface
)
3491 domdoc
*This
= impl_from_IObjectSafety(iface
);
3492 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3495 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3497 static HRESULT WINAPI
domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3498 DWORD
*supported
, DWORD
*enabled
)
3500 domdoc
*This
= impl_from_IObjectSafety(iface
);
3502 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
3504 if(!supported
|| !enabled
) return E_POINTER
;
3506 *supported
= SAFETY_SUPPORTED_OPTIONS
;
3507 *enabled
= This
->safeopt
;
3512 static HRESULT WINAPI
domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3513 DWORD mask
, DWORD enabled
)
3515 domdoc
*This
= impl_from_IObjectSafety(iface
);
3516 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
3518 if ((mask
& ~SAFETY_SUPPORTED_OPTIONS
) != 0)
3521 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
3526 #undef SAFETY_SUPPORTED_OPTIONS
3528 static const IObjectSafetyVtbl domdocObjectSafetyVtbl
= {
3529 domdoc_Safety_QueryInterface
,
3530 domdoc_Safety_AddRef
,
3531 domdoc_Safety_Release
,
3532 domdoc_Safety_GetInterfaceSafetyOptions
,
3533 domdoc_Safety_SetInterfaceSafetyOptions
3536 static const tid_t domdoc_iface_tids
[] = {
3537 IXMLDOMDocument3_tid
,
3541 static dispex_static_data_t domdoc_dispex
= {
3543 IXMLDOMDocument3_tid
,
3548 HRESULT
get_domdoc_from_xmldoc(xmlDocPtr xmldoc
, IXMLDOMDocument3
**document
)
3552 doc
= heap_alloc( sizeof (*doc
) );
3554 return E_OUTOFMEMORY
;
3556 doc
->IXMLDOMDocument3_iface
.lpVtbl
= &XMLDOMDocument3Vtbl
;
3557 doc
->IPersistStreamInit_iface
.lpVtbl
= &xmldoc_IPersistStreamInit_VTable
;
3558 doc
->IObjectWithSite_iface
.lpVtbl
= &domdocObjectSite
;
3559 doc
->IObjectSafety_iface
.lpVtbl
= &domdocObjectSafetyVtbl
;
3560 doc
->IConnectionPointContainer_iface
.lpVtbl
= &ConnectionPointContainerVtbl
;
3562 doc
->async
= VARIANT_TRUE
;
3563 doc
->validating
= 0;
3565 doc
->properties
= properties_from_xmlDocPtr(xmldoc
);
3569 doc
->cp_list
= NULL
;
3570 doc
->namespaces
= NULL
;
3572 memset(doc
->events
, 0, sizeof(doc
->events
));
3574 /* events connection points */
3575 ConnectionPoint_Init(&doc
->cp_dispatch
, doc
, &IID_IDispatch
);
3576 ConnectionPoint_Init(&doc
->cp_propnotif
, doc
, &IID_IPropertyNotifySink
);
3577 ConnectionPoint_Init(&doc
->cp_domdocevents
, doc
, &DIID_XMLDOMDocumentEvents
);
3579 init_xmlnode(&doc
->node
, (xmlNodePtr
)xmldoc
, (IXMLDOMNode
*)&doc
->IXMLDOMDocument3_iface
,
3582 *document
= &doc
->IXMLDOMDocument3_iface
;
3584 TRACE("returning iface %p\n", *document
);
3588 HRESULT
DOMDocument_create(MSXML_VERSION version
, IUnknown
*pUnkOuter
, void **ppObj
)
3593 TRACE("(%d, %p, %p)\n", version
, pUnkOuter
, ppObj
);
3595 xmldoc
= xmlNewDoc(NULL
);
3597 return E_OUTOFMEMORY
;
3599 xmldoc_init(xmldoc
, version
);
3601 hr
= get_domdoc_from_xmldoc(xmldoc
, (IXMLDOMDocument3
**)ppObj
);
3604 free_properties(properties_from_xmlDocPtr(xmldoc
));
3605 heap_free(xmldoc
->_private
);
3613 IUnknown
* create_domdoc( xmlNodePtr document
)
3618 TRACE("(%p)\n", document
);
3620 hr
= get_domdoc_from_xmldoc((xmlDocPtr
)document
, (IXMLDOMDocument3
**)&pObj
);
3629 HRESULT
DOMDocument_create(MSXML_VERSION version
, IUnknown
*pUnkOuter
, void **ppObj
)
3631 MESSAGE("This program tried to use a DOMDocument object, but\n"
3632 "libxml2 support was not present at compile time.\n");