2 * DOM Document implementation
4 * Copyright 2005 Mike McCormack
5 * Copyright 2010-2011 Adam Martinson for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 # include <libxml/parser.h>
30 # include <libxml/xmlerror.h>
31 # include <libxml/xpathInternals.h>
32 # include <libxml/xmlsave.h>
33 # include <libxml/SAX2.h>
34 # include <libxml/parserInternals.h>
50 #include "wine/debug.h"
52 #include "msxml_private.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
58 /* not defined in older versions */
59 #define XML_SAVE_FORMAT 1
60 #define XML_SAVE_NO_DECL 2
61 #define XML_SAVE_NO_EMPTY 4
62 #define XML_SAVE_NO_XHTML 8
63 #define XML_SAVE_XHTML 16
64 #define XML_SAVE_AS_XML 32
65 #define XML_SAVE_AS_HTML 64
67 static const WCHAR PropertySelectionLanguageW
[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
68 static const WCHAR PropertySelectionNamespacesW
[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
69 static const WCHAR PropertyProhibitDTDW
[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
70 static const WCHAR PropertyNewParserW
[] = {'N','e','w','P','a','r','s','e','r',0};
71 static const WCHAR PropValueXPathW
[] = {'X','P','a','t','h',0};
72 static const WCHAR PropValueXSLPatternW
[] = {'X','S','L','P','a','t','t','e','r','n',0};
73 static const WCHAR PropertyResolveExternalsW
[] = {'R','e','s','o','l','v','e','E','x','t','e','r','n','a','l','s',0};
75 /* Anything that passes the test_get_ownerDocument()
76 * tests can go here (data shared between all instances).
77 * We need to preserve this when reloading a document,
78 * and also need access to it from the libxml backend. */
80 MSXML_VERSION version
;
81 VARIANT_BOOL preserving
;
82 IXMLDOMSchemaCollection2
* schemaCache
;
83 struct list selectNsList
;
84 xmlChar
const* selectNsStr
;
90 typedef struct ConnectionPoint ConnectionPoint
;
91 typedef struct domdoc domdoc
;
93 struct ConnectionPoint
95 IConnectionPoint IConnectionPoint_iface
;
98 ConnectionPoint
*next
;
99 IConnectionPointContainer
*container
;
106 IPropertyNotifySink
*propnotif
;
112 EVENTID_READYSTATECHANGE
= 0,
113 EVENTID_DATAAVAILABLE
,
114 EVENTID_TRANSFORMNODE
,
121 IXMLDOMDocument3 IXMLDOMDocument3_iface
;
122 IPersistStreamInit IPersistStreamInit_iface
;
123 IObjectWithSite IObjectWithSite_iface
;
124 IObjectSafety IObjectSafety_iface
;
125 IConnectionPointContainer IConnectionPointContainer_iface
;
128 VARIANT_BOOL validating
;
129 VARIANT_BOOL resolving
;
130 domdoc_properties
* properties
;
133 /* IObjectWithSite */
139 /* connection list */
140 ConnectionPoint
*cp_list
;
141 ConnectionPoint cp_domdocevents
;
142 ConnectionPoint cp_propnotif
;
143 ConnectionPoint cp_dispatch
;
146 IDispatch
*events
[EVENTID_LAST
];
148 IXMLDOMSchemaCollection2
*namespaces
;
151 static HRESULT
set_doc_event(domdoc
*doc
, eventid_t eid
, const VARIANT
*v
)
159 IUnknown_QueryInterface(V_UNKNOWN(v
), &IID_IDispatch
, (void**)&disp
);
164 disp
= V_DISPATCH(v
);
165 if (disp
) IDispatch_AddRef(disp
);
168 return DISP_E_TYPEMISMATCH
;
171 if (doc
->events
[eid
]) IDispatch_Release(doc
->events
[eid
]);
172 doc
->events
[eid
] = disp
;
177 static inline ConnectionPoint
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
179 return CONTAINING_RECORD(iface
, ConnectionPoint
, IConnectionPoint_iface
);
183 In native windows, the whole lifetime management of XMLDOMNodes is
184 managed automatically using reference counts. Wine emulates that by
185 maintaining a reference count to the document that is increased for
186 each IXMLDOMNode pointer passed out for this document. If all these
187 pointers are gone, the document is unreachable and gets freed, that
188 is, all nodes in the tree of the document get freed.
190 You are able to create nodes that are associated to a document (in
191 fact, in msxml's XMLDOM model, all nodes are associated to a document),
192 but not in the tree of that document, for example using the createFoo
193 functions from IXMLDOMDocument. These nodes do not get cleaned up
194 by libxml, so we have to do it ourselves.
196 To catch these nodes, a list of "orphan nodes" is introduced.
197 It contains pointers to all roots of node trees that are
198 associated with the document without being part of the document
199 tree. All nodes with parent==NULL (except for the document root nodes)
200 should be in the orphan node list of their document. All orphan nodes
201 get freed together with the document itself.
204 typedef struct _xmldoc_priv
{
207 domdoc_properties
* properties
;
210 typedef struct _orphan_entry
{
215 typedef struct _select_ns_entry
{
217 xmlChar
const* prefix
;
223 static inline xmldoc_priv
* priv_from_xmlDocPtr(const xmlDocPtr doc
)
225 return doc
->_private
;
228 static inline domdoc_properties
* properties_from_xmlDocPtr(xmlDocPtr doc
)
230 return priv_from_xmlDocPtr(doc
)->properties
;
233 BOOL
is_xpathmode(const xmlDocPtr doc
)
235 return properties_from_xmlDocPtr(doc
)->XPath
;
238 void set_xpathmode(xmlDocPtr doc
, BOOL xpath
)
240 properties_from_xmlDocPtr(doc
)->XPath
= xpath
;
243 int registerNamespaces(xmlXPathContextPtr ctxt
)
246 const select_ns_entry
* ns
= NULL
;
247 const struct list
* pNsList
= &properties_from_xmlDocPtr(ctxt
->doc
)->selectNsList
;
249 TRACE("(%p)\n", ctxt
);
251 LIST_FOR_EACH_ENTRY( ns
, pNsList
, select_ns_entry
, entry
)
253 xmlXPathRegisterNs(ctxt
, ns
->prefix
, ns
->href
);
260 static inline void clear_selectNsList(struct list
* pNsList
)
262 select_ns_entry
*ns
, *ns2
;
263 LIST_FOR_EACH_ENTRY_SAFE( ns
, ns2
, pNsList
, select_ns_entry
, entry
)
270 static xmldoc_priv
* create_priv(void)
273 priv
= heap_alloc( sizeof (*priv
) );
278 list_init( &priv
->orphans
);
279 priv
->properties
= NULL
;
285 static domdoc_properties
*create_properties(MSXML_VERSION version
)
287 domdoc_properties
*properties
= heap_alloc(sizeof(domdoc_properties
));
289 list_init(&properties
->selectNsList
);
290 properties
->preserving
= VARIANT_FALSE
;
291 properties
->schemaCache
= NULL
;
292 properties
->selectNsStr
= heap_alloc_zero(sizeof(xmlChar
));
293 properties
->selectNsStr_len
= 0;
295 /* properties that are dependent on object versions */
296 properties
->version
= version
;
297 properties
->XPath
= (version
== MSXML4
|| version
== MSXML6
);
300 properties
->url
= NULL
;
305 static domdoc_properties
* copy_properties(domdoc_properties
const* properties
)
307 domdoc_properties
* pcopy
= heap_alloc(sizeof(domdoc_properties
));
308 select_ns_entry
const* ns
= NULL
;
309 select_ns_entry
* new_ns
= NULL
;
310 int len
= (properties
->selectNsStr_len
+1)*sizeof(xmlChar
);
315 pcopy
->version
= properties
->version
;
316 pcopy
->preserving
= properties
->preserving
;
317 pcopy
->schemaCache
= properties
->schemaCache
;
318 if (pcopy
->schemaCache
)
319 IXMLDOMSchemaCollection2_AddRef(pcopy
->schemaCache
);
320 pcopy
->XPath
= properties
->XPath
;
321 pcopy
->selectNsStr_len
= properties
->selectNsStr_len
;
322 list_init( &pcopy
->selectNsList
);
323 pcopy
->selectNsStr
= heap_alloc(len
);
324 memcpy((xmlChar
*)pcopy
->selectNsStr
, properties
->selectNsStr
, len
);
325 offset
= pcopy
->selectNsStr
- properties
->selectNsStr
;
327 LIST_FOR_EACH_ENTRY( ns
, (&properties
->selectNsList
), select_ns_entry
, entry
)
329 new_ns
= heap_alloc(sizeof(select_ns_entry
));
330 memcpy(new_ns
, ns
, sizeof(select_ns_entry
));
331 new_ns
->href
+= offset
;
332 new_ns
->prefix
+= offset
;
333 list_add_tail(&pcopy
->selectNsList
, &new_ns
->entry
);
338 int len
= strlenW(properties
->url
);
340 pcopy
->url
= CoTaskMemAlloc((len
+1)*sizeof(WCHAR
));
341 memcpy(pcopy
->url
, properties
->url
, len
*sizeof(WCHAR
));
351 static void free_properties(domdoc_properties
* properties
)
355 if (properties
->schemaCache
)
356 IXMLDOMSchemaCollection2_Release(properties
->schemaCache
);
357 clear_selectNsList(&properties
->selectNsList
);
358 heap_free((xmlChar
*)properties
->selectNsStr
);
359 CoTaskMemFree(properties
->url
);
360 heap_free(properties
);
364 static void release_namespaces(domdoc
*This
)
366 if (This
->namespaces
)
368 IXMLDOMSchemaCollection2_Release(This
->namespaces
);
369 This
->namespaces
= NULL
;
373 /* links a "<?xml" node as a first child */
374 void xmldoc_link_xmldecl(xmlDocPtr doc
, xmlNodePtr node
)
377 if (doc
->standalone
!= -1) xmlAddPrevSibling( doc
->children
, node
);
380 /* unlinks a first "<?xml" child if it was created */
381 xmlNodePtr
xmldoc_unlink_xmldecl(xmlDocPtr doc
)
383 static const xmlChar xmlA
[] = "xml";
384 xmlNodePtr node
, first_child
;
388 /* xml declaration node could be created automatically after parsing or added
390 first_child
= doc
->children
;
391 if (first_child
&& first_child
->type
== XML_PI_NODE
&& xmlStrEqual(first_child
->name
, xmlA
))
394 xmlUnlinkNode( node
);
402 BOOL
is_preserving_whitespace(xmlNodePtr node
)
404 domdoc_properties
* properties
= NULL
;
405 /* during parsing the xmlDoc._private stuff is not there */
406 if (priv_from_xmlDocPtr(node
->doc
))
407 properties
= properties_from_xmlDocPtr(node
->doc
);
408 return ((properties
&& properties
->preserving
== VARIANT_TRUE
) ||
409 xmlNodeGetSpacePreserve(node
) == 1);
412 static inline BOOL
strn_isspace(xmlChar
const* str
, int len
)
414 for (; str
&& len
> 0 && *str
; ++str
, --len
)
421 static void sax_characters(void *ctx
, const xmlChar
*ch
, int len
)
423 xmlParserCtxtPtr ctxt
;
426 ctxt
= (xmlParserCtxtPtr
) ctx
;
427 This
= (const domdoc
*) ctxt
->_private
;
431 xmlChar cur
= *(ctxt
->input
->cur
);
433 /* Characters are reported with multiple calls, for example each charref is reported with a separate
434 call and then parser appends it to a single text node or creates a new node if not created.
435 It's not possible to tell if it's ignorable data or not just looking at data itself cause it could be
436 space chars that separate charrefs or similar case. We only need to skip leading and trailing spaces,
437 or whole node if it has nothing but space chars, so to detect leading space node->last is checked that
438 contains text node pointer if already created, trailing spaces are detected directly looking at parser input
439 for next '<' opening bracket - similar logic is used by libxml2 itself. Basically 'cur' == '<' means the last
440 chunk of char data, in case it's not the last chunk we check for previously added node type and if it's not
441 a text node it's safe to ignore.
443 Note that during domdoc_loadXML() the xmlDocPtr->_private data is not available. */
445 if (!This
->properties
->preserving
&&
446 !is_preserving_whitespace(ctxt
->node
) &&
447 strn_isspace(ch
, len
) &&
448 (!ctxt
->node
->last
||
449 ((ctxt
->node
->last
&& (cur
== '<' || ctxt
->node
->last
->type
!= XML_TEXT_NODE
))
452 /* Keep information about ignorable whitespace text node in previous or parent node */
453 if (ctxt
->node
->last
)
454 *(DWORD
*)&ctxt
->node
->last
->_private
|= NODE_PRIV_TRAILING_IGNORABLE_WS
;
455 else if (ctxt
->node
->type
!= XML_DOCUMENT_NODE
)
456 *(DWORD
*)&ctxt
->node
->_private
|= NODE_PRIV_CHILD_IGNORABLE_WS
;
461 xmlSAX2Characters(ctxt
, ch
, len
);
464 static void LIBXML2_LOG_CALLBACK
sax_error(void* ctx
, char const* msg
, ...)
468 LIBXML2_CALLBACK_ERR(doparse
, msg
, ap
);
472 static void LIBXML2_LOG_CALLBACK
sax_warning(void* ctx
, char const* msg
, ...)
476 LIBXML2_CALLBACK_WARN(doparse
, msg
, ap
);
480 static void sax_serror(void* ctx
, xmlErrorPtr err
)
482 LIBXML2_CALLBACK_SERROR(doparse
, err
);
485 static xmlDocPtr
doparse(domdoc
* This
, char const* ptr
, int len
, xmlCharEncoding encoding
)
487 xmlDocPtr doc
= NULL
;
488 xmlParserCtxtPtr pctx
;
489 static xmlSAXHandler sax_handler
= {
490 xmlSAX2InternalSubset
, /* internalSubset */
491 xmlSAX2IsStandalone
, /* isStandalone */
492 xmlSAX2HasInternalSubset
, /* hasInternalSubset */
493 xmlSAX2HasExternalSubset
, /* hasExternalSubset */
494 xmlSAX2ResolveEntity
, /* resolveEntity */
495 xmlSAX2GetEntity
, /* getEntity */
496 xmlSAX2EntityDecl
, /* entityDecl */
497 xmlSAX2NotationDecl
, /* notationDecl */
498 xmlSAX2AttributeDecl
, /* attributeDecl */
499 xmlSAX2ElementDecl
, /* elementDecl */
500 xmlSAX2UnparsedEntityDecl
, /* unparsedEntityDecl */
501 xmlSAX2SetDocumentLocator
, /* setDocumentLocator */
502 xmlSAX2StartDocument
, /* startDocument */
503 xmlSAX2EndDocument
, /* endDocument */
504 xmlSAX2StartElement
, /* startElement */
505 xmlSAX2EndElement
, /* endElement */
506 xmlSAX2Reference
, /* reference */
507 sax_characters
, /* characters */
508 sax_characters
, /* ignorableWhitespace */
509 xmlSAX2ProcessingInstruction
, /* processingInstruction */
510 xmlSAX2Comment
, /* comment */
511 sax_warning
, /* warning */
512 sax_error
, /* error */
513 sax_error
, /* fatalError */
514 xmlSAX2GetParameterEntity
, /* getParameterEntity */
515 xmlSAX2CDataBlock
, /* cdataBlock */
516 xmlSAX2ExternalSubset
, /* externalSubset */
519 xmlSAX2StartElementNs
, /* startElementNs */
520 xmlSAX2EndElementNs
, /* endElementNs */
521 sax_serror
/* serror */
524 pctx
= xmlCreateMemoryParserCtxt(ptr
, len
);
527 ERR("Failed to create parser context\n");
531 if (pctx
->sax
) xmlFree(pctx
->sax
);
532 pctx
->sax
= &sax_handler
;
533 pctx
->_private
= This
;
536 if (encoding
!= XML_CHAR_ENCODING_NONE
)
537 xmlSwitchEncoding(pctx
, encoding
);
539 xmlParseDocument(pctx
);
541 if (pctx
->wellFormed
)
547 xmlFreeDoc(pctx
->myDoc
);
551 xmlFreeParserCtxt(pctx
);
553 /* TODO: put this in one of the SAX callbacks */
554 /* create first child as a <?xml...?> */
555 if (doc
&& doc
->standalone
!= -1)
559 xmlChar
*xmlbuff
= (xmlChar
*)buff
;
561 node
= xmlNewDocPI( doc
, (xmlChar
*)"xml", NULL
);
563 /* version attribute can't be omitted */
564 sprintf(buff
, "version=\"%s\"", doc
->version
? (char*)doc
->version
: "1.0");
565 xmlNodeAddContent( node
, xmlbuff
);
569 sprintf(buff
, " encoding=\"%s\"", doc
->encoding
);
570 xmlNodeAddContent( node
, xmlbuff
);
573 if (doc
->standalone
!= -2)
575 sprintf(buff
, " standalone=\"%s\"", doc
->standalone
== 0 ? "no" : "yes");
576 xmlNodeAddContent( node
, xmlbuff
);
579 xmldoc_link_xmldecl( doc
, node
);
585 void xmldoc_init(xmlDocPtr doc
, MSXML_VERSION version
)
587 doc
->_private
= create_priv();
588 priv_from_xmlDocPtr(doc
)->properties
= create_properties(version
);
591 LONG
xmldoc_add_refs(xmlDocPtr doc
, LONG refs
)
593 LONG ref
= InterlockedExchangeAdd(&priv_from_xmlDocPtr(doc
)->refs
, refs
) + refs
;
594 TRACE("(%p)->(%d)\n", doc
, ref
);
598 LONG
xmldoc_add_ref(xmlDocPtr doc
)
600 return xmldoc_add_refs(doc
, 1);
603 LONG
xmldoc_release_refs(xmlDocPtr doc
, LONG refs
)
605 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
606 LONG ref
= InterlockedExchangeAdd(&priv
->refs
, -refs
) - refs
;
607 TRACE("(%p)->(%d)\n", doc
, ref
);
610 WARN("negative refcount, expect troubles\n");
614 orphan_entry
*orphan
, *orphan2
;
615 TRACE("freeing docptr %p\n", doc
);
617 LIST_FOR_EACH_ENTRY_SAFE( orphan
, orphan2
, &priv
->orphans
, orphan_entry
, entry
)
619 xmlFreeNode( orphan
->node
);
622 free_properties(priv
->properties
);
623 heap_free(doc
->_private
);
631 LONG
xmldoc_release(xmlDocPtr doc
)
633 return xmldoc_release_refs(doc
, 1);
636 HRESULT
xmldoc_add_orphan(xmlDocPtr doc
, xmlNodePtr node
)
638 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
641 entry
= heap_alloc( sizeof (*entry
) );
643 return E_OUTOFMEMORY
;
646 list_add_head( &priv
->orphans
, &entry
->entry
);
650 HRESULT
xmldoc_remove_orphan(xmlDocPtr doc
, xmlNodePtr node
)
652 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
653 orphan_entry
*entry
, *entry2
;
655 LIST_FOR_EACH_ENTRY_SAFE( entry
, entry2
, &priv
->orphans
, orphan_entry
, entry
)
657 if( entry
->node
== node
)
659 list_remove( &entry
->entry
);
668 static inline xmlDocPtr
get_doc( domdoc
*This
)
670 return This
->node
.node
->doc
;
673 static HRESULT
attach_xmldoc(domdoc
*This
, xmlDocPtr xml
)
675 release_namespaces(This
);
679 priv_from_xmlDocPtr(get_doc(This
))->properties
= NULL
;
680 if (xmldoc_release(get_doc(This
)) != 0)
681 priv_from_xmlDocPtr(get_doc(This
))->properties
=
682 copy_properties(This
->properties
);
685 This
->node
.node
= (xmlNodePtr
) xml
;
689 xmldoc_add_ref(get_doc(This
));
690 priv_from_xmlDocPtr(get_doc(This
))->properties
= This
->properties
;
696 static inline domdoc
*impl_from_IXMLDOMDocument3( IXMLDOMDocument3
*iface
)
698 return CONTAINING_RECORD(iface
, domdoc
, IXMLDOMDocument3_iface
);
701 static inline domdoc
*impl_from_IPersistStreamInit(IPersistStreamInit
*iface
)
703 return CONTAINING_RECORD(iface
, domdoc
, IPersistStreamInit_iface
);
706 static inline domdoc
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
708 return CONTAINING_RECORD(iface
, domdoc
, IObjectWithSite_iface
);
711 static inline domdoc
*impl_from_IObjectSafety(IObjectSafety
*iface
)
713 return CONTAINING_RECORD(iface
, domdoc
, IObjectSafety_iface
);
716 static inline domdoc
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
718 return CONTAINING_RECORD(iface
, domdoc
, IConnectionPointContainer_iface
);
721 /************************************************************************
722 * domdoc implementation of IPersistStream.
724 static HRESULT WINAPI
PersistStreamInit_QueryInterface(
725 IPersistStreamInit
*iface
, REFIID riid
, void **ppvObj
)
727 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
728 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObj
);
731 static ULONG WINAPI
PersistStreamInit_AddRef(
732 IPersistStreamInit
*iface
)
734 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
735 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
738 static ULONG WINAPI
PersistStreamInit_Release(
739 IPersistStreamInit
*iface
)
741 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
742 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
745 static HRESULT WINAPI
PersistStreamInit_GetClassID(
746 IPersistStreamInit
*iface
, CLSID
*classid
)
748 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
749 TRACE("(%p)->(%p)\n", This
, classid
);
754 *classid
= *DOMDocument_version(This
->properties
->version
);
759 static HRESULT WINAPI
PersistStreamInit_IsDirty(
760 IPersistStreamInit
*iface
)
762 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
763 FIXME("(%p): stub!\n", This
);
767 static HRESULT
domdoc_load_from_stream(domdoc
*doc
, ISequentialStream
*stream
)
769 DWORD read
, written
, len
;
770 xmlDocPtr xmldoc
= NULL
;
778 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &hstream
);
784 ISequentialStream_Read(stream
, buf
, sizeof(buf
), &read
);
785 hr
= IStream_Write(hstream
, buf
, read
, &written
);
786 } while(SUCCEEDED(hr
) && written
!= 0 && read
!= 0);
790 ERR("failed to copy stream 0x%08x\n", hr
);
791 IStream_Release(hstream
);
795 hr
= GetHGlobalFromStream(hstream
, &hglobal
);
799 len
= GlobalSize(hglobal
);
800 ptr
= GlobalLock(hglobal
);
802 xmldoc
= doparse(doc
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
803 GlobalUnlock(hglobal
);
807 ERR("Failed to parse xml\n");
811 xmldoc
->_private
= create_priv();
813 return attach_xmldoc(doc
, xmldoc
);
816 static HRESULT WINAPI
PersistStreamInit_Load(IPersistStreamInit
*iface
, IStream
*stream
)
818 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
820 TRACE("(%p)->(%p)\n", This
, stream
);
825 return domdoc_load_from_stream(This
, (ISequentialStream
*)stream
);
828 static HRESULT WINAPI
PersistStreamInit_Save(
829 IPersistStreamInit
*iface
, IStream
*stream
, BOOL clr_dirty
)
831 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
835 TRACE("(%p)->(%p %d)\n", This
, stream
, clr_dirty
);
837 hr
= IXMLDOMDocument3_get_xml(&This
->IXMLDOMDocument3_iface
, &xmlString
);
840 DWORD len
= SysStringLen(xmlString
) * sizeof(WCHAR
);
842 hr
= IStream_Write( stream
, xmlString
, len
, NULL
);
843 SysFreeString(xmlString
);
846 TRACE("ret 0x%08x\n", hr
);
851 static HRESULT WINAPI
PersistStreamInit_GetSizeMax(
852 IPersistStreamInit
*iface
, ULARGE_INTEGER
*pcbSize
)
854 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
855 TRACE("(%p)->(%p)\n", This
, pcbSize
);
859 static HRESULT WINAPI
PersistStreamInit_InitNew(
860 IPersistStreamInit
*iface
)
862 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
863 TRACE("(%p)\n", This
);
867 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable
=
869 PersistStreamInit_QueryInterface
,
870 PersistStreamInit_AddRef
,
871 PersistStreamInit_Release
,
872 PersistStreamInit_GetClassID
,
873 PersistStreamInit_IsDirty
,
874 PersistStreamInit_Load
,
875 PersistStreamInit_Save
,
876 PersistStreamInit_GetSizeMax
,
877 PersistStreamInit_InitNew
880 /* IXMLDOMDocument3 interface */
882 static const tid_t domdoc_se_tids
[] = {
885 IXMLDOMDocument2_tid
,
886 IXMLDOMDocument3_tid
,
890 static HRESULT WINAPI
domdoc_QueryInterface( IXMLDOMDocument3
*iface
, REFIID riid
, void** ppvObject
)
892 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
894 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( riid
), ppvObject
);
898 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
899 IsEqualGUID( riid
, &IID_IDispatch
) ||
900 IsEqualGUID( riid
, &IID_IXMLDOMNode
) ||
901 IsEqualGUID( riid
, &IID_IXMLDOMDocument
) ||
902 IsEqualGUID( riid
, &IID_IXMLDOMDocument2
)||
903 IsEqualGUID( riid
, &IID_IXMLDOMDocument3
))
907 else if (IsEqualGUID(&IID_IPersistStream
, riid
) ||
908 IsEqualGUID(&IID_IPersistStreamInit
, riid
))
910 *ppvObject
= &This
->IPersistStreamInit_iface
;
912 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
914 *ppvObject
= &This
->IObjectWithSite_iface
;
916 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
918 *ppvObject
= &This
->IObjectSafety_iface
;
920 else if( IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
922 return node_create_supporterrorinfo(domdoc_se_tids
, ppvObject
);
924 else if(node_query_interface(&This
->node
, riid
, ppvObject
))
926 return *ppvObject
? S_OK
: E_NOINTERFACE
;
928 else if (IsEqualGUID( riid
, &IID_IConnectionPointContainer
))
930 *ppvObject
= &This
->IConnectionPointContainer_iface
;
934 TRACE("interface %s not implemented\n", debugstr_guid(riid
));
935 return E_NOINTERFACE
;
938 IUnknown_AddRef((IUnknown
*)*ppvObject
);
943 static ULONG WINAPI
domdoc_AddRef( IXMLDOMDocument3
*iface
)
945 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
946 ULONG ref
= InterlockedIncrement( &This
->ref
);
947 TRACE("(%p)->(%d)\n", This
, ref
);
951 static ULONG WINAPI
domdoc_Release( IXMLDOMDocument3
*iface
)
953 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
954 LONG ref
= InterlockedDecrement( &This
->ref
);
956 TRACE("(%p)->(%d)\n", This
, ref
);
963 IUnknown_Release( This
->site
);
964 destroy_xmlnode(&This
->node
);
966 for (eid
= 0; eid
< EVENTID_LAST
; eid
++)
967 if (This
->events
[eid
]) IDispatch_Release(This
->events
[eid
]);
969 release_namespaces(This
);
976 static HRESULT WINAPI
domdoc_GetTypeInfoCount( IXMLDOMDocument3
*iface
, UINT
* pctinfo
)
978 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
979 return IDispatchEx_GetTypeInfoCount(&This
->node
.dispex
.IDispatchEx_iface
, pctinfo
);
982 static HRESULT WINAPI
domdoc_GetTypeInfo(
983 IXMLDOMDocument3
*iface
,
984 UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
986 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
987 return IDispatchEx_GetTypeInfo(&This
->node
.dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
990 static HRESULT WINAPI
domdoc_GetIDsOfNames(
991 IXMLDOMDocument3
*iface
,
998 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
999 return IDispatchEx_GetIDsOfNames(&This
->node
.dispex
.IDispatchEx_iface
,
1000 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
1003 static HRESULT WINAPI
domdoc_Invoke(
1004 IXMLDOMDocument3
*iface
,
1005 DISPID dispIdMember
,
1009 DISPPARAMS
* pDispParams
,
1010 VARIANT
* pVarResult
,
1011 EXCEPINFO
* pExcepInfo
,
1014 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1015 return IDispatchEx_Invoke(&This
->node
.dispex
.IDispatchEx_iface
,
1016 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1019 static HRESULT WINAPI
domdoc_get_nodeName(
1020 IXMLDOMDocument3
*iface
,
1023 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1025 static const WCHAR documentW
[] = {'#','d','o','c','u','m','e','n','t',0};
1027 TRACE("(%p)->(%p)\n", This
, name
);
1029 return return_bstr(documentW
, name
);
1033 static HRESULT WINAPI
domdoc_get_nodeValue(
1034 IXMLDOMDocument3
*iface
,
1037 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1039 TRACE("(%p)->(%p)\n", This
, value
);
1042 return E_INVALIDARG
;
1044 V_VT(value
) = VT_NULL
;
1045 V_BSTR(value
) = NULL
; /* tests show that we should do this */
1050 static HRESULT WINAPI
domdoc_put_nodeValue(
1051 IXMLDOMDocument3
*iface
,
1054 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1055 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&value
));
1060 static HRESULT WINAPI
domdoc_get_nodeType(
1061 IXMLDOMDocument3
*iface
,
1064 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1066 TRACE("(%p)->(%p)\n", This
, type
);
1068 *type
= NODE_DOCUMENT
;
1073 static HRESULT WINAPI
domdoc_get_parentNode(
1074 IXMLDOMDocument3
*iface
,
1075 IXMLDOMNode
** parent
)
1077 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1079 TRACE("(%p)->(%p)\n", This
, parent
);
1081 return node_get_parent(&This
->node
, parent
);
1085 static HRESULT WINAPI
domdoc_get_childNodes(
1086 IXMLDOMDocument3
*iface
,
1087 IXMLDOMNodeList
** childList
)
1089 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1091 TRACE("(%p)->(%p)\n", This
, childList
);
1093 return node_get_child_nodes(&This
->node
, childList
);
1097 static HRESULT WINAPI
domdoc_get_firstChild(
1098 IXMLDOMDocument3
*iface
,
1099 IXMLDOMNode
** firstChild
)
1101 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1103 TRACE("(%p)->(%p)\n", This
, firstChild
);
1105 return node_get_first_child(&This
->node
, firstChild
);
1109 static HRESULT WINAPI
domdoc_get_lastChild(
1110 IXMLDOMDocument3
*iface
,
1111 IXMLDOMNode
** lastChild
)
1113 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1115 TRACE("(%p)->(%p)\n", This
, lastChild
);
1117 return node_get_last_child(&This
->node
, lastChild
);
1121 static HRESULT WINAPI
domdoc_get_previousSibling(
1122 IXMLDOMDocument3
*iface
,
1123 IXMLDOMNode
** previousSibling
)
1125 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1127 TRACE("(%p)->(%p)\n", This
, previousSibling
);
1129 return return_null_node(previousSibling
);
1133 static HRESULT WINAPI
domdoc_get_nextSibling(
1134 IXMLDOMDocument3
*iface
,
1135 IXMLDOMNode
** nextSibling
)
1137 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1139 TRACE("(%p)->(%p)\n", This
, nextSibling
);
1141 return return_null_node(nextSibling
);
1145 static HRESULT WINAPI
domdoc_get_attributes(
1146 IXMLDOMDocument3
*iface
,
1147 IXMLDOMNamedNodeMap
** attributeMap
)
1149 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1151 TRACE("(%p)->(%p)\n", This
, attributeMap
);
1153 return return_null_ptr((void**)attributeMap
);
1157 static HRESULT WINAPI
domdoc_insertBefore(
1158 IXMLDOMDocument3
*iface
,
1159 IXMLDOMNode
* newChild
,
1161 IXMLDOMNode
** outNewChild
)
1163 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1167 TRACE("(%p)->(%p %s %p)\n", This
, newChild
, debugstr_variant(&refChild
), outNewChild
);
1169 hr
= IXMLDOMNode_get_nodeType(newChild
, &type
);
1170 if (hr
!= S_OK
) return hr
;
1172 TRACE("new node type %d\n", type
);
1175 case NODE_ATTRIBUTE
:
1177 case NODE_CDATA_SECTION
:
1178 if (outNewChild
) *outNewChild
= NULL
;
1181 return node_insert_before(&This
->node
, newChild
, &refChild
, outNewChild
);
1185 static HRESULT WINAPI
domdoc_replaceChild(
1186 IXMLDOMDocument3
*iface
,
1187 IXMLDOMNode
* newChild
,
1188 IXMLDOMNode
* oldChild
,
1189 IXMLDOMNode
** outOldChild
)
1191 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1193 TRACE("(%p)->(%p %p %p)\n", This
, newChild
, oldChild
, outOldChild
);
1195 return node_replace_child(&This
->node
, newChild
, oldChild
, outOldChild
);
1199 static HRESULT WINAPI
domdoc_removeChild(
1200 IXMLDOMDocument3
*iface
,
1202 IXMLDOMNode
**oldChild
)
1204 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1205 TRACE("(%p)->(%p %p)\n", This
, child
, oldChild
);
1206 return node_remove_child(&This
->node
, child
, oldChild
);
1210 static HRESULT WINAPI
domdoc_appendChild(
1211 IXMLDOMDocument3
*iface
,
1213 IXMLDOMNode
**outChild
)
1215 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1216 TRACE("(%p)->(%p %p)\n", This
, child
, outChild
);
1217 return node_append_child(&This
->node
, child
, outChild
);
1221 static HRESULT WINAPI
domdoc_hasChildNodes(
1222 IXMLDOMDocument3
*iface
,
1225 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1226 TRACE("(%p)->(%p)\n", This
, ret
);
1227 return node_has_childnodes(&This
->node
, ret
);
1231 static HRESULT WINAPI
domdoc_get_ownerDocument(
1232 IXMLDOMDocument3
*iface
,
1233 IXMLDOMDocument
**doc
)
1235 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1236 TRACE("(%p)->(%p)\n", This
, doc
);
1237 return node_get_owner_doc(&This
->node
, doc
);
1241 static HRESULT WINAPI
domdoc_cloneNode(
1242 IXMLDOMDocument3
*iface
,
1244 IXMLDOMNode
** outNode
)
1246 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1247 TRACE("(%p)->(%d %p)\n", This
, deep
, outNode
);
1248 return node_clone( &This
->node
, deep
, outNode
);
1252 static HRESULT WINAPI
domdoc_get_nodeTypeString(
1253 IXMLDOMDocument3
*iface
,
1256 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1257 static const WCHAR documentW
[] = {'d','o','c','u','m','e','n','t',0};
1259 TRACE("(%p)->(%p)\n", This
, p
);
1261 return return_bstr(documentW
, p
);
1265 static HRESULT WINAPI
domdoc_get_text(
1266 IXMLDOMDocument3
*iface
,
1269 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1270 TRACE("(%p)->(%p)\n", This
, p
);
1271 return node_get_text(&This
->node
, p
);
1275 static HRESULT WINAPI
domdoc_put_text(
1276 IXMLDOMDocument3
*iface
,
1279 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1280 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
1285 static HRESULT WINAPI
domdoc_get_specified(
1286 IXMLDOMDocument3
*iface
,
1287 VARIANT_BOOL
* isSpecified
)
1289 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1290 FIXME("(%p)->(%p) stub!\n", This
, isSpecified
);
1291 *isSpecified
= VARIANT_TRUE
;
1296 static HRESULT WINAPI
domdoc_get_definition(
1297 IXMLDOMDocument3
*iface
,
1298 IXMLDOMNode
** definitionNode
)
1300 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1301 FIXME("(%p)->(%p)\n", This
, definitionNode
);
1306 static HRESULT WINAPI
domdoc_get_nodeTypedValue(
1307 IXMLDOMDocument3
*iface
,
1310 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1311 TRACE("(%p)->(%p)\n", This
, v
);
1312 return return_null_var(v
);
1315 static HRESULT WINAPI
domdoc_put_nodeTypedValue(
1316 IXMLDOMDocument3
*iface
,
1317 VARIANT typedValue
)
1319 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1320 FIXME("(%p)->(%s)\n", This
, debugstr_variant(&typedValue
));
1325 static HRESULT WINAPI
domdoc_get_dataType(
1326 IXMLDOMDocument3
*iface
,
1329 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1330 TRACE("(%p)->(%p)\n", This
, typename
);
1331 return return_null_var( typename
);
1335 static HRESULT WINAPI
domdoc_put_dataType(
1336 IXMLDOMDocument3
*iface
,
1339 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1341 FIXME("(%p)->(%s)\n", This
, debugstr_w(dataTypeName
));
1344 return E_INVALIDARG
;
1349 static int XMLCALL
domdoc_get_xml_writecallback(void *ctx
, const char *data
, int len
)
1351 return xmlBufferAdd((xmlBufferPtr
)ctx
, (xmlChar
*)data
, len
) == 0 ? len
: 0;
1354 static HRESULT WINAPI
domdoc_get_xml(
1355 IXMLDOMDocument3
*iface
,
1358 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1359 xmlSaveCtxtPtr ctxt
;
1364 TRACE("(%p)->(%p)\n", This
, p
);
1367 return E_INVALIDARG
;
1371 buf
= xmlBufferCreate();
1373 return E_OUTOFMEMORY
;
1375 options
= XML_SAVE_FORMAT
| XML_SAVE_NO_DECL
;
1376 ctxt
= xmlSaveToIO(domdoc_get_xml_writecallback
, NULL
, buf
, "UTF-8", options
);
1381 return E_OUTOFMEMORY
;
1384 ret
= xmlSaveDoc(ctxt
, get_doc(This
));
1385 /* flushes on close */
1388 TRACE("%ld, len=%d\n", ret
, xmlBufferLength(buf
));
1389 if(ret
!= -1 && xmlBufferLength(buf
) > 0)
1393 content
= bstr_from_xmlChar(xmlBufferContent(buf
));
1394 content
= EnsureCorrectEOL(content
);
1400 *p
= SysAllocStringLen(NULL
, 0);
1405 return *p
? S_OK
: E_OUTOFMEMORY
;
1409 static HRESULT WINAPI
domdoc_transformNode(
1410 IXMLDOMDocument3
*iface
,
1414 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1415 TRACE("(%p)->(%p %p)\n", This
, node
, p
);
1416 return node_transform_node(&This
->node
, node
, p
);
1420 static HRESULT WINAPI
domdoc_selectNodes(
1421 IXMLDOMDocument3
*iface
,
1423 IXMLDOMNodeList
**outList
)
1425 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1426 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outList
);
1427 return node_select_nodes(&This
->node
, p
, outList
);
1431 static HRESULT WINAPI
domdoc_selectSingleNode(
1432 IXMLDOMDocument3
*iface
,
1434 IXMLDOMNode
**outNode
)
1436 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1437 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outNode
);
1438 return node_select_singlenode(&This
->node
, p
, outNode
);
1442 static HRESULT WINAPI
domdoc_get_parsed(
1443 IXMLDOMDocument3
*iface
,
1444 VARIANT_BOOL
* isParsed
)
1446 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1447 FIXME("(%p)->(%p) stub!\n", This
, isParsed
);
1448 *isParsed
= VARIANT_TRUE
;
1452 static HRESULT WINAPI
domdoc_get_namespaceURI(
1453 IXMLDOMDocument3
*iface
,
1454 BSTR
* namespaceURI
)
1456 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1457 TRACE("(%p)->(%p)\n", This
, namespaceURI
);
1458 return return_null_bstr( namespaceURI
);
1461 static HRESULT WINAPI
domdoc_get_prefix(
1462 IXMLDOMDocument3
*iface
,
1465 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1466 TRACE("(%p)->(%p)\n", This
, prefix
);
1467 return return_null_bstr( prefix
);
1471 static HRESULT WINAPI
domdoc_get_baseName(
1472 IXMLDOMDocument3
*iface
,
1475 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1476 TRACE("(%p)->(%p)\n", This
, name
);
1477 return return_null_bstr( name
);
1481 static HRESULT WINAPI
domdoc_transformNodeToObject(
1482 IXMLDOMDocument3
*iface
,
1483 IXMLDOMNode
* stylesheet
,
1484 VARIANT outputObject
)
1486 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1487 FIXME("(%p)->(%p %s)\n", This
, stylesheet
, debugstr_variant(&outputObject
));
1492 static HRESULT WINAPI
domdoc_get_doctype(
1493 IXMLDOMDocument3
*iface
,
1494 IXMLDOMDocumentType
** doctype
)
1496 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1501 TRACE("(%p)->(%p)\n", This
, doctype
);
1503 if (!doctype
) return E_INVALIDARG
;
1507 dtd
= xmlGetIntSubset(get_doc(This
));
1508 if (!dtd
) return S_FALSE
;
1510 node
= create_node((xmlNodePtr
)dtd
);
1511 if (!node
) return S_FALSE
;
1513 hr
= IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentType
, (void**)doctype
);
1514 IXMLDOMNode_Release(node
);
1520 static HRESULT WINAPI
domdoc_get_implementation(
1521 IXMLDOMDocument3
*iface
,
1522 IXMLDOMImplementation
** impl
)
1524 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1526 TRACE("(%p)->(%p)\n", This
, impl
);
1529 return E_INVALIDARG
;
1531 *impl
= (IXMLDOMImplementation
*)create_doc_Implementation();
1536 static HRESULT WINAPI
domdoc_get_documentElement(
1537 IXMLDOMDocument3
*iface
,
1538 IXMLDOMElement
** DOMElement
)
1540 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1541 IXMLDOMNode
*element_node
;
1545 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1548 return E_INVALIDARG
;
1552 root
= xmlDocGetRootElement( get_doc(This
) );
1556 element_node
= create_node( root
);
1557 if(!element_node
) return S_FALSE
;
1559 hr
= IXMLDOMNode_QueryInterface(element_node
, &IID_IXMLDOMElement
, (void**)DOMElement
);
1560 IXMLDOMNode_Release(element_node
);
1566 static HRESULT WINAPI
domdoc_put_documentElement(
1567 IXMLDOMDocument3
*iface
,
1568 IXMLDOMElement
* DOMElement
)
1570 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1571 IXMLDOMNode
*elementNode
;
1578 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1580 hr
= IXMLDOMElement_QueryInterface( DOMElement
, &IID_IXMLDOMNode
, (void**)&elementNode
);
1584 xmlNode
= get_node_obj( elementNode
);
1585 if(!xmlNode
) return E_FAIL
;
1587 if(!xmlNode
->node
->parent
)
1588 if(xmldoc_remove_orphan(xmlNode
->node
->doc
, xmlNode
->node
) != S_OK
)
1589 WARN("%p is not an orphan of %p\n", xmlNode
->node
->doc
, xmlNode
->node
);
1591 old_doc
= xmlNode
->node
->doc
;
1592 if (old_doc
!= get_doc(This
))
1593 refcount
= xmlnode_get_inst_cnt(xmlNode
);
1595 /* old root is still orphaned by its document, update refcount from new root */
1596 if (refcount
) xmldoc_add_refs(get_doc(This
), refcount
);
1597 oldRoot
= xmlDocSetRootElement( get_doc(This
), xmlNode
->node
);
1598 if (refcount
) xmldoc_release_refs(old_doc
, refcount
);
1599 IXMLDOMNode_Release( elementNode
);
1602 xmldoc_add_orphan(oldRoot
->doc
, oldRoot
);
1608 static HRESULT WINAPI
domdoc_createElement(
1609 IXMLDOMDocument3
*iface
,
1611 IXMLDOMElement
** element
)
1613 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1618 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(tagname
), element
);
1620 if (!element
|| !tagname
) return E_INVALIDARG
;
1622 V_VT(&type
) = VT_I1
;
1623 V_I1(&type
) = NODE_ELEMENT
;
1625 hr
= IXMLDOMDocument3_createNode(iface
, type
, tagname
, NULL
, &node
);
1628 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMElement
, (void**)element
);
1629 IXMLDOMNode_Release(node
);
1636 static HRESULT WINAPI
domdoc_createDocumentFragment(
1637 IXMLDOMDocument3
*iface
,
1638 IXMLDOMDocumentFragment
** frag
)
1640 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1645 TRACE("(%p)->(%p)\n", This
, frag
);
1647 if (!frag
) return E_INVALIDARG
;
1651 V_VT(&type
) = VT_I1
;
1652 V_I1(&type
) = NODE_DOCUMENT_FRAGMENT
;
1654 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1657 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentFragment
, (void**)frag
);
1658 IXMLDOMNode_Release(node
);
1665 static HRESULT WINAPI
domdoc_createTextNode(
1666 IXMLDOMDocument3
*iface
,
1668 IXMLDOMText
** text
)
1670 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1675 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), text
);
1677 if (!text
) return E_INVALIDARG
;
1681 V_VT(&type
) = VT_I1
;
1682 V_I1(&type
) = NODE_TEXT
;
1684 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1687 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMText
, (void**)text
);
1688 IXMLDOMNode_Release(node
);
1689 hr
= IXMLDOMText_put_data(*text
, data
);
1696 static HRESULT WINAPI
domdoc_createComment(
1697 IXMLDOMDocument3
*iface
,
1699 IXMLDOMComment
** comment
)
1701 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1706 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), comment
);
1708 if (!comment
) return E_INVALIDARG
;
1712 V_VT(&type
) = VT_I1
;
1713 V_I1(&type
) = NODE_COMMENT
;
1715 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1718 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMComment
, (void**)comment
);
1719 IXMLDOMNode_Release(node
);
1720 hr
= IXMLDOMComment_put_data(*comment
, data
);
1727 static HRESULT WINAPI
domdoc_createCDATASection(
1728 IXMLDOMDocument3
*iface
,
1730 IXMLDOMCDATASection
** cdata
)
1732 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1737 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), cdata
);
1739 if (!cdata
) return E_INVALIDARG
;
1743 V_VT(&type
) = VT_I1
;
1744 V_I1(&type
) = NODE_CDATA_SECTION
;
1746 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1749 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMCDATASection
, (void**)cdata
);
1750 IXMLDOMNode_Release(node
);
1751 hr
= IXMLDOMCDATASection_put_data(*cdata
, data
);
1758 static HRESULT WINAPI
domdoc_createProcessingInstruction(
1759 IXMLDOMDocument3
*iface
,
1762 IXMLDOMProcessingInstruction
** pi
)
1764 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1769 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_w(target
), debugstr_w(data
), pi
);
1771 if (!pi
) return E_INVALIDARG
;
1775 V_VT(&type
) = VT_I1
;
1776 V_I1(&type
) = NODE_PROCESSING_INSTRUCTION
;
1778 hr
= IXMLDOMDocument3_createNode(iface
, type
, target
, NULL
, &node
);
1783 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1784 node_obj
= get_node_obj(node
);
1785 hr
= node_set_content(node_obj
, data
);
1787 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMProcessingInstruction
, (void**)pi
);
1788 IXMLDOMNode_Release(node
);
1795 static HRESULT WINAPI
domdoc_createAttribute(
1796 IXMLDOMDocument3
*iface
,
1798 IXMLDOMAttribute
** attribute
)
1800 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1805 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), attribute
);
1807 if (!attribute
|| !name
) return E_INVALIDARG
;
1809 V_VT(&type
) = VT_I1
;
1810 V_I1(&type
) = NODE_ATTRIBUTE
;
1812 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1815 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMAttribute
, (void**)attribute
);
1816 IXMLDOMNode_Release(node
);
1823 static HRESULT WINAPI
domdoc_createEntityReference(
1824 IXMLDOMDocument3
*iface
,
1826 IXMLDOMEntityReference
** entityref
)
1828 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1833 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), entityref
);
1835 if (!entityref
) return E_INVALIDARG
;
1839 V_VT(&type
) = VT_I1
;
1840 V_I1(&type
) = NODE_ENTITY_REFERENCE
;
1842 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1845 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMEntityReference
, (void**)entityref
);
1846 IXMLDOMNode_Release(node
);
1852 xmlChar
* tagName_to_XPath(const BSTR tagName
)
1854 xmlChar
*query
, *tmp
;
1855 static const xmlChar everything
[] = "/descendant::node()";
1856 static const xmlChar mod_pre
[] = "*[local-name()='";
1857 static const xmlChar mod_post
[] = "']";
1858 static const xmlChar prefix
[] = "descendant::";
1859 const WCHAR
*tokBegin
, *tokEnd
;
1862 /* Special case - empty tagname - means select all nodes,
1863 except document itself. */
1865 return xmlStrdup(everything
);
1867 query
= xmlStrdup(prefix
);
1870 while (tokBegin
&& *tokBegin
)
1875 query
= xmlStrcat(query
, BAD_CAST
"/");
1879 query
= xmlStrcat(query
, BAD_CAST
"*");
1883 query
= xmlStrcat(query
, mod_pre
);
1885 while (*tokEnd
&& *tokEnd
!= '/')
1887 len
= WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, NULL
, 0, NULL
, NULL
);
1888 tmp
= xmlMalloc(len
);
1889 WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, (char*)tmp
, len
, NULL
, NULL
);
1890 query
= xmlStrncat(query
, tmp
, len
);
1893 query
= xmlStrcat(query
, mod_post
);
1900 static HRESULT WINAPI
domdoc_getElementsByTagName(
1901 IXMLDOMDocument3
*iface
,
1903 IXMLDOMNodeList
** resultList
)
1905 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1910 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(tagName
), resultList
);
1912 if (!tagName
|| !resultList
) return E_INVALIDARG
;
1914 XPath
= This
->properties
->XPath
;
1915 This
->properties
->XPath
= TRUE
;
1916 query
= tagName_to_XPath(tagName
);
1917 hr
= create_selection((xmlNodePtr
)get_doc(This
), query
, resultList
);
1919 This
->properties
->XPath
= XPath
;
1924 static HRESULT
get_node_type(VARIANT Type
, DOMNodeType
* type
)
1930 hr
= VariantChangeType(&tmp
, &Type
, 0, VT_I4
);
1932 return E_INVALIDARG
;
1939 static HRESULT WINAPI
domdoc_createNode(
1940 IXMLDOMDocument3
*iface
,
1944 IXMLDOMNode
** node
)
1946 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1947 DOMNodeType node_type
;
1949 xmlChar
*xml_name
, *href
;
1952 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_variant(&Type
), debugstr_w(name
), debugstr_w(namespaceURI
), node
);
1954 if(!node
) return E_INVALIDARG
;
1956 hr
= get_node_type(Type
, &node_type
);
1957 if(FAILED(hr
)) return hr
;
1959 TRACE("node_type %d\n", node_type
);
1961 /* exit earlier for types that need name */
1965 case NODE_ATTRIBUTE
:
1966 case NODE_ENTITY_REFERENCE
:
1967 case NODE_PROCESSING_INSTRUCTION
:
1968 if (!name
|| *name
== 0) return E_FAIL
;
1974 xml_name
= xmlchar_from_wchar(name
);
1975 /* prevent empty href from being allocated */
1976 href
= namespaceURI
? xmlchar_from_wchar(namespaceURI
) : NULL
;
1982 xmlChar
*local
, *prefix
;
1984 local
= xmlSplitQName2(xml_name
, &prefix
);
1986 xmlnode
= xmlNewDocNode(get_doc(This
), NULL
, local
? local
: xml_name
, NULL
);
1988 /* allow creating the default namespace xmlns= */
1989 if (local
|| (href
&& *href
))
1991 xmlNsPtr ns
= xmlNewNs(xmlnode
, href
, prefix
);
1992 xmlSetNs(xmlnode
, ns
);
2000 case NODE_ATTRIBUTE
:
2002 xmlChar
*local
, *prefix
;
2004 local
= xmlSplitQName2(xml_name
, &prefix
);
2006 xmlnode
= (xmlNodePtr
)xmlNewDocProp(get_doc(This
), local
? local
: xml_name
, NULL
);
2008 if (local
|| (href
&& *href
))
2010 /* we need a floating namespace here, it can't be created linked to attribute from
2012 xmlNsPtr ns
= xmlNewNs(NULL
, href
, prefix
);
2013 xmlSetNs(xmlnode
, ns
);
2022 xmlnode
= (xmlNodePtr
)xmlNewDocText(get_doc(This
), NULL
);
2024 case NODE_CDATA_SECTION
:
2025 xmlnode
= xmlNewCDataBlock(get_doc(This
), NULL
, 0);
2027 case NODE_ENTITY_REFERENCE
:
2028 xmlnode
= xmlNewReference(get_doc(This
), xml_name
);
2030 case NODE_PROCESSING_INSTRUCTION
:
2031 #ifdef HAVE_XMLNEWDOCPI
2032 xmlnode
= xmlNewDocPI(get_doc(This
), xml_name
, NULL
);
2034 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2039 xmlnode
= xmlNewDocComment(get_doc(This
), NULL
);
2041 case NODE_DOCUMENT_FRAGMENT
:
2042 xmlnode
= xmlNewDocFragment(get_doc(This
));
2044 /* unsupported types */
2046 case NODE_DOCUMENT_TYPE
:
2049 heap_free(xml_name
);
2050 return E_INVALIDARG
;
2052 FIXME("unhandled node type %d\n", node_type
);
2057 *node
= create_node(xmlnode
);
2058 heap_free(xml_name
);
2063 TRACE("created node (%d, %p, %p)\n", node_type
, *node
, xmlnode
);
2064 xmldoc_add_orphan(xmlnode
->doc
, xmlnode
);
2071 static HRESULT WINAPI
domdoc_nodeFromID(
2072 IXMLDOMDocument3
*iface
,
2074 IXMLDOMNode
** node
)
2076 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2077 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(idString
), node
);
2081 static HRESULT
domdoc_onDataAvailable(void *obj
, char *ptr
, DWORD len
)
2086 xmldoc
= doparse(This
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
2088 xmldoc
->_private
= create_priv();
2089 return attach_xmldoc(This
, xmldoc
);
2095 static HRESULT
domdoc_load_moniker(domdoc
*This
, IMoniker
*mon
)
2100 hr
= bind_url(mon
, domdoc_onDataAvailable
, This
, &bsc
);
2104 return detach_bsc(bsc
);
2107 static HRESULT WINAPI
domdoc_load(
2108 IXMLDOMDocument3
*iface
,
2110 VARIANT_BOOL
* isSuccessful
)
2112 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2113 LPWSTR filename
= NULL
;
2114 HRESULT hr
= S_FALSE
;
2117 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&source
));
2121 *isSuccessful
= VARIANT_FALSE
;
2123 assert( &This
->node
);
2125 switch( V_VT(&source
) )
2128 filename
= V_BSTR(&source
);
2130 case VT_BSTR
|VT_BYREF
:
2131 if (!V_BSTRREF(&source
)) return E_INVALIDARG
;
2132 filename
= *V_BSTRREF(&source
);
2134 case VT_ARRAY
|VT_UI1
:
2136 SAFEARRAY
*psa
= V_ARRAY(&source
);
2139 UINT dim
= SafeArrayGetDim(psa
);
2144 ERR("SAFEARRAY == NULL\n");
2145 hr
= This
->error
= E_INVALIDARG
;
2148 /* Only takes UTF-8 strings.
2149 * NOT NULL-terminated. */
2150 hr
= SafeArrayAccessData(psa
, (void**)&str
);
2154 WARN("failed to access array data, 0x%08x\n", hr
);
2157 SafeArrayGetUBound(psa
, 1, &len
);
2159 if ((xmldoc
= doparse(This
, str
, ++len
, XML_CHAR_ENCODING_UTF8
)))
2161 hr
= This
->error
= S_OK
;
2162 *isSuccessful
= VARIANT_TRUE
;
2163 TRACE("parsed document %p\n", xmldoc
);
2167 This
->error
= E_FAIL
;
2168 TRACE("failed to parse document\n");
2171 SafeArrayUnaccessData(psa
);
2175 xmldoc
->_private
= create_priv();
2176 return attach_xmldoc(This
, xmldoc
);
2180 FIXME("unhandled SAFEARRAY dim: %d\n", dim
);
2181 hr
= This
->error
= E_NOTIMPL
;
2187 ISequentialStream
*stream
= NULL
;
2188 IXMLDOMDocument3
*newdoc
= NULL
;
2190 if (!V_UNKNOWN(&source
)) return E_INVALIDARG
;
2192 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IXMLDOMDocument3
, (void**)&newdoc
);
2197 domdoc
*newDoc
= impl_from_IXMLDOMDocument3( newdoc
);
2199 xmldoc
= xmlCopyDoc(get_doc(newDoc
), 1);
2200 xmldoc
->_private
= create_priv();
2201 hr
= attach_xmldoc(This
, xmldoc
);
2204 *isSuccessful
= VARIANT_TRUE
;
2210 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IStream
, (void**)&stream
);
2212 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_ISequentialStream
, (void**)&stream
);
2216 hr
= domdoc_load_from_stream(This
, stream
);
2218 *isSuccessful
= VARIANT_TRUE
;
2219 ISequentialStream_Release(stream
);
2223 FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr
, V_UNKNOWN(&source
)->lpVtbl
);
2227 FIXME("VT type not supported (%d)\n", V_VT(&source
));
2234 CoTaskMemFree(This
->properties
->url
);
2235 This
->properties
->url
= NULL
;
2237 hr
= create_moniker_from_url( filename
, &mon
);
2238 if ( SUCCEEDED(hr
) )
2240 hr
= domdoc_load_moniker( This
, mon
);
2242 IMoniker_GetDisplayName(mon
, NULL
, NULL
, &This
->properties
->url
);
2243 IMoniker_Release(mon
);
2247 This
->error
= E_FAIL
;
2250 hr
= This
->error
= S_OK
;
2251 *isSuccessful
= VARIANT_TRUE
;
2255 if(!filename
|| FAILED(hr
)) {
2256 xmldoc
= xmlNewDoc(NULL
);
2257 xmldoc
->_private
= create_priv();
2258 hr
= attach_xmldoc(This
, xmldoc
);
2263 TRACE("ret (%d)\n", hr
);
2269 static HRESULT WINAPI
domdoc_get_readyState(
2270 IXMLDOMDocument3
*iface
,
2273 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2274 FIXME("stub! (%p)->(%p)\n", This
, value
);
2277 return E_INVALIDARG
;
2279 *value
= READYSTATE_COMPLETE
;
2284 static HRESULT WINAPI
domdoc_get_parseError(
2285 IXMLDOMDocument3
*iface
,
2286 IXMLDOMParseError
** errorObj
)
2288 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2289 static const WCHAR err
[] = {'e','r','r','o','r',0};
2290 BSTR error_string
= NULL
;
2292 FIXME("(%p)->(%p): creating a dummy parseError\n", iface
, errorObj
);
2295 error_string
= SysAllocString(err
);
2297 *errorObj
= create_parseError(This
->error
, NULL
, error_string
, NULL
, 0, 0, 0);
2298 if(!*errorObj
) return E_OUTOFMEMORY
;
2303 static HRESULT WINAPI
domdoc_get_url(
2304 IXMLDOMDocument3
*iface
,
2307 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2309 TRACE("(%p)->(%p)\n", This
, url
);
2312 return E_INVALIDARG
;
2314 if (This
->properties
->url
)
2316 *url
= SysAllocString(This
->properties
->url
);
2318 return E_OUTOFMEMORY
;
2323 return return_null_bstr(url
);
2327 static HRESULT WINAPI
domdoc_get_async(
2328 IXMLDOMDocument3
*iface
,
2329 VARIANT_BOOL
* isAsync
)
2331 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2333 TRACE("(%p)->(%p: %d)\n", This
, isAsync
, This
->async
);
2334 *isAsync
= This
->async
;
2339 static HRESULT WINAPI
domdoc_put_async(
2340 IXMLDOMDocument3
*iface
,
2341 VARIANT_BOOL isAsync
)
2343 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2345 TRACE("(%p)->(%d)\n", This
, isAsync
);
2346 This
->async
= isAsync
;
2351 static HRESULT WINAPI
domdoc_abort(
2352 IXMLDOMDocument3
*iface
)
2354 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2355 FIXME("%p\n", This
);
2359 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2360 static HRESULT WINAPI
domdoc_loadXML(
2361 IXMLDOMDocument3
*iface
,
2363 VARIANT_BOOL
* isSuccessful
)
2365 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2366 xmlDocPtr xmldoc
= NULL
;
2367 HRESULT hr
= S_FALSE
, hr2
;
2369 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), isSuccessful
);
2371 assert ( &This
->node
);
2375 *isSuccessful
= VARIANT_FALSE
;
2381 /* skip leading spaces if needed */
2382 if (This
->properties
->version
== MSXML_DEFAULT
|| This
->properties
->version
== MSXML26
)
2383 while (*ptr
&& isspaceW(*ptr
)) ptr
++;
2385 xmldoc
= doparse(This
, (char*)ptr
, strlenW(ptr
)*sizeof(WCHAR
), XML_CHAR_ENCODING_UTF16LE
);
2388 This
->error
= E_FAIL
;
2389 TRACE("failed to parse document\n");
2393 hr
= This
->error
= S_OK
;
2394 *isSuccessful
= VARIANT_TRUE
;
2395 TRACE("parsed document %p\n", xmldoc
);
2401 xmldoc
= xmlNewDoc(NULL
);
2402 xmldoc
->_private
= create_priv();
2403 hr2
= attach_xmldoc(This
, xmldoc
);
2410 static int XMLCALL
domdoc_save_writecallback(void *ctx
, const char *buffer
, int len
)
2414 if(!WriteFile(ctx
, buffer
, len
, &written
, NULL
))
2416 WARN("write error\n");
2423 static int XMLCALL
domdoc_save_closecallback(void *ctx
)
2425 return CloseHandle(ctx
) ? 0 : -1;
2428 static int XMLCALL
domdoc_stream_save_writecallback(void *ctx
, const char *buffer
, int len
)
2433 hr
= IStream_Write((IStream
*)ctx
, buffer
, len
, &written
);
2434 TRACE("0x%08x %p %d %u\n", hr
, buffer
, len
, written
);
2437 WARN("stream write error: 0x%08x\n", hr
);
2444 static int XMLCALL
domdoc_stream_save_closecallback(void *ctx
)
2446 IStream_Release((IStream
*)ctx
);
2450 static HRESULT WINAPI
domdoc_save(
2451 IXMLDOMDocument3
*iface
,
2452 VARIANT destination
)
2454 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2455 xmlSaveCtxtPtr ctx
= NULL
;
2459 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&destination
));
2461 switch (V_VT(&destination
))
2465 IUnknown
*pUnk
= V_UNKNOWN(&destination
);
2466 IXMLDOMDocument3
*document
;
2469 ret
= IUnknown_QueryInterface(pUnk
, &IID_IXMLDOMDocument3
, (void**)&document
);
2472 VARIANT_BOOL success
;
2475 ret
= IXMLDOMDocument3_get_xml(iface
, &xml
);
2478 ret
= IXMLDOMDocument3_loadXML(document
, xml
, &success
);
2482 IXMLDOMDocument3_Release(document
);
2486 ret
= IUnknown_QueryInterface(pUnk
, &IID_IStream
, (void**)&stream
);
2489 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2490 ctx
= xmlSaveToIO(domdoc_stream_save_writecallback
,
2491 domdoc_stream_save_closecallback
, stream
, NULL
, options
);
2495 IStream_Release(stream
);
2503 case VT_BSTR
| VT_BYREF
:
2505 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2507 /* save with file path */
2508 HANDLE handle
= CreateFileW( (V_VT(&destination
) & VT_BYREF
)? *V_BSTRREF(&destination
) : V_BSTR(&destination
),
2509 GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2510 if( handle
== INVALID_HANDLE_VALUE
)
2512 WARN("failed to create file\n");
2516 /* disable top XML declaration */
2517 ctx
= xmlSaveToIO(domdoc_save_writecallback
, domdoc_save_closecallback
,
2518 handle
, NULL
, options
);
2521 CloseHandle(handle
);
2528 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination
));
2532 xmldecl
= xmldoc_unlink_xmldecl(get_doc(This
));
2533 if (xmlSaveDoc(ctx
, get_doc(This
)) == -1) ret
= S_FALSE
;
2534 xmldoc_link_xmldecl(get_doc(This
), xmldecl
);
2536 /* will release resources through close callback */
2542 static HRESULT WINAPI
domdoc_get_validateOnParse(
2543 IXMLDOMDocument3
*iface
,
2544 VARIANT_BOOL
* isValidating
)
2546 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2547 TRACE("(%p)->(%p: %d)\n", This
, isValidating
, This
->validating
);
2548 *isValidating
= This
->validating
;
2553 static HRESULT WINAPI
domdoc_put_validateOnParse(
2554 IXMLDOMDocument3
*iface
,
2555 VARIANT_BOOL isValidating
)
2557 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2558 TRACE("(%p)->(%d)\n", This
, isValidating
);
2559 This
->validating
= isValidating
;
2564 static HRESULT WINAPI
domdoc_get_resolveExternals(
2565 IXMLDOMDocument3
*iface
,
2566 VARIANT_BOOL
* isResolving
)
2568 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2569 TRACE("(%p)->(%p: %d)\n", This
, isResolving
, This
->resolving
);
2570 *isResolving
= This
->resolving
;
2575 static HRESULT WINAPI
domdoc_put_resolveExternals(
2576 IXMLDOMDocument3
*iface
,
2577 VARIANT_BOOL isResolving
)
2579 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2580 TRACE("(%p)->(%d)\n", This
, isResolving
);
2581 This
->resolving
= isResolving
;
2586 static HRESULT WINAPI
domdoc_get_preserveWhiteSpace(
2587 IXMLDOMDocument3
*iface
,
2588 VARIANT_BOOL
* isPreserving
)
2590 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2591 TRACE("(%p)->(%p: %d)\n", This
, isPreserving
, This
->properties
->preserving
);
2592 *isPreserving
= This
->properties
->preserving
;
2597 static HRESULT WINAPI
domdoc_put_preserveWhiteSpace(
2598 IXMLDOMDocument3
*iface
,
2599 VARIANT_BOOL isPreserving
)
2601 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2602 TRACE("(%p)->(%d)\n", This
, isPreserving
);
2603 This
->properties
->preserving
= isPreserving
;
2608 static HRESULT WINAPI
domdoc_put_onreadystatechange(
2609 IXMLDOMDocument3
*iface
,
2612 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2614 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&event
));
2615 return set_doc_event(This
, EVENTID_READYSTATECHANGE
, &event
);
2619 static HRESULT WINAPI
domdoc_put_onDataAvailable(IXMLDOMDocument3
*iface
, VARIANT sink
)
2621 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2622 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2626 static HRESULT WINAPI
domdoc_put_onTransformNode(IXMLDOMDocument3
*iface
, VARIANT sink
)
2628 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2629 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2633 static HRESULT WINAPI
domdoc_get_namespaces(
2634 IXMLDOMDocument3
* iface
,
2635 IXMLDOMSchemaCollection
** collection
)
2637 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2640 FIXME("(%p)->(%p): semi-stub\n", This
, collection
);
2642 if (!collection
) return E_POINTER
;
2644 if (!This
->namespaces
)
2646 hr
= SchemaCache_create(This
->properties
->version
, (void**)&This
->namespaces
);
2647 if (hr
!= S_OK
) return hr
;
2649 hr
= cache_from_doc_ns(This
->namespaces
, &This
->node
);
2651 release_namespaces(This
);
2654 if (This
->namespaces
)
2655 return IXMLDOMSchemaCollection2_QueryInterface(This
->namespaces
,
2656 &IID_IXMLDOMSchemaCollection
, (void**)collection
);
2661 static HRESULT WINAPI
domdoc_get_schemas(
2662 IXMLDOMDocument3
* iface
,
2665 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2666 IXMLDOMSchemaCollection2
* cur_schema
= This
->properties
->schemaCache
;
2667 HRESULT hr
= S_FALSE
;
2669 TRACE("(%p)->(%p)\n", This
, schema
);
2671 V_VT(schema
) = VT_NULL
;
2672 /* just to reset pointer part, cause that's what application is expected to use */
2673 V_DISPATCH(schema
) = NULL
;
2677 hr
= IXMLDOMSchemaCollection2_QueryInterface(cur_schema
, &IID_IDispatch
, (void**)&V_DISPATCH(schema
));
2679 V_VT(schema
) = VT_DISPATCH
;
2684 static HRESULT WINAPI
domdoc_putref_schemas(
2685 IXMLDOMDocument3
* iface
,
2688 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2689 HRESULT hr
= E_FAIL
;
2690 IXMLDOMSchemaCollection2
* new_schema
= NULL
;
2692 FIXME("(%p)->(%s): semi-stub\n", This
, debugstr_variant(&schema
));
2693 switch(V_VT(&schema
))
2696 if (V_UNKNOWN(&schema
))
2698 hr
= IUnknown_QueryInterface(V_UNKNOWN(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2703 if (V_DISPATCH(&schema
))
2705 hr
= IDispatch_QueryInterface(V_DISPATCH(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2715 WARN("Can't get schema from vt %x\n", V_VT(&schema
));
2720 IXMLDOMSchemaCollection2
* old_schema
= InterlockedExchangePointer((void**)&This
->properties
->schemaCache
, new_schema
);
2721 if(old_schema
) IXMLDOMSchemaCollection2_Release(old_schema
);
2727 static inline BOOL
is_wellformed(xmlDocPtr doc
)
2729 #ifdef HAVE_XMLDOC_PROPERTIES
2730 return doc
->properties
& XML_DOC_WELLFORMED
;
2732 /* Not a full check, but catches the worst violations */
2736 for (child
= doc
->children
; child
!= NULL
; child
= child
->next
)
2738 switch (child
->type
)
2740 case XML_ELEMENT_NODE
:
2745 case XML_CDATA_SECTION_NODE
:
2757 static void LIBXML2_LOG_CALLBACK
validate_error(void* ctx
, char const* msg
, ...)
2761 LIBXML2_CALLBACK_ERR(domdoc_validateNode
, msg
, ap
);
2765 static void LIBXML2_LOG_CALLBACK
validate_warning(void* ctx
, char const* msg
, ...)
2769 LIBXML2_CALLBACK_WARN(domdoc_validateNode
, msg
, ap
);
2773 static HRESULT WINAPI
domdoc_validateNode(
2774 IXMLDOMDocument3
* iface
,
2776 IXMLDOMParseError
** err
)
2778 domdoc
* This
= impl_from_IXMLDOMDocument3(iface
);
2779 LONG state
, err_code
= 0;
2783 TRACE("(%p)->(%p, %p)\n", This
, node
, err
);
2784 IXMLDOMDocument3_get_readyState(iface
, &state
);
2785 if (state
!= READYSTATE_COMPLETE
)
2788 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2795 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2799 if (!get_node_obj(node
)->node
|| get_node_obj(node
)->node
->doc
!= get_doc(This
))
2802 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2806 if (!is_wellformed(get_doc(This
)))
2808 ERR("doc not well-formed\n");
2810 *err
= create_parseError(E_XML_NOTWF
, NULL
, NULL
, NULL
, 0, 0, 0);
2814 /* DTD validation */
2815 if (get_doc(This
)->intSubset
|| get_doc(This
)->extSubset
)
2817 xmlValidCtxtPtr vctx
= xmlNewValidCtxt();
2818 vctx
->error
= validate_error
;
2819 vctx
->warning
= validate_warning
;
2822 if (!((node
== (IXMLDOMNode
*)iface
)?
2823 xmlValidateDocument(vctx
, get_doc(This
)) :
2824 xmlValidateElement(vctx
, get_doc(This
), get_node_obj(node
)->node
)))
2826 /* TODO: get a real error code here */
2827 TRACE("DTD validation failed\n");
2828 err_code
= E_XML_INVALID
;
2831 xmlFreeValidCtxt(vctx
);
2834 /* Schema validation */
2835 if (hr
== S_OK
&& This
->properties
->schemaCache
!= NULL
)
2838 hr
= SchemaCache_validate_tree(This
->properties
->schemaCache
, get_node_obj(node
)->node
);
2842 /* TODO: get a real error code here */
2845 TRACE("schema validation succeeded\n");
2849 ERR("schema validation failed\n");
2850 err_code
= E_XML_INVALID
;
2855 /* not really OK, just didn't find a schema for the ns */
2862 ERR("no DTD or schema found\n");
2863 err_code
= E_XML_NODTD
;
2868 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2873 static HRESULT WINAPI
domdoc_validate(
2874 IXMLDOMDocument3
* iface
,
2875 IXMLDOMParseError
** err
)
2877 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2878 TRACE("(%p)->(%p)\n", This
, err
);
2879 return IXMLDOMDocument3_validateNode(iface
, (IXMLDOMNode
*)iface
, err
);
2882 static HRESULT WINAPI
domdoc_setProperty(
2883 IXMLDOMDocument3
* iface
,
2887 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2889 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(p
), debugstr_variant(&value
));
2891 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
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
);
2908 if (lstrcmpiW(bstr
, PropValueXPathW
) == 0)
2909 This
->properties
->XPath
= TRUE
;
2910 else if (lstrcmpiW(bstr
, PropValueXSLPatternW
) == 0)
2911 This
->properties
->XPath
= FALSE
;
2915 VariantClear(&varStr
);
2918 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
2920 xmlChar
*nsStr
= (xmlChar
*)This
->properties
->selectNsStr
;
2921 struct list
*pNsList
;
2926 V_VT(&varStr
) = VT_EMPTY
;
2927 if (V_VT(&value
) != VT_BSTR
)
2929 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2931 bstr
= V_BSTR(&varStr
);
2934 bstr
= V_BSTR(&value
);
2938 pNsList
= &(This
->properties
->selectNsList
);
2939 clear_selectNsList(pNsList
);
2941 nsStr
= xmlchar_from_wchar(bstr
);
2943 TRACE("property value: \"%s\"\n", debugstr_w(bstr
));
2945 This
->properties
->selectNsStr
= nsStr
;
2946 This
->properties
->selectNsStr_len
= xmlStrlen(nsStr
);
2949 xmlChar
*pTokBegin
, *pTokEnd
, *pTokInner
;
2950 select_ns_entry
* ns_entry
= NULL
;
2951 xmlXPathContextPtr ctx
;
2953 ctx
= xmlXPathNewContext(This
->node
.node
->doc
);
2956 /* skip leading spaces */
2957 while (*pTokBegin
== ' ' || *pTokBegin
== '\n' ||
2958 *pTokBegin
== '\t' || *pTokBegin
== '\r')
2961 for (; *pTokBegin
; pTokBegin
= pTokEnd
)
2964 memset(ns_entry
, 0, sizeof(select_ns_entry
));
2966 ns_entry
= heap_alloc_zero(sizeof(select_ns_entry
));
2968 while (*pTokBegin
== ' ')
2970 pTokEnd
= pTokBegin
;
2971 while (*pTokEnd
!= ' ' && *pTokEnd
!= 0)
2974 /* so it failed to advance which means we've got some trailing spaces */
2975 if (pTokEnd
== pTokBegin
) break;
2977 if (xmlStrncmp(pTokBegin
, (xmlChar
const*)"xmlns", 5) != 0)
2980 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2981 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2986 if (*pTokBegin
== '=')
2988 /*valid for XSLPattern?*/
2989 FIXME("Setting default xmlns not supported - skipping.\n");
2992 else if (*pTokBegin
== ':')
2994 ns_entry
->prefix
= ++pTokBegin
;
2995 for (pTokInner
= pTokBegin
; pTokInner
!= pTokEnd
&& *pTokInner
!= '='; ++pTokInner
)
2998 if (pTokInner
== pTokEnd
)
3001 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3002 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
3006 ns_entry
->prefix_end
= *pTokInner
;
3010 if (pTokEnd
-pTokInner
> 1 &&
3011 ((*pTokInner
== '\'' && *(pTokEnd
-1) == '\'') ||
3012 (*pTokInner
== '"' && *(pTokEnd
-1) == '"')))
3014 ns_entry
->href
= ++pTokInner
;
3015 ns_entry
->href_end
= *(pTokEnd
-1);
3017 list_add_tail(pNsList
, &ns_entry
->entry
);
3018 /*let libxml figure out if they're valid from here ;)*/
3019 if (xmlXPathRegisterNs(ctx
, ns_entry
->prefix
, ns_entry
->href
) != 0)
3028 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3029 debugstr_w(bstr
), debugstr_an((const char*)pTokInner
, pTokEnd
-pTokInner
));
3030 list_add_tail(pNsList
, &ns_entry
->entry
);
3043 heap_free(ns_entry
);
3044 xmlXPathFreeContext(ctx
);
3047 VariantClear(&varStr
);
3050 else if (lstrcmpiW(p
, PropertyProhibitDTDW
) == 0 ||
3051 lstrcmpiW(p
, PropertyNewParserW
) == 0 ||
3052 lstrcmpiW(p
, PropertyResolveExternalsW
) == 0)
3055 FIXME("Ignoring property %s, value %s\n", debugstr_w(p
), debugstr_variant(&value
));
3059 FIXME("Unknown property %s\n", debugstr_w(p
));
3063 static HRESULT WINAPI
domdoc_getProperty(
3064 IXMLDOMDocument3
* iface
,
3068 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3070 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
3073 return E_INVALIDARG
;
3075 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
3077 V_VT(var
) = VT_BSTR
;
3078 V_BSTR(var
) = This
->properties
->XPath
?
3079 SysAllocString(PropValueXPathW
) :
3080 SysAllocString(PropValueXSLPatternW
);
3081 return V_BSTR(var
) ? S_OK
: E_OUTOFMEMORY
;
3083 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3086 BSTR rebuiltStr
, cur
;
3087 const xmlChar
*nsStr
;
3088 struct list
*pNsList
;
3089 select_ns_entry
* pNsEntry
;
3091 V_VT(var
) = VT_BSTR
;
3092 nsStr
= This
->properties
->selectNsStr
;
3093 pNsList
= &This
->properties
->selectNsList
;
3094 lenA
= This
->properties
->selectNsStr_len
;
3095 lenW
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, NULL
, 0);
3096 rebuiltStr
= heap_alloc(lenW
*sizeof(WCHAR
));
3097 MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, rebuiltStr
, lenW
);
3099 /* this is fine because all of the chars that end tokens are ASCII*/
3100 LIST_FOR_EACH_ENTRY(pNsEntry
, pNsList
, select_ns_entry
, entry
)
3102 while (*cur
!= 0) ++cur
;
3103 if (pNsEntry
->prefix_end
)
3105 *cur
= pNsEntry
->prefix_end
;
3106 while (*cur
!= 0) ++cur
;
3109 if (pNsEntry
->href_end
)
3111 *cur
= pNsEntry
->href_end
;
3114 V_BSTR(var
) = SysAllocString(rebuiltStr
);
3115 heap_free(rebuiltStr
);
3119 FIXME("Unknown property %s\n", debugstr_w(p
));
3123 static HRESULT WINAPI
domdoc_importNode(
3124 IXMLDOMDocument3
* iface
,
3127 IXMLDOMNode
** clone
)
3129 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3130 FIXME("(%p)->(%p %d %p): stub\n", This
, node
, deep
, clone
);
3134 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl
=
3136 domdoc_QueryInterface
,
3139 domdoc_GetTypeInfoCount
,
3141 domdoc_GetIDsOfNames
,
3143 domdoc_get_nodeName
,
3144 domdoc_get_nodeValue
,
3145 domdoc_put_nodeValue
,
3146 domdoc_get_nodeType
,
3147 domdoc_get_parentNode
,
3148 domdoc_get_childNodes
,
3149 domdoc_get_firstChild
,
3150 domdoc_get_lastChild
,
3151 domdoc_get_previousSibling
,
3152 domdoc_get_nextSibling
,
3153 domdoc_get_attributes
,
3154 domdoc_insertBefore
,
3155 domdoc_replaceChild
,
3158 domdoc_hasChildNodes
,
3159 domdoc_get_ownerDocument
,
3161 domdoc_get_nodeTypeString
,
3164 domdoc_get_specified
,
3165 domdoc_get_definition
,
3166 domdoc_get_nodeTypedValue
,
3167 domdoc_put_nodeTypedValue
,
3168 domdoc_get_dataType
,
3169 domdoc_put_dataType
,
3171 domdoc_transformNode
,
3173 domdoc_selectSingleNode
,
3175 domdoc_get_namespaceURI
,
3177 domdoc_get_baseName
,
3178 domdoc_transformNodeToObject
,
3180 domdoc_get_implementation
,
3181 domdoc_get_documentElement
,
3182 domdoc_put_documentElement
,
3183 domdoc_createElement
,
3184 domdoc_createDocumentFragment
,
3185 domdoc_createTextNode
,
3186 domdoc_createComment
,
3187 domdoc_createCDATASection
,
3188 domdoc_createProcessingInstruction
,
3189 domdoc_createAttribute
,
3190 domdoc_createEntityReference
,
3191 domdoc_getElementsByTagName
,
3195 domdoc_get_readyState
,
3196 domdoc_get_parseError
,
3203 domdoc_get_validateOnParse
,
3204 domdoc_put_validateOnParse
,
3205 domdoc_get_resolveExternals
,
3206 domdoc_put_resolveExternals
,
3207 domdoc_get_preserveWhiteSpace
,
3208 domdoc_put_preserveWhiteSpace
,
3209 domdoc_put_onreadystatechange
,
3210 domdoc_put_onDataAvailable
,
3211 domdoc_put_onTransformNode
,
3212 domdoc_get_namespaces
,
3214 domdoc_putref_schemas
,
3218 domdoc_validateNode
,
3222 /* IConnectionPointContainer */
3223 static HRESULT WINAPI
ConnectionPointContainer_QueryInterface(IConnectionPointContainer
*iface
,
3224 REFIID riid
, void **ppv
)
3226 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3227 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3230 static ULONG WINAPI
ConnectionPointContainer_AddRef(IConnectionPointContainer
*iface
)
3232 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3233 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3236 static ULONG WINAPI
ConnectionPointContainer_Release(IConnectionPointContainer
*iface
)
3238 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3239 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3242 static HRESULT WINAPI
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer
*iface
,
3243 IEnumConnectionPoints
**ppEnum
)
3245 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3246 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3250 static HRESULT WINAPI
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer
*iface
,
3251 REFIID riid
, IConnectionPoint
**cp
)
3253 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3254 ConnectionPoint
*iter
;
3256 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), cp
);
3260 for(iter
= This
->cp_list
; iter
; iter
= iter
->next
)
3262 if (IsEqualGUID(iter
->iid
, riid
))
3263 *cp
= &iter
->IConnectionPoint_iface
;
3268 IConnectionPoint_AddRef(*cp
);
3272 FIXME("unsupported riid %s\n", debugstr_guid(riid
));
3273 return CONNECT_E_NOCONNECTION
;
3277 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl
=
3279 ConnectionPointContainer_QueryInterface
,
3280 ConnectionPointContainer_AddRef
,
3281 ConnectionPointContainer_Release
,
3282 ConnectionPointContainer_EnumConnectionPoints
,
3283 ConnectionPointContainer_FindConnectionPoint
3286 /* IConnectionPoint */
3287 static HRESULT WINAPI
ConnectionPoint_QueryInterface(IConnectionPoint
*iface
,
3288 REFIID riid
, void **ppv
)
3290 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3292 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
3296 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
3297 IsEqualGUID(&IID_IConnectionPoint
, riid
))
3304 IConnectionPoint_AddRef(iface
);
3308 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
3309 return E_NOINTERFACE
;
3312 static ULONG WINAPI
ConnectionPoint_AddRef(IConnectionPoint
*iface
)
3314 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3315 return IConnectionPointContainer_AddRef(This
->container
);
3318 static ULONG WINAPI
ConnectionPoint_Release(IConnectionPoint
*iface
)
3320 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3321 return IConnectionPointContainer_Release(This
->container
);
3324 static HRESULT WINAPI
ConnectionPoint_GetConnectionInterface(IConnectionPoint
*iface
, IID
*iid
)
3326 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3328 TRACE("(%p)->(%p)\n", This
, iid
);
3330 if (!iid
) return E_POINTER
;
3336 static HRESULT WINAPI
ConnectionPoint_GetConnectionPointContainer(IConnectionPoint
*iface
,
3337 IConnectionPointContainer
**container
)
3339 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3341 TRACE("(%p)->(%p)\n", This
, container
);
3343 if (!container
) return E_POINTER
;
3345 *container
= This
->container
;
3346 IConnectionPointContainer_AddRef(*container
);
3350 static HRESULT WINAPI
ConnectionPoint_Advise(IConnectionPoint
*iface
, IUnknown
*unk_sink
,
3353 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3358 TRACE("(%p)->(%p %p)\n", This
, unk_sink
, cookie
);
3360 hr
= IUnknown_QueryInterface(unk_sink
, This
->iid
, (void**)&sink
);
3361 if(FAILED(hr
) && !IsEqualGUID(&IID_IPropertyNotifySink
, This
->iid
))
3362 hr
= IUnknown_QueryInterface(unk_sink
, &IID_IDispatch
, (void**)&sink
);
3364 return CONNECT_E_CANNOTCONNECT
;
3368 for (i
= 0; i
< This
->sinks_size
; i
++)
3369 if (!This
->sinks
[i
].unk
)
3372 if (i
== This
->sinks_size
)
3373 This
->sinks
= heap_realloc(This
->sinks
,(++This
->sinks_size
)*sizeof(*This
->sinks
));
3377 This
->sinks
= heap_alloc(sizeof(*This
->sinks
));
3378 This
->sinks_size
= 1;
3382 This
->sinks
[i
].unk
= sink
;
3389 static HRESULT WINAPI
ConnectionPoint_Unadvise(IConnectionPoint
*iface
, DWORD cookie
)
3391 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3393 TRACE("(%p)->(%d)\n", This
, cookie
);
3395 if (cookie
== 0 || cookie
> This
->sinks_size
|| !This
->sinks
[cookie
-1].unk
)
3396 return CONNECT_E_NOCONNECTION
;
3398 IUnknown_Release(This
->sinks
[cookie
-1].unk
);
3399 This
->sinks
[cookie
-1].unk
= NULL
;
3404 static HRESULT WINAPI
ConnectionPoint_EnumConnections(IConnectionPoint
*iface
,
3405 IEnumConnections
**ppEnum
)
3407 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3408 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3412 static const IConnectionPointVtbl ConnectionPointVtbl
=
3414 ConnectionPoint_QueryInterface
,
3415 ConnectionPoint_AddRef
,
3416 ConnectionPoint_Release
,
3417 ConnectionPoint_GetConnectionInterface
,
3418 ConnectionPoint_GetConnectionPointContainer
,
3419 ConnectionPoint_Advise
,
3420 ConnectionPoint_Unadvise
,
3421 ConnectionPoint_EnumConnections
3424 static void ConnectionPoint_Init(ConnectionPoint
*cp
, struct domdoc
*doc
, REFIID riid
)
3426 cp
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointVtbl
;
3432 cp
->next
= doc
->cp_list
;
3435 cp
->container
= &doc
->IConnectionPointContainer_iface
;
3438 /* domdoc implementation of IObjectWithSite */
3439 static HRESULT WINAPI
3440 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
3442 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3443 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObject
);
3446 static ULONG WINAPI
domdoc_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
3448 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3449 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3452 static ULONG WINAPI
domdoc_ObjectWithSite_Release( IObjectWithSite
* iface
)
3454 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3455 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3458 static HRESULT WINAPI
domdoc_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
3460 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3462 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
3467 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
3470 static HRESULT WINAPI
domdoc_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
3472 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3474 TRACE("(%p)->(%p)\n", iface
, punk
);
3480 IUnknown_Release( This
->site
);
3487 IUnknown_AddRef( punk
);
3490 IUnknown_Release( This
->site
);
3497 static const IObjectWithSiteVtbl domdocObjectSite
=
3499 domdoc_ObjectWithSite_QueryInterface
,
3500 domdoc_ObjectWithSite_AddRef
,
3501 domdoc_ObjectWithSite_Release
,
3502 domdoc_ObjectWithSite_SetSite
,
3503 domdoc_ObjectWithSite_GetSite
3506 static HRESULT WINAPI
domdoc_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
3508 domdoc
*This
= impl_from_IObjectSafety(iface
);
3509 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3512 static ULONG WINAPI
domdoc_Safety_AddRef(IObjectSafety
*iface
)
3514 domdoc
*This
= impl_from_IObjectSafety(iface
);
3515 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3518 static ULONG WINAPI
domdoc_Safety_Release(IObjectSafety
*iface
)
3520 domdoc
*This
= impl_from_IObjectSafety(iface
);
3521 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3524 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3526 static HRESULT WINAPI
domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3527 DWORD
*supported
, DWORD
*enabled
)
3529 domdoc
*This
= impl_from_IObjectSafety(iface
);
3531 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
3533 if(!supported
|| !enabled
) return E_POINTER
;
3535 *supported
= SAFETY_SUPPORTED_OPTIONS
;
3536 *enabled
= This
->safeopt
;
3541 static HRESULT WINAPI
domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3542 DWORD mask
, DWORD enabled
)
3544 domdoc
*This
= impl_from_IObjectSafety(iface
);
3545 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
3547 if ((mask
& ~SAFETY_SUPPORTED_OPTIONS
) != 0)
3550 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
3555 #undef SAFETY_SUPPORTED_OPTIONS
3557 static const IObjectSafetyVtbl domdocObjectSafetyVtbl
= {
3558 domdoc_Safety_QueryInterface
,
3559 domdoc_Safety_AddRef
,
3560 domdoc_Safety_Release
,
3561 domdoc_Safety_GetInterfaceSafetyOptions
,
3562 domdoc_Safety_SetInterfaceSafetyOptions
3565 static const tid_t domdoc_iface_tids
[] = {
3566 IXMLDOMDocument3_tid
,
3570 static dispex_static_data_t domdoc_dispex
= {
3572 IXMLDOMDocument3_tid
,
3577 HRESULT
get_domdoc_from_xmldoc(xmlDocPtr xmldoc
, IXMLDOMDocument3
**document
)
3581 doc
= heap_alloc( sizeof (*doc
) );
3583 return E_OUTOFMEMORY
;
3585 doc
->IXMLDOMDocument3_iface
.lpVtbl
= &XMLDOMDocument3Vtbl
;
3586 doc
->IPersistStreamInit_iface
.lpVtbl
= &xmldoc_IPersistStreamInit_VTable
;
3587 doc
->IObjectWithSite_iface
.lpVtbl
= &domdocObjectSite
;
3588 doc
->IObjectSafety_iface
.lpVtbl
= &domdocObjectSafetyVtbl
;
3589 doc
->IConnectionPointContainer_iface
.lpVtbl
= &ConnectionPointContainerVtbl
;
3591 doc
->async
= VARIANT_TRUE
;
3592 doc
->validating
= 0;
3594 doc
->properties
= properties_from_xmlDocPtr(xmldoc
);
3598 doc
->cp_list
= NULL
;
3599 doc
->namespaces
= NULL
;
3600 memset(doc
->events
, 0, sizeof(doc
->events
));
3602 /* events connection points */
3603 ConnectionPoint_Init(&doc
->cp_dispatch
, doc
, &IID_IDispatch
);
3604 ConnectionPoint_Init(&doc
->cp_propnotif
, doc
, &IID_IPropertyNotifySink
);
3605 ConnectionPoint_Init(&doc
->cp_domdocevents
, doc
, &DIID_XMLDOMDocumentEvents
);
3607 init_xmlnode(&doc
->node
, (xmlNodePtr
)xmldoc
, (IXMLDOMNode
*)&doc
->IXMLDOMDocument3_iface
,
3610 *document
= &doc
->IXMLDOMDocument3_iface
;
3612 TRACE("returning iface %p\n", *document
);
3616 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3621 TRACE("(%d, %p)\n", version
, ppObj
);
3623 xmldoc
= xmlNewDoc(NULL
);
3625 return E_OUTOFMEMORY
;
3627 xmldoc_init(xmldoc
, version
);
3629 hr
= get_domdoc_from_xmldoc(xmldoc
, (IXMLDOMDocument3
**)ppObj
);
3632 free_properties(properties_from_xmlDocPtr(xmldoc
));
3633 heap_free(xmldoc
->_private
);
3641 IUnknown
* create_domdoc( xmlNodePtr document
)
3646 TRACE("(%p)\n", document
);
3648 hr
= get_domdoc_from_xmldoc((xmlDocPtr
)document
, (IXMLDOMDocument3
**)&pObj
);
3657 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3659 MESSAGE("This program tried to use a DOMDocument object, but\n"
3660 "libxml2 support was not present at compile time.\n");