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
);
1249 TRACE("(%p)->(%d %p)\n", This
, deep
, outNode
);
1252 return E_INVALIDARG
;
1256 clone
= xmlCopyNode((xmlNodePtr
)get_doc(This
), deep
? 1 : 2);
1260 clone
->doc
->_private
= create_priv();
1261 xmldoc_add_orphan(clone
->doc
, clone
);
1262 xmldoc_add_ref(clone
->doc
);
1264 priv_from_xmlDocPtr(clone
->doc
)->properties
= copy_properties(This
->properties
);
1265 if (!(*outNode
= (IXMLDOMNode
*)create_domdoc(clone
)))
1267 xmldoc_release(clone
->doc
);
1275 static HRESULT WINAPI
domdoc_get_nodeTypeString(
1276 IXMLDOMDocument3
*iface
,
1279 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1280 static const WCHAR documentW
[] = {'d','o','c','u','m','e','n','t',0};
1282 TRACE("(%p)->(%p)\n", This
, p
);
1284 return return_bstr(documentW
, p
);
1288 static HRESULT WINAPI
domdoc_get_text(
1289 IXMLDOMDocument3
*iface
,
1292 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1293 TRACE("(%p)->(%p)\n", This
, p
);
1294 return node_get_text(&This
->node
, p
);
1298 static HRESULT WINAPI
domdoc_put_text(
1299 IXMLDOMDocument3
*iface
,
1302 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1303 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
1308 static HRESULT WINAPI
domdoc_get_specified(
1309 IXMLDOMDocument3
*iface
,
1310 VARIANT_BOOL
* isSpecified
)
1312 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1313 FIXME("(%p)->(%p) stub!\n", This
, isSpecified
);
1314 *isSpecified
= VARIANT_TRUE
;
1319 static HRESULT WINAPI
domdoc_get_definition(
1320 IXMLDOMDocument3
*iface
,
1321 IXMLDOMNode
** definitionNode
)
1323 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1324 FIXME("(%p)->(%p)\n", This
, definitionNode
);
1329 static HRESULT WINAPI
domdoc_get_nodeTypedValue(
1330 IXMLDOMDocument3
*iface
,
1333 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1334 TRACE("(%p)->(%p)\n", This
, v
);
1335 return return_null_var(v
);
1338 static HRESULT WINAPI
domdoc_put_nodeTypedValue(
1339 IXMLDOMDocument3
*iface
,
1340 VARIANT typedValue
)
1342 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1343 FIXME("(%p)->(%s)\n", This
, debugstr_variant(&typedValue
));
1348 static HRESULT WINAPI
domdoc_get_dataType(
1349 IXMLDOMDocument3
*iface
,
1352 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1353 TRACE("(%p)->(%p)\n", This
, typename
);
1354 return return_null_var( typename
);
1358 static HRESULT WINAPI
domdoc_put_dataType(
1359 IXMLDOMDocument3
*iface
,
1362 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1364 FIXME("(%p)->(%s)\n", This
, debugstr_w(dataTypeName
));
1367 return E_INVALIDARG
;
1372 static int XMLCALL
domdoc_get_xml_writecallback(void *ctx
, const char *data
, int len
)
1374 return xmlBufferAdd((xmlBufferPtr
)ctx
, (xmlChar
*)data
, len
) == 0 ? len
: 0;
1377 static HRESULT WINAPI
domdoc_get_xml(
1378 IXMLDOMDocument3
*iface
,
1381 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1382 xmlSaveCtxtPtr ctxt
;
1387 TRACE("(%p)->(%p)\n", This
, p
);
1390 return E_INVALIDARG
;
1394 buf
= xmlBufferCreate();
1396 return E_OUTOFMEMORY
;
1398 options
= XML_SAVE_FORMAT
| XML_SAVE_NO_DECL
;
1399 ctxt
= xmlSaveToIO(domdoc_get_xml_writecallback
, NULL
, buf
, "UTF-8", options
);
1404 return E_OUTOFMEMORY
;
1407 ret
= xmlSaveDoc(ctxt
, get_doc(This
));
1408 /* flushes on close */
1411 TRACE("%ld, len=%d\n", ret
, xmlBufferLength(buf
));
1412 if(ret
!= -1 && xmlBufferLength(buf
) > 0)
1416 content
= bstr_from_xmlChar(xmlBufferContent(buf
));
1417 content
= EnsureCorrectEOL(content
);
1423 *p
= SysAllocStringLen(NULL
, 0);
1428 return *p
? S_OK
: E_OUTOFMEMORY
;
1432 static HRESULT WINAPI
domdoc_transformNode(
1433 IXMLDOMDocument3
*iface
,
1437 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1438 TRACE("(%p)->(%p %p)\n", This
, node
, p
);
1439 return node_transform_node(&This
->node
, node
, p
);
1443 static HRESULT WINAPI
domdoc_selectNodes(
1444 IXMLDOMDocument3
*iface
,
1446 IXMLDOMNodeList
**outList
)
1448 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1449 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outList
);
1450 return node_select_nodes(&This
->node
, p
, outList
);
1454 static HRESULT WINAPI
domdoc_selectSingleNode(
1455 IXMLDOMDocument3
*iface
,
1457 IXMLDOMNode
**outNode
)
1459 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1460 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outNode
);
1461 return node_select_singlenode(&This
->node
, p
, outNode
);
1465 static HRESULT WINAPI
domdoc_get_parsed(
1466 IXMLDOMDocument3
*iface
,
1467 VARIANT_BOOL
* isParsed
)
1469 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1470 FIXME("(%p)->(%p) stub!\n", This
, isParsed
);
1471 *isParsed
= VARIANT_TRUE
;
1475 static HRESULT WINAPI
domdoc_get_namespaceURI(
1476 IXMLDOMDocument3
*iface
,
1477 BSTR
* namespaceURI
)
1479 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1480 TRACE("(%p)->(%p)\n", This
, namespaceURI
);
1481 return return_null_bstr( namespaceURI
);
1484 static HRESULT WINAPI
domdoc_get_prefix(
1485 IXMLDOMDocument3
*iface
,
1488 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1489 TRACE("(%p)->(%p)\n", This
, prefix
);
1490 return return_null_bstr( prefix
);
1494 static HRESULT WINAPI
domdoc_get_baseName(
1495 IXMLDOMDocument3
*iface
,
1498 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1499 TRACE("(%p)->(%p)\n", This
, name
);
1500 return return_null_bstr( name
);
1504 static HRESULT WINAPI
domdoc_transformNodeToObject(
1505 IXMLDOMDocument3
*iface
,
1506 IXMLDOMNode
* stylesheet
,
1507 VARIANT outputObject
)
1509 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1510 FIXME("(%p)->(%p %s)\n", This
, stylesheet
, debugstr_variant(&outputObject
));
1515 static HRESULT WINAPI
domdoc_get_doctype(
1516 IXMLDOMDocument3
*iface
,
1517 IXMLDOMDocumentType
** doctype
)
1519 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1524 TRACE("(%p)->(%p)\n", This
, doctype
);
1526 if (!doctype
) return E_INVALIDARG
;
1530 dtd
= xmlGetIntSubset(get_doc(This
));
1531 if (!dtd
) return S_FALSE
;
1533 node
= create_node((xmlNodePtr
)dtd
);
1534 if (!node
) return S_FALSE
;
1536 hr
= IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentType
, (void**)doctype
);
1537 IXMLDOMNode_Release(node
);
1543 static HRESULT WINAPI
domdoc_get_implementation(
1544 IXMLDOMDocument3
*iface
,
1545 IXMLDOMImplementation
** impl
)
1547 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1549 TRACE("(%p)->(%p)\n", This
, impl
);
1552 return E_INVALIDARG
;
1554 *impl
= (IXMLDOMImplementation
*)create_doc_Implementation();
1559 static HRESULT WINAPI
domdoc_get_documentElement(
1560 IXMLDOMDocument3
*iface
,
1561 IXMLDOMElement
** DOMElement
)
1563 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1564 IXMLDOMNode
*element_node
;
1568 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1571 return E_INVALIDARG
;
1575 root
= xmlDocGetRootElement( get_doc(This
) );
1579 element_node
= create_node( root
);
1580 if(!element_node
) return S_FALSE
;
1582 hr
= IXMLDOMNode_QueryInterface(element_node
, &IID_IXMLDOMElement
, (void**)DOMElement
);
1583 IXMLDOMNode_Release(element_node
);
1589 static HRESULT WINAPI
domdoc_put_documentElement(
1590 IXMLDOMDocument3
*iface
,
1591 IXMLDOMElement
* DOMElement
)
1593 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1594 IXMLDOMNode
*elementNode
;
1601 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1603 hr
= IXMLDOMElement_QueryInterface( DOMElement
, &IID_IXMLDOMNode
, (void**)&elementNode
);
1607 xmlNode
= get_node_obj( elementNode
);
1608 if(!xmlNode
) return E_FAIL
;
1610 if(!xmlNode
->node
->parent
)
1611 if(xmldoc_remove_orphan(xmlNode
->node
->doc
, xmlNode
->node
) != S_OK
)
1612 WARN("%p is not an orphan of %p\n", xmlNode
->node
->doc
, xmlNode
->node
);
1614 old_doc
= xmlNode
->node
->doc
;
1615 if (old_doc
!= get_doc(This
))
1616 refcount
= xmlnode_get_inst_cnt(xmlNode
);
1618 /* old root is still orphaned by its document, update refcount from new root */
1619 if (refcount
) xmldoc_add_refs(get_doc(This
), refcount
);
1620 oldRoot
= xmlDocSetRootElement( get_doc(This
), xmlNode
->node
);
1621 if (refcount
) xmldoc_release_refs(old_doc
, refcount
);
1622 IXMLDOMNode_Release( elementNode
);
1625 xmldoc_add_orphan(oldRoot
->doc
, oldRoot
);
1631 static HRESULT WINAPI
domdoc_createElement(
1632 IXMLDOMDocument3
*iface
,
1634 IXMLDOMElement
** element
)
1636 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1641 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(tagname
), element
);
1643 if (!element
|| !tagname
) return E_INVALIDARG
;
1645 V_VT(&type
) = VT_I1
;
1646 V_I1(&type
) = NODE_ELEMENT
;
1648 hr
= IXMLDOMDocument3_createNode(iface
, type
, tagname
, NULL
, &node
);
1651 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMElement
, (void**)element
);
1652 IXMLDOMNode_Release(node
);
1659 static HRESULT WINAPI
domdoc_createDocumentFragment(
1660 IXMLDOMDocument3
*iface
,
1661 IXMLDOMDocumentFragment
** frag
)
1663 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1668 TRACE("(%p)->(%p)\n", This
, frag
);
1670 if (!frag
) return E_INVALIDARG
;
1674 V_VT(&type
) = VT_I1
;
1675 V_I1(&type
) = NODE_DOCUMENT_FRAGMENT
;
1677 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1680 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentFragment
, (void**)frag
);
1681 IXMLDOMNode_Release(node
);
1688 static HRESULT WINAPI
domdoc_createTextNode(
1689 IXMLDOMDocument3
*iface
,
1691 IXMLDOMText
** text
)
1693 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1698 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), text
);
1700 if (!text
) return E_INVALIDARG
;
1704 V_VT(&type
) = VT_I1
;
1705 V_I1(&type
) = NODE_TEXT
;
1707 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1710 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMText
, (void**)text
);
1711 IXMLDOMNode_Release(node
);
1712 hr
= IXMLDOMText_put_data(*text
, data
);
1719 static HRESULT WINAPI
domdoc_createComment(
1720 IXMLDOMDocument3
*iface
,
1722 IXMLDOMComment
** comment
)
1724 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1729 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), comment
);
1731 if (!comment
) return E_INVALIDARG
;
1735 V_VT(&type
) = VT_I1
;
1736 V_I1(&type
) = NODE_COMMENT
;
1738 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1741 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMComment
, (void**)comment
);
1742 IXMLDOMNode_Release(node
);
1743 hr
= IXMLDOMComment_put_data(*comment
, data
);
1750 static HRESULT WINAPI
domdoc_createCDATASection(
1751 IXMLDOMDocument3
*iface
,
1753 IXMLDOMCDATASection
** cdata
)
1755 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1760 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), cdata
);
1762 if (!cdata
) return E_INVALIDARG
;
1766 V_VT(&type
) = VT_I1
;
1767 V_I1(&type
) = NODE_CDATA_SECTION
;
1769 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1772 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMCDATASection
, (void**)cdata
);
1773 IXMLDOMNode_Release(node
);
1774 hr
= IXMLDOMCDATASection_put_data(*cdata
, data
);
1781 static HRESULT WINAPI
domdoc_createProcessingInstruction(
1782 IXMLDOMDocument3
*iface
,
1785 IXMLDOMProcessingInstruction
** pi
)
1787 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1792 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_w(target
), debugstr_w(data
), pi
);
1794 if (!pi
) return E_INVALIDARG
;
1798 V_VT(&type
) = VT_I1
;
1799 V_I1(&type
) = NODE_PROCESSING_INSTRUCTION
;
1801 hr
= IXMLDOMDocument3_createNode(iface
, type
, target
, NULL
, &node
);
1806 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1807 node_obj
= get_node_obj(node
);
1808 hr
= node_set_content(node_obj
, data
);
1810 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMProcessingInstruction
, (void**)pi
);
1811 IXMLDOMNode_Release(node
);
1818 static HRESULT WINAPI
domdoc_createAttribute(
1819 IXMLDOMDocument3
*iface
,
1821 IXMLDOMAttribute
** attribute
)
1823 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1828 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), attribute
);
1830 if (!attribute
|| !name
) return E_INVALIDARG
;
1832 V_VT(&type
) = VT_I1
;
1833 V_I1(&type
) = NODE_ATTRIBUTE
;
1835 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1838 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMAttribute
, (void**)attribute
);
1839 IXMLDOMNode_Release(node
);
1846 static HRESULT WINAPI
domdoc_createEntityReference(
1847 IXMLDOMDocument3
*iface
,
1849 IXMLDOMEntityReference
** entityref
)
1851 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1856 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), entityref
);
1858 if (!entityref
) return E_INVALIDARG
;
1862 V_VT(&type
) = VT_I1
;
1863 V_I1(&type
) = NODE_ENTITY_REFERENCE
;
1865 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1868 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMEntityReference
, (void**)entityref
);
1869 IXMLDOMNode_Release(node
);
1875 xmlChar
* tagName_to_XPath(const BSTR tagName
)
1877 xmlChar
*query
, *tmp
;
1878 static const xmlChar everything
[] = "/descendant::node()";
1879 static const xmlChar mod_pre
[] = "*[local-name()='";
1880 static const xmlChar mod_post
[] = "']";
1881 static const xmlChar prefix
[] = "descendant::";
1882 const WCHAR
*tokBegin
, *tokEnd
;
1885 /* Special case - empty tagname - means select all nodes,
1886 except document itself. */
1888 return xmlStrdup(everything
);
1890 query
= xmlStrdup(prefix
);
1893 while (tokBegin
&& *tokBegin
)
1898 query
= xmlStrcat(query
, BAD_CAST
"/");
1902 query
= xmlStrcat(query
, BAD_CAST
"*");
1906 query
= xmlStrcat(query
, mod_pre
);
1908 while (*tokEnd
&& *tokEnd
!= '/')
1910 len
= WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, NULL
, 0, NULL
, NULL
);
1911 tmp
= xmlMalloc(len
);
1912 WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, (char*)tmp
, len
, NULL
, NULL
);
1913 query
= xmlStrncat(query
, tmp
, len
);
1916 query
= xmlStrcat(query
, mod_post
);
1923 static HRESULT WINAPI
domdoc_getElementsByTagName(
1924 IXMLDOMDocument3
*iface
,
1926 IXMLDOMNodeList
** resultList
)
1928 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1933 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(tagName
), resultList
);
1935 if (!tagName
|| !resultList
) return E_INVALIDARG
;
1937 XPath
= This
->properties
->XPath
;
1938 This
->properties
->XPath
= TRUE
;
1939 query
= tagName_to_XPath(tagName
);
1940 hr
= create_selection((xmlNodePtr
)get_doc(This
), query
, resultList
);
1942 This
->properties
->XPath
= XPath
;
1947 static HRESULT
get_node_type(VARIANT Type
, DOMNodeType
* type
)
1953 hr
= VariantChangeType(&tmp
, &Type
, 0, VT_I4
);
1955 return E_INVALIDARG
;
1962 static HRESULT WINAPI
domdoc_createNode(
1963 IXMLDOMDocument3
*iface
,
1967 IXMLDOMNode
** node
)
1969 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1970 DOMNodeType node_type
;
1972 xmlChar
*xml_name
, *href
;
1975 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_variant(&Type
), debugstr_w(name
), debugstr_w(namespaceURI
), node
);
1977 if(!node
) return E_INVALIDARG
;
1979 hr
= get_node_type(Type
, &node_type
);
1980 if(FAILED(hr
)) return hr
;
1982 TRACE("node_type %d\n", node_type
);
1984 /* exit earlier for types that need name */
1988 case NODE_ATTRIBUTE
:
1989 case NODE_ENTITY_REFERENCE
:
1990 case NODE_PROCESSING_INSTRUCTION
:
1991 if (!name
|| *name
== 0) return E_FAIL
;
1997 xml_name
= xmlchar_from_wchar(name
);
1998 /* prevent empty href from being allocated */
1999 href
= namespaceURI
? xmlchar_from_wchar(namespaceURI
) : NULL
;
2005 xmlChar
*local
, *prefix
;
2007 local
= xmlSplitQName2(xml_name
, &prefix
);
2009 xmlnode
= xmlNewDocNode(get_doc(This
), NULL
, local
? local
: xml_name
, NULL
);
2011 /* allow creating the default namespace xmlns= */
2012 if (local
|| (href
&& *href
))
2014 xmlNsPtr ns
= xmlNewNs(xmlnode
, href
, prefix
);
2015 xmlSetNs(xmlnode
, ns
);
2023 case NODE_ATTRIBUTE
:
2025 xmlChar
*local
, *prefix
;
2027 local
= xmlSplitQName2(xml_name
, &prefix
);
2029 xmlnode
= (xmlNodePtr
)xmlNewDocProp(get_doc(This
), local
? local
: xml_name
, NULL
);
2031 if (local
|| (href
&& *href
))
2033 /* we need a floating namespace here, it can't be created linked to attribute from
2035 xmlNsPtr ns
= xmlNewNs(NULL
, href
, prefix
);
2036 xmlSetNs(xmlnode
, ns
);
2045 xmlnode
= (xmlNodePtr
)xmlNewDocText(get_doc(This
), NULL
);
2047 case NODE_CDATA_SECTION
:
2048 xmlnode
= xmlNewCDataBlock(get_doc(This
), NULL
, 0);
2050 case NODE_ENTITY_REFERENCE
:
2051 xmlnode
= xmlNewReference(get_doc(This
), xml_name
);
2053 case NODE_PROCESSING_INSTRUCTION
:
2054 #ifdef HAVE_XMLNEWDOCPI
2055 xmlnode
= xmlNewDocPI(get_doc(This
), xml_name
, NULL
);
2057 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2062 xmlnode
= xmlNewDocComment(get_doc(This
), NULL
);
2064 case NODE_DOCUMENT_FRAGMENT
:
2065 xmlnode
= xmlNewDocFragment(get_doc(This
));
2067 /* unsupported types */
2069 case NODE_DOCUMENT_TYPE
:
2072 heap_free(xml_name
);
2073 return E_INVALIDARG
;
2075 FIXME("unhandled node type %d\n", node_type
);
2080 *node
= create_node(xmlnode
);
2081 heap_free(xml_name
);
2086 TRACE("created node (%d, %p, %p)\n", node_type
, *node
, xmlnode
);
2087 xmldoc_add_orphan(xmlnode
->doc
, xmlnode
);
2094 static HRESULT WINAPI
domdoc_nodeFromID(
2095 IXMLDOMDocument3
*iface
,
2097 IXMLDOMNode
** node
)
2099 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2100 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(idString
), node
);
2104 static HRESULT
domdoc_onDataAvailable(void *obj
, char *ptr
, DWORD len
)
2109 xmldoc
= doparse(This
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
2111 xmldoc
->_private
= create_priv();
2112 return attach_xmldoc(This
, xmldoc
);
2118 static HRESULT
domdoc_load_moniker(domdoc
*This
, IMoniker
*mon
)
2123 hr
= bind_url(mon
, domdoc_onDataAvailable
, This
, &bsc
);
2127 return detach_bsc(bsc
);
2130 static HRESULT WINAPI
domdoc_load(
2131 IXMLDOMDocument3
*iface
,
2133 VARIANT_BOOL
* isSuccessful
)
2135 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2136 LPWSTR filename
= NULL
;
2137 HRESULT hr
= S_FALSE
;
2140 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&source
));
2144 *isSuccessful
= VARIANT_FALSE
;
2146 assert( &This
->node
);
2148 switch( V_VT(&source
) )
2151 filename
= V_BSTR(&source
);
2153 case VT_BSTR
|VT_BYREF
:
2154 if (!V_BSTRREF(&source
)) return E_INVALIDARG
;
2155 filename
= *V_BSTRREF(&source
);
2157 case VT_ARRAY
|VT_UI1
:
2159 SAFEARRAY
*psa
= V_ARRAY(&source
);
2162 UINT dim
= SafeArrayGetDim(psa
);
2167 ERR("SAFEARRAY == NULL\n");
2168 hr
= This
->error
= E_INVALIDARG
;
2171 /* Only takes UTF-8 strings.
2172 * NOT NULL-terminated. */
2173 hr
= SafeArrayAccessData(psa
, (void**)&str
);
2177 WARN("failed to access array data, 0x%08x\n", hr
);
2180 SafeArrayGetUBound(psa
, 1, &len
);
2182 if ((xmldoc
= doparse(This
, str
, ++len
, XML_CHAR_ENCODING_UTF8
)))
2184 hr
= This
->error
= S_OK
;
2185 *isSuccessful
= VARIANT_TRUE
;
2186 TRACE("parsed document %p\n", xmldoc
);
2190 This
->error
= E_FAIL
;
2191 TRACE("failed to parse document\n");
2194 SafeArrayUnaccessData(psa
);
2198 xmldoc
->_private
= create_priv();
2199 return attach_xmldoc(This
, xmldoc
);
2203 FIXME("unhandled SAFEARRAY dim: %d\n", dim
);
2204 hr
= This
->error
= E_NOTIMPL
;
2210 ISequentialStream
*stream
= NULL
;
2211 IXMLDOMDocument3
*newdoc
= NULL
;
2213 if (!V_UNKNOWN(&source
)) return E_INVALIDARG
;
2215 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IXMLDOMDocument3
, (void**)&newdoc
);
2220 domdoc
*newDoc
= impl_from_IXMLDOMDocument3( newdoc
);
2222 xmldoc
= xmlCopyDoc(get_doc(newDoc
), 1);
2223 xmldoc
->_private
= create_priv();
2224 hr
= attach_xmldoc(This
, xmldoc
);
2227 *isSuccessful
= VARIANT_TRUE
;
2233 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IStream
, (void**)&stream
);
2235 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_ISequentialStream
, (void**)&stream
);
2239 hr
= domdoc_load_from_stream(This
, stream
);
2241 *isSuccessful
= VARIANT_TRUE
;
2242 ISequentialStream_Release(stream
);
2246 FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr
, V_UNKNOWN(&source
)->lpVtbl
);
2250 FIXME("VT type not supported (%d)\n", V_VT(&source
));
2257 CoTaskMemFree(This
->properties
->url
);
2258 This
->properties
->url
= NULL
;
2260 hr
= create_moniker_from_url( filename
, &mon
);
2261 if ( SUCCEEDED(hr
) )
2263 hr
= domdoc_load_moniker( This
, mon
);
2265 IMoniker_GetDisplayName(mon
, NULL
, NULL
, &This
->properties
->url
);
2266 IMoniker_Release(mon
);
2270 This
->error
= E_FAIL
;
2273 hr
= This
->error
= S_OK
;
2274 *isSuccessful
= VARIANT_TRUE
;
2278 if(!filename
|| FAILED(hr
)) {
2279 xmldoc
= xmlNewDoc(NULL
);
2280 xmldoc
->_private
= create_priv();
2281 hr
= attach_xmldoc(This
, xmldoc
);
2286 TRACE("ret (%d)\n", hr
);
2292 static HRESULT WINAPI
domdoc_get_readyState(
2293 IXMLDOMDocument3
*iface
,
2296 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2297 FIXME("stub! (%p)->(%p)\n", This
, value
);
2300 return E_INVALIDARG
;
2302 *value
= READYSTATE_COMPLETE
;
2307 static HRESULT WINAPI
domdoc_get_parseError(
2308 IXMLDOMDocument3
*iface
,
2309 IXMLDOMParseError
** errorObj
)
2311 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2312 static const WCHAR err
[] = {'e','r','r','o','r',0};
2313 BSTR error_string
= NULL
;
2315 FIXME("(%p)->(%p): creating a dummy parseError\n", iface
, errorObj
);
2318 error_string
= SysAllocString(err
);
2320 *errorObj
= create_parseError(This
->error
, NULL
, error_string
, NULL
, 0, 0, 0);
2321 if(!*errorObj
) return E_OUTOFMEMORY
;
2326 static HRESULT WINAPI
domdoc_get_url(
2327 IXMLDOMDocument3
*iface
,
2330 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2332 TRACE("(%p)->(%p)\n", This
, url
);
2335 return E_INVALIDARG
;
2337 if (This
->properties
->url
)
2339 *url
= SysAllocString(This
->properties
->url
);
2341 return E_OUTOFMEMORY
;
2346 return return_null_bstr(url
);
2350 static HRESULT WINAPI
domdoc_get_async(
2351 IXMLDOMDocument3
*iface
,
2352 VARIANT_BOOL
* isAsync
)
2354 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2356 TRACE("(%p)->(%p: %d)\n", This
, isAsync
, This
->async
);
2357 *isAsync
= This
->async
;
2362 static HRESULT WINAPI
domdoc_put_async(
2363 IXMLDOMDocument3
*iface
,
2364 VARIANT_BOOL isAsync
)
2366 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2368 TRACE("(%p)->(%d)\n", This
, isAsync
);
2369 This
->async
= isAsync
;
2374 static HRESULT WINAPI
domdoc_abort(
2375 IXMLDOMDocument3
*iface
)
2377 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2378 FIXME("%p\n", This
);
2382 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2383 static HRESULT WINAPI
domdoc_loadXML(
2384 IXMLDOMDocument3
*iface
,
2386 VARIANT_BOOL
* isSuccessful
)
2388 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2389 xmlDocPtr xmldoc
= NULL
;
2390 HRESULT hr
= S_FALSE
, hr2
;
2392 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), isSuccessful
);
2394 assert ( &This
->node
);
2398 *isSuccessful
= VARIANT_FALSE
;
2404 /* skip leading spaces if needed */
2405 if (This
->properties
->version
== MSXML_DEFAULT
|| This
->properties
->version
== MSXML26
)
2406 while (*ptr
&& isspaceW(*ptr
)) ptr
++;
2408 xmldoc
= doparse(This
, (char*)ptr
, strlenW(ptr
)*sizeof(WCHAR
), XML_CHAR_ENCODING_UTF16LE
);
2411 This
->error
= E_FAIL
;
2412 TRACE("failed to parse document\n");
2416 hr
= This
->error
= S_OK
;
2417 *isSuccessful
= VARIANT_TRUE
;
2418 TRACE("parsed document %p\n", xmldoc
);
2424 xmldoc
= xmlNewDoc(NULL
);
2425 xmldoc
->_private
= create_priv();
2426 hr2
= attach_xmldoc(This
, xmldoc
);
2433 static int XMLCALL
domdoc_save_writecallback(void *ctx
, const char *buffer
, int len
)
2437 if(!WriteFile(ctx
, buffer
, len
, &written
, NULL
))
2439 WARN("write error\n");
2446 static int XMLCALL
domdoc_save_closecallback(void *ctx
)
2448 return CloseHandle(ctx
) ? 0 : -1;
2451 static int XMLCALL
domdoc_stream_save_writecallback(void *ctx
, const char *buffer
, int len
)
2456 hr
= IStream_Write((IStream
*)ctx
, buffer
, len
, &written
);
2457 TRACE("0x%08x %p %d %u\n", hr
, buffer
, len
, written
);
2460 WARN("stream write error: 0x%08x\n", hr
);
2467 static int XMLCALL
domdoc_stream_save_closecallback(void *ctx
)
2469 IStream_Release((IStream
*)ctx
);
2473 static HRESULT WINAPI
domdoc_save(
2474 IXMLDOMDocument3
*iface
,
2475 VARIANT destination
)
2477 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2478 xmlSaveCtxtPtr ctx
= NULL
;
2482 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&destination
));
2484 switch (V_VT(&destination
))
2488 IUnknown
*pUnk
= V_UNKNOWN(&destination
);
2489 IXMLDOMDocument3
*document
;
2492 ret
= IUnknown_QueryInterface(pUnk
, &IID_IXMLDOMDocument3
, (void**)&document
);
2495 VARIANT_BOOL success
;
2498 ret
= IXMLDOMDocument3_get_xml(iface
, &xml
);
2501 ret
= IXMLDOMDocument3_loadXML(document
, xml
, &success
);
2505 IXMLDOMDocument3_Release(document
);
2509 ret
= IUnknown_QueryInterface(pUnk
, &IID_IStream
, (void**)&stream
);
2512 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2513 ctx
= xmlSaveToIO(domdoc_stream_save_writecallback
,
2514 domdoc_stream_save_closecallback
, stream
, NULL
, options
);
2518 IStream_Release(stream
);
2526 case VT_BSTR
| VT_BYREF
:
2528 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2530 /* save with file path */
2531 HANDLE handle
= CreateFileW( (V_VT(&destination
) & VT_BYREF
)? *V_BSTRREF(&destination
) : V_BSTR(&destination
),
2532 GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2533 if( handle
== INVALID_HANDLE_VALUE
)
2535 WARN("failed to create file\n");
2539 /* disable top XML declaration */
2540 ctx
= xmlSaveToIO(domdoc_save_writecallback
, domdoc_save_closecallback
,
2541 handle
, NULL
, options
);
2544 CloseHandle(handle
);
2551 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination
));
2555 xmldecl
= xmldoc_unlink_xmldecl(get_doc(This
));
2556 if (xmlSaveDoc(ctx
, get_doc(This
)) == -1) ret
= S_FALSE
;
2557 xmldoc_link_xmldecl(get_doc(This
), xmldecl
);
2559 /* will release resources through close callback */
2565 static HRESULT WINAPI
domdoc_get_validateOnParse(
2566 IXMLDOMDocument3
*iface
,
2567 VARIANT_BOOL
* isValidating
)
2569 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2570 TRACE("(%p)->(%p: %d)\n", This
, isValidating
, This
->validating
);
2571 *isValidating
= This
->validating
;
2576 static HRESULT WINAPI
domdoc_put_validateOnParse(
2577 IXMLDOMDocument3
*iface
,
2578 VARIANT_BOOL isValidating
)
2580 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2581 TRACE("(%p)->(%d)\n", This
, isValidating
);
2582 This
->validating
= isValidating
;
2587 static HRESULT WINAPI
domdoc_get_resolveExternals(
2588 IXMLDOMDocument3
*iface
,
2589 VARIANT_BOOL
* isResolving
)
2591 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2592 TRACE("(%p)->(%p: %d)\n", This
, isResolving
, This
->resolving
);
2593 *isResolving
= This
->resolving
;
2598 static HRESULT WINAPI
domdoc_put_resolveExternals(
2599 IXMLDOMDocument3
*iface
,
2600 VARIANT_BOOL isResolving
)
2602 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2603 TRACE("(%p)->(%d)\n", This
, isResolving
);
2604 This
->resolving
= isResolving
;
2609 static HRESULT WINAPI
domdoc_get_preserveWhiteSpace(
2610 IXMLDOMDocument3
*iface
,
2611 VARIANT_BOOL
* isPreserving
)
2613 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2614 TRACE("(%p)->(%p: %d)\n", This
, isPreserving
, This
->properties
->preserving
);
2615 *isPreserving
= This
->properties
->preserving
;
2620 static HRESULT WINAPI
domdoc_put_preserveWhiteSpace(
2621 IXMLDOMDocument3
*iface
,
2622 VARIANT_BOOL isPreserving
)
2624 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2625 TRACE("(%p)->(%d)\n", This
, isPreserving
);
2626 This
->properties
->preserving
= isPreserving
;
2631 static HRESULT WINAPI
domdoc_put_onreadystatechange(
2632 IXMLDOMDocument3
*iface
,
2635 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2637 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&event
));
2638 return set_doc_event(This
, EVENTID_READYSTATECHANGE
, &event
);
2642 static HRESULT WINAPI
domdoc_put_onDataAvailable(IXMLDOMDocument3
*iface
, VARIANT sink
)
2644 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2645 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2649 static HRESULT WINAPI
domdoc_put_onTransformNode(IXMLDOMDocument3
*iface
, VARIANT sink
)
2651 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2652 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2656 static HRESULT WINAPI
domdoc_get_namespaces(
2657 IXMLDOMDocument3
* iface
,
2658 IXMLDOMSchemaCollection
** collection
)
2660 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2663 FIXME("(%p)->(%p): semi-stub\n", This
, collection
);
2665 if (!collection
) return E_POINTER
;
2667 if (!This
->namespaces
)
2669 hr
= SchemaCache_create(This
->properties
->version
, (void**)&This
->namespaces
);
2670 if (hr
!= S_OK
) return hr
;
2672 hr
= cache_from_doc_ns(This
->namespaces
, &This
->node
);
2674 release_namespaces(This
);
2677 if (This
->namespaces
)
2678 return IXMLDOMSchemaCollection2_QueryInterface(This
->namespaces
,
2679 &IID_IXMLDOMSchemaCollection
, (void**)collection
);
2684 static HRESULT WINAPI
domdoc_get_schemas(
2685 IXMLDOMDocument3
* iface
,
2688 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2689 IXMLDOMSchemaCollection2
* cur_schema
= This
->properties
->schemaCache
;
2690 HRESULT hr
= S_FALSE
;
2692 TRACE("(%p)->(%p)\n", This
, schema
);
2694 V_VT(schema
) = VT_NULL
;
2695 /* just to reset pointer part, cause that's what application is expected to use */
2696 V_DISPATCH(schema
) = NULL
;
2700 hr
= IXMLDOMSchemaCollection2_QueryInterface(cur_schema
, &IID_IDispatch
, (void**)&V_DISPATCH(schema
));
2702 V_VT(schema
) = VT_DISPATCH
;
2707 static HRESULT WINAPI
domdoc_putref_schemas(
2708 IXMLDOMDocument3
* iface
,
2711 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2712 HRESULT hr
= E_FAIL
;
2713 IXMLDOMSchemaCollection2
* new_schema
= NULL
;
2715 FIXME("(%p)->(%s): semi-stub\n", This
, debugstr_variant(&schema
));
2716 switch(V_VT(&schema
))
2719 if (V_UNKNOWN(&schema
))
2721 hr
= IUnknown_QueryInterface(V_UNKNOWN(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2726 if (V_DISPATCH(&schema
))
2728 hr
= IDispatch_QueryInterface(V_DISPATCH(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2738 WARN("Can't get schema from vt %x\n", V_VT(&schema
));
2743 IXMLDOMSchemaCollection2
* old_schema
= InterlockedExchangePointer((void**)&This
->properties
->schemaCache
, new_schema
);
2744 if(old_schema
) IXMLDOMSchemaCollection2_Release(old_schema
);
2750 static inline BOOL
is_wellformed(xmlDocPtr doc
)
2752 #ifdef HAVE_XMLDOC_PROPERTIES
2753 return doc
->properties
& XML_DOC_WELLFORMED
;
2755 /* Not a full check, but catches the worst violations */
2759 for (child
= doc
->children
; child
!= NULL
; child
= child
->next
)
2761 switch (child
->type
)
2763 case XML_ELEMENT_NODE
:
2768 case XML_CDATA_SECTION_NODE
:
2780 static void LIBXML2_LOG_CALLBACK
validate_error(void* ctx
, char const* msg
, ...)
2784 LIBXML2_CALLBACK_ERR(domdoc_validateNode
, msg
, ap
);
2788 static void LIBXML2_LOG_CALLBACK
validate_warning(void* ctx
, char const* msg
, ...)
2792 LIBXML2_CALLBACK_WARN(domdoc_validateNode
, msg
, ap
);
2796 static HRESULT WINAPI
domdoc_validateNode(
2797 IXMLDOMDocument3
* iface
,
2799 IXMLDOMParseError
** err
)
2801 domdoc
* This
= impl_from_IXMLDOMDocument3(iface
);
2802 LONG state
, err_code
= 0;
2806 TRACE("(%p)->(%p, %p)\n", This
, node
, err
);
2807 IXMLDOMDocument3_get_readyState(iface
, &state
);
2808 if (state
!= READYSTATE_COMPLETE
)
2811 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2818 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2822 if (!get_node_obj(node
)->node
|| get_node_obj(node
)->node
->doc
!= get_doc(This
))
2825 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2829 if (!is_wellformed(get_doc(This
)))
2831 ERR("doc not well-formed\n");
2833 *err
= create_parseError(E_XML_NOTWF
, NULL
, NULL
, NULL
, 0, 0, 0);
2837 /* DTD validation */
2838 if (get_doc(This
)->intSubset
|| get_doc(This
)->extSubset
)
2840 xmlValidCtxtPtr vctx
= xmlNewValidCtxt();
2841 vctx
->error
= validate_error
;
2842 vctx
->warning
= validate_warning
;
2845 if (!((node
== (IXMLDOMNode
*)iface
)?
2846 xmlValidateDocument(vctx
, get_doc(This
)) :
2847 xmlValidateElement(vctx
, get_doc(This
), get_node_obj(node
)->node
)))
2849 /* TODO: get a real error code here */
2850 TRACE("DTD validation failed\n");
2851 err_code
= E_XML_INVALID
;
2854 xmlFreeValidCtxt(vctx
);
2857 /* Schema validation */
2858 if (hr
== S_OK
&& This
->properties
->schemaCache
!= NULL
)
2861 hr
= SchemaCache_validate_tree(This
->properties
->schemaCache
, get_node_obj(node
)->node
);
2865 /* TODO: get a real error code here */
2868 TRACE("schema validation succeeded\n");
2872 ERR("schema validation failed\n");
2873 err_code
= E_XML_INVALID
;
2878 /* not really OK, just didn't find a schema for the ns */
2885 ERR("no DTD or schema found\n");
2886 err_code
= E_XML_NODTD
;
2891 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2896 static HRESULT WINAPI
domdoc_validate(
2897 IXMLDOMDocument3
* iface
,
2898 IXMLDOMParseError
** err
)
2900 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2901 TRACE("(%p)->(%p)\n", This
, err
);
2902 return IXMLDOMDocument3_validateNode(iface
, (IXMLDOMNode
*)iface
, err
);
2905 static HRESULT WINAPI
domdoc_setProperty(
2906 IXMLDOMDocument3
* iface
,
2910 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2912 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(p
), debugstr_variant(&value
));
2914 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
2920 V_VT(&varStr
) = VT_EMPTY
;
2921 if (V_VT(&value
) != VT_BSTR
)
2923 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2925 bstr
= V_BSTR(&varStr
);
2928 bstr
= V_BSTR(&value
);
2931 if (lstrcmpiW(bstr
, PropValueXPathW
) == 0)
2932 This
->properties
->XPath
= TRUE
;
2933 else if (lstrcmpiW(bstr
, PropValueXSLPatternW
) == 0)
2934 This
->properties
->XPath
= FALSE
;
2938 VariantClear(&varStr
);
2941 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
2943 xmlChar
*nsStr
= (xmlChar
*)This
->properties
->selectNsStr
;
2944 struct list
*pNsList
;
2949 V_VT(&varStr
) = VT_EMPTY
;
2950 if (V_VT(&value
) != VT_BSTR
)
2952 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2954 bstr
= V_BSTR(&varStr
);
2957 bstr
= V_BSTR(&value
);
2961 pNsList
= &(This
->properties
->selectNsList
);
2962 clear_selectNsList(pNsList
);
2964 nsStr
= xmlchar_from_wchar(bstr
);
2966 TRACE("property value: \"%s\"\n", debugstr_w(bstr
));
2968 This
->properties
->selectNsStr
= nsStr
;
2969 This
->properties
->selectNsStr_len
= xmlStrlen(nsStr
);
2972 xmlChar
*pTokBegin
, *pTokEnd
, *pTokInner
;
2973 select_ns_entry
* ns_entry
= NULL
;
2974 xmlXPathContextPtr ctx
;
2976 ctx
= xmlXPathNewContext(This
->node
.node
->doc
);
2979 /* skip leading spaces */
2980 while (*pTokBegin
== ' ' || *pTokBegin
== '\n' ||
2981 *pTokBegin
== '\t' || *pTokBegin
== '\r')
2984 for (; *pTokBegin
; pTokBegin
= pTokEnd
)
2987 memset(ns_entry
, 0, sizeof(select_ns_entry
));
2989 ns_entry
= heap_alloc_zero(sizeof(select_ns_entry
));
2991 while (*pTokBegin
== ' ')
2993 pTokEnd
= pTokBegin
;
2994 while (*pTokEnd
!= ' ' && *pTokEnd
!= 0)
2997 /* so it failed to advance which means we've got some trailing spaces */
2998 if (pTokEnd
== pTokBegin
) break;
3000 if (xmlStrncmp(pTokBegin
, (xmlChar
const*)"xmlns", 5) != 0)
3003 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3004 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
3009 if (*pTokBegin
== '=')
3011 /*valid for XSLPattern?*/
3012 FIXME("Setting default xmlns not supported - skipping.\n");
3015 else if (*pTokBegin
== ':')
3017 ns_entry
->prefix
= ++pTokBegin
;
3018 for (pTokInner
= pTokBegin
; pTokInner
!= pTokEnd
&& *pTokInner
!= '='; ++pTokInner
)
3021 if (pTokInner
== pTokEnd
)
3024 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3025 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
3029 ns_entry
->prefix_end
= *pTokInner
;
3033 if (pTokEnd
-pTokInner
> 1 &&
3034 ((*pTokInner
== '\'' && *(pTokEnd
-1) == '\'') ||
3035 (*pTokInner
== '"' && *(pTokEnd
-1) == '"')))
3037 ns_entry
->href
= ++pTokInner
;
3038 ns_entry
->href_end
= *(pTokEnd
-1);
3040 list_add_tail(pNsList
, &ns_entry
->entry
);
3041 /*let libxml figure out if they're valid from here ;)*/
3042 if (xmlXPathRegisterNs(ctx
, ns_entry
->prefix
, ns_entry
->href
) != 0)
3051 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3052 debugstr_w(bstr
), debugstr_an((const char*)pTokInner
, pTokEnd
-pTokInner
));
3053 list_add_tail(pNsList
, &ns_entry
->entry
);
3066 heap_free(ns_entry
);
3067 xmlXPathFreeContext(ctx
);
3070 VariantClear(&varStr
);
3073 else if (lstrcmpiW(p
, PropertyProhibitDTDW
) == 0 ||
3074 lstrcmpiW(p
, PropertyNewParserW
) == 0 ||
3075 lstrcmpiW(p
, PropertyResolveExternalsW
) == 0)
3078 FIXME("Ignoring property %s, value %s\n", debugstr_w(p
), debugstr_variant(&value
));
3082 FIXME("Unknown property %s\n", debugstr_w(p
));
3086 static HRESULT WINAPI
domdoc_getProperty(
3087 IXMLDOMDocument3
* iface
,
3091 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3093 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
3096 return E_INVALIDARG
;
3098 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
3100 V_VT(var
) = VT_BSTR
;
3101 V_BSTR(var
) = This
->properties
->XPath
?
3102 SysAllocString(PropValueXPathW
) :
3103 SysAllocString(PropValueXSLPatternW
);
3104 return V_BSTR(var
) ? S_OK
: E_OUTOFMEMORY
;
3106 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3109 BSTR rebuiltStr
, cur
;
3110 const xmlChar
*nsStr
;
3111 struct list
*pNsList
;
3112 select_ns_entry
* pNsEntry
;
3114 V_VT(var
) = VT_BSTR
;
3115 nsStr
= This
->properties
->selectNsStr
;
3116 pNsList
= &This
->properties
->selectNsList
;
3117 lenA
= This
->properties
->selectNsStr_len
;
3118 lenW
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, NULL
, 0);
3119 rebuiltStr
= heap_alloc(lenW
*sizeof(WCHAR
));
3120 MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, rebuiltStr
, lenW
);
3122 /* this is fine because all of the chars that end tokens are ASCII*/
3123 LIST_FOR_EACH_ENTRY(pNsEntry
, pNsList
, select_ns_entry
, entry
)
3125 while (*cur
!= 0) ++cur
;
3126 if (pNsEntry
->prefix_end
)
3128 *cur
= pNsEntry
->prefix_end
;
3129 while (*cur
!= 0) ++cur
;
3132 if (pNsEntry
->href_end
)
3134 *cur
= pNsEntry
->href_end
;
3137 V_BSTR(var
) = SysAllocString(rebuiltStr
);
3138 heap_free(rebuiltStr
);
3142 FIXME("Unknown property %s\n", debugstr_w(p
));
3146 static HRESULT WINAPI
domdoc_importNode(
3147 IXMLDOMDocument3
* iface
,
3150 IXMLDOMNode
** clone
)
3152 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3153 FIXME("(%p)->(%p %d %p): stub\n", This
, node
, deep
, clone
);
3157 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl
=
3159 domdoc_QueryInterface
,
3162 domdoc_GetTypeInfoCount
,
3164 domdoc_GetIDsOfNames
,
3166 domdoc_get_nodeName
,
3167 domdoc_get_nodeValue
,
3168 domdoc_put_nodeValue
,
3169 domdoc_get_nodeType
,
3170 domdoc_get_parentNode
,
3171 domdoc_get_childNodes
,
3172 domdoc_get_firstChild
,
3173 domdoc_get_lastChild
,
3174 domdoc_get_previousSibling
,
3175 domdoc_get_nextSibling
,
3176 domdoc_get_attributes
,
3177 domdoc_insertBefore
,
3178 domdoc_replaceChild
,
3181 domdoc_hasChildNodes
,
3182 domdoc_get_ownerDocument
,
3184 domdoc_get_nodeTypeString
,
3187 domdoc_get_specified
,
3188 domdoc_get_definition
,
3189 domdoc_get_nodeTypedValue
,
3190 domdoc_put_nodeTypedValue
,
3191 domdoc_get_dataType
,
3192 domdoc_put_dataType
,
3194 domdoc_transformNode
,
3196 domdoc_selectSingleNode
,
3198 domdoc_get_namespaceURI
,
3200 domdoc_get_baseName
,
3201 domdoc_transformNodeToObject
,
3203 domdoc_get_implementation
,
3204 domdoc_get_documentElement
,
3205 domdoc_put_documentElement
,
3206 domdoc_createElement
,
3207 domdoc_createDocumentFragment
,
3208 domdoc_createTextNode
,
3209 domdoc_createComment
,
3210 domdoc_createCDATASection
,
3211 domdoc_createProcessingInstruction
,
3212 domdoc_createAttribute
,
3213 domdoc_createEntityReference
,
3214 domdoc_getElementsByTagName
,
3218 domdoc_get_readyState
,
3219 domdoc_get_parseError
,
3226 domdoc_get_validateOnParse
,
3227 domdoc_put_validateOnParse
,
3228 domdoc_get_resolveExternals
,
3229 domdoc_put_resolveExternals
,
3230 domdoc_get_preserveWhiteSpace
,
3231 domdoc_put_preserveWhiteSpace
,
3232 domdoc_put_onreadystatechange
,
3233 domdoc_put_onDataAvailable
,
3234 domdoc_put_onTransformNode
,
3235 domdoc_get_namespaces
,
3237 domdoc_putref_schemas
,
3241 domdoc_validateNode
,
3245 /* IConnectionPointContainer */
3246 static HRESULT WINAPI
ConnectionPointContainer_QueryInterface(IConnectionPointContainer
*iface
,
3247 REFIID riid
, void **ppv
)
3249 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3250 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3253 static ULONG WINAPI
ConnectionPointContainer_AddRef(IConnectionPointContainer
*iface
)
3255 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3256 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3259 static ULONG WINAPI
ConnectionPointContainer_Release(IConnectionPointContainer
*iface
)
3261 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3262 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3265 static HRESULT WINAPI
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer
*iface
,
3266 IEnumConnectionPoints
**ppEnum
)
3268 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3269 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3273 static HRESULT WINAPI
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer
*iface
,
3274 REFIID riid
, IConnectionPoint
**cp
)
3276 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3277 ConnectionPoint
*iter
;
3279 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), cp
);
3283 for(iter
= This
->cp_list
; iter
; iter
= iter
->next
)
3285 if (IsEqualGUID(iter
->iid
, riid
))
3286 *cp
= &iter
->IConnectionPoint_iface
;
3291 IConnectionPoint_AddRef(*cp
);
3295 FIXME("unsupported riid %s\n", debugstr_guid(riid
));
3296 return CONNECT_E_NOCONNECTION
;
3300 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl
=
3302 ConnectionPointContainer_QueryInterface
,
3303 ConnectionPointContainer_AddRef
,
3304 ConnectionPointContainer_Release
,
3305 ConnectionPointContainer_EnumConnectionPoints
,
3306 ConnectionPointContainer_FindConnectionPoint
3309 /* IConnectionPoint */
3310 static HRESULT WINAPI
ConnectionPoint_QueryInterface(IConnectionPoint
*iface
,
3311 REFIID riid
, void **ppv
)
3313 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3315 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
3319 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
3320 IsEqualGUID(&IID_IConnectionPoint
, riid
))
3327 IConnectionPoint_AddRef(iface
);
3331 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
3332 return E_NOINTERFACE
;
3335 static ULONG WINAPI
ConnectionPoint_AddRef(IConnectionPoint
*iface
)
3337 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3338 return IConnectionPointContainer_AddRef(This
->container
);
3341 static ULONG WINAPI
ConnectionPoint_Release(IConnectionPoint
*iface
)
3343 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3344 return IConnectionPointContainer_Release(This
->container
);
3347 static HRESULT WINAPI
ConnectionPoint_GetConnectionInterface(IConnectionPoint
*iface
, IID
*iid
)
3349 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3351 TRACE("(%p)->(%p)\n", This
, iid
);
3353 if (!iid
) return E_POINTER
;
3359 static HRESULT WINAPI
ConnectionPoint_GetConnectionPointContainer(IConnectionPoint
*iface
,
3360 IConnectionPointContainer
**container
)
3362 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3364 TRACE("(%p)->(%p)\n", This
, container
);
3366 if (!container
) return E_POINTER
;
3368 *container
= This
->container
;
3369 IConnectionPointContainer_AddRef(*container
);
3373 static HRESULT WINAPI
ConnectionPoint_Advise(IConnectionPoint
*iface
, IUnknown
*unk_sink
,
3376 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3381 TRACE("(%p)->(%p %p)\n", This
, unk_sink
, cookie
);
3383 hr
= IUnknown_QueryInterface(unk_sink
, This
->iid
, (void**)&sink
);
3384 if(FAILED(hr
) && !IsEqualGUID(&IID_IPropertyNotifySink
, This
->iid
))
3385 hr
= IUnknown_QueryInterface(unk_sink
, &IID_IDispatch
, (void**)&sink
);
3387 return CONNECT_E_CANNOTCONNECT
;
3391 for (i
= 0; i
< This
->sinks_size
; i
++)
3392 if (!This
->sinks
[i
].unk
)
3395 if (i
== This
->sinks_size
)
3396 This
->sinks
= heap_realloc(This
->sinks
,(++This
->sinks_size
)*sizeof(*This
->sinks
));
3400 This
->sinks
= heap_alloc(sizeof(*This
->sinks
));
3401 This
->sinks_size
= 1;
3405 This
->sinks
[i
].unk
= sink
;
3412 static HRESULT WINAPI
ConnectionPoint_Unadvise(IConnectionPoint
*iface
, DWORD cookie
)
3414 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3416 TRACE("(%p)->(%d)\n", This
, cookie
);
3418 if (cookie
== 0 || cookie
> This
->sinks_size
|| !This
->sinks
[cookie
-1].unk
)
3419 return CONNECT_E_NOCONNECTION
;
3421 IUnknown_Release(This
->sinks
[cookie
-1].unk
);
3422 This
->sinks
[cookie
-1].unk
= NULL
;
3427 static HRESULT WINAPI
ConnectionPoint_EnumConnections(IConnectionPoint
*iface
,
3428 IEnumConnections
**ppEnum
)
3430 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3431 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3435 static const IConnectionPointVtbl ConnectionPointVtbl
=
3437 ConnectionPoint_QueryInterface
,
3438 ConnectionPoint_AddRef
,
3439 ConnectionPoint_Release
,
3440 ConnectionPoint_GetConnectionInterface
,
3441 ConnectionPoint_GetConnectionPointContainer
,
3442 ConnectionPoint_Advise
,
3443 ConnectionPoint_Unadvise
,
3444 ConnectionPoint_EnumConnections
3447 static void ConnectionPoint_Init(ConnectionPoint
*cp
, struct domdoc
*doc
, REFIID riid
)
3449 cp
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointVtbl
;
3455 cp
->next
= doc
->cp_list
;
3458 cp
->container
= &doc
->IConnectionPointContainer_iface
;
3461 /* domdoc implementation of IObjectWithSite */
3462 static HRESULT WINAPI
3463 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
3465 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3466 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObject
);
3469 static ULONG WINAPI
domdoc_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
3471 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3472 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3475 static ULONG WINAPI
domdoc_ObjectWithSite_Release( IObjectWithSite
* iface
)
3477 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3478 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3481 static HRESULT WINAPI
domdoc_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
3483 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3485 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
3490 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
3493 static HRESULT WINAPI
domdoc_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
3495 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3497 TRACE("(%p)->(%p)\n", iface
, punk
);
3503 IUnknown_Release( This
->site
);
3510 IUnknown_AddRef( punk
);
3513 IUnknown_Release( This
->site
);
3520 static const IObjectWithSiteVtbl domdocObjectSite
=
3522 domdoc_ObjectWithSite_QueryInterface
,
3523 domdoc_ObjectWithSite_AddRef
,
3524 domdoc_ObjectWithSite_Release
,
3525 domdoc_ObjectWithSite_SetSite
,
3526 domdoc_ObjectWithSite_GetSite
3529 static HRESULT WINAPI
domdoc_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
3531 domdoc
*This
= impl_from_IObjectSafety(iface
);
3532 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3535 static ULONG WINAPI
domdoc_Safety_AddRef(IObjectSafety
*iface
)
3537 domdoc
*This
= impl_from_IObjectSafety(iface
);
3538 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3541 static ULONG WINAPI
domdoc_Safety_Release(IObjectSafety
*iface
)
3543 domdoc
*This
= impl_from_IObjectSafety(iface
);
3544 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3547 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3549 static HRESULT WINAPI
domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3550 DWORD
*supported
, DWORD
*enabled
)
3552 domdoc
*This
= impl_from_IObjectSafety(iface
);
3554 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
3556 if(!supported
|| !enabled
) return E_POINTER
;
3558 *supported
= SAFETY_SUPPORTED_OPTIONS
;
3559 *enabled
= This
->safeopt
;
3564 static HRESULT WINAPI
domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3565 DWORD mask
, DWORD enabled
)
3567 domdoc
*This
= impl_from_IObjectSafety(iface
);
3568 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
3570 if ((mask
& ~SAFETY_SUPPORTED_OPTIONS
) != 0)
3573 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
3578 #undef SAFETY_SUPPORTED_OPTIONS
3580 static const IObjectSafetyVtbl domdocObjectSafetyVtbl
= {
3581 domdoc_Safety_QueryInterface
,
3582 domdoc_Safety_AddRef
,
3583 domdoc_Safety_Release
,
3584 domdoc_Safety_GetInterfaceSafetyOptions
,
3585 domdoc_Safety_SetInterfaceSafetyOptions
3588 static const tid_t domdoc_iface_tids
[] = {
3589 IXMLDOMDocument3_tid
,
3593 static dispex_static_data_t domdoc_dispex
= {
3595 IXMLDOMDocument3_tid
,
3600 HRESULT
get_domdoc_from_xmldoc(xmlDocPtr xmldoc
, IXMLDOMDocument3
**document
)
3604 doc
= heap_alloc( sizeof (*doc
) );
3606 return E_OUTOFMEMORY
;
3608 doc
->IXMLDOMDocument3_iface
.lpVtbl
= &XMLDOMDocument3Vtbl
;
3609 doc
->IPersistStreamInit_iface
.lpVtbl
= &xmldoc_IPersistStreamInit_VTable
;
3610 doc
->IObjectWithSite_iface
.lpVtbl
= &domdocObjectSite
;
3611 doc
->IObjectSafety_iface
.lpVtbl
= &domdocObjectSafetyVtbl
;
3612 doc
->IConnectionPointContainer_iface
.lpVtbl
= &ConnectionPointContainerVtbl
;
3614 doc
->async
= VARIANT_TRUE
;
3615 doc
->validating
= 0;
3617 doc
->properties
= properties_from_xmlDocPtr(xmldoc
);
3621 doc
->cp_list
= NULL
;
3622 doc
->namespaces
= NULL
;
3623 memset(doc
->events
, 0, sizeof(doc
->events
));
3625 /* events connection points */
3626 ConnectionPoint_Init(&doc
->cp_dispatch
, doc
, &IID_IDispatch
);
3627 ConnectionPoint_Init(&doc
->cp_propnotif
, doc
, &IID_IPropertyNotifySink
);
3628 ConnectionPoint_Init(&doc
->cp_domdocevents
, doc
, &DIID_XMLDOMDocumentEvents
);
3630 init_xmlnode(&doc
->node
, (xmlNodePtr
)xmldoc
, (IXMLDOMNode
*)&doc
->IXMLDOMDocument3_iface
,
3633 *document
= &doc
->IXMLDOMDocument3_iface
;
3635 TRACE("returning iface %p\n", *document
);
3639 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3644 TRACE("(%d, %p)\n", version
, ppObj
);
3646 xmldoc
= xmlNewDoc(NULL
);
3648 return E_OUTOFMEMORY
;
3650 xmldoc_init(xmldoc
, version
);
3652 hr
= get_domdoc_from_xmldoc(xmldoc
, (IXMLDOMDocument3
**)ppObj
);
3655 free_properties(properties_from_xmlDocPtr(xmldoc
));
3656 heap_free(xmldoc
->_private
);
3664 IUnknown
* create_domdoc( xmlNodePtr document
)
3666 IUnknown
*obj
= NULL
;
3669 TRACE("(%p)\n", document
);
3671 hr
= get_domdoc_from_xmldoc((xmlDocPtr
)document
, (IXMLDOMDocument3
**)&obj
);
3680 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3682 MESSAGE("This program tried to use a DOMDocument object, but\n"
3683 "libxml2 support was not present at compile time.\n");