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};
74 static const WCHAR PropertyAllowXsltScriptW
[] = {'A','l','l','o','w','X','s','l','t','S','c','r','i','p','t',0};
75 static const WCHAR PropertyAllowDocumentFunctionW
[] = {'A','l','l','o','w','D','o','c','u','m','e','n','t','F','u','n','c','t','i','o','n',0};
77 /* Anything that passes the test_get_ownerDocument()
78 * tests can go here (data shared between all instances).
79 * We need to preserve this when reloading a document,
80 * and also need access to it from the libxml backend. */
82 MSXML_VERSION version
;
83 VARIANT_BOOL preserving
;
84 IXMLDOMSchemaCollection2
* schemaCache
;
85 struct list selectNsList
;
86 xmlChar
const* selectNsStr
;
92 typedef struct ConnectionPoint ConnectionPoint
;
93 typedef struct domdoc domdoc
;
95 struct ConnectionPoint
97 IConnectionPoint IConnectionPoint_iface
;
100 ConnectionPoint
*next
;
101 IConnectionPointContainer
*container
;
108 IPropertyNotifySink
*propnotif
;
114 EVENTID_READYSTATECHANGE
= 0,
115 EVENTID_DATAAVAILABLE
,
116 EVENTID_TRANSFORMNODE
,
123 IXMLDOMDocument3 IXMLDOMDocument3_iface
;
124 IPersistStreamInit IPersistStreamInit_iface
;
125 IObjectWithSite IObjectWithSite_iface
;
126 IObjectSafety IObjectSafety_iface
;
127 IConnectionPointContainer IConnectionPointContainer_iface
;
130 VARIANT_BOOL validating
;
131 VARIANT_BOOL resolving
;
132 domdoc_properties
* properties
;
135 /* IObjectWithSite */
141 /* connection list */
142 ConnectionPoint
*cp_list
;
143 ConnectionPoint cp_domdocevents
;
144 ConnectionPoint cp_propnotif
;
145 ConnectionPoint cp_dispatch
;
148 IDispatch
*events
[EVENTID_LAST
];
150 IXMLDOMSchemaCollection2
*namespaces
;
153 static HRESULT
set_doc_event(domdoc
*doc
, eventid_t eid
, const VARIANT
*v
)
161 IUnknown_QueryInterface(V_UNKNOWN(v
), &IID_IDispatch
, (void**)&disp
);
166 disp
= V_DISPATCH(v
);
167 if (disp
) IDispatch_AddRef(disp
);
170 return DISP_E_TYPEMISMATCH
;
173 if (doc
->events
[eid
]) IDispatch_Release(doc
->events
[eid
]);
174 doc
->events
[eid
] = disp
;
179 static inline ConnectionPoint
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
181 return CONTAINING_RECORD(iface
, ConnectionPoint
, IConnectionPoint_iface
);
185 In native windows, the whole lifetime management of XMLDOMNodes is
186 managed automatically using reference counts. Wine emulates that by
187 maintaining a reference count to the document that is increased for
188 each IXMLDOMNode pointer passed out for this document. If all these
189 pointers are gone, the document is unreachable and gets freed, that
190 is, all nodes in the tree of the document get freed.
192 You are able to create nodes that are associated to a document (in
193 fact, in msxml's XMLDOM model, all nodes are associated to a document),
194 but not in the tree of that document, for example using the createFoo
195 functions from IXMLDOMDocument. These nodes do not get cleaned up
196 by libxml, so we have to do it ourselves.
198 To catch these nodes, a list of "orphan nodes" is introduced.
199 It contains pointers to all roots of node trees that are
200 associated with the document without being part of the document
201 tree. All nodes with parent==NULL (except for the document root nodes)
202 should be in the orphan node list of their document. All orphan nodes
203 get freed together with the document itself.
206 typedef struct _xmldoc_priv
{
209 domdoc_properties
* properties
;
212 typedef struct _orphan_entry
{
217 typedef struct _select_ns_entry
{
219 xmlChar
const* prefix
;
225 static inline xmldoc_priv
* priv_from_xmlDocPtr(const xmlDocPtr doc
)
227 return doc
->_private
;
230 static inline domdoc_properties
* properties_from_xmlDocPtr(xmlDocPtr doc
)
232 return priv_from_xmlDocPtr(doc
)->properties
;
235 BOOL
is_xpathmode(const xmlDocPtr doc
)
237 return properties_from_xmlDocPtr(doc
)->XPath
;
240 void set_xpathmode(xmlDocPtr doc
, BOOL xpath
)
242 properties_from_xmlDocPtr(doc
)->XPath
= xpath
;
245 int registerNamespaces(xmlXPathContextPtr ctxt
)
248 const select_ns_entry
* ns
= NULL
;
249 const struct list
* pNsList
= &properties_from_xmlDocPtr(ctxt
->doc
)->selectNsList
;
251 TRACE("(%p)\n", ctxt
);
253 LIST_FOR_EACH_ENTRY( ns
, pNsList
, select_ns_entry
, entry
)
255 xmlXPathRegisterNs(ctxt
, ns
->prefix
, ns
->href
);
262 static inline void clear_selectNsList(struct list
* pNsList
)
264 select_ns_entry
*ns
, *ns2
;
265 LIST_FOR_EACH_ENTRY_SAFE( ns
, ns2
, pNsList
, select_ns_entry
, entry
)
272 static xmldoc_priv
* create_priv(void)
275 priv
= heap_alloc( sizeof (*priv
) );
280 list_init( &priv
->orphans
);
281 priv
->properties
= NULL
;
287 static domdoc_properties
*create_properties(MSXML_VERSION version
)
289 domdoc_properties
*properties
= heap_alloc(sizeof(domdoc_properties
));
291 list_init(&properties
->selectNsList
);
292 properties
->preserving
= VARIANT_FALSE
;
293 properties
->schemaCache
= NULL
;
294 properties
->selectNsStr
= heap_alloc_zero(sizeof(xmlChar
));
295 properties
->selectNsStr_len
= 0;
297 /* properties that are dependent on object versions */
298 properties
->version
= version
;
299 properties
->XPath
= (version
== MSXML4
|| version
== MSXML6
);
302 properties
->uri
= NULL
;
307 static domdoc_properties
* copy_properties(domdoc_properties
const* properties
)
309 domdoc_properties
* pcopy
= heap_alloc(sizeof(domdoc_properties
));
310 select_ns_entry
const* ns
= NULL
;
311 select_ns_entry
* new_ns
= NULL
;
312 int len
= (properties
->selectNsStr_len
+1)*sizeof(xmlChar
);
317 pcopy
->version
= properties
->version
;
318 pcopy
->preserving
= properties
->preserving
;
319 pcopy
->schemaCache
= properties
->schemaCache
;
320 if (pcopy
->schemaCache
)
321 IXMLDOMSchemaCollection2_AddRef(pcopy
->schemaCache
);
322 pcopy
->XPath
= properties
->XPath
;
323 pcopy
->selectNsStr_len
= properties
->selectNsStr_len
;
324 list_init( &pcopy
->selectNsList
);
325 pcopy
->selectNsStr
= heap_alloc(len
);
326 memcpy((xmlChar
*)pcopy
->selectNsStr
, properties
->selectNsStr
, len
);
327 offset
= pcopy
->selectNsStr
- properties
->selectNsStr
;
329 LIST_FOR_EACH_ENTRY( ns
, (&properties
->selectNsList
), select_ns_entry
, entry
)
331 new_ns
= heap_alloc(sizeof(select_ns_entry
));
332 memcpy(new_ns
, ns
, sizeof(select_ns_entry
));
333 new_ns
->href
+= offset
;
334 new_ns
->prefix
+= offset
;
335 list_add_tail(&pcopy
->selectNsList
, &new_ns
->entry
);
338 pcopy
->uri
= properties
->uri
;
340 IUri_AddRef(pcopy
->uri
);
346 static void free_properties(domdoc_properties
* properties
)
350 if (properties
->schemaCache
)
351 IXMLDOMSchemaCollection2_Release(properties
->schemaCache
);
352 clear_selectNsList(&properties
->selectNsList
);
353 heap_free((xmlChar
*)properties
->selectNsStr
);
355 IUri_Release(properties
->uri
);
356 heap_free(properties
);
360 static void release_namespaces(domdoc
*This
)
362 if (This
->namespaces
)
364 IXMLDOMSchemaCollection2_Release(This
->namespaces
);
365 This
->namespaces
= NULL
;
369 /* links a "<?xml" node as a first child */
370 void xmldoc_link_xmldecl(xmlDocPtr doc
, xmlNodePtr node
)
373 if (doc
->standalone
!= -1) xmlAddPrevSibling( doc
->children
, node
);
376 /* unlinks a first "<?xml" child if it was created */
377 xmlNodePtr
xmldoc_unlink_xmldecl(xmlDocPtr doc
)
379 static const xmlChar xmlA
[] = "xml";
380 xmlNodePtr node
, first_child
;
384 /* xml declaration node could be created automatically after parsing or added
386 first_child
= doc
->children
;
387 if (first_child
&& first_child
->type
== XML_PI_NODE
&& xmlStrEqual(first_child
->name
, xmlA
))
390 xmlUnlinkNode( node
);
398 BOOL
is_preserving_whitespace(xmlNodePtr node
)
400 domdoc_properties
* properties
= NULL
;
401 /* during parsing the xmlDoc._private stuff is not there */
402 if (priv_from_xmlDocPtr(node
->doc
))
403 properties
= properties_from_xmlDocPtr(node
->doc
);
404 return ((properties
&& properties
->preserving
== VARIANT_TRUE
) ||
405 xmlNodeGetSpacePreserve(node
) == 1);
408 static inline BOOL
strn_isspace(xmlChar
const* str
, int len
)
410 for (; str
&& len
> 0 && *str
; ++str
, --len
)
417 static void sax_characters(void *ctx
, const xmlChar
*ch
, int len
)
419 xmlParserCtxtPtr ctxt
;
422 ctxt
= (xmlParserCtxtPtr
) ctx
;
423 This
= (const domdoc
*) ctxt
->_private
;
427 xmlChar cur
= *(ctxt
->input
->cur
);
429 /* Characters are reported with multiple calls, for example each charref is reported with a separate
430 call and then parser appends it to a single text node or creates a new node if not created.
431 It's not possible to tell if it's ignorable data or not just looking at data itself cause it could be
432 space chars that separate charrefs or similar case. We only need to skip leading and trailing spaces,
433 or whole node if it has nothing but space chars, so to detect leading space node->last is checked that
434 contains text node pointer if already created, trailing spaces are detected directly looking at parser input
435 for next '<' opening bracket - similar logic is used by libxml2 itself. Basically 'cur' == '<' means the last
436 chunk of char data, in case it's not the last chunk we check for previously added node type and if it's not
437 a text node it's safe to ignore.
439 Note that during domdoc_loadXML() the xmlDocPtr->_private data is not available. */
441 if (!This
->properties
->preserving
&&
442 !is_preserving_whitespace(ctxt
->node
) &&
443 strn_isspace(ch
, len
) &&
444 (!ctxt
->node
->last
||
445 ((ctxt
->node
->last
&& (cur
== '<' || ctxt
->node
->last
->type
!= XML_TEXT_NODE
))
448 /* Keep information about ignorable whitespace text node in previous or parent node */
449 if (ctxt
->node
->last
)
450 *(DWORD
*)&ctxt
->node
->last
->_private
|= NODE_PRIV_TRAILING_IGNORABLE_WS
;
451 else if (ctxt
->node
->type
!= XML_DOCUMENT_NODE
)
452 *(DWORD
*)&ctxt
->node
->_private
|= NODE_PRIV_CHILD_IGNORABLE_WS
;
457 xmlSAX2Characters(ctxt
, ch
, len
);
460 static void LIBXML2_LOG_CALLBACK
sax_error(void* ctx
, char const* msg
, ...)
464 LIBXML2_CALLBACK_ERR(doparse
, msg
, ap
);
468 static void LIBXML2_LOG_CALLBACK
sax_warning(void* ctx
, char const* msg
, ...)
472 LIBXML2_CALLBACK_WARN(doparse
, msg
, ap
);
476 static void sax_serror(void* ctx
, xmlErrorPtr err
)
478 LIBXML2_CALLBACK_SERROR(doparse
, err
);
481 static xmlDocPtr
doparse(domdoc
* This
, char const* ptr
, int len
, xmlCharEncoding encoding
)
483 xmlDocPtr doc
= NULL
;
484 xmlParserCtxtPtr pctx
;
485 static xmlSAXHandler sax_handler
= {
486 xmlSAX2InternalSubset
, /* internalSubset */
487 xmlSAX2IsStandalone
, /* isStandalone */
488 xmlSAX2HasInternalSubset
, /* hasInternalSubset */
489 xmlSAX2HasExternalSubset
, /* hasExternalSubset */
490 xmlSAX2ResolveEntity
, /* resolveEntity */
491 xmlSAX2GetEntity
, /* getEntity */
492 xmlSAX2EntityDecl
, /* entityDecl */
493 xmlSAX2NotationDecl
, /* notationDecl */
494 xmlSAX2AttributeDecl
, /* attributeDecl */
495 xmlSAX2ElementDecl
, /* elementDecl */
496 xmlSAX2UnparsedEntityDecl
, /* unparsedEntityDecl */
497 xmlSAX2SetDocumentLocator
, /* setDocumentLocator */
498 xmlSAX2StartDocument
, /* startDocument */
499 xmlSAX2EndDocument
, /* endDocument */
500 xmlSAX2StartElement
, /* startElement */
501 xmlSAX2EndElement
, /* endElement */
502 xmlSAX2Reference
, /* reference */
503 sax_characters
, /* characters */
504 sax_characters
, /* ignorableWhitespace */
505 xmlSAX2ProcessingInstruction
, /* processingInstruction */
506 xmlSAX2Comment
, /* comment */
507 sax_warning
, /* warning */
508 sax_error
, /* error */
509 sax_error
, /* fatalError */
510 xmlSAX2GetParameterEntity
, /* getParameterEntity */
511 xmlSAX2CDataBlock
, /* cdataBlock */
512 xmlSAX2ExternalSubset
, /* externalSubset */
515 xmlSAX2StartElementNs
, /* startElementNs */
516 xmlSAX2EndElementNs
, /* endElementNs */
517 sax_serror
/* serror */
520 pctx
= xmlCreateMemoryParserCtxt(ptr
, len
);
523 ERR("Failed to create parser context\n");
527 if (pctx
->sax
) xmlFree(pctx
->sax
);
528 pctx
->sax
= &sax_handler
;
529 pctx
->_private
= This
;
532 if (encoding
!= XML_CHAR_ENCODING_NONE
)
533 xmlSwitchEncoding(pctx
, encoding
);
535 xmlParseDocument(pctx
);
537 if (pctx
->wellFormed
)
543 xmlFreeDoc(pctx
->myDoc
);
547 xmlFreeParserCtxt(pctx
);
549 /* TODO: put this in one of the SAX callbacks */
550 /* create first child as a <?xml...?> */
551 if (doc
&& doc
->standalone
!= -1)
555 xmlChar
*xmlbuff
= (xmlChar
*)buff
;
557 node
= xmlNewDocPI( doc
, (xmlChar
*)"xml", NULL
);
559 /* version attribute can't be omitted */
560 sprintf(buff
, "version=\"%s\"", doc
->version
? (char*)doc
->version
: "1.0");
561 xmlNodeAddContent( node
, xmlbuff
);
565 sprintf(buff
, " encoding=\"%s\"", doc
->encoding
);
566 xmlNodeAddContent( node
, xmlbuff
);
569 if (doc
->standalone
!= -2)
571 sprintf(buff
, " standalone=\"%s\"", doc
->standalone
== 0 ? "no" : "yes");
572 xmlNodeAddContent( node
, xmlbuff
);
575 xmldoc_link_xmldecl( doc
, node
);
581 void xmldoc_init(xmlDocPtr doc
, MSXML_VERSION version
)
583 doc
->_private
= create_priv();
584 priv_from_xmlDocPtr(doc
)->properties
= create_properties(version
);
587 LONG
xmldoc_add_refs(xmlDocPtr doc
, LONG refs
)
589 LONG ref
= InterlockedExchangeAdd(&priv_from_xmlDocPtr(doc
)->refs
, refs
) + refs
;
590 TRACE("(%p)->(%d)\n", doc
, ref
);
594 LONG
xmldoc_add_ref(xmlDocPtr doc
)
596 return xmldoc_add_refs(doc
, 1);
599 LONG
xmldoc_release_refs(xmlDocPtr doc
, LONG refs
)
601 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
602 LONG ref
= InterlockedExchangeAdd(&priv
->refs
, -refs
) - refs
;
603 TRACE("(%p)->(%d)\n", doc
, ref
);
606 WARN("negative refcount, expect troubles\n");
610 orphan_entry
*orphan
, *orphan2
;
611 TRACE("freeing docptr %p\n", doc
);
613 LIST_FOR_EACH_ENTRY_SAFE( orphan
, orphan2
, &priv
->orphans
, orphan_entry
, entry
)
615 xmlFreeNode( orphan
->node
);
618 free_properties(priv
->properties
);
619 heap_free(doc
->_private
);
627 LONG
xmldoc_release(xmlDocPtr doc
)
629 return xmldoc_release_refs(doc
, 1);
632 HRESULT
xmldoc_add_orphan(xmlDocPtr doc
, xmlNodePtr node
)
634 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
637 entry
= heap_alloc( sizeof (*entry
) );
639 return E_OUTOFMEMORY
;
642 list_add_head( &priv
->orphans
, &entry
->entry
);
646 HRESULT
xmldoc_remove_orphan(xmlDocPtr doc
, xmlNodePtr node
)
648 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
649 orphan_entry
*entry
, *entry2
;
651 LIST_FOR_EACH_ENTRY_SAFE( entry
, entry2
, &priv
->orphans
, orphan_entry
, entry
)
653 if( entry
->node
== node
)
655 list_remove( &entry
->entry
);
664 static inline xmlDocPtr
get_doc( domdoc
*This
)
666 return This
->node
.node
->doc
;
669 static HRESULT
attach_xmldoc(domdoc
*This
, xmlDocPtr xml
)
671 release_namespaces(This
);
675 priv_from_xmlDocPtr(get_doc(This
))->properties
= NULL
;
676 if (xmldoc_release(get_doc(This
)) != 0)
677 priv_from_xmlDocPtr(get_doc(This
))->properties
=
678 copy_properties(This
->properties
);
681 This
->node
.node
= (xmlNodePtr
) xml
;
685 xmldoc_add_ref(get_doc(This
));
686 priv_from_xmlDocPtr(get_doc(This
))->properties
= This
->properties
;
692 static inline domdoc
*impl_from_IXMLDOMDocument3( IXMLDOMDocument3
*iface
)
694 return CONTAINING_RECORD(iface
, domdoc
, IXMLDOMDocument3_iface
);
697 static inline domdoc
*impl_from_IPersistStreamInit(IPersistStreamInit
*iface
)
699 return CONTAINING_RECORD(iface
, domdoc
, IPersistStreamInit_iface
);
702 static inline domdoc
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
704 return CONTAINING_RECORD(iface
, domdoc
, IObjectWithSite_iface
);
707 static inline domdoc
*impl_from_IObjectSafety(IObjectSafety
*iface
)
709 return CONTAINING_RECORD(iface
, domdoc
, IObjectSafety_iface
);
712 static inline domdoc
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
714 return CONTAINING_RECORD(iface
, domdoc
, IConnectionPointContainer_iface
);
717 /************************************************************************
718 * domdoc implementation of IPersistStream.
720 static HRESULT WINAPI
PersistStreamInit_QueryInterface(
721 IPersistStreamInit
*iface
, REFIID riid
, void **ppvObj
)
723 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
724 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObj
);
727 static ULONG WINAPI
PersistStreamInit_AddRef(
728 IPersistStreamInit
*iface
)
730 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
731 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
734 static ULONG WINAPI
PersistStreamInit_Release(
735 IPersistStreamInit
*iface
)
737 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
738 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
741 static HRESULT WINAPI
PersistStreamInit_GetClassID(
742 IPersistStreamInit
*iface
, CLSID
*classid
)
744 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
745 TRACE("(%p)->(%p)\n", This
, classid
);
750 *classid
= *DOMDocument_version(This
->properties
->version
);
755 static HRESULT WINAPI
PersistStreamInit_IsDirty(
756 IPersistStreamInit
*iface
)
758 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
759 FIXME("(%p): stub!\n", This
);
763 static HRESULT
domdoc_load_from_stream(domdoc
*doc
, ISequentialStream
*stream
)
765 DWORD read
, written
, len
;
766 xmlDocPtr xmldoc
= NULL
;
774 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &hstream
);
780 ISequentialStream_Read(stream
, buf
, sizeof(buf
), &read
);
781 hr
= IStream_Write(hstream
, buf
, read
, &written
);
782 } while(SUCCEEDED(hr
) && written
!= 0 && read
!= 0);
786 ERR("failed to copy stream 0x%08x\n", hr
);
787 IStream_Release(hstream
);
791 hr
= GetHGlobalFromStream(hstream
, &hglobal
);
795 len
= GlobalSize(hglobal
);
796 ptr
= GlobalLock(hglobal
);
798 xmldoc
= doparse(doc
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
799 GlobalUnlock(hglobal
);
803 ERR("Failed to parse xml\n");
807 xmldoc
->_private
= create_priv();
809 return attach_xmldoc(doc
, xmldoc
);
812 static HRESULT WINAPI
PersistStreamInit_Load(IPersistStreamInit
*iface
, IStream
*stream
)
814 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
816 TRACE("(%p)->(%p)\n", This
, stream
);
821 return domdoc_load_from_stream(This
, (ISequentialStream
*)stream
);
824 static HRESULT WINAPI
PersistStreamInit_Save(
825 IPersistStreamInit
*iface
, IStream
*stream
, BOOL clr_dirty
)
827 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
831 TRACE("(%p)->(%p %d)\n", This
, stream
, clr_dirty
);
833 hr
= IXMLDOMDocument3_get_xml(&This
->IXMLDOMDocument3_iface
, &xmlString
);
836 DWORD len
= SysStringLen(xmlString
) * sizeof(WCHAR
);
838 hr
= IStream_Write( stream
, xmlString
, len
, NULL
);
839 SysFreeString(xmlString
);
842 TRACE("ret 0x%08x\n", hr
);
847 static HRESULT WINAPI
PersistStreamInit_GetSizeMax(
848 IPersistStreamInit
*iface
, ULARGE_INTEGER
*pcbSize
)
850 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
851 TRACE("(%p)->(%p)\n", This
, pcbSize
);
855 static HRESULT WINAPI
PersistStreamInit_InitNew(
856 IPersistStreamInit
*iface
)
858 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
859 TRACE("(%p)\n", This
);
863 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable
=
865 PersistStreamInit_QueryInterface
,
866 PersistStreamInit_AddRef
,
867 PersistStreamInit_Release
,
868 PersistStreamInit_GetClassID
,
869 PersistStreamInit_IsDirty
,
870 PersistStreamInit_Load
,
871 PersistStreamInit_Save
,
872 PersistStreamInit_GetSizeMax
,
873 PersistStreamInit_InitNew
876 /* IXMLDOMDocument3 interface */
878 static const tid_t domdoc_se_tids
[] = {
881 IXMLDOMDocument2_tid
,
882 IXMLDOMDocument3_tid
,
886 static HRESULT WINAPI
domdoc_QueryInterface( IXMLDOMDocument3
*iface
, REFIID riid
, void** ppvObject
)
888 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
890 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( riid
), ppvObject
);
894 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
895 IsEqualGUID( riid
, &IID_IDispatch
) ||
896 IsEqualGUID( riid
, &IID_IXMLDOMNode
) ||
897 IsEqualGUID( riid
, &IID_IXMLDOMDocument
) ||
898 IsEqualGUID( riid
, &IID_IXMLDOMDocument2
)||
899 IsEqualGUID( riid
, &IID_IXMLDOMDocument3
))
903 else if (IsEqualGUID(&IID_IPersistStream
, riid
) ||
904 IsEqualGUID(&IID_IPersistStreamInit
, riid
))
906 *ppvObject
= &This
->IPersistStreamInit_iface
;
908 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
910 *ppvObject
= &This
->IObjectWithSite_iface
;
912 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
914 *ppvObject
= &This
->IObjectSafety_iface
;
916 else if( IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
918 return node_create_supporterrorinfo(domdoc_se_tids
, ppvObject
);
920 else if(node_query_interface(&This
->node
, riid
, ppvObject
))
922 return *ppvObject
? S_OK
: E_NOINTERFACE
;
924 else if (IsEqualGUID( riid
, &IID_IConnectionPointContainer
))
926 *ppvObject
= &This
->IConnectionPointContainer_iface
;
930 TRACE("interface %s not implemented\n", debugstr_guid(riid
));
931 return E_NOINTERFACE
;
934 IUnknown_AddRef((IUnknown
*)*ppvObject
);
939 static ULONG WINAPI
domdoc_AddRef( IXMLDOMDocument3
*iface
)
941 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
942 ULONG ref
= InterlockedIncrement( &This
->ref
);
943 TRACE("(%p)->(%d)\n", This
, ref
);
947 static ULONG WINAPI
domdoc_Release( IXMLDOMDocument3
*iface
)
949 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
950 LONG ref
= InterlockedDecrement( &This
->ref
);
952 TRACE("(%p)->(%d)\n", This
, ref
);
959 IUnknown_Release( This
->site
);
960 destroy_xmlnode(&This
->node
);
962 for (eid
= 0; eid
< EVENTID_LAST
; eid
++)
963 if (This
->events
[eid
]) IDispatch_Release(This
->events
[eid
]);
965 release_namespaces(This
);
972 static HRESULT WINAPI
domdoc_GetTypeInfoCount( IXMLDOMDocument3
*iface
, UINT
* pctinfo
)
974 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
975 return IDispatchEx_GetTypeInfoCount(&This
->node
.dispex
.IDispatchEx_iface
, pctinfo
);
978 static HRESULT WINAPI
domdoc_GetTypeInfo(
979 IXMLDOMDocument3
*iface
,
980 UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
982 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
983 return IDispatchEx_GetTypeInfo(&This
->node
.dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
986 static HRESULT WINAPI
domdoc_GetIDsOfNames(
987 IXMLDOMDocument3
*iface
,
994 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
995 return IDispatchEx_GetIDsOfNames(&This
->node
.dispex
.IDispatchEx_iface
,
996 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
999 static HRESULT WINAPI
domdoc_Invoke(
1000 IXMLDOMDocument3
*iface
,
1001 DISPID dispIdMember
,
1005 DISPPARAMS
* pDispParams
,
1006 VARIANT
* pVarResult
,
1007 EXCEPINFO
* pExcepInfo
,
1010 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1011 return IDispatchEx_Invoke(&This
->node
.dispex
.IDispatchEx_iface
,
1012 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1015 static HRESULT WINAPI
domdoc_get_nodeName(
1016 IXMLDOMDocument3
*iface
,
1019 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1021 static const WCHAR documentW
[] = {'#','d','o','c','u','m','e','n','t',0};
1023 TRACE("(%p)->(%p)\n", This
, name
);
1025 return return_bstr(documentW
, name
);
1029 static HRESULT WINAPI
domdoc_get_nodeValue(
1030 IXMLDOMDocument3
*iface
,
1033 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1035 TRACE("(%p)->(%p)\n", This
, value
);
1038 return E_INVALIDARG
;
1040 V_VT(value
) = VT_NULL
;
1041 V_BSTR(value
) = NULL
; /* tests show that we should do this */
1046 static HRESULT WINAPI
domdoc_put_nodeValue(
1047 IXMLDOMDocument3
*iface
,
1050 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1051 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&value
));
1056 static HRESULT WINAPI
domdoc_get_nodeType(
1057 IXMLDOMDocument3
*iface
,
1060 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1062 TRACE("(%p)->(%p)\n", This
, type
);
1064 *type
= NODE_DOCUMENT
;
1069 static HRESULT WINAPI
domdoc_get_parentNode(
1070 IXMLDOMDocument3
*iface
,
1071 IXMLDOMNode
** parent
)
1073 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1075 TRACE("(%p)->(%p)\n", This
, parent
);
1077 return node_get_parent(&This
->node
, parent
);
1081 static HRESULT WINAPI
domdoc_get_childNodes(
1082 IXMLDOMDocument3
*iface
,
1083 IXMLDOMNodeList
** childList
)
1085 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1087 TRACE("(%p)->(%p)\n", This
, childList
);
1089 return node_get_child_nodes(&This
->node
, childList
);
1093 static HRESULT WINAPI
domdoc_get_firstChild(
1094 IXMLDOMDocument3
*iface
,
1095 IXMLDOMNode
** firstChild
)
1097 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1099 TRACE("(%p)->(%p)\n", This
, firstChild
);
1101 return node_get_first_child(&This
->node
, firstChild
);
1105 static HRESULT WINAPI
domdoc_get_lastChild(
1106 IXMLDOMDocument3
*iface
,
1107 IXMLDOMNode
** lastChild
)
1109 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1111 TRACE("(%p)->(%p)\n", This
, lastChild
);
1113 return node_get_last_child(&This
->node
, lastChild
);
1117 static HRESULT WINAPI
domdoc_get_previousSibling(
1118 IXMLDOMDocument3
*iface
,
1119 IXMLDOMNode
** previousSibling
)
1121 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1123 TRACE("(%p)->(%p)\n", This
, previousSibling
);
1125 return return_null_node(previousSibling
);
1129 static HRESULT WINAPI
domdoc_get_nextSibling(
1130 IXMLDOMDocument3
*iface
,
1131 IXMLDOMNode
** nextSibling
)
1133 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1135 TRACE("(%p)->(%p)\n", This
, nextSibling
);
1137 return return_null_node(nextSibling
);
1141 static HRESULT WINAPI
domdoc_get_attributes(
1142 IXMLDOMDocument3
*iface
,
1143 IXMLDOMNamedNodeMap
** attributeMap
)
1145 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1147 TRACE("(%p)->(%p)\n", This
, attributeMap
);
1149 return return_null_ptr((void**)attributeMap
);
1153 static HRESULT WINAPI
domdoc_insertBefore(
1154 IXMLDOMDocument3
*iface
,
1155 IXMLDOMNode
* newChild
,
1157 IXMLDOMNode
** outNewChild
)
1159 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1163 TRACE("(%p)->(%p %s %p)\n", This
, newChild
, debugstr_variant(&refChild
), outNewChild
);
1165 hr
= IXMLDOMNode_get_nodeType(newChild
, &type
);
1166 if (hr
!= S_OK
) return hr
;
1168 TRACE("new node type %d\n", type
);
1171 case NODE_ATTRIBUTE
:
1173 case NODE_CDATA_SECTION
:
1174 if (outNewChild
) *outNewChild
= NULL
;
1177 return node_insert_before(&This
->node
, newChild
, &refChild
, outNewChild
);
1181 static HRESULT WINAPI
domdoc_replaceChild(
1182 IXMLDOMDocument3
*iface
,
1183 IXMLDOMNode
* newChild
,
1184 IXMLDOMNode
* oldChild
,
1185 IXMLDOMNode
** outOldChild
)
1187 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1189 TRACE("(%p)->(%p %p %p)\n", This
, newChild
, oldChild
, outOldChild
);
1191 return node_replace_child(&This
->node
, newChild
, oldChild
, outOldChild
);
1195 static HRESULT WINAPI
domdoc_removeChild(
1196 IXMLDOMDocument3
*iface
,
1198 IXMLDOMNode
**oldChild
)
1200 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1201 TRACE("(%p)->(%p %p)\n", This
, child
, oldChild
);
1202 return node_remove_child(&This
->node
, child
, oldChild
);
1206 static HRESULT WINAPI
domdoc_appendChild(
1207 IXMLDOMDocument3
*iface
,
1209 IXMLDOMNode
**outChild
)
1211 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1212 TRACE("(%p)->(%p %p)\n", This
, child
, outChild
);
1213 return node_append_child(&This
->node
, child
, outChild
);
1217 static HRESULT WINAPI
domdoc_hasChildNodes(
1218 IXMLDOMDocument3
*iface
,
1221 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1222 TRACE("(%p)->(%p)\n", This
, ret
);
1223 return node_has_childnodes(&This
->node
, ret
);
1227 static HRESULT WINAPI
domdoc_get_ownerDocument(
1228 IXMLDOMDocument3
*iface
,
1229 IXMLDOMDocument
**doc
)
1231 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1232 TRACE("(%p)->(%p)\n", This
, doc
);
1233 return node_get_owner_doc(&This
->node
, doc
);
1237 static HRESULT WINAPI
domdoc_cloneNode(
1238 IXMLDOMDocument3
*iface
,
1240 IXMLDOMNode
** outNode
)
1242 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1245 TRACE("(%p)->(%d %p)\n", This
, deep
, outNode
);
1248 return E_INVALIDARG
;
1252 clone
= xmlCopyNode((xmlNodePtr
)get_doc(This
), deep
? 1 : 2);
1256 clone
->doc
->_private
= create_priv();
1257 xmldoc_add_orphan(clone
->doc
, clone
);
1258 xmldoc_add_ref(clone
->doc
);
1260 priv_from_xmlDocPtr(clone
->doc
)->properties
= copy_properties(This
->properties
);
1261 if (!(*outNode
= (IXMLDOMNode
*)create_domdoc(clone
)))
1263 xmldoc_release(clone
->doc
);
1271 static HRESULT WINAPI
domdoc_get_nodeTypeString(
1272 IXMLDOMDocument3
*iface
,
1275 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1276 static const WCHAR documentW
[] = {'d','o','c','u','m','e','n','t',0};
1278 TRACE("(%p)->(%p)\n", This
, p
);
1280 return return_bstr(documentW
, p
);
1284 static HRESULT WINAPI
domdoc_get_text(
1285 IXMLDOMDocument3
*iface
,
1288 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1289 TRACE("(%p)->(%p)\n", This
, p
);
1290 return node_get_text(&This
->node
, p
);
1294 static HRESULT WINAPI
domdoc_put_text(
1295 IXMLDOMDocument3
*iface
,
1298 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1299 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
1304 static HRESULT WINAPI
domdoc_get_specified(
1305 IXMLDOMDocument3
*iface
,
1306 VARIANT_BOOL
* isSpecified
)
1308 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1309 FIXME("(%p)->(%p) stub!\n", This
, isSpecified
);
1310 *isSpecified
= VARIANT_TRUE
;
1315 static HRESULT WINAPI
domdoc_get_definition(
1316 IXMLDOMDocument3
*iface
,
1317 IXMLDOMNode
** definitionNode
)
1319 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1320 FIXME("(%p)->(%p)\n", This
, definitionNode
);
1325 static HRESULT WINAPI
domdoc_get_nodeTypedValue(
1326 IXMLDOMDocument3
*iface
,
1329 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1330 TRACE("(%p)->(%p)\n", This
, v
);
1331 return return_null_var(v
);
1334 static HRESULT WINAPI
domdoc_put_nodeTypedValue(
1335 IXMLDOMDocument3
*iface
,
1336 VARIANT typedValue
)
1338 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1339 FIXME("(%p)->(%s)\n", This
, debugstr_variant(&typedValue
));
1344 static HRESULT WINAPI
domdoc_get_dataType(
1345 IXMLDOMDocument3
*iface
,
1348 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1349 TRACE("(%p)->(%p)\n", This
, typename
);
1350 return return_null_var( typename
);
1354 static HRESULT WINAPI
domdoc_put_dataType(
1355 IXMLDOMDocument3
*iface
,
1358 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1360 FIXME("(%p)->(%s)\n", This
, debugstr_w(dataTypeName
));
1363 return E_INVALIDARG
;
1368 static int XMLCALL
domdoc_get_xml_writecallback(void *ctx
, const char *data
, int len
)
1370 return xmlBufferAdd((xmlBufferPtr
)ctx
, (xmlChar
*)data
, len
) == 0 ? len
: 0;
1373 static HRESULT WINAPI
domdoc_get_xml(
1374 IXMLDOMDocument3
*iface
,
1377 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1378 xmlSaveCtxtPtr ctxt
;
1383 TRACE("(%p)->(%p)\n", This
, p
);
1386 return E_INVALIDARG
;
1390 buf
= xmlBufferCreate();
1392 return E_OUTOFMEMORY
;
1394 options
= XML_SAVE_FORMAT
| XML_SAVE_NO_DECL
;
1395 ctxt
= xmlSaveToIO(domdoc_get_xml_writecallback
, NULL
, buf
, "UTF-8", options
);
1400 return E_OUTOFMEMORY
;
1403 ret
= xmlSaveDoc(ctxt
, get_doc(This
));
1404 /* flushes on close */
1407 TRACE("%ld, len=%d\n", ret
, xmlBufferLength(buf
));
1408 if(ret
!= -1 && xmlBufferLength(buf
) > 0)
1412 content
= bstr_from_xmlChar(xmlBufferContent(buf
));
1413 content
= EnsureCorrectEOL(content
);
1419 *p
= SysAllocStringLen(NULL
, 0);
1424 return *p
? S_OK
: E_OUTOFMEMORY
;
1428 static HRESULT WINAPI
domdoc_transformNode(
1429 IXMLDOMDocument3
*iface
,
1433 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1434 TRACE("(%p)->(%p %p)\n", This
, node
, p
);
1435 return node_transform_node(&This
->node
, node
, p
);
1439 static HRESULT WINAPI
domdoc_selectNodes(
1440 IXMLDOMDocument3
*iface
,
1442 IXMLDOMNodeList
**outList
)
1444 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1445 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outList
);
1446 return node_select_nodes(&This
->node
, p
, outList
);
1450 static HRESULT WINAPI
domdoc_selectSingleNode(
1451 IXMLDOMDocument3
*iface
,
1453 IXMLDOMNode
**outNode
)
1455 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1456 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outNode
);
1457 return node_select_singlenode(&This
->node
, p
, outNode
);
1461 static HRESULT WINAPI
domdoc_get_parsed(
1462 IXMLDOMDocument3
*iface
,
1463 VARIANT_BOOL
* isParsed
)
1465 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1466 FIXME("(%p)->(%p) stub!\n", This
, isParsed
);
1467 *isParsed
= VARIANT_TRUE
;
1471 static HRESULT WINAPI
domdoc_get_namespaceURI(
1472 IXMLDOMDocument3
*iface
,
1473 BSTR
* namespaceURI
)
1475 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1476 TRACE("(%p)->(%p)\n", This
, namespaceURI
);
1477 return return_null_bstr( namespaceURI
);
1480 static HRESULT WINAPI
domdoc_get_prefix(
1481 IXMLDOMDocument3
*iface
,
1484 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1485 TRACE("(%p)->(%p)\n", This
, prefix
);
1486 return return_null_bstr( prefix
);
1490 static HRESULT WINAPI
domdoc_get_baseName(
1491 IXMLDOMDocument3
*iface
,
1494 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1495 TRACE("(%p)->(%p)\n", This
, name
);
1496 return return_null_bstr( name
);
1500 static HRESULT WINAPI
domdoc_transformNodeToObject(
1501 IXMLDOMDocument3
*iface
,
1502 IXMLDOMNode
* stylesheet
,
1505 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1507 TRACE("(%p)->(%p %s)\n", This
, stylesheet
, debugstr_variant(&output
));
1509 switch (V_VT(&output
))
1514 IXMLDOMDocument
*doc
;
1517 if (!V_UNKNOWN(&output
))
1518 return E_INVALIDARG
;
1520 /* FIXME: we're not supposed to query for document interface, should use IStream
1521 which we don't support currently. */
1522 if (IUnknown_QueryInterface(V_UNKNOWN(&output
), &IID_IXMLDOMDocument
, (void **)&doc
) == S_OK
)
1527 if (FAILED(hr
= node_transform_node(&This
->node
, stylesheet
, &str
)))
1530 hr
= IXMLDOMDocument_loadXML(doc
, str
, &b
);
1536 FIXME("Unsupported destination type.\n");
1537 return E_INVALIDARG
;
1541 FIXME("Output type %d not handled.\n", V_VT(&output
));
1549 static HRESULT WINAPI
domdoc_get_doctype(
1550 IXMLDOMDocument3
*iface
,
1551 IXMLDOMDocumentType
** doctype
)
1553 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1558 TRACE("(%p)->(%p)\n", This
, doctype
);
1560 if (!doctype
) return E_INVALIDARG
;
1564 dtd
= xmlGetIntSubset(get_doc(This
));
1565 if (!dtd
) return S_FALSE
;
1567 node
= create_node((xmlNodePtr
)dtd
);
1568 if (!node
) return S_FALSE
;
1570 hr
= IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentType
, (void**)doctype
);
1571 IXMLDOMNode_Release(node
);
1577 static HRESULT WINAPI
domdoc_get_implementation(
1578 IXMLDOMDocument3
*iface
,
1579 IXMLDOMImplementation
** impl
)
1581 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1583 TRACE("(%p)->(%p)\n", This
, impl
);
1586 return E_INVALIDARG
;
1588 *impl
= (IXMLDOMImplementation
*)create_doc_Implementation();
1593 static HRESULT WINAPI
domdoc_get_documentElement(
1594 IXMLDOMDocument3
*iface
,
1595 IXMLDOMElement
** DOMElement
)
1597 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1598 IXMLDOMNode
*element_node
;
1602 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1605 return E_INVALIDARG
;
1609 root
= xmlDocGetRootElement( get_doc(This
) );
1613 element_node
= create_node( root
);
1614 if(!element_node
) return S_FALSE
;
1616 hr
= IXMLDOMNode_QueryInterface(element_node
, &IID_IXMLDOMElement
, (void**)DOMElement
);
1617 IXMLDOMNode_Release(element_node
);
1623 static HRESULT WINAPI
domdoc_put_documentElement(
1624 IXMLDOMDocument3
*iface
,
1625 IXMLDOMElement
* DOMElement
)
1627 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1628 IXMLDOMNode
*elementNode
;
1635 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1637 hr
= IXMLDOMElement_QueryInterface( DOMElement
, &IID_IXMLDOMNode
, (void**)&elementNode
);
1641 xmlNode
= get_node_obj( elementNode
);
1642 if(!xmlNode
) return E_FAIL
;
1644 if(!xmlNode
->node
->parent
)
1645 if(xmldoc_remove_orphan(xmlNode
->node
->doc
, xmlNode
->node
) != S_OK
)
1646 WARN("%p is not an orphan of %p\n", xmlNode
->node
->doc
, xmlNode
->node
);
1648 old_doc
= xmlNode
->node
->doc
;
1649 if (old_doc
!= get_doc(This
))
1650 refcount
= xmlnode_get_inst_cnt(xmlNode
);
1652 /* old root is still orphaned by its document, update refcount from new root */
1653 if (refcount
) xmldoc_add_refs(get_doc(This
), refcount
);
1654 oldRoot
= xmlDocSetRootElement( get_doc(This
), xmlNode
->node
);
1655 if (refcount
) xmldoc_release_refs(old_doc
, refcount
);
1656 IXMLDOMNode_Release( elementNode
);
1659 xmldoc_add_orphan(oldRoot
->doc
, oldRoot
);
1665 static HRESULT WINAPI
domdoc_createElement(
1666 IXMLDOMDocument3
*iface
,
1668 IXMLDOMElement
** element
)
1670 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1675 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(tagname
), element
);
1677 if (!element
|| !tagname
) return E_INVALIDARG
;
1679 V_VT(&type
) = VT_I1
;
1680 V_I1(&type
) = NODE_ELEMENT
;
1682 hr
= IXMLDOMDocument3_createNode(iface
, type
, tagname
, NULL
, &node
);
1685 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMElement
, (void**)element
);
1686 IXMLDOMNode_Release(node
);
1693 static HRESULT WINAPI
domdoc_createDocumentFragment(
1694 IXMLDOMDocument3
*iface
,
1695 IXMLDOMDocumentFragment
** frag
)
1697 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1702 TRACE("(%p)->(%p)\n", This
, frag
);
1704 if (!frag
) return E_INVALIDARG
;
1708 V_VT(&type
) = VT_I1
;
1709 V_I1(&type
) = NODE_DOCUMENT_FRAGMENT
;
1711 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1714 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentFragment
, (void**)frag
);
1715 IXMLDOMNode_Release(node
);
1722 static HRESULT WINAPI
domdoc_createTextNode(
1723 IXMLDOMDocument3
*iface
,
1725 IXMLDOMText
** text
)
1727 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1732 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), text
);
1734 if (!text
) return E_INVALIDARG
;
1738 V_VT(&type
) = VT_I1
;
1739 V_I1(&type
) = NODE_TEXT
;
1741 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1744 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMText
, (void**)text
);
1745 IXMLDOMNode_Release(node
);
1746 hr
= IXMLDOMText_put_data(*text
, data
);
1753 static HRESULT WINAPI
domdoc_createComment(
1754 IXMLDOMDocument3
*iface
,
1756 IXMLDOMComment
** comment
)
1758 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1763 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), comment
);
1765 if (!comment
) return E_INVALIDARG
;
1769 V_VT(&type
) = VT_I1
;
1770 V_I1(&type
) = NODE_COMMENT
;
1772 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1775 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMComment
, (void**)comment
);
1776 IXMLDOMNode_Release(node
);
1777 hr
= IXMLDOMComment_put_data(*comment
, data
);
1784 static HRESULT WINAPI
domdoc_createCDATASection(
1785 IXMLDOMDocument3
*iface
,
1787 IXMLDOMCDATASection
** cdata
)
1789 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1794 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), cdata
);
1796 if (!cdata
) return E_INVALIDARG
;
1800 V_VT(&type
) = VT_I1
;
1801 V_I1(&type
) = NODE_CDATA_SECTION
;
1803 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1806 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMCDATASection
, (void**)cdata
);
1807 IXMLDOMNode_Release(node
);
1808 hr
= IXMLDOMCDATASection_put_data(*cdata
, data
);
1815 static HRESULT WINAPI
domdoc_createProcessingInstruction(
1816 IXMLDOMDocument3
*iface
,
1819 IXMLDOMProcessingInstruction
** pi
)
1821 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1826 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_w(target
), debugstr_w(data
), pi
);
1828 if (!pi
) return E_INVALIDARG
;
1832 V_VT(&type
) = VT_I1
;
1833 V_I1(&type
) = NODE_PROCESSING_INSTRUCTION
;
1835 hr
= IXMLDOMDocument3_createNode(iface
, type
, target
, NULL
, &node
);
1840 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1841 node_obj
= get_node_obj(node
);
1842 hr
= node_set_content(node_obj
, data
);
1844 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMProcessingInstruction
, (void**)pi
);
1845 IXMLDOMNode_Release(node
);
1852 static HRESULT WINAPI
domdoc_createAttribute(
1853 IXMLDOMDocument3
*iface
,
1855 IXMLDOMAttribute
** attribute
)
1857 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1862 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), attribute
);
1864 if (!attribute
|| !name
) return E_INVALIDARG
;
1866 V_VT(&type
) = VT_I1
;
1867 V_I1(&type
) = NODE_ATTRIBUTE
;
1869 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1872 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMAttribute
, (void**)attribute
);
1873 IXMLDOMNode_Release(node
);
1880 static HRESULT WINAPI
domdoc_createEntityReference(
1881 IXMLDOMDocument3
*iface
,
1883 IXMLDOMEntityReference
** entityref
)
1885 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1890 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), entityref
);
1892 if (!entityref
) return E_INVALIDARG
;
1896 V_VT(&type
) = VT_I1
;
1897 V_I1(&type
) = NODE_ENTITY_REFERENCE
;
1899 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1902 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMEntityReference
, (void**)entityref
);
1903 IXMLDOMNode_Release(node
);
1909 xmlChar
* tagName_to_XPath(const BSTR tagName
)
1911 xmlChar
*query
, *tmp
;
1912 static const xmlChar everything
[] = "/descendant::node()";
1913 static const xmlChar mod_pre
[] = "*[local-name()='";
1914 static const xmlChar mod_post
[] = "']";
1915 static const xmlChar prefix
[] = "descendant::";
1916 const WCHAR
*tokBegin
, *tokEnd
;
1919 /* Special case - empty tagname - means select all nodes,
1920 except document itself. */
1922 return xmlStrdup(everything
);
1924 query
= xmlStrdup(prefix
);
1927 while (tokBegin
&& *tokBegin
)
1932 query
= xmlStrcat(query
, BAD_CAST
"/");
1936 query
= xmlStrcat(query
, BAD_CAST
"*");
1940 query
= xmlStrcat(query
, mod_pre
);
1942 while (*tokEnd
&& *tokEnd
!= '/')
1944 len
= WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, NULL
, 0, NULL
, NULL
);
1945 tmp
= xmlMalloc(len
);
1946 WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, (char*)tmp
, len
, NULL
, NULL
);
1947 query
= xmlStrncat(query
, tmp
, len
);
1950 query
= xmlStrcat(query
, mod_post
);
1957 static HRESULT WINAPI
domdoc_getElementsByTagName(
1958 IXMLDOMDocument3
*iface
,
1960 IXMLDOMNodeList
** resultList
)
1962 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1967 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(tagName
), resultList
);
1969 if (!tagName
|| !resultList
) return E_INVALIDARG
;
1971 XPath
= This
->properties
->XPath
;
1972 This
->properties
->XPath
= TRUE
;
1973 query
= tagName_to_XPath(tagName
);
1974 hr
= create_selection((xmlNodePtr
)get_doc(This
), query
, resultList
);
1976 This
->properties
->XPath
= XPath
;
1981 static HRESULT
get_node_type(VARIANT Type
, DOMNodeType
* type
)
1987 hr
= VariantChangeType(&tmp
, &Type
, 0, VT_I4
);
1989 return E_INVALIDARG
;
1996 static HRESULT WINAPI
domdoc_createNode(
1997 IXMLDOMDocument3
*iface
,
2001 IXMLDOMNode
** node
)
2003 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2004 DOMNodeType node_type
;
2006 xmlChar
*xml_name
, *href
;
2009 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_variant(&Type
), debugstr_w(name
), debugstr_w(namespaceURI
), node
);
2011 if(!node
) return E_INVALIDARG
;
2013 hr
= get_node_type(Type
, &node_type
);
2014 if(FAILED(hr
)) return hr
;
2016 TRACE("node_type %d\n", node_type
);
2018 /* exit earlier for types that need name */
2022 case NODE_ATTRIBUTE
:
2023 case NODE_ENTITY_REFERENCE
:
2024 case NODE_PROCESSING_INSTRUCTION
:
2025 if (!name
|| *name
== 0) return E_FAIL
;
2031 xml_name
= xmlchar_from_wchar(name
);
2032 /* prevent empty href from being allocated */
2033 href
= namespaceURI
? xmlchar_from_wchar(namespaceURI
) : NULL
;
2039 xmlChar
*local
, *prefix
;
2041 local
= xmlSplitQName2(xml_name
, &prefix
);
2043 xmlnode
= xmlNewDocNode(get_doc(This
), NULL
, local
? local
: xml_name
, NULL
);
2045 /* allow creating the default namespace xmlns= */
2046 if (local
|| (href
&& *href
))
2048 xmlNsPtr ns
= xmlNewNs(xmlnode
, href
, prefix
);
2049 xmlSetNs(xmlnode
, ns
);
2057 case NODE_ATTRIBUTE
:
2059 xmlChar
*local
, *prefix
;
2061 local
= xmlSplitQName2(xml_name
, &prefix
);
2063 xmlnode
= (xmlNodePtr
)xmlNewDocProp(get_doc(This
), local
? local
: xml_name
, NULL
);
2065 if (local
|| (href
&& *href
))
2067 /* we need a floating namespace here, it can't be created linked to attribute from
2069 xmlNsPtr ns
= xmlNewNs(NULL
, href
, prefix
);
2070 xmlSetNs(xmlnode
, ns
);
2079 xmlnode
= (xmlNodePtr
)xmlNewDocText(get_doc(This
), NULL
);
2081 case NODE_CDATA_SECTION
:
2082 xmlnode
= xmlNewCDataBlock(get_doc(This
), NULL
, 0);
2084 case NODE_ENTITY_REFERENCE
:
2085 xmlnode
= xmlNewReference(get_doc(This
), xml_name
);
2087 case NODE_PROCESSING_INSTRUCTION
:
2088 #ifdef HAVE_XMLNEWDOCPI
2089 xmlnode
= xmlNewDocPI(get_doc(This
), xml_name
, NULL
);
2091 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2096 xmlnode
= xmlNewDocComment(get_doc(This
), NULL
);
2098 case NODE_DOCUMENT_FRAGMENT
:
2099 xmlnode
= xmlNewDocFragment(get_doc(This
));
2101 /* unsupported types */
2103 case NODE_DOCUMENT_TYPE
:
2106 heap_free(xml_name
);
2107 return E_INVALIDARG
;
2109 FIXME("unhandled node type %d\n", node_type
);
2114 *node
= create_node(xmlnode
);
2115 heap_free(xml_name
);
2120 TRACE("created node (%d, %p, %p)\n", node_type
, *node
, xmlnode
);
2121 xmldoc_add_orphan(xmlnode
->doc
, xmlnode
);
2128 static HRESULT WINAPI
domdoc_nodeFromID(
2129 IXMLDOMDocument3
*iface
,
2131 IXMLDOMNode
** node
)
2133 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2134 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(idString
), node
);
2138 static HRESULT
domdoc_onDataAvailable(void *obj
, char *ptr
, DWORD len
)
2143 xmldoc
= doparse(This
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
2145 xmldoc
->_private
= create_priv();
2146 return attach_xmldoc(This
, xmldoc
);
2152 static HRESULT
domdoc_load_moniker(domdoc
*This
, IMoniker
*mon
)
2157 hr
= bind_url(mon
, domdoc_onDataAvailable
, This
, &bsc
);
2161 return detach_bsc(bsc
);
2164 static HRESULT WINAPI
domdoc_load(
2165 IXMLDOMDocument3
*iface
,
2167 VARIANT_BOOL
* isSuccessful
)
2169 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2170 LPWSTR filename
= NULL
;
2171 HRESULT hr
= S_FALSE
;
2174 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&source
));
2178 *isSuccessful
= VARIANT_FALSE
;
2180 assert( &This
->node
);
2182 switch( V_VT(&source
) )
2185 filename
= V_BSTR(&source
);
2187 case VT_BSTR
|VT_BYREF
:
2188 if (!V_BSTRREF(&source
)) return E_INVALIDARG
;
2189 filename
= *V_BSTRREF(&source
);
2191 case VT_ARRAY
|VT_UI1
:
2193 SAFEARRAY
*psa
= V_ARRAY(&source
);
2196 UINT dim
= SafeArrayGetDim(psa
);
2201 ERR("SAFEARRAY == NULL\n");
2202 hr
= This
->error
= E_INVALIDARG
;
2205 /* Only takes UTF-8 strings.
2206 * NOT NULL-terminated. */
2207 hr
= SafeArrayAccessData(psa
, (void**)&str
);
2211 WARN("failed to access array data, 0x%08x\n", hr
);
2214 SafeArrayGetUBound(psa
, 1, &len
);
2216 if ((xmldoc
= doparse(This
, str
, ++len
, XML_CHAR_ENCODING_UTF8
)))
2218 hr
= This
->error
= S_OK
;
2219 *isSuccessful
= VARIANT_TRUE
;
2220 TRACE("parsed document %p\n", xmldoc
);
2224 This
->error
= E_FAIL
;
2225 TRACE("failed to parse document\n");
2228 SafeArrayUnaccessData(psa
);
2232 xmldoc
->_private
= create_priv();
2233 return attach_xmldoc(This
, xmldoc
);
2237 FIXME("unhandled SAFEARRAY dim: %d\n", dim
);
2238 hr
= This
->error
= E_NOTIMPL
;
2244 ISequentialStream
*stream
= NULL
;
2245 IXMLDOMDocument3
*newdoc
= NULL
;
2247 if (!V_UNKNOWN(&source
)) return E_INVALIDARG
;
2249 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IXMLDOMDocument3
, (void**)&newdoc
);
2254 domdoc
*newDoc
= impl_from_IXMLDOMDocument3( newdoc
);
2256 xmldoc
= xmlCopyDoc(get_doc(newDoc
), 1);
2257 xmldoc
->_private
= create_priv();
2258 hr
= attach_xmldoc(This
, xmldoc
);
2261 *isSuccessful
= VARIANT_TRUE
;
2267 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IStream
, (void**)&stream
);
2269 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_ISequentialStream
, (void**)&stream
);
2273 hr
= domdoc_load_from_stream(This
, stream
);
2275 *isSuccessful
= VARIANT_TRUE
;
2276 ISequentialStream_Release(stream
);
2280 FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr
, V_UNKNOWN(&source
)->lpVtbl
);
2284 FIXME("VT type not supported (%d)\n", V_VT(&source
));
2292 if (This
->properties
->uri
)
2294 IUri_Release(This
->properties
->uri
);
2295 This
->properties
->uri
= NULL
;
2298 hr
= create_uri(filename
, &uri
);
2300 hr
= CreateURLMonikerEx2(NULL
, uri
, &mon
, 0);
2301 if ( SUCCEEDED(hr
) )
2303 hr
= domdoc_load_moniker( This
, mon
);
2304 IMoniker_Release(mon
);
2308 This
->error
= E_FAIL
;
2311 get_doc(This
)->name
= (char *)xmlchar_from_wcharn(filename
, -1, TRUE
);
2312 This
->properties
->uri
= uri
;
2313 hr
= This
->error
= S_OK
;
2314 *isSuccessful
= VARIANT_TRUE
;
2318 if(!filename
|| FAILED(hr
)) {
2319 xmldoc
= xmlNewDoc(NULL
);
2320 xmldoc
->_private
= create_priv();
2321 hr
= attach_xmldoc(This
, xmldoc
);
2326 TRACE("ret (%d)\n", hr
);
2332 static HRESULT WINAPI
domdoc_get_readyState(
2333 IXMLDOMDocument3
*iface
,
2336 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2337 FIXME("stub! (%p)->(%p)\n", This
, value
);
2340 return E_INVALIDARG
;
2342 *value
= READYSTATE_COMPLETE
;
2347 static HRESULT WINAPI
domdoc_get_parseError(
2348 IXMLDOMDocument3
*iface
,
2349 IXMLDOMParseError
** errorObj
)
2351 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2352 static const WCHAR err
[] = {'e','r','r','o','r',0};
2353 BSTR error_string
= NULL
;
2355 FIXME("(%p)->(%p): creating a dummy parseError\n", iface
, errorObj
);
2358 error_string
= SysAllocString(err
);
2360 *errorObj
= create_parseError(This
->error
, NULL
, error_string
, NULL
, 0, 0, 0);
2361 if(!*errorObj
) return E_OUTOFMEMORY
;
2366 static HRESULT WINAPI
domdoc_get_url(
2367 IXMLDOMDocument3
*iface
,
2370 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2372 TRACE("(%p)->(%p)\n", This
, url
);
2375 return E_INVALIDARG
;
2377 if (!This
->properties
->uri
)
2378 return return_null_bstr(url
);
2380 return IUri_GetPropertyBSTR(This
->properties
->uri
, Uri_PROPERTY_DISPLAY_URI
, url
, 0);
2384 static HRESULT WINAPI
domdoc_get_async(
2385 IXMLDOMDocument3
*iface
,
2386 VARIANT_BOOL
* isAsync
)
2388 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2390 TRACE("(%p)->(%p: %d)\n", This
, isAsync
, This
->async
);
2391 *isAsync
= This
->async
;
2396 static HRESULT WINAPI
domdoc_put_async(
2397 IXMLDOMDocument3
*iface
,
2398 VARIANT_BOOL isAsync
)
2400 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2402 TRACE("(%p)->(%d)\n", This
, isAsync
);
2403 This
->async
= isAsync
;
2408 static HRESULT WINAPI
domdoc_abort(
2409 IXMLDOMDocument3
*iface
)
2411 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2412 FIXME("%p\n", This
);
2416 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2417 static HRESULT WINAPI
domdoc_loadXML(
2418 IXMLDOMDocument3
*iface
,
2420 VARIANT_BOOL
* isSuccessful
)
2422 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2423 xmlDocPtr xmldoc
= NULL
;
2424 HRESULT hr
= S_FALSE
, hr2
;
2426 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), isSuccessful
);
2428 assert ( &This
->node
);
2432 *isSuccessful
= VARIANT_FALSE
;
2438 /* skip leading spaces if needed */
2439 if (This
->properties
->version
== MSXML_DEFAULT
|| This
->properties
->version
== MSXML26
)
2440 while (*ptr
&& isspaceW(*ptr
)) ptr
++;
2442 xmldoc
= doparse(This
, (char*)ptr
, strlenW(ptr
)*sizeof(WCHAR
), XML_CHAR_ENCODING_UTF16LE
);
2445 This
->error
= E_FAIL
;
2446 TRACE("failed to parse document\n");
2450 hr
= This
->error
= S_OK
;
2451 *isSuccessful
= VARIANT_TRUE
;
2452 TRACE("parsed document %p\n", xmldoc
);
2458 xmldoc
= xmlNewDoc(NULL
);
2459 xmldoc
->_private
= create_priv();
2460 hr2
= attach_xmldoc(This
, xmldoc
);
2467 static int XMLCALL
domdoc_save_writecallback(void *ctx
, const char *buffer
, int len
)
2471 if(!WriteFile(ctx
, buffer
, len
, &written
, NULL
))
2473 WARN("write error\n");
2480 static int XMLCALL
domdoc_save_closecallback(void *ctx
)
2482 return CloseHandle(ctx
) ? 0 : -1;
2485 static int XMLCALL
domdoc_stream_save_writecallback(void *ctx
, const char *buffer
, int len
)
2490 hr
= IStream_Write((IStream
*)ctx
, buffer
, len
, &written
);
2491 TRACE("0x%08x %p %d %u\n", hr
, buffer
, len
, written
);
2494 WARN("stream write error: 0x%08x\n", hr
);
2501 static int XMLCALL
domdoc_stream_save_closecallback(void *ctx
)
2503 IStream_Release((IStream
*)ctx
);
2507 static HRESULT WINAPI
domdoc_save(
2508 IXMLDOMDocument3
*iface
,
2509 VARIANT destination
)
2511 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2512 xmlSaveCtxtPtr ctx
= NULL
;
2516 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&destination
));
2518 switch (V_VT(&destination
))
2522 IUnknown
*pUnk
= V_UNKNOWN(&destination
);
2523 IXMLDOMDocument3
*document
;
2526 ret
= IUnknown_QueryInterface(pUnk
, &IID_IXMLDOMDocument3
, (void**)&document
);
2529 VARIANT_BOOL success
;
2532 ret
= IXMLDOMDocument3_get_xml(iface
, &xml
);
2535 ret
= IXMLDOMDocument3_loadXML(document
, xml
, &success
);
2539 IXMLDOMDocument3_Release(document
);
2543 ret
= IUnknown_QueryInterface(pUnk
, &IID_IStream
, (void**)&stream
);
2546 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2547 ctx
= xmlSaveToIO(domdoc_stream_save_writecallback
,
2548 domdoc_stream_save_closecallback
, stream
, NULL
, options
);
2552 IStream_Release(stream
);
2560 case VT_BSTR
| VT_BYREF
:
2562 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2564 /* save with file path */
2565 HANDLE handle
= CreateFileW( (V_VT(&destination
) & VT_BYREF
)? *V_BSTRREF(&destination
) : V_BSTR(&destination
),
2566 GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2567 if( handle
== INVALID_HANDLE_VALUE
)
2569 WARN("failed to create file\n");
2573 /* disable top XML declaration */
2574 ctx
= xmlSaveToIO(domdoc_save_writecallback
, domdoc_save_closecallback
,
2575 handle
, NULL
, options
);
2578 CloseHandle(handle
);
2585 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination
));
2589 xmldecl
= xmldoc_unlink_xmldecl(get_doc(This
));
2590 if (xmlSaveDoc(ctx
, get_doc(This
)) == -1) ret
= S_FALSE
;
2591 xmldoc_link_xmldecl(get_doc(This
), xmldecl
);
2593 /* will release resources through close callback */
2599 static HRESULT WINAPI
domdoc_get_validateOnParse(
2600 IXMLDOMDocument3
*iface
,
2601 VARIANT_BOOL
* isValidating
)
2603 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2604 TRACE("(%p)->(%p: %d)\n", This
, isValidating
, This
->validating
);
2605 *isValidating
= This
->validating
;
2610 static HRESULT WINAPI
domdoc_put_validateOnParse(
2611 IXMLDOMDocument3
*iface
,
2612 VARIANT_BOOL isValidating
)
2614 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2615 TRACE("(%p)->(%d)\n", This
, isValidating
);
2616 This
->validating
= isValidating
;
2621 static HRESULT WINAPI
domdoc_get_resolveExternals(
2622 IXMLDOMDocument3
*iface
,
2623 VARIANT_BOOL
* isResolving
)
2625 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2626 TRACE("(%p)->(%p: %d)\n", This
, isResolving
, This
->resolving
);
2627 *isResolving
= This
->resolving
;
2632 static HRESULT WINAPI
domdoc_put_resolveExternals(
2633 IXMLDOMDocument3
*iface
,
2634 VARIANT_BOOL isResolving
)
2636 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2637 TRACE("(%p)->(%d)\n", This
, isResolving
);
2638 This
->resolving
= isResolving
;
2643 static HRESULT WINAPI
domdoc_get_preserveWhiteSpace(
2644 IXMLDOMDocument3
*iface
,
2645 VARIANT_BOOL
* isPreserving
)
2647 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2648 TRACE("(%p)->(%p: %d)\n", This
, isPreserving
, This
->properties
->preserving
);
2649 *isPreserving
= This
->properties
->preserving
;
2654 static HRESULT WINAPI
domdoc_put_preserveWhiteSpace(
2655 IXMLDOMDocument3
*iface
,
2656 VARIANT_BOOL isPreserving
)
2658 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2659 TRACE("(%p)->(%d)\n", This
, isPreserving
);
2660 This
->properties
->preserving
= isPreserving
;
2665 static HRESULT WINAPI
domdoc_put_onreadystatechange(
2666 IXMLDOMDocument3
*iface
,
2669 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2671 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&event
));
2672 return set_doc_event(This
, EVENTID_READYSTATECHANGE
, &event
);
2676 static HRESULT WINAPI
domdoc_put_onDataAvailable(IXMLDOMDocument3
*iface
, VARIANT sink
)
2678 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2679 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2683 static HRESULT WINAPI
domdoc_put_onTransformNode(IXMLDOMDocument3
*iface
, VARIANT sink
)
2685 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2686 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2690 static HRESULT WINAPI
domdoc_get_namespaces(
2691 IXMLDOMDocument3
* iface
,
2692 IXMLDOMSchemaCollection
** collection
)
2694 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2697 FIXME("(%p)->(%p): semi-stub\n", This
, collection
);
2699 if (!collection
) return E_POINTER
;
2701 if (!This
->namespaces
)
2703 hr
= SchemaCache_create(This
->properties
->version
, (void**)&This
->namespaces
);
2704 if (hr
!= S_OK
) return hr
;
2706 hr
= cache_from_doc_ns(This
->namespaces
, &This
->node
);
2708 release_namespaces(This
);
2711 if (This
->namespaces
)
2712 return IXMLDOMSchemaCollection2_QueryInterface(This
->namespaces
,
2713 &IID_IXMLDOMSchemaCollection
, (void**)collection
);
2718 static HRESULT WINAPI
domdoc_get_schemas(
2719 IXMLDOMDocument3
* iface
,
2722 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2723 IXMLDOMSchemaCollection2
* cur_schema
= This
->properties
->schemaCache
;
2724 HRESULT hr
= S_FALSE
;
2726 TRACE("(%p)->(%p)\n", This
, schema
);
2728 V_VT(schema
) = VT_NULL
;
2729 /* just to reset pointer part, cause that's what application is expected to use */
2730 V_DISPATCH(schema
) = NULL
;
2734 hr
= IXMLDOMSchemaCollection2_QueryInterface(cur_schema
, &IID_IDispatch
, (void**)&V_DISPATCH(schema
));
2736 V_VT(schema
) = VT_DISPATCH
;
2741 static HRESULT WINAPI
domdoc_putref_schemas(
2742 IXMLDOMDocument3
* iface
,
2745 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2746 HRESULT hr
= E_FAIL
;
2747 IXMLDOMSchemaCollection2
* new_schema
= NULL
;
2749 FIXME("(%p)->(%s): semi-stub\n", This
, debugstr_variant(&schema
));
2750 switch(V_VT(&schema
))
2753 if (V_UNKNOWN(&schema
))
2755 hr
= IUnknown_QueryInterface(V_UNKNOWN(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2760 if (V_DISPATCH(&schema
))
2762 hr
= IDispatch_QueryInterface(V_DISPATCH(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2772 WARN("Can't get schema from vt %x\n", V_VT(&schema
));
2777 IXMLDOMSchemaCollection2
* old_schema
= InterlockedExchangePointer((void**)&This
->properties
->schemaCache
, new_schema
);
2778 if(old_schema
) IXMLDOMSchemaCollection2_Release(old_schema
);
2784 static inline BOOL
is_wellformed(xmlDocPtr doc
)
2786 #ifdef HAVE_XMLDOC_PROPERTIES
2787 return doc
->properties
& XML_DOC_WELLFORMED
;
2789 /* Not a full check, but catches the worst violations */
2793 for (child
= doc
->children
; child
!= NULL
; child
= child
->next
)
2795 switch (child
->type
)
2797 case XML_ELEMENT_NODE
:
2802 case XML_CDATA_SECTION_NODE
:
2814 static void LIBXML2_LOG_CALLBACK
validate_error(void* ctx
, char const* msg
, ...)
2818 LIBXML2_CALLBACK_ERR(domdoc_validateNode
, msg
, ap
);
2822 static void LIBXML2_LOG_CALLBACK
validate_warning(void* ctx
, char const* msg
, ...)
2826 LIBXML2_CALLBACK_WARN(domdoc_validateNode
, msg
, ap
);
2830 static HRESULT WINAPI
domdoc_validateNode(
2831 IXMLDOMDocument3
* iface
,
2833 IXMLDOMParseError
** err
)
2835 domdoc
* This
= impl_from_IXMLDOMDocument3(iface
);
2836 LONG state
, err_code
= 0;
2840 TRACE("(%p)->(%p, %p)\n", This
, node
, err
);
2841 IXMLDOMDocument3_get_readyState(iface
, &state
);
2842 if (state
!= READYSTATE_COMPLETE
)
2845 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2852 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2856 if (!get_node_obj(node
)->node
|| get_node_obj(node
)->node
->doc
!= get_doc(This
))
2859 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2863 if (!is_wellformed(get_doc(This
)))
2865 ERR("doc not well-formed\n");
2867 *err
= create_parseError(E_XML_NOTWF
, NULL
, NULL
, NULL
, 0, 0, 0);
2871 /* DTD validation */
2872 if (get_doc(This
)->intSubset
|| get_doc(This
)->extSubset
)
2874 xmlValidCtxtPtr vctx
= xmlNewValidCtxt();
2875 vctx
->error
= validate_error
;
2876 vctx
->warning
= validate_warning
;
2879 if (!((node
== (IXMLDOMNode
*)iface
)?
2880 xmlValidateDocument(vctx
, get_doc(This
)) :
2881 xmlValidateElement(vctx
, get_doc(This
), get_node_obj(node
)->node
)))
2883 /* TODO: get a real error code here */
2884 TRACE("DTD validation failed\n");
2885 err_code
= E_XML_INVALID
;
2888 xmlFreeValidCtxt(vctx
);
2891 /* Schema validation */
2892 if (hr
== S_OK
&& This
->properties
->schemaCache
!= NULL
)
2895 hr
= SchemaCache_validate_tree(This
->properties
->schemaCache
, get_node_obj(node
)->node
);
2899 /* TODO: get a real error code here */
2902 TRACE("schema validation succeeded\n");
2906 ERR("schema validation failed\n");
2907 err_code
= E_XML_INVALID
;
2912 /* not really OK, just didn't find a schema for the ns */
2919 ERR("no DTD or schema found\n");
2920 err_code
= E_XML_NODTD
;
2925 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2930 static HRESULT WINAPI
domdoc_validate(
2931 IXMLDOMDocument3
* iface
,
2932 IXMLDOMParseError
** err
)
2934 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2935 TRACE("(%p)->(%p)\n", This
, err
);
2936 return IXMLDOMDocument3_validateNode(iface
, (IXMLDOMNode
*)iface
, err
);
2939 static HRESULT WINAPI
domdoc_setProperty(
2940 IXMLDOMDocument3
* iface
,
2944 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2946 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(p
), debugstr_variant(&value
));
2948 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
2954 V_VT(&varStr
) = VT_EMPTY
;
2955 if (V_VT(&value
) != VT_BSTR
)
2957 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2959 bstr
= V_BSTR(&varStr
);
2962 bstr
= V_BSTR(&value
);
2965 if (lstrcmpiW(bstr
, PropValueXPathW
) == 0)
2966 This
->properties
->XPath
= TRUE
;
2967 else if (lstrcmpiW(bstr
, PropValueXSLPatternW
) == 0)
2968 This
->properties
->XPath
= FALSE
;
2972 VariantClear(&varStr
);
2975 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
2977 xmlChar
*nsStr
= (xmlChar
*)This
->properties
->selectNsStr
;
2978 struct list
*pNsList
;
2983 V_VT(&varStr
) = VT_EMPTY
;
2984 if (V_VT(&value
) != VT_BSTR
)
2986 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2988 bstr
= V_BSTR(&varStr
);
2991 bstr
= V_BSTR(&value
);
2995 pNsList
= &(This
->properties
->selectNsList
);
2996 clear_selectNsList(pNsList
);
2998 nsStr
= xmlchar_from_wchar(bstr
);
3000 TRACE("property value: \"%s\"\n", debugstr_w(bstr
));
3002 This
->properties
->selectNsStr
= nsStr
;
3003 This
->properties
->selectNsStr_len
= xmlStrlen(nsStr
);
3006 xmlChar
*pTokBegin
, *pTokEnd
, *pTokInner
;
3007 select_ns_entry
* ns_entry
= NULL
;
3008 xmlXPathContextPtr ctx
;
3010 ctx
= xmlXPathNewContext(This
->node
.node
->doc
);
3013 /* skip leading spaces */
3014 while (*pTokBegin
== ' ' || *pTokBegin
== '\n' ||
3015 *pTokBegin
== '\t' || *pTokBegin
== '\r')
3018 for (; *pTokBegin
; pTokBegin
= pTokEnd
)
3021 memset(ns_entry
, 0, sizeof(select_ns_entry
));
3023 ns_entry
= heap_alloc_zero(sizeof(select_ns_entry
));
3025 while (*pTokBegin
== ' ')
3027 pTokEnd
= pTokBegin
;
3028 while (*pTokEnd
!= ' ' && *pTokEnd
!= 0)
3031 /* so it failed to advance which means we've got some trailing spaces */
3032 if (pTokEnd
== pTokBegin
) break;
3034 if (xmlStrncmp(pTokBegin
, (xmlChar
const*)"xmlns", 5) != 0)
3037 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3038 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
3043 if (*pTokBegin
== '=')
3045 /*valid for XSLPattern?*/
3046 FIXME("Setting default xmlns not supported - skipping.\n");
3049 else if (*pTokBegin
== ':')
3051 ns_entry
->prefix
= ++pTokBegin
;
3052 for (pTokInner
= pTokBegin
; pTokInner
!= pTokEnd
&& *pTokInner
!= '='; ++pTokInner
)
3055 if (pTokInner
== pTokEnd
)
3058 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3059 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
3063 ns_entry
->prefix_end
= *pTokInner
;
3067 if (pTokEnd
-pTokInner
> 1 &&
3068 ((*pTokInner
== '\'' && *(pTokEnd
-1) == '\'') ||
3069 (*pTokInner
== '"' && *(pTokEnd
-1) == '"')))
3071 ns_entry
->href
= ++pTokInner
;
3072 ns_entry
->href_end
= *(pTokEnd
-1);
3074 list_add_tail(pNsList
, &ns_entry
->entry
);
3075 /*let libxml figure out if they're valid from here ;)*/
3076 if (xmlXPathRegisterNs(ctx
, ns_entry
->prefix
, ns_entry
->href
) != 0)
3085 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3086 debugstr_w(bstr
), debugstr_an((const char*)pTokInner
, pTokEnd
-pTokInner
));
3087 list_add_tail(pNsList
, &ns_entry
->entry
);
3100 heap_free(ns_entry
);
3101 xmlXPathFreeContext(ctx
);
3104 VariantClear(&varStr
);
3107 else if (lstrcmpiW(p
, PropertyProhibitDTDW
) == 0 ||
3108 lstrcmpiW(p
, PropertyNewParserW
) == 0 ||
3109 lstrcmpiW(p
, PropertyResolveExternalsW
) == 0 ||
3110 lstrcmpiW(p
, PropertyAllowXsltScriptW
) == 0 ||
3111 lstrcmpiW(p
, PropertyAllowDocumentFunctionW
) == 0)
3114 FIXME("Ignoring property %s, value %s\n", debugstr_w(p
), debugstr_variant(&value
));
3118 FIXME("Unknown property %s\n", debugstr_w(p
));
3122 static HRESULT WINAPI
domdoc_getProperty(
3123 IXMLDOMDocument3
* iface
,
3127 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3129 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
3132 return E_INVALIDARG
;
3134 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
3136 V_VT(var
) = VT_BSTR
;
3137 V_BSTR(var
) = This
->properties
->XPath
?
3138 SysAllocString(PropValueXPathW
) :
3139 SysAllocString(PropValueXSLPatternW
);
3140 return V_BSTR(var
) ? S_OK
: E_OUTOFMEMORY
;
3142 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3145 BSTR rebuiltStr
, cur
;
3146 const xmlChar
*nsStr
;
3147 struct list
*pNsList
;
3148 select_ns_entry
* pNsEntry
;
3150 V_VT(var
) = VT_BSTR
;
3151 nsStr
= This
->properties
->selectNsStr
;
3152 pNsList
= &This
->properties
->selectNsList
;
3153 lenA
= This
->properties
->selectNsStr_len
;
3154 lenW
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, NULL
, 0);
3155 rebuiltStr
= heap_alloc(lenW
*sizeof(WCHAR
));
3156 MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, rebuiltStr
, lenW
);
3158 /* this is fine because all of the chars that end tokens are ASCII*/
3159 LIST_FOR_EACH_ENTRY(pNsEntry
, pNsList
, select_ns_entry
, entry
)
3161 while (*cur
!= 0) ++cur
;
3162 if (pNsEntry
->prefix_end
)
3164 *cur
= pNsEntry
->prefix_end
;
3165 while (*cur
!= 0) ++cur
;
3168 if (pNsEntry
->href_end
)
3170 *cur
= pNsEntry
->href_end
;
3173 V_BSTR(var
) = SysAllocString(rebuiltStr
);
3174 heap_free(rebuiltStr
);
3178 FIXME("Unknown property %s\n", debugstr_w(p
));
3182 static HRESULT WINAPI
domdoc_importNode(
3183 IXMLDOMDocument3
* iface
,
3186 IXMLDOMNode
** clone
)
3188 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3189 FIXME("(%p)->(%p %d %p): stub\n", This
, node
, deep
, clone
);
3193 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl
=
3195 domdoc_QueryInterface
,
3198 domdoc_GetTypeInfoCount
,
3200 domdoc_GetIDsOfNames
,
3202 domdoc_get_nodeName
,
3203 domdoc_get_nodeValue
,
3204 domdoc_put_nodeValue
,
3205 domdoc_get_nodeType
,
3206 domdoc_get_parentNode
,
3207 domdoc_get_childNodes
,
3208 domdoc_get_firstChild
,
3209 domdoc_get_lastChild
,
3210 domdoc_get_previousSibling
,
3211 domdoc_get_nextSibling
,
3212 domdoc_get_attributes
,
3213 domdoc_insertBefore
,
3214 domdoc_replaceChild
,
3217 domdoc_hasChildNodes
,
3218 domdoc_get_ownerDocument
,
3220 domdoc_get_nodeTypeString
,
3223 domdoc_get_specified
,
3224 domdoc_get_definition
,
3225 domdoc_get_nodeTypedValue
,
3226 domdoc_put_nodeTypedValue
,
3227 domdoc_get_dataType
,
3228 domdoc_put_dataType
,
3230 domdoc_transformNode
,
3232 domdoc_selectSingleNode
,
3234 domdoc_get_namespaceURI
,
3236 domdoc_get_baseName
,
3237 domdoc_transformNodeToObject
,
3239 domdoc_get_implementation
,
3240 domdoc_get_documentElement
,
3241 domdoc_put_documentElement
,
3242 domdoc_createElement
,
3243 domdoc_createDocumentFragment
,
3244 domdoc_createTextNode
,
3245 domdoc_createComment
,
3246 domdoc_createCDATASection
,
3247 domdoc_createProcessingInstruction
,
3248 domdoc_createAttribute
,
3249 domdoc_createEntityReference
,
3250 domdoc_getElementsByTagName
,
3254 domdoc_get_readyState
,
3255 domdoc_get_parseError
,
3262 domdoc_get_validateOnParse
,
3263 domdoc_put_validateOnParse
,
3264 domdoc_get_resolveExternals
,
3265 domdoc_put_resolveExternals
,
3266 domdoc_get_preserveWhiteSpace
,
3267 domdoc_put_preserveWhiteSpace
,
3268 domdoc_put_onreadystatechange
,
3269 domdoc_put_onDataAvailable
,
3270 domdoc_put_onTransformNode
,
3271 domdoc_get_namespaces
,
3273 domdoc_putref_schemas
,
3277 domdoc_validateNode
,
3281 /* IConnectionPointContainer */
3282 static HRESULT WINAPI
ConnectionPointContainer_QueryInterface(IConnectionPointContainer
*iface
,
3283 REFIID riid
, void **ppv
)
3285 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3286 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3289 static ULONG WINAPI
ConnectionPointContainer_AddRef(IConnectionPointContainer
*iface
)
3291 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3292 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3295 static ULONG WINAPI
ConnectionPointContainer_Release(IConnectionPointContainer
*iface
)
3297 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3298 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3301 static HRESULT WINAPI
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer
*iface
,
3302 IEnumConnectionPoints
**ppEnum
)
3304 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3305 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3309 static HRESULT WINAPI
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer
*iface
,
3310 REFIID riid
, IConnectionPoint
**cp
)
3312 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3313 ConnectionPoint
*iter
;
3315 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), cp
);
3319 for(iter
= This
->cp_list
; iter
; iter
= iter
->next
)
3321 if (IsEqualGUID(iter
->iid
, riid
))
3322 *cp
= &iter
->IConnectionPoint_iface
;
3327 IConnectionPoint_AddRef(*cp
);
3331 FIXME("unsupported riid %s\n", debugstr_guid(riid
));
3332 return CONNECT_E_NOCONNECTION
;
3336 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl
=
3338 ConnectionPointContainer_QueryInterface
,
3339 ConnectionPointContainer_AddRef
,
3340 ConnectionPointContainer_Release
,
3341 ConnectionPointContainer_EnumConnectionPoints
,
3342 ConnectionPointContainer_FindConnectionPoint
3345 /* IConnectionPoint */
3346 static HRESULT WINAPI
ConnectionPoint_QueryInterface(IConnectionPoint
*iface
,
3347 REFIID riid
, void **ppv
)
3349 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3351 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
3355 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
3356 IsEqualGUID(&IID_IConnectionPoint
, riid
))
3363 IConnectionPoint_AddRef(iface
);
3367 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
3368 return E_NOINTERFACE
;
3371 static ULONG WINAPI
ConnectionPoint_AddRef(IConnectionPoint
*iface
)
3373 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3374 return IConnectionPointContainer_AddRef(This
->container
);
3377 static ULONG WINAPI
ConnectionPoint_Release(IConnectionPoint
*iface
)
3379 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3380 return IConnectionPointContainer_Release(This
->container
);
3383 static HRESULT WINAPI
ConnectionPoint_GetConnectionInterface(IConnectionPoint
*iface
, IID
*iid
)
3385 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3387 TRACE("(%p)->(%p)\n", This
, iid
);
3389 if (!iid
) return E_POINTER
;
3395 static HRESULT WINAPI
ConnectionPoint_GetConnectionPointContainer(IConnectionPoint
*iface
,
3396 IConnectionPointContainer
**container
)
3398 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3400 TRACE("(%p)->(%p)\n", This
, container
);
3402 if (!container
) return E_POINTER
;
3404 *container
= This
->container
;
3405 IConnectionPointContainer_AddRef(*container
);
3409 static HRESULT WINAPI
ConnectionPoint_Advise(IConnectionPoint
*iface
, IUnknown
*unk_sink
,
3412 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3417 TRACE("(%p)->(%p %p)\n", This
, unk_sink
, cookie
);
3419 hr
= IUnknown_QueryInterface(unk_sink
, This
->iid
, (void**)&sink
);
3420 if(FAILED(hr
) && !IsEqualGUID(&IID_IPropertyNotifySink
, This
->iid
))
3421 hr
= IUnknown_QueryInterface(unk_sink
, &IID_IDispatch
, (void**)&sink
);
3423 return CONNECT_E_CANNOTCONNECT
;
3427 for (i
= 0; i
< This
->sinks_size
; i
++)
3428 if (!This
->sinks
[i
].unk
)
3431 if (i
== This
->sinks_size
)
3432 This
->sinks
= heap_realloc(This
->sinks
,(++This
->sinks_size
)*sizeof(*This
->sinks
));
3436 This
->sinks
= heap_alloc(sizeof(*This
->sinks
));
3437 This
->sinks_size
= 1;
3441 This
->sinks
[i
].unk
= sink
;
3448 static HRESULT WINAPI
ConnectionPoint_Unadvise(IConnectionPoint
*iface
, DWORD cookie
)
3450 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3452 TRACE("(%p)->(%d)\n", This
, cookie
);
3454 if (cookie
== 0 || cookie
> This
->sinks_size
|| !This
->sinks
[cookie
-1].unk
)
3455 return CONNECT_E_NOCONNECTION
;
3457 IUnknown_Release(This
->sinks
[cookie
-1].unk
);
3458 This
->sinks
[cookie
-1].unk
= NULL
;
3463 static HRESULT WINAPI
ConnectionPoint_EnumConnections(IConnectionPoint
*iface
,
3464 IEnumConnections
**ppEnum
)
3466 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3467 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3471 static const IConnectionPointVtbl ConnectionPointVtbl
=
3473 ConnectionPoint_QueryInterface
,
3474 ConnectionPoint_AddRef
,
3475 ConnectionPoint_Release
,
3476 ConnectionPoint_GetConnectionInterface
,
3477 ConnectionPoint_GetConnectionPointContainer
,
3478 ConnectionPoint_Advise
,
3479 ConnectionPoint_Unadvise
,
3480 ConnectionPoint_EnumConnections
3483 static void ConnectionPoint_Init(ConnectionPoint
*cp
, struct domdoc
*doc
, REFIID riid
)
3485 cp
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointVtbl
;
3491 cp
->next
= doc
->cp_list
;
3494 cp
->container
= &doc
->IConnectionPointContainer_iface
;
3497 /* domdoc implementation of IObjectWithSite */
3498 static HRESULT WINAPI
3499 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
3501 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3502 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObject
);
3505 static ULONG WINAPI
domdoc_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
3507 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3508 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3511 static ULONG WINAPI
domdoc_ObjectWithSite_Release( IObjectWithSite
* iface
)
3513 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3514 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3517 static HRESULT WINAPI
domdoc_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
3519 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3521 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
3526 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
3529 static HRESULT WINAPI
domdoc_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
3531 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3533 TRACE("(%p)->(%p)\n", iface
, punk
);
3539 IUnknown_Release( This
->site
);
3546 IUnknown_AddRef( punk
);
3549 IUnknown_Release( This
->site
);
3556 static const IObjectWithSiteVtbl domdocObjectSite
=
3558 domdoc_ObjectWithSite_QueryInterface
,
3559 domdoc_ObjectWithSite_AddRef
,
3560 domdoc_ObjectWithSite_Release
,
3561 domdoc_ObjectWithSite_SetSite
,
3562 domdoc_ObjectWithSite_GetSite
3565 static HRESULT WINAPI
domdoc_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
3567 domdoc
*This
= impl_from_IObjectSafety(iface
);
3568 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3571 static ULONG WINAPI
domdoc_Safety_AddRef(IObjectSafety
*iface
)
3573 domdoc
*This
= impl_from_IObjectSafety(iface
);
3574 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3577 static ULONG WINAPI
domdoc_Safety_Release(IObjectSafety
*iface
)
3579 domdoc
*This
= impl_from_IObjectSafety(iface
);
3580 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3583 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3585 static HRESULT WINAPI
domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3586 DWORD
*supported
, DWORD
*enabled
)
3588 domdoc
*This
= impl_from_IObjectSafety(iface
);
3590 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
3592 if(!supported
|| !enabled
) return E_POINTER
;
3594 *supported
= SAFETY_SUPPORTED_OPTIONS
;
3595 *enabled
= This
->safeopt
;
3600 static HRESULT WINAPI
domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3601 DWORD mask
, DWORD enabled
)
3603 domdoc
*This
= impl_from_IObjectSafety(iface
);
3604 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
3606 if ((mask
& ~SAFETY_SUPPORTED_OPTIONS
) != 0)
3609 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
3614 #undef SAFETY_SUPPORTED_OPTIONS
3616 static const IObjectSafetyVtbl domdocObjectSafetyVtbl
= {
3617 domdoc_Safety_QueryInterface
,
3618 domdoc_Safety_AddRef
,
3619 domdoc_Safety_Release
,
3620 domdoc_Safety_GetInterfaceSafetyOptions
,
3621 domdoc_Safety_SetInterfaceSafetyOptions
3624 static const tid_t domdoc_iface_tids
[] = {
3625 IXMLDOMDocument3_tid
,
3629 static dispex_static_data_t domdoc_dispex
= {
3631 IXMLDOMDocument3_tid
,
3636 HRESULT
get_domdoc_from_xmldoc(xmlDocPtr xmldoc
, IXMLDOMDocument3
**document
)
3640 doc
= heap_alloc( sizeof (*doc
) );
3642 return E_OUTOFMEMORY
;
3644 doc
->IXMLDOMDocument3_iface
.lpVtbl
= &XMLDOMDocument3Vtbl
;
3645 doc
->IPersistStreamInit_iface
.lpVtbl
= &xmldoc_IPersistStreamInit_VTable
;
3646 doc
->IObjectWithSite_iface
.lpVtbl
= &domdocObjectSite
;
3647 doc
->IObjectSafety_iface
.lpVtbl
= &domdocObjectSafetyVtbl
;
3648 doc
->IConnectionPointContainer_iface
.lpVtbl
= &ConnectionPointContainerVtbl
;
3650 doc
->async
= VARIANT_TRUE
;
3651 doc
->validating
= 0;
3653 doc
->properties
= properties_from_xmlDocPtr(xmldoc
);
3657 doc
->cp_list
= NULL
;
3658 doc
->namespaces
= NULL
;
3659 memset(doc
->events
, 0, sizeof(doc
->events
));
3661 /* events connection points */
3662 ConnectionPoint_Init(&doc
->cp_dispatch
, doc
, &IID_IDispatch
);
3663 ConnectionPoint_Init(&doc
->cp_propnotif
, doc
, &IID_IPropertyNotifySink
);
3664 ConnectionPoint_Init(&doc
->cp_domdocevents
, doc
, &DIID_XMLDOMDocumentEvents
);
3666 init_xmlnode(&doc
->node
, (xmlNodePtr
)xmldoc
, (IXMLDOMNode
*)&doc
->IXMLDOMDocument3_iface
,
3669 *document
= &doc
->IXMLDOMDocument3_iface
;
3671 TRACE("returning iface %p\n", *document
);
3675 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3680 TRACE("(%d, %p)\n", version
, ppObj
);
3682 xmldoc
= xmlNewDoc(NULL
);
3684 return E_OUTOFMEMORY
;
3686 xmldoc_init(xmldoc
, version
);
3688 hr
= get_domdoc_from_xmldoc(xmldoc
, (IXMLDOMDocument3
**)ppObj
);
3691 free_properties(properties_from_xmlDocPtr(xmldoc
));
3692 heap_free(xmldoc
->_private
);
3700 IUnknown
* create_domdoc( xmlNodePtr document
)
3702 IUnknown
*obj
= NULL
;
3705 TRACE("(%p)\n", document
);
3707 hr
= get_domdoc_from_xmldoc((xmlDocPtr
)document
, (IXMLDOMDocument3
**)&obj
);
3716 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3718 MESSAGE("This program tried to use a DOMDocument object, but\n"
3719 "libxml2 support was not present at compile time.\n");