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
27 # include <libxml/xpathInternals.h>
28 # include <libxml/xmlsave.h>
29 # include <libxml/SAX2.h>
30 # include <libxml/parserInternals.h>
38 /* not defined in older versions */
39 #define XML_SAVE_FORMAT 1
40 #define XML_SAVE_NO_DECL 2
41 #define XML_SAVE_NO_EMPTY 4
42 #define XML_SAVE_NO_XHTML 8
43 #define XML_SAVE_XHTML 16
44 #define XML_SAVE_AS_XML 32
45 #define XML_SAVE_AS_HTML 64
47 static const WCHAR PropertySelectionLanguageW
[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
48 static const WCHAR PropertySelectionNamespacesW
[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
49 static const WCHAR PropertyProhibitDTDW
[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
50 static const WCHAR PropertyNewParserW
[] = {'N','e','w','P','a','r','s','e','r',0};
51 static const WCHAR PropValueXPathW
[] = {'X','P','a','t','h',0};
52 static const WCHAR PropValueXSLPatternW
[] = {'X','S','L','P','a','t','t','e','r','n',0};
53 static const WCHAR PropertyResolveExternalsW
[] = {'R','e','s','o','l','v','e','E','x','t','e','r','n','a','l','s',0};
54 static const WCHAR PropertyAllowXsltScriptW
[] = {'A','l','l','o','w','X','s','l','t','S','c','r','i','p','t',0};
55 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};
57 /* Anything that passes the test_get_ownerDocument()
58 * tests can go here (data shared between all instances).
59 * We need to preserve this when reloading a document,
60 * and also need access to it from the libxml backend. */
62 MSXML_VERSION version
;
63 VARIANT_BOOL preserving
;
64 IXMLDOMSchemaCollection2
* schemaCache
;
65 struct list selectNsList
;
66 xmlChar
const* selectNsStr
;
72 typedef struct ConnectionPoint ConnectionPoint
;
73 typedef struct domdoc domdoc
;
75 struct ConnectionPoint
77 IConnectionPoint IConnectionPoint_iface
;
80 ConnectionPoint
*next
;
81 IConnectionPointContainer
*container
;
88 IPropertyNotifySink
*propnotif
;
94 EVENTID_READYSTATECHANGE
= 0,
95 EVENTID_DATAAVAILABLE
,
96 EVENTID_TRANSFORMNODE
,
103 IXMLDOMDocument3 IXMLDOMDocument3_iface
;
104 IPersistStreamInit IPersistStreamInit_iface
;
105 IObjectWithSite IObjectWithSite_iface
;
106 IObjectSafety IObjectSafety_iface
;
107 IConnectionPointContainer IConnectionPointContainer_iface
;
110 VARIANT_BOOL validating
;
111 VARIANT_BOOL resolving
;
112 domdoc_properties
* properties
;
115 /* IObjectWithSite */
121 /* connection list */
122 ConnectionPoint
*cp_list
;
123 ConnectionPoint cp_domdocevents
;
124 ConnectionPoint cp_propnotif
;
125 ConnectionPoint cp_dispatch
;
128 IDispatch
*events
[EVENTID_LAST
];
130 IXMLDOMSchemaCollection2
*namespaces
;
133 static HRESULT
set_doc_event(domdoc
*doc
, eventid_t eid
, const VARIANT
*v
)
141 IUnknown_QueryInterface(V_UNKNOWN(v
), &IID_IDispatch
, (void**)&disp
);
146 disp
= V_DISPATCH(v
);
147 if (disp
) IDispatch_AddRef(disp
);
150 return DISP_E_TYPEMISMATCH
;
153 if (doc
->events
[eid
]) IDispatch_Release(doc
->events
[eid
]);
154 doc
->events
[eid
] = disp
;
159 static inline ConnectionPoint
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
161 return CONTAINING_RECORD(iface
, ConnectionPoint
, IConnectionPoint_iface
);
165 In native windows, the whole lifetime management of XMLDOMNodes is
166 managed automatically using reference counts. Wine emulates that by
167 maintaining a reference count to the document that is increased for
168 each IXMLDOMNode pointer passed out for this document. If all these
169 pointers are gone, the document is unreachable and gets freed, that
170 is, all nodes in the tree of the document get freed.
172 You are able to create nodes that are associated to a document (in
173 fact, in msxml's XMLDOM model, all nodes are associated to a document),
174 but not in the tree of that document, for example using the createFoo
175 functions from IXMLDOMDocument. These nodes do not get cleaned up
176 by libxml, so we have to do it ourselves.
178 To catch these nodes, a list of "orphan nodes" is introduced.
179 It contains pointers to all roots of node trees that are
180 associated with the document without being part of the document
181 tree. All nodes with parent==NULL (except for the document root nodes)
182 should be in the orphan node list of their document. All orphan nodes
183 get freed together with the document itself.
186 typedef struct _xmldoc_priv
{
189 domdoc_properties
* properties
;
192 typedef struct _orphan_entry
{
197 typedef struct _select_ns_entry
{
199 xmlChar
const* prefix
;
205 static inline xmldoc_priv
* priv_from_xmlDocPtr(const xmlDocPtr doc
)
207 return doc
->_private
;
210 static inline domdoc_properties
* properties_from_xmlDocPtr(xmlDocPtr doc
)
212 return priv_from_xmlDocPtr(doc
)->properties
;
215 BOOL
is_xpathmode(const xmlDocPtr doc
)
217 return properties_from_xmlDocPtr(doc
)->XPath
;
220 void set_xpathmode(xmlDocPtr doc
, BOOL xpath
)
222 properties_from_xmlDocPtr(doc
)->XPath
= xpath
;
225 int registerNamespaces(xmlXPathContextPtr ctxt
)
228 const select_ns_entry
* ns
= NULL
;
229 const struct list
* pNsList
= &properties_from_xmlDocPtr(ctxt
->doc
)->selectNsList
;
231 TRACE("(%p)\n", ctxt
);
233 LIST_FOR_EACH_ENTRY( ns
, pNsList
, select_ns_entry
, entry
)
235 xmlXPathRegisterNs(ctxt
, ns
->prefix
, ns
->href
);
242 static inline void clear_selectNsList(struct list
* pNsList
)
244 select_ns_entry
*ns
, *ns2
;
245 LIST_FOR_EACH_ENTRY_SAFE( ns
, ns2
, pNsList
, select_ns_entry
, entry
)
252 static xmldoc_priv
* create_priv(void)
255 priv
= heap_alloc( sizeof (*priv
) );
260 list_init( &priv
->orphans
);
261 priv
->properties
= NULL
;
267 static domdoc_properties
*create_properties(MSXML_VERSION version
)
269 domdoc_properties
*properties
= heap_alloc(sizeof(domdoc_properties
));
271 list_init(&properties
->selectNsList
);
272 properties
->preserving
= VARIANT_FALSE
;
273 properties
->schemaCache
= NULL
;
274 properties
->selectNsStr
= heap_alloc_zero(sizeof(xmlChar
));
275 properties
->selectNsStr_len
= 0;
277 /* properties that are dependent on object versions */
278 properties
->version
= version
;
279 properties
->XPath
= (version
== MSXML4
|| version
== MSXML6
);
282 properties
->url
= NULL
;
287 static domdoc_properties
* copy_properties(domdoc_properties
const* properties
)
289 domdoc_properties
* pcopy
= heap_alloc(sizeof(domdoc_properties
));
290 select_ns_entry
const* ns
= NULL
;
291 select_ns_entry
* new_ns
= NULL
;
292 int len
= (properties
->selectNsStr_len
+1)*sizeof(xmlChar
);
297 pcopy
->version
= properties
->version
;
298 pcopy
->preserving
= properties
->preserving
;
299 pcopy
->schemaCache
= properties
->schemaCache
;
300 if (pcopy
->schemaCache
)
301 IXMLDOMSchemaCollection2_AddRef(pcopy
->schemaCache
);
302 pcopy
->XPath
= properties
->XPath
;
303 pcopy
->selectNsStr_len
= properties
->selectNsStr_len
;
304 list_init( &pcopy
->selectNsList
);
305 pcopy
->selectNsStr
= heap_alloc(len
);
306 memcpy((xmlChar
*)pcopy
->selectNsStr
, properties
->selectNsStr
, len
);
307 offset
= pcopy
->selectNsStr
- properties
->selectNsStr
;
309 LIST_FOR_EACH_ENTRY( ns
, (&properties
->selectNsList
), select_ns_entry
, entry
)
311 new_ns
= heap_alloc(sizeof(select_ns_entry
));
312 memcpy(new_ns
, ns
, sizeof(select_ns_entry
));
313 new_ns
->href
+= offset
;
314 new_ns
->prefix
+= offset
;
315 list_add_tail(&pcopy
->selectNsList
, &new_ns
->entry
);
320 int len
= strlenW(properties
->url
);
322 pcopy
->url
= CoTaskMemAlloc((len
+1)*sizeof(WCHAR
));
323 memcpy(pcopy
->url
, properties
->url
, len
*sizeof(WCHAR
));
333 static void free_properties(domdoc_properties
* properties
)
337 if (properties
->schemaCache
)
338 IXMLDOMSchemaCollection2_Release(properties
->schemaCache
);
339 clear_selectNsList(&properties
->selectNsList
);
340 heap_free((xmlChar
*)properties
->selectNsStr
);
341 CoTaskMemFree(properties
->url
);
342 heap_free(properties
);
346 static void release_namespaces(domdoc
*This
)
348 if (This
->namespaces
)
350 IXMLDOMSchemaCollection2_Release(This
->namespaces
);
351 This
->namespaces
= NULL
;
355 /* links a "<?xml" node as a first child */
356 void xmldoc_link_xmldecl(xmlDocPtr doc
, xmlNodePtr node
)
359 if (doc
->standalone
!= -1) xmlAddPrevSibling( doc
->children
, node
);
362 /* unlinks a first "<?xml" child if it was created */
363 xmlNodePtr
xmldoc_unlink_xmldecl(xmlDocPtr doc
)
365 static const xmlChar xmlA
[] = "xml";
366 xmlNodePtr node
, first_child
;
370 /* xml declaration node could be created automatically after parsing or added
372 first_child
= doc
->children
;
373 if (first_child
&& first_child
->type
== XML_PI_NODE
&& xmlStrEqual(first_child
->name
, xmlA
))
376 xmlUnlinkNode( node
);
384 BOOL
is_preserving_whitespace(xmlNodePtr node
)
386 domdoc_properties
* properties
= NULL
;
387 /* during parsing the xmlDoc._private stuff is not there */
388 if (priv_from_xmlDocPtr(node
->doc
))
389 properties
= properties_from_xmlDocPtr(node
->doc
);
390 return ((properties
&& properties
->preserving
== VARIANT_TRUE
) ||
391 xmlNodeGetSpacePreserve(node
) == 1);
394 static inline BOOL
strn_isspace(xmlChar
const* str
, int len
)
396 for (; str
&& len
> 0 && *str
; ++str
, --len
)
403 static void sax_characters(void *ctx
, const xmlChar
*ch
, int len
)
405 xmlParserCtxtPtr ctxt
;
408 ctxt
= (xmlParserCtxtPtr
) ctx
;
409 This
= (const domdoc
*) ctxt
->_private
;
413 xmlChar cur
= *(ctxt
->input
->cur
);
415 /* Characters are reported with multiple calls, for example each charref is reported with a separate
416 call and then parser appends it to a single text node or creates a new node if not created.
417 It's not possible to tell if it's ignorable data or not just looking at data itself cause it could be
418 space chars that separate charrefs or similar case. We only need to skip leading and trailing spaces,
419 or whole node if it has nothing but space chars, so to detect leading space node->last is checked that
420 contains text node pointer if already created, trailing spaces are detected directly looking at parser input
421 for next '<' opening bracket - similar logic is used by libxml2 itself. Basically 'cur' == '<' means the last
422 chunk of char data, in case it's not the last chunk we check for previously added node type and if it's not
423 a text node it's safe to ignore.
425 Note that during domdoc_loadXML() the xmlDocPtr->_private data is not available. */
427 if (!This
->properties
->preserving
&&
428 !is_preserving_whitespace(ctxt
->node
) &&
429 strn_isspace(ch
, len
) &&
430 (!ctxt
->node
->last
||
431 ((ctxt
->node
->last
&& (cur
== '<' || ctxt
->node
->last
->type
!= XML_TEXT_NODE
))
434 /* Keep information about ignorable whitespace text node in previous or parent node */
435 if (ctxt
->node
->last
)
436 *(DWORD
*)&ctxt
->node
->last
->_private
|= NODE_PRIV_TRAILING_IGNORABLE_WS
;
437 else if (ctxt
->node
->type
!= XML_DOCUMENT_NODE
)
438 *(DWORD
*)&ctxt
->node
->_private
|= NODE_PRIV_CHILD_IGNORABLE_WS
;
443 xmlSAX2Characters(ctxt
, ch
, len
);
446 static void LIBXML2_LOG_CALLBACK
sax_error(void* ctx
, char const* msg
, ...)
450 LIBXML2_CALLBACK_ERR(doparse
, msg
, ap
);
454 static void LIBXML2_LOG_CALLBACK
sax_warning(void* ctx
, char const* msg
, ...)
458 LIBXML2_CALLBACK_WARN(doparse
, msg
, ap
);
462 static void sax_serror(void* ctx
, xmlErrorPtr err
)
464 LIBXML2_CALLBACK_SERROR(doparse
, err
);
467 static xmlDocPtr
doparse(domdoc
* This
, char const* ptr
, int len
, xmlCharEncoding encoding
)
469 xmlDocPtr doc
= NULL
;
470 xmlParserCtxtPtr pctx
;
471 static xmlSAXHandler sax_handler
= {
472 xmlSAX2InternalSubset
, /* internalSubset */
473 xmlSAX2IsStandalone
, /* isStandalone */
474 xmlSAX2HasInternalSubset
, /* hasInternalSubset */
475 xmlSAX2HasExternalSubset
, /* hasExternalSubset */
476 xmlSAX2ResolveEntity
, /* resolveEntity */
477 xmlSAX2GetEntity
, /* getEntity */
478 xmlSAX2EntityDecl
, /* entityDecl */
479 xmlSAX2NotationDecl
, /* notationDecl */
480 xmlSAX2AttributeDecl
, /* attributeDecl */
481 xmlSAX2ElementDecl
, /* elementDecl */
482 xmlSAX2UnparsedEntityDecl
, /* unparsedEntityDecl */
483 xmlSAX2SetDocumentLocator
, /* setDocumentLocator */
484 xmlSAX2StartDocument
, /* startDocument */
485 xmlSAX2EndDocument
, /* endDocument */
486 xmlSAX2StartElement
, /* startElement */
487 xmlSAX2EndElement
, /* endElement */
488 xmlSAX2Reference
, /* reference */
489 sax_characters
, /* characters */
490 sax_characters
, /* ignorableWhitespace */
491 xmlSAX2ProcessingInstruction
, /* processingInstruction */
492 xmlSAX2Comment
, /* comment */
493 sax_warning
, /* warning */
494 sax_error
, /* error */
495 sax_error
, /* fatalError */
496 xmlSAX2GetParameterEntity
, /* getParameterEntity */
497 xmlSAX2CDataBlock
, /* cdataBlock */
498 xmlSAX2ExternalSubset
, /* externalSubset */
501 xmlSAX2StartElementNs
, /* startElementNs */
502 xmlSAX2EndElementNs
, /* endElementNs */
503 sax_serror
/* serror */
506 pctx
= xmlCreateMemoryParserCtxt(ptr
, len
);
509 ERR("Failed to create parser context\n");
513 if (pctx
->sax
) xmlFree(pctx
->sax
);
514 pctx
->sax
= &sax_handler
;
515 pctx
->_private
= This
;
518 if (encoding
!= XML_CHAR_ENCODING_NONE
)
519 xmlSwitchEncoding(pctx
, encoding
);
521 xmlParseDocument(pctx
);
523 if (pctx
->wellFormed
)
529 xmlFreeDoc(pctx
->myDoc
);
533 xmlFreeParserCtxt(pctx
);
535 /* TODO: put this in one of the SAX callbacks */
536 /* create first child as a <?xml...?> */
537 if (doc
&& doc
->standalone
!= -1)
541 xmlChar
*xmlbuff
= (xmlChar
*)buff
;
543 node
= xmlNewDocPI( doc
, (xmlChar
*)"xml", NULL
);
545 /* version attribute can't be omitted */
546 sprintf(buff
, "version=\"%s\"", doc
->version
? (char*)doc
->version
: "1.0");
547 xmlNodeAddContent( node
, xmlbuff
);
551 sprintf(buff
, " encoding=\"%s\"", doc
->encoding
);
552 xmlNodeAddContent( node
, xmlbuff
);
555 if (doc
->standalone
!= -2)
557 sprintf(buff
, " standalone=\"%s\"", doc
->standalone
== 0 ? "no" : "yes");
558 xmlNodeAddContent( node
, xmlbuff
);
561 xmldoc_link_xmldecl( doc
, node
);
567 void xmldoc_init(xmlDocPtr doc
, MSXML_VERSION version
)
569 doc
->_private
= create_priv();
570 priv_from_xmlDocPtr(doc
)->properties
= create_properties(version
);
573 LONG
xmldoc_add_refs(xmlDocPtr doc
, LONG refs
)
575 LONG ref
= InterlockedExchangeAdd(&priv_from_xmlDocPtr(doc
)->refs
, refs
) + refs
;
576 TRACE("(%p)->(%d)\n", doc
, ref
);
580 LONG
xmldoc_add_ref(xmlDocPtr doc
)
582 return xmldoc_add_refs(doc
, 1);
585 LONG
xmldoc_release_refs(xmlDocPtr doc
, LONG refs
)
587 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
588 LONG ref
= InterlockedExchangeAdd(&priv
->refs
, -refs
) - refs
;
589 TRACE("(%p)->(%d)\n", doc
, ref
);
592 WARN("negative refcount, expect troubles\n");
596 orphan_entry
*orphan
, *orphan2
;
597 TRACE("freeing docptr %p\n", doc
);
599 LIST_FOR_EACH_ENTRY_SAFE( orphan
, orphan2
, &priv
->orphans
, orphan_entry
, entry
)
601 xmlFreeNode( orphan
->node
);
604 free_properties(priv
->properties
);
605 heap_free(doc
->_private
);
613 LONG
xmldoc_release(xmlDocPtr doc
)
615 return xmldoc_release_refs(doc
, 1);
618 HRESULT
xmldoc_add_orphan(xmlDocPtr doc
, xmlNodePtr node
)
620 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
623 entry
= heap_alloc( sizeof (*entry
) );
625 return E_OUTOFMEMORY
;
628 list_add_head( &priv
->orphans
, &entry
->entry
);
632 HRESULT
xmldoc_remove_orphan(xmlDocPtr doc
, xmlNodePtr node
)
634 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
635 orphan_entry
*entry
, *entry2
;
637 LIST_FOR_EACH_ENTRY_SAFE( entry
, entry2
, &priv
->orphans
, orphan_entry
, entry
)
639 if( entry
->node
== node
)
641 list_remove( &entry
->entry
);
650 static inline xmlDocPtr
get_doc( domdoc
*This
)
652 return This
->node
.node
->doc
;
655 static HRESULT
attach_xmldoc(domdoc
*This
, xmlDocPtr xml
)
657 release_namespaces(This
);
661 priv_from_xmlDocPtr(get_doc(This
))->properties
= NULL
;
662 if (xmldoc_release(get_doc(This
)) != 0)
663 priv_from_xmlDocPtr(get_doc(This
))->properties
=
664 copy_properties(This
->properties
);
667 This
->node
.node
= (xmlNodePtr
) xml
;
671 xmldoc_add_ref(get_doc(This
));
672 priv_from_xmlDocPtr(get_doc(This
))->properties
= This
->properties
;
678 static inline domdoc
*impl_from_IXMLDOMDocument3( IXMLDOMDocument3
*iface
)
680 return CONTAINING_RECORD(iface
, domdoc
, IXMLDOMDocument3_iface
);
683 static inline domdoc
*impl_from_IPersistStreamInit(IPersistStreamInit
*iface
)
685 return CONTAINING_RECORD(iface
, domdoc
, IPersistStreamInit_iface
);
688 static inline domdoc
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
690 return CONTAINING_RECORD(iface
, domdoc
, IObjectWithSite_iface
);
693 static inline domdoc
*impl_from_IObjectSafety(IObjectSafety
*iface
)
695 return CONTAINING_RECORD(iface
, domdoc
, IObjectSafety_iface
);
698 static inline domdoc
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
700 return CONTAINING_RECORD(iface
, domdoc
, IConnectionPointContainer_iface
);
703 /************************************************************************
704 * domdoc implementation of IPersistStream.
706 static HRESULT WINAPI
PersistStreamInit_QueryInterface(
707 IPersistStreamInit
*iface
, REFIID riid
, void **ppvObj
)
709 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
710 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObj
);
713 static ULONG WINAPI
PersistStreamInit_AddRef(
714 IPersistStreamInit
*iface
)
716 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
717 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
720 static ULONG WINAPI
PersistStreamInit_Release(
721 IPersistStreamInit
*iface
)
723 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
724 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
727 static HRESULT WINAPI
PersistStreamInit_GetClassID(
728 IPersistStreamInit
*iface
, CLSID
*classid
)
730 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
731 TRACE("(%p)->(%p)\n", This
, classid
);
736 *classid
= *DOMDocument_version(This
->properties
->version
);
741 static HRESULT WINAPI
PersistStreamInit_IsDirty(
742 IPersistStreamInit
*iface
)
744 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
745 FIXME("(%p): stub!\n", This
);
749 static HRESULT
domdoc_load_from_stream(domdoc
*doc
, ISequentialStream
*stream
)
751 DWORD read
, written
, len
;
752 xmlDocPtr xmldoc
= NULL
;
760 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &hstream
);
766 ISequentialStream_Read(stream
, buf
, sizeof(buf
), &read
);
767 hr
= IStream_Write(hstream
, buf
, read
, &written
);
768 } while(SUCCEEDED(hr
) && written
!= 0 && read
!= 0);
772 ERR("failed to copy stream 0x%08x\n", hr
);
773 IStream_Release(hstream
);
777 hr
= GetHGlobalFromStream(hstream
, &hglobal
);
781 len
= GlobalSize(hglobal
);
782 ptr
= GlobalLock(hglobal
);
784 xmldoc
= doparse(doc
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
785 GlobalUnlock(hglobal
);
789 ERR("Failed to parse xml\n");
793 xmldoc
->_private
= create_priv();
795 return attach_xmldoc(doc
, xmldoc
);
798 static HRESULT WINAPI
PersistStreamInit_Load(IPersistStreamInit
*iface
, IStream
*stream
)
800 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
802 TRACE("(%p)->(%p)\n", This
, stream
);
807 return domdoc_load_from_stream(This
, (ISequentialStream
*)stream
);
810 static HRESULT WINAPI
PersistStreamInit_Save(
811 IPersistStreamInit
*iface
, IStream
*stream
, BOOL clr_dirty
)
813 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
817 TRACE("(%p)->(%p %d)\n", This
, stream
, clr_dirty
);
819 hr
= IXMLDOMDocument3_get_xml(&This
->IXMLDOMDocument3_iface
, &xmlString
);
822 DWORD len
= SysStringLen(xmlString
) * sizeof(WCHAR
);
824 hr
= IStream_Write( stream
, xmlString
, len
, NULL
);
825 SysFreeString(xmlString
);
828 TRACE("ret 0x%08x\n", hr
);
833 static HRESULT WINAPI
PersistStreamInit_GetSizeMax(
834 IPersistStreamInit
*iface
, ULARGE_INTEGER
*pcbSize
)
836 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
837 TRACE("(%p)->(%p)\n", This
, pcbSize
);
841 static HRESULT WINAPI
PersistStreamInit_InitNew(
842 IPersistStreamInit
*iface
)
844 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
845 TRACE("(%p)\n", This
);
849 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable
=
851 PersistStreamInit_QueryInterface
,
852 PersistStreamInit_AddRef
,
853 PersistStreamInit_Release
,
854 PersistStreamInit_GetClassID
,
855 PersistStreamInit_IsDirty
,
856 PersistStreamInit_Load
,
857 PersistStreamInit_Save
,
858 PersistStreamInit_GetSizeMax
,
859 PersistStreamInit_InitNew
862 /* IXMLDOMDocument3 interface */
864 static const tid_t domdoc_se_tids
[] = {
867 IXMLDOMDocument2_tid
,
868 IXMLDOMDocument3_tid
,
872 static HRESULT WINAPI
domdoc_QueryInterface( IXMLDOMDocument3
*iface
, REFIID riid
, void** ppvObject
)
874 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
876 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( riid
), ppvObject
);
880 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
881 IsEqualGUID( riid
, &IID_IDispatch
) ||
882 IsEqualGUID( riid
, &IID_IXMLDOMNode
) ||
883 IsEqualGUID( riid
, &IID_IXMLDOMDocument
) ||
884 IsEqualGUID( riid
, &IID_IXMLDOMDocument2
)||
885 IsEqualGUID( riid
, &IID_IXMLDOMDocument3
))
889 else if (IsEqualGUID(&IID_IPersistStream
, riid
) ||
890 IsEqualGUID(&IID_IPersistStreamInit
, riid
))
892 *ppvObject
= &This
->IPersistStreamInit_iface
;
894 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
896 *ppvObject
= &This
->IObjectWithSite_iface
;
898 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
900 *ppvObject
= &This
->IObjectSafety_iface
;
902 else if( IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
904 return node_create_supporterrorinfo(domdoc_se_tids
, ppvObject
);
906 else if(node_query_interface(&This
->node
, riid
, ppvObject
))
908 return *ppvObject
? S_OK
: E_NOINTERFACE
;
910 else if (IsEqualGUID( riid
, &IID_IConnectionPointContainer
))
912 *ppvObject
= &This
->IConnectionPointContainer_iface
;
916 TRACE("interface %s not implemented\n", debugstr_guid(riid
));
917 return E_NOINTERFACE
;
920 IUnknown_AddRef((IUnknown
*)*ppvObject
);
925 static ULONG WINAPI
domdoc_AddRef( IXMLDOMDocument3
*iface
)
927 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
928 ULONG ref
= InterlockedIncrement( &This
->ref
);
929 TRACE("(%p)->(%d)\n", This
, ref
);
933 static ULONG WINAPI
domdoc_Release( IXMLDOMDocument3
*iface
)
935 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
936 LONG ref
= InterlockedDecrement( &This
->ref
);
938 TRACE("(%p)->(%d)\n", This
, ref
);
945 IUnknown_Release( This
->site
);
946 destroy_xmlnode(&This
->node
);
948 for (eid
= 0; eid
< EVENTID_LAST
; eid
++)
949 if (This
->events
[eid
]) IDispatch_Release(This
->events
[eid
]);
951 release_namespaces(This
);
958 static HRESULT WINAPI
domdoc_GetTypeInfoCount( IXMLDOMDocument3
*iface
, UINT
* pctinfo
)
960 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
961 return IDispatchEx_GetTypeInfoCount(&This
->node
.dispex
.IDispatchEx_iface
, pctinfo
);
964 static HRESULT WINAPI
domdoc_GetTypeInfo(
965 IXMLDOMDocument3
*iface
,
966 UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
968 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
969 return IDispatchEx_GetTypeInfo(&This
->node
.dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
972 static HRESULT WINAPI
domdoc_GetIDsOfNames(
973 IXMLDOMDocument3
*iface
,
980 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
981 return IDispatchEx_GetIDsOfNames(&This
->node
.dispex
.IDispatchEx_iface
,
982 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
985 static HRESULT WINAPI
domdoc_Invoke(
986 IXMLDOMDocument3
*iface
,
991 DISPPARAMS
* pDispParams
,
993 EXCEPINFO
* pExcepInfo
,
996 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
997 return IDispatchEx_Invoke(&This
->node
.dispex
.IDispatchEx_iface
,
998 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1001 static HRESULT WINAPI
domdoc_get_nodeName(
1002 IXMLDOMDocument3
*iface
,
1005 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1007 static const WCHAR documentW
[] = {'#','d','o','c','u','m','e','n','t',0};
1009 TRACE("(%p)->(%p)\n", This
, name
);
1011 return return_bstr(documentW
, name
);
1015 static HRESULT WINAPI
domdoc_get_nodeValue(
1016 IXMLDOMDocument3
*iface
,
1019 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1021 TRACE("(%p)->(%p)\n", This
, value
);
1024 return E_INVALIDARG
;
1026 V_VT(value
) = VT_NULL
;
1027 V_BSTR(value
) = NULL
; /* tests show that we should do this */
1032 static HRESULT WINAPI
domdoc_put_nodeValue(
1033 IXMLDOMDocument3
*iface
,
1036 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1037 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&value
));
1042 static HRESULT WINAPI
domdoc_get_nodeType(
1043 IXMLDOMDocument3
*iface
,
1046 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1048 TRACE("(%p)->(%p)\n", This
, type
);
1050 *type
= NODE_DOCUMENT
;
1055 static HRESULT WINAPI
domdoc_get_parentNode(
1056 IXMLDOMDocument3
*iface
,
1057 IXMLDOMNode
** parent
)
1059 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1061 TRACE("(%p)->(%p)\n", This
, parent
);
1063 return node_get_parent(&This
->node
, parent
);
1067 static HRESULT WINAPI
domdoc_get_childNodes(
1068 IXMLDOMDocument3
*iface
,
1069 IXMLDOMNodeList
** childList
)
1071 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1073 TRACE("(%p)->(%p)\n", This
, childList
);
1075 return node_get_child_nodes(&This
->node
, childList
);
1079 static HRESULT WINAPI
domdoc_get_firstChild(
1080 IXMLDOMDocument3
*iface
,
1081 IXMLDOMNode
** firstChild
)
1083 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1085 TRACE("(%p)->(%p)\n", This
, firstChild
);
1087 return node_get_first_child(&This
->node
, firstChild
);
1091 static HRESULT WINAPI
domdoc_get_lastChild(
1092 IXMLDOMDocument3
*iface
,
1093 IXMLDOMNode
** lastChild
)
1095 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1097 TRACE("(%p)->(%p)\n", This
, lastChild
);
1099 return node_get_last_child(&This
->node
, lastChild
);
1103 static HRESULT WINAPI
domdoc_get_previousSibling(
1104 IXMLDOMDocument3
*iface
,
1105 IXMLDOMNode
** previousSibling
)
1107 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1109 TRACE("(%p)->(%p)\n", This
, previousSibling
);
1111 return return_null_node(previousSibling
);
1115 static HRESULT WINAPI
domdoc_get_nextSibling(
1116 IXMLDOMDocument3
*iface
,
1117 IXMLDOMNode
** nextSibling
)
1119 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1121 TRACE("(%p)->(%p)\n", This
, nextSibling
);
1123 return return_null_node(nextSibling
);
1127 static HRESULT WINAPI
domdoc_get_attributes(
1128 IXMLDOMDocument3
*iface
,
1129 IXMLDOMNamedNodeMap
** attributeMap
)
1131 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1133 TRACE("(%p)->(%p)\n", This
, attributeMap
);
1135 return return_null_ptr((void**)attributeMap
);
1139 static HRESULT WINAPI
domdoc_insertBefore(
1140 IXMLDOMDocument3
*iface
,
1141 IXMLDOMNode
* newChild
,
1143 IXMLDOMNode
** outNewChild
)
1145 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1149 TRACE("(%p)->(%p %s %p)\n", This
, newChild
, debugstr_variant(&refChild
), outNewChild
);
1151 hr
= IXMLDOMNode_get_nodeType(newChild
, &type
);
1152 if (hr
!= S_OK
) return hr
;
1154 TRACE("new node type %d\n", type
);
1157 case NODE_ATTRIBUTE
:
1159 case NODE_CDATA_SECTION
:
1160 if (outNewChild
) *outNewChild
= NULL
;
1163 return node_insert_before(&This
->node
, newChild
, &refChild
, outNewChild
);
1167 static HRESULT WINAPI
domdoc_replaceChild(
1168 IXMLDOMDocument3
*iface
,
1169 IXMLDOMNode
* newChild
,
1170 IXMLDOMNode
* oldChild
,
1171 IXMLDOMNode
** outOldChild
)
1173 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1175 TRACE("(%p)->(%p %p %p)\n", This
, newChild
, oldChild
, outOldChild
);
1177 return node_replace_child(&This
->node
, newChild
, oldChild
, outOldChild
);
1181 static HRESULT WINAPI
domdoc_removeChild(
1182 IXMLDOMDocument3
*iface
,
1184 IXMLDOMNode
**oldChild
)
1186 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1187 TRACE("(%p)->(%p %p)\n", This
, child
, oldChild
);
1188 return node_remove_child(&This
->node
, child
, oldChild
);
1192 static HRESULT WINAPI
domdoc_appendChild(
1193 IXMLDOMDocument3
*iface
,
1195 IXMLDOMNode
**outChild
)
1197 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1198 TRACE("(%p)->(%p %p)\n", This
, child
, outChild
);
1199 return node_append_child(&This
->node
, child
, outChild
);
1203 static HRESULT WINAPI
domdoc_hasChildNodes(
1204 IXMLDOMDocument3
*iface
,
1207 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1208 TRACE("(%p)->(%p)\n", This
, ret
);
1209 return node_has_childnodes(&This
->node
, ret
);
1213 static HRESULT WINAPI
domdoc_get_ownerDocument(
1214 IXMLDOMDocument3
*iface
,
1215 IXMLDOMDocument
**doc
)
1217 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1218 TRACE("(%p)->(%p)\n", This
, doc
);
1219 return node_get_owner_doc(&This
->node
, doc
);
1223 static HRESULT WINAPI
domdoc_cloneNode(
1224 IXMLDOMDocument3
*iface
,
1226 IXMLDOMNode
** outNode
)
1228 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1231 TRACE("(%p)->(%d %p)\n", This
, deep
, outNode
);
1234 return E_INVALIDARG
;
1238 clone
= xmlCopyNode((xmlNodePtr
)get_doc(This
), deep
? 1 : 2);
1242 clone
->doc
->_private
= create_priv();
1243 xmldoc_add_orphan(clone
->doc
, clone
);
1244 xmldoc_add_ref(clone
->doc
);
1246 priv_from_xmlDocPtr(clone
->doc
)->properties
= copy_properties(This
->properties
);
1247 if (!(*outNode
= (IXMLDOMNode
*)create_domdoc(clone
)))
1249 xmldoc_release(clone
->doc
);
1257 static HRESULT WINAPI
domdoc_get_nodeTypeString(
1258 IXMLDOMDocument3
*iface
,
1261 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1262 static const WCHAR documentW
[] = {'d','o','c','u','m','e','n','t',0};
1264 TRACE("(%p)->(%p)\n", This
, p
);
1266 return return_bstr(documentW
, p
);
1270 static HRESULT WINAPI
domdoc_get_text(
1271 IXMLDOMDocument3
*iface
,
1274 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1275 TRACE("(%p)->(%p)\n", This
, p
);
1276 return node_get_text(&This
->node
, p
);
1280 static HRESULT WINAPI
domdoc_put_text(
1281 IXMLDOMDocument3
*iface
,
1284 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1285 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
1290 static HRESULT WINAPI
domdoc_get_specified(
1291 IXMLDOMDocument3
*iface
,
1292 VARIANT_BOOL
* isSpecified
)
1294 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1295 FIXME("(%p)->(%p) stub!\n", This
, isSpecified
);
1296 *isSpecified
= VARIANT_TRUE
;
1301 static HRESULT WINAPI
domdoc_get_definition(
1302 IXMLDOMDocument3
*iface
,
1303 IXMLDOMNode
** definitionNode
)
1305 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1306 FIXME("(%p)->(%p)\n", This
, definitionNode
);
1311 static HRESULT WINAPI
domdoc_get_nodeTypedValue(
1312 IXMLDOMDocument3
*iface
,
1315 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1316 TRACE("(%p)->(%p)\n", This
, v
);
1317 return return_null_var(v
);
1320 static HRESULT WINAPI
domdoc_put_nodeTypedValue(
1321 IXMLDOMDocument3
*iface
,
1322 VARIANT typedValue
)
1324 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1325 FIXME("(%p)->(%s)\n", This
, debugstr_variant(&typedValue
));
1330 static HRESULT WINAPI
domdoc_get_dataType(
1331 IXMLDOMDocument3
*iface
,
1334 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1335 TRACE("(%p)->(%p)\n", This
, typename
);
1336 return return_null_var( typename
);
1340 static HRESULT WINAPI
domdoc_put_dataType(
1341 IXMLDOMDocument3
*iface
,
1344 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1346 FIXME("(%p)->(%s)\n", This
, debugstr_w(dataTypeName
));
1349 return E_INVALIDARG
;
1354 static int XMLCALL
domdoc_get_xml_writecallback(void *ctx
, const char *data
, int len
)
1356 return xmlBufferAdd((xmlBufferPtr
)ctx
, (xmlChar
*)data
, len
) == 0 ? len
: 0;
1359 static HRESULT WINAPI
domdoc_get_xml(
1360 IXMLDOMDocument3
*iface
,
1363 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1364 xmlSaveCtxtPtr ctxt
;
1369 TRACE("(%p)->(%p)\n", This
, p
);
1372 return E_INVALIDARG
;
1376 buf
= xmlBufferCreate();
1378 return E_OUTOFMEMORY
;
1380 options
= XML_SAVE_FORMAT
| XML_SAVE_NO_DECL
;
1381 ctxt
= xmlSaveToIO(domdoc_get_xml_writecallback
, NULL
, buf
, "UTF-8", options
);
1386 return E_OUTOFMEMORY
;
1389 ret
= xmlSaveDoc(ctxt
, get_doc(This
));
1390 /* flushes on close */
1393 TRACE("%ld, len=%d\n", ret
, xmlBufferLength(buf
));
1394 if(ret
!= -1 && xmlBufferLength(buf
) > 0)
1398 content
= bstr_from_xmlChar(xmlBufferContent(buf
));
1399 content
= EnsureCorrectEOL(content
);
1405 *p
= SysAllocStringLen(NULL
, 0);
1410 return *p
? S_OK
: E_OUTOFMEMORY
;
1414 static HRESULT WINAPI
domdoc_transformNode(
1415 IXMLDOMDocument3
*iface
,
1419 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1420 TRACE("(%p)->(%p %p)\n", This
, node
, p
);
1421 return node_transform_node(&This
->node
, node
, p
);
1425 static HRESULT WINAPI
domdoc_selectNodes(
1426 IXMLDOMDocument3
*iface
,
1428 IXMLDOMNodeList
**outList
)
1430 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1431 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outList
);
1432 return node_select_nodes(&This
->node
, p
, outList
);
1436 static HRESULT WINAPI
domdoc_selectSingleNode(
1437 IXMLDOMDocument3
*iface
,
1439 IXMLDOMNode
**outNode
)
1441 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1442 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outNode
);
1443 return node_select_singlenode(&This
->node
, p
, outNode
);
1447 static HRESULT WINAPI
domdoc_get_parsed(
1448 IXMLDOMDocument3
*iface
,
1449 VARIANT_BOOL
* isParsed
)
1451 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1452 FIXME("(%p)->(%p) stub!\n", This
, isParsed
);
1453 *isParsed
= VARIANT_TRUE
;
1457 static HRESULT WINAPI
domdoc_get_namespaceURI(
1458 IXMLDOMDocument3
*iface
,
1459 BSTR
* namespaceURI
)
1461 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1462 TRACE("(%p)->(%p)\n", This
, namespaceURI
);
1463 return return_null_bstr( namespaceURI
);
1466 static HRESULT WINAPI
domdoc_get_prefix(
1467 IXMLDOMDocument3
*iface
,
1470 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1471 TRACE("(%p)->(%p)\n", This
, prefix
);
1472 return return_null_bstr( prefix
);
1476 static HRESULT WINAPI
domdoc_get_baseName(
1477 IXMLDOMDocument3
*iface
,
1480 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1481 TRACE("(%p)->(%p)\n", This
, name
);
1482 return return_null_bstr( name
);
1486 static HRESULT WINAPI
domdoc_transformNodeToObject(
1487 IXMLDOMDocument3
*iface
,
1488 IXMLDOMNode
* stylesheet
,
1489 VARIANT outputObject
)
1491 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1492 FIXME("(%p)->(%p %s)\n", This
, stylesheet
, debugstr_variant(&outputObject
));
1497 static HRESULT WINAPI
domdoc_get_doctype(
1498 IXMLDOMDocument3
*iface
,
1499 IXMLDOMDocumentType
** doctype
)
1501 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1506 TRACE("(%p)->(%p)\n", This
, doctype
);
1508 if (!doctype
) return E_INVALIDARG
;
1512 dtd
= xmlGetIntSubset(get_doc(This
));
1513 if (!dtd
) return S_FALSE
;
1515 node
= create_node((xmlNodePtr
)dtd
);
1516 if (!node
) return S_FALSE
;
1518 hr
= IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentType
, (void**)doctype
);
1519 IXMLDOMNode_Release(node
);
1525 static HRESULT WINAPI
domdoc_get_implementation(
1526 IXMLDOMDocument3
*iface
,
1527 IXMLDOMImplementation
** impl
)
1529 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1531 TRACE("(%p)->(%p)\n", This
, impl
);
1534 return E_INVALIDARG
;
1536 *impl
= (IXMLDOMImplementation
*)create_doc_Implementation();
1541 static HRESULT WINAPI
domdoc_get_documentElement(
1542 IXMLDOMDocument3
*iface
,
1543 IXMLDOMElement
** DOMElement
)
1545 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1546 IXMLDOMNode
*element_node
;
1550 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1553 return E_INVALIDARG
;
1557 root
= xmlDocGetRootElement( get_doc(This
) );
1561 element_node
= create_node( root
);
1562 if(!element_node
) return S_FALSE
;
1564 hr
= IXMLDOMNode_QueryInterface(element_node
, &IID_IXMLDOMElement
, (void**)DOMElement
);
1565 IXMLDOMNode_Release(element_node
);
1571 static HRESULT WINAPI
domdoc_put_documentElement(
1572 IXMLDOMDocument3
*iface
,
1573 IXMLDOMElement
* DOMElement
)
1575 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1576 IXMLDOMNode
*elementNode
;
1583 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1585 hr
= IXMLDOMElement_QueryInterface( DOMElement
, &IID_IXMLDOMNode
, (void**)&elementNode
);
1589 xmlNode
= get_node_obj( elementNode
);
1590 if(!xmlNode
) return E_FAIL
;
1592 if(!xmlNode
->node
->parent
)
1593 if(xmldoc_remove_orphan(xmlNode
->node
->doc
, xmlNode
->node
) != S_OK
)
1594 WARN("%p is not an orphan of %p\n", xmlNode
->node
->doc
, xmlNode
->node
);
1596 old_doc
= xmlNode
->node
->doc
;
1597 if (old_doc
!= get_doc(This
))
1598 refcount
= xmlnode_get_inst_cnt(xmlNode
);
1600 /* old root is still orphaned by its document, update refcount from new root */
1601 if (refcount
) xmldoc_add_refs(get_doc(This
), refcount
);
1602 oldRoot
= xmlDocSetRootElement( get_doc(This
), xmlNode
->node
);
1603 if (refcount
) xmldoc_release_refs(old_doc
, refcount
);
1604 IXMLDOMNode_Release( elementNode
);
1607 xmldoc_add_orphan(oldRoot
->doc
, oldRoot
);
1613 static HRESULT WINAPI
domdoc_createElement(
1614 IXMLDOMDocument3
*iface
,
1616 IXMLDOMElement
** element
)
1618 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1623 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(tagname
), element
);
1625 if (!element
|| !tagname
) return E_INVALIDARG
;
1627 V_VT(&type
) = VT_I1
;
1628 V_I1(&type
) = NODE_ELEMENT
;
1630 hr
= IXMLDOMDocument3_createNode(iface
, type
, tagname
, NULL
, &node
);
1633 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMElement
, (void**)element
);
1634 IXMLDOMNode_Release(node
);
1641 static HRESULT WINAPI
domdoc_createDocumentFragment(
1642 IXMLDOMDocument3
*iface
,
1643 IXMLDOMDocumentFragment
** frag
)
1645 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1650 TRACE("(%p)->(%p)\n", This
, frag
);
1652 if (!frag
) return E_INVALIDARG
;
1656 V_VT(&type
) = VT_I1
;
1657 V_I1(&type
) = NODE_DOCUMENT_FRAGMENT
;
1659 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1662 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentFragment
, (void**)frag
);
1663 IXMLDOMNode_Release(node
);
1670 static HRESULT WINAPI
domdoc_createTextNode(
1671 IXMLDOMDocument3
*iface
,
1673 IXMLDOMText
** text
)
1675 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1680 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), text
);
1682 if (!text
) return E_INVALIDARG
;
1686 V_VT(&type
) = VT_I1
;
1687 V_I1(&type
) = NODE_TEXT
;
1689 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1692 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMText
, (void**)text
);
1693 IXMLDOMNode_Release(node
);
1694 hr
= IXMLDOMText_put_data(*text
, data
);
1701 static HRESULT WINAPI
domdoc_createComment(
1702 IXMLDOMDocument3
*iface
,
1704 IXMLDOMComment
** comment
)
1706 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1711 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), comment
);
1713 if (!comment
) return E_INVALIDARG
;
1717 V_VT(&type
) = VT_I1
;
1718 V_I1(&type
) = NODE_COMMENT
;
1720 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1723 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMComment
, (void**)comment
);
1724 IXMLDOMNode_Release(node
);
1725 hr
= IXMLDOMComment_put_data(*comment
, data
);
1732 static HRESULT WINAPI
domdoc_createCDATASection(
1733 IXMLDOMDocument3
*iface
,
1735 IXMLDOMCDATASection
** cdata
)
1737 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1742 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), cdata
);
1744 if (!cdata
) return E_INVALIDARG
;
1748 V_VT(&type
) = VT_I1
;
1749 V_I1(&type
) = NODE_CDATA_SECTION
;
1751 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1754 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMCDATASection
, (void**)cdata
);
1755 IXMLDOMNode_Release(node
);
1756 hr
= IXMLDOMCDATASection_put_data(*cdata
, data
);
1763 static HRESULT WINAPI
domdoc_createProcessingInstruction(
1764 IXMLDOMDocument3
*iface
,
1767 IXMLDOMProcessingInstruction
** pi
)
1769 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1774 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_w(target
), debugstr_w(data
), pi
);
1776 if (!pi
) return E_INVALIDARG
;
1780 V_VT(&type
) = VT_I1
;
1781 V_I1(&type
) = NODE_PROCESSING_INSTRUCTION
;
1783 hr
= IXMLDOMDocument3_createNode(iface
, type
, target
, NULL
, &node
);
1788 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1789 node_obj
= get_node_obj(node
);
1790 hr
= node_set_content(node_obj
, data
);
1792 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMProcessingInstruction
, (void**)pi
);
1793 IXMLDOMNode_Release(node
);
1800 static HRESULT WINAPI
domdoc_createAttribute(
1801 IXMLDOMDocument3
*iface
,
1803 IXMLDOMAttribute
** attribute
)
1805 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1810 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), attribute
);
1812 if (!attribute
|| !name
) return E_INVALIDARG
;
1814 V_VT(&type
) = VT_I1
;
1815 V_I1(&type
) = NODE_ATTRIBUTE
;
1817 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1820 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMAttribute
, (void**)attribute
);
1821 IXMLDOMNode_Release(node
);
1828 static HRESULT WINAPI
domdoc_createEntityReference(
1829 IXMLDOMDocument3
*iface
,
1831 IXMLDOMEntityReference
** entityref
)
1833 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1838 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), entityref
);
1840 if (!entityref
) return E_INVALIDARG
;
1844 V_VT(&type
) = VT_I1
;
1845 V_I1(&type
) = NODE_ENTITY_REFERENCE
;
1847 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1850 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMEntityReference
, (void**)entityref
);
1851 IXMLDOMNode_Release(node
);
1857 xmlChar
* tagName_to_XPath(const BSTR tagName
)
1859 xmlChar
*query
, *tmp
;
1860 static const xmlChar everything
[] = "/descendant::node()";
1861 static const xmlChar mod_pre
[] = "*[local-name()='";
1862 static const xmlChar mod_post
[] = "']";
1863 static const xmlChar prefix
[] = "descendant::";
1864 const WCHAR
*tokBegin
, *tokEnd
;
1867 /* Special case - empty tagname - means select all nodes,
1868 except document itself. */
1870 return xmlStrdup(everything
);
1872 query
= xmlStrdup(prefix
);
1875 while (tokBegin
&& *tokBegin
)
1880 query
= xmlStrcat(query
, BAD_CAST
"/");
1884 query
= xmlStrcat(query
, BAD_CAST
"*");
1888 query
= xmlStrcat(query
, mod_pre
);
1890 while (*tokEnd
&& *tokEnd
!= '/')
1892 len
= WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, NULL
, 0, NULL
, NULL
);
1893 tmp
= xmlMalloc(len
);
1894 WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, (char*)tmp
, len
, NULL
, NULL
);
1895 query
= xmlStrncat(query
, tmp
, len
);
1898 query
= xmlStrcat(query
, mod_post
);
1905 static HRESULT WINAPI
domdoc_getElementsByTagName(
1906 IXMLDOMDocument3
*iface
,
1908 IXMLDOMNodeList
** resultList
)
1910 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1915 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(tagName
), resultList
);
1917 if (!tagName
|| !resultList
) return E_INVALIDARG
;
1919 XPath
= This
->properties
->XPath
;
1920 This
->properties
->XPath
= TRUE
;
1921 query
= tagName_to_XPath(tagName
);
1922 hr
= create_selection((xmlNodePtr
)get_doc(This
), query
, resultList
);
1924 This
->properties
->XPath
= XPath
;
1929 static HRESULT
get_node_type(VARIANT Type
, DOMNodeType
* type
)
1935 hr
= VariantChangeType(&tmp
, &Type
, 0, VT_I4
);
1937 return E_INVALIDARG
;
1944 static HRESULT WINAPI
domdoc_createNode(
1945 IXMLDOMDocument3
*iface
,
1949 IXMLDOMNode
** node
)
1951 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1952 DOMNodeType node_type
;
1954 xmlChar
*xml_name
, *href
;
1957 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_variant(&Type
), debugstr_w(name
), debugstr_w(namespaceURI
), node
);
1959 if(!node
) return E_INVALIDARG
;
1961 hr
= get_node_type(Type
, &node_type
);
1962 if(FAILED(hr
)) return hr
;
1964 TRACE("node_type %d\n", node_type
);
1966 /* exit earlier for types that need name */
1970 case NODE_ATTRIBUTE
:
1971 case NODE_ENTITY_REFERENCE
:
1972 case NODE_PROCESSING_INSTRUCTION
:
1973 if (!name
|| *name
== 0) return E_FAIL
;
1979 xml_name
= xmlchar_from_wchar(name
);
1980 /* prevent empty href from being allocated */
1981 href
= namespaceURI
? xmlchar_from_wchar(namespaceURI
) : NULL
;
1987 xmlChar
*local
, *prefix
;
1989 local
= xmlSplitQName2(xml_name
, &prefix
);
1991 xmlnode
= xmlNewDocNode(get_doc(This
), NULL
, local
? local
: xml_name
, NULL
);
1993 /* allow creating the default namespace xmlns= */
1994 if (local
|| (href
&& *href
))
1996 xmlNsPtr ns
= xmlNewNs(xmlnode
, href
, prefix
);
1997 xmlSetNs(xmlnode
, ns
);
2005 case NODE_ATTRIBUTE
:
2007 xmlChar
*local
, *prefix
;
2009 local
= xmlSplitQName2(xml_name
, &prefix
);
2011 xmlnode
= (xmlNodePtr
)xmlNewDocProp(get_doc(This
), local
? local
: xml_name
, NULL
);
2013 if (local
|| (href
&& *href
))
2015 /* we need a floating namespace here, it can't be created linked to attribute from
2017 xmlNsPtr ns
= xmlNewNs(NULL
, href
, prefix
);
2018 xmlSetNs(xmlnode
, ns
);
2027 xmlnode
= (xmlNodePtr
)xmlNewDocText(get_doc(This
), NULL
);
2029 case NODE_CDATA_SECTION
:
2030 xmlnode
= xmlNewCDataBlock(get_doc(This
), NULL
, 0);
2032 case NODE_ENTITY_REFERENCE
:
2033 xmlnode
= xmlNewReference(get_doc(This
), xml_name
);
2035 case NODE_PROCESSING_INSTRUCTION
:
2036 #ifdef HAVE_XMLNEWDOCPI
2037 xmlnode
= xmlNewDocPI(get_doc(This
), xml_name
, NULL
);
2039 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2044 xmlnode
= xmlNewDocComment(get_doc(This
), NULL
);
2046 case NODE_DOCUMENT_FRAGMENT
:
2047 xmlnode
= xmlNewDocFragment(get_doc(This
));
2049 /* unsupported types */
2051 case NODE_DOCUMENT_TYPE
:
2054 heap_free(xml_name
);
2055 return E_INVALIDARG
;
2057 FIXME("unhandled node type %d\n", node_type
);
2062 *node
= create_node(xmlnode
);
2063 heap_free(xml_name
);
2068 TRACE("created node (%d, %p, %p)\n", node_type
, *node
, xmlnode
);
2069 xmldoc_add_orphan(xmlnode
->doc
, xmlnode
);
2076 static HRESULT WINAPI
domdoc_nodeFromID(
2077 IXMLDOMDocument3
*iface
,
2079 IXMLDOMNode
** node
)
2081 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2082 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(idString
), node
);
2086 static HRESULT
domdoc_onDataAvailable(void *obj
, char *ptr
, DWORD len
)
2091 xmldoc
= doparse(This
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
2093 xmldoc
->_private
= create_priv();
2094 return attach_xmldoc(This
, xmldoc
);
2100 static HRESULT
domdoc_load_moniker(domdoc
*This
, IMoniker
*mon
)
2105 hr
= bind_url(mon
, domdoc_onDataAvailable
, This
, &bsc
);
2109 return detach_bsc(bsc
);
2112 static HRESULT WINAPI
domdoc_load(
2113 IXMLDOMDocument3
*iface
,
2115 VARIANT_BOOL
* isSuccessful
)
2117 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2118 LPWSTR filename
= NULL
;
2119 HRESULT hr
= S_FALSE
;
2122 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&source
));
2126 *isSuccessful
= VARIANT_FALSE
;
2128 assert( &This
->node
);
2130 switch( V_VT(&source
) )
2133 filename
= V_BSTR(&source
);
2135 case VT_BSTR
|VT_BYREF
:
2136 if (!V_BSTRREF(&source
)) return E_INVALIDARG
;
2137 filename
= *V_BSTRREF(&source
);
2139 case VT_ARRAY
|VT_UI1
:
2141 SAFEARRAY
*psa
= V_ARRAY(&source
);
2144 UINT dim
= SafeArrayGetDim(psa
);
2149 ERR("SAFEARRAY == NULL\n");
2150 hr
= This
->error
= E_INVALIDARG
;
2153 /* Only takes UTF-8 strings.
2154 * NOT NULL-terminated. */
2155 hr
= SafeArrayAccessData(psa
, (void**)&str
);
2159 WARN("failed to access array data, 0x%08x\n", hr
);
2162 SafeArrayGetUBound(psa
, 1, &len
);
2164 if ((xmldoc
= doparse(This
, str
, ++len
, XML_CHAR_ENCODING_UTF8
)))
2166 hr
= This
->error
= S_OK
;
2167 *isSuccessful
= VARIANT_TRUE
;
2168 TRACE("parsed document %p\n", xmldoc
);
2172 This
->error
= E_FAIL
;
2173 TRACE("failed to parse document\n");
2176 SafeArrayUnaccessData(psa
);
2180 xmldoc
->_private
= create_priv();
2181 return attach_xmldoc(This
, xmldoc
);
2185 FIXME("unhandled SAFEARRAY dim: %d\n", dim
);
2186 hr
= This
->error
= E_NOTIMPL
;
2192 ISequentialStream
*stream
= NULL
;
2193 IXMLDOMDocument3
*newdoc
= NULL
;
2195 if (!V_UNKNOWN(&source
)) return E_INVALIDARG
;
2197 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IXMLDOMDocument3
, (void**)&newdoc
);
2202 domdoc
*newDoc
= impl_from_IXMLDOMDocument3( newdoc
);
2204 xmldoc
= xmlCopyDoc(get_doc(newDoc
), 1);
2205 xmldoc
->_private
= create_priv();
2206 hr
= attach_xmldoc(This
, xmldoc
);
2209 *isSuccessful
= VARIANT_TRUE
;
2215 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IStream
, (void**)&stream
);
2217 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_ISequentialStream
, (void**)&stream
);
2221 hr
= domdoc_load_from_stream(This
, stream
);
2223 *isSuccessful
= VARIANT_TRUE
;
2224 ISequentialStream_Release(stream
);
2228 FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr
, V_UNKNOWN(&source
)->lpVtbl
);
2232 FIXME("VT type not supported (%d)\n", V_VT(&source
));
2239 CoTaskMemFree(This
->properties
->url
);
2240 This
->properties
->url
= NULL
;
2242 hr
= create_moniker_from_url( filename
, &mon
);
2243 if ( SUCCEEDED(hr
) )
2245 hr
= domdoc_load_moniker( This
, mon
);
2247 IMoniker_GetDisplayName(mon
, NULL
, NULL
, &This
->properties
->url
);
2248 IMoniker_Release(mon
);
2252 This
->error
= E_FAIL
;
2255 hr
= This
->error
= S_OK
;
2256 *isSuccessful
= VARIANT_TRUE
;
2260 if(!filename
|| FAILED(hr
)) {
2261 xmldoc
= xmlNewDoc(NULL
);
2262 xmldoc
->_private
= create_priv();
2263 hr
= attach_xmldoc(This
, xmldoc
);
2268 TRACE("ret (%d)\n", hr
);
2274 static HRESULT WINAPI
domdoc_get_readyState(
2275 IXMLDOMDocument3
*iface
,
2278 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2279 FIXME("stub! (%p)->(%p)\n", This
, value
);
2282 return E_INVALIDARG
;
2284 *value
= READYSTATE_COMPLETE
;
2289 static HRESULT WINAPI
domdoc_get_parseError(
2290 IXMLDOMDocument3
*iface
,
2291 IXMLDOMParseError
** errorObj
)
2293 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2294 static const WCHAR err
[] = {'e','r','r','o','r',0};
2295 BSTR error_string
= NULL
;
2297 FIXME("(%p)->(%p): creating a dummy parseError\n", iface
, errorObj
);
2300 error_string
= SysAllocString(err
);
2302 *errorObj
= create_parseError(This
->error
, NULL
, error_string
, NULL
, 0, 0, 0);
2303 if(!*errorObj
) return E_OUTOFMEMORY
;
2308 static HRESULT WINAPI
domdoc_get_url(
2309 IXMLDOMDocument3
*iface
,
2312 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2314 TRACE("(%p)->(%p)\n", This
, url
);
2317 return E_INVALIDARG
;
2319 if (This
->properties
->url
)
2321 *url
= SysAllocString(This
->properties
->url
);
2323 return E_OUTOFMEMORY
;
2328 return return_null_bstr(url
);
2332 static HRESULT WINAPI
domdoc_get_async(
2333 IXMLDOMDocument3
*iface
,
2334 VARIANT_BOOL
* isAsync
)
2336 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2338 TRACE("(%p)->(%p: %d)\n", This
, isAsync
, This
->async
);
2339 *isAsync
= This
->async
;
2344 static HRESULT WINAPI
domdoc_put_async(
2345 IXMLDOMDocument3
*iface
,
2346 VARIANT_BOOL isAsync
)
2348 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2350 TRACE("(%p)->(%d)\n", This
, isAsync
);
2351 This
->async
= isAsync
;
2356 static HRESULT WINAPI
domdoc_abort(
2357 IXMLDOMDocument3
*iface
)
2359 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2360 FIXME("%p\n", This
);
2364 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2365 static HRESULT WINAPI
domdoc_loadXML(
2366 IXMLDOMDocument3
*iface
,
2368 VARIANT_BOOL
* isSuccessful
)
2370 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2371 xmlDocPtr xmldoc
= NULL
;
2372 HRESULT hr
= S_FALSE
, hr2
;
2374 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), isSuccessful
);
2376 assert ( &This
->node
);
2380 *isSuccessful
= VARIANT_FALSE
;
2386 /* skip leading spaces if needed */
2387 if (This
->properties
->version
== MSXML_DEFAULT
|| This
->properties
->version
== MSXML26
)
2388 while (*ptr
&& isspaceW(*ptr
)) ptr
++;
2390 xmldoc
= doparse(This
, (char*)ptr
, strlenW(ptr
)*sizeof(WCHAR
), XML_CHAR_ENCODING_UTF16LE
);
2393 This
->error
= E_FAIL
;
2394 TRACE("failed to parse document\n");
2398 hr
= This
->error
= S_OK
;
2399 *isSuccessful
= VARIANT_TRUE
;
2400 TRACE("parsed document %p\n", xmldoc
);
2406 xmldoc
= xmlNewDoc(NULL
);
2407 xmldoc
->_private
= create_priv();
2408 hr2
= attach_xmldoc(This
, xmldoc
);
2415 static int XMLCALL
domdoc_save_writecallback(void *ctx
, const char *buffer
, int len
)
2419 if(!WriteFile(ctx
, buffer
, len
, &written
, NULL
))
2421 WARN("write error\n");
2428 static int XMLCALL
domdoc_save_closecallback(void *ctx
)
2430 return CloseHandle(ctx
) ? 0 : -1;
2433 static int XMLCALL
domdoc_stream_save_writecallback(void *ctx
, const char *buffer
, int len
)
2438 hr
= IStream_Write((IStream
*)ctx
, buffer
, len
, &written
);
2439 TRACE("0x%08x %p %d %u\n", hr
, buffer
, len
, written
);
2442 WARN("stream write error: 0x%08x\n", hr
);
2449 static int XMLCALL
domdoc_stream_save_closecallback(void *ctx
)
2451 IStream_Release((IStream
*)ctx
);
2455 static HRESULT WINAPI
domdoc_save(
2456 IXMLDOMDocument3
*iface
,
2457 VARIANT destination
)
2459 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2460 xmlSaveCtxtPtr ctx
= NULL
;
2464 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&destination
));
2466 switch (V_VT(&destination
))
2470 IUnknown
*pUnk
= V_UNKNOWN(&destination
);
2471 IXMLDOMDocument3
*document
;
2474 ret
= IUnknown_QueryInterface(pUnk
, &IID_IXMLDOMDocument3
, (void**)&document
);
2477 VARIANT_BOOL success
;
2480 ret
= IXMLDOMDocument3_get_xml(iface
, &xml
);
2483 ret
= IXMLDOMDocument3_loadXML(document
, xml
, &success
);
2487 IXMLDOMDocument3_Release(document
);
2491 ret
= IUnknown_QueryInterface(pUnk
, &IID_IStream
, (void**)&stream
);
2494 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2495 ctx
= xmlSaveToIO(domdoc_stream_save_writecallback
,
2496 domdoc_stream_save_closecallback
, stream
, NULL
, options
);
2500 IStream_Release(stream
);
2508 case VT_BSTR
| VT_BYREF
:
2510 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2512 /* save with file path */
2513 HANDLE handle
= CreateFileW( (V_VT(&destination
) & VT_BYREF
)? *V_BSTRREF(&destination
) : V_BSTR(&destination
),
2514 GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2515 if( handle
== INVALID_HANDLE_VALUE
)
2517 WARN("failed to create file\n");
2521 /* disable top XML declaration */
2522 ctx
= xmlSaveToIO(domdoc_save_writecallback
, domdoc_save_closecallback
,
2523 handle
, NULL
, options
);
2526 CloseHandle(handle
);
2533 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination
));
2537 xmldecl
= xmldoc_unlink_xmldecl(get_doc(This
));
2538 if (xmlSaveDoc(ctx
, get_doc(This
)) == -1) ret
= S_FALSE
;
2539 xmldoc_link_xmldecl(get_doc(This
), xmldecl
);
2541 /* will release resources through close callback */
2547 static HRESULT WINAPI
domdoc_get_validateOnParse(
2548 IXMLDOMDocument3
*iface
,
2549 VARIANT_BOOL
* isValidating
)
2551 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2552 TRACE("(%p)->(%p: %d)\n", This
, isValidating
, This
->validating
);
2553 *isValidating
= This
->validating
;
2558 static HRESULT WINAPI
domdoc_put_validateOnParse(
2559 IXMLDOMDocument3
*iface
,
2560 VARIANT_BOOL isValidating
)
2562 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2563 TRACE("(%p)->(%d)\n", This
, isValidating
);
2564 This
->validating
= isValidating
;
2569 static HRESULT WINAPI
domdoc_get_resolveExternals(
2570 IXMLDOMDocument3
*iface
,
2571 VARIANT_BOOL
* isResolving
)
2573 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2574 TRACE("(%p)->(%p: %d)\n", This
, isResolving
, This
->resolving
);
2575 *isResolving
= This
->resolving
;
2580 static HRESULT WINAPI
domdoc_put_resolveExternals(
2581 IXMLDOMDocument3
*iface
,
2582 VARIANT_BOOL isResolving
)
2584 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2585 TRACE("(%p)->(%d)\n", This
, isResolving
);
2586 This
->resolving
= isResolving
;
2591 static HRESULT WINAPI
domdoc_get_preserveWhiteSpace(
2592 IXMLDOMDocument3
*iface
,
2593 VARIANT_BOOL
* isPreserving
)
2595 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2596 TRACE("(%p)->(%p: %d)\n", This
, isPreserving
, This
->properties
->preserving
);
2597 *isPreserving
= This
->properties
->preserving
;
2602 static HRESULT WINAPI
domdoc_put_preserveWhiteSpace(
2603 IXMLDOMDocument3
*iface
,
2604 VARIANT_BOOL isPreserving
)
2606 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2607 TRACE("(%p)->(%d)\n", This
, isPreserving
);
2608 This
->properties
->preserving
= isPreserving
;
2613 static HRESULT WINAPI
domdoc_put_onreadystatechange(
2614 IXMLDOMDocument3
*iface
,
2617 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2619 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&event
));
2620 return set_doc_event(This
, EVENTID_READYSTATECHANGE
, &event
);
2624 static HRESULT WINAPI
domdoc_put_onDataAvailable(IXMLDOMDocument3
*iface
, VARIANT sink
)
2626 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2627 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2631 static HRESULT WINAPI
domdoc_put_onTransformNode(IXMLDOMDocument3
*iface
, VARIANT sink
)
2633 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2634 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2638 static HRESULT WINAPI
domdoc_get_namespaces(
2639 IXMLDOMDocument3
* iface
,
2640 IXMLDOMSchemaCollection
** collection
)
2642 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2645 FIXME("(%p)->(%p): semi-stub\n", This
, collection
);
2647 if (!collection
) return E_POINTER
;
2649 if (!This
->namespaces
)
2651 hr
= SchemaCache_create(This
->properties
->version
, (void**)&This
->namespaces
);
2652 if (hr
!= S_OK
) return hr
;
2654 hr
= cache_from_doc_ns(This
->namespaces
, &This
->node
);
2656 release_namespaces(This
);
2659 if (This
->namespaces
)
2660 return IXMLDOMSchemaCollection2_QueryInterface(This
->namespaces
,
2661 &IID_IXMLDOMSchemaCollection
, (void**)collection
);
2666 static HRESULT WINAPI
domdoc_get_schemas(
2667 IXMLDOMDocument3
* iface
,
2670 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2671 IXMLDOMSchemaCollection2
* cur_schema
= This
->properties
->schemaCache
;
2672 HRESULT hr
= S_FALSE
;
2674 TRACE("(%p)->(%p)\n", This
, schema
);
2676 V_VT(schema
) = VT_NULL
;
2677 /* just to reset pointer part, cause that's what application is expected to use */
2678 V_DISPATCH(schema
) = NULL
;
2682 hr
= IXMLDOMSchemaCollection2_QueryInterface(cur_schema
, &IID_IDispatch
, (void**)&V_DISPATCH(schema
));
2684 V_VT(schema
) = VT_DISPATCH
;
2689 static HRESULT WINAPI
domdoc_putref_schemas(
2690 IXMLDOMDocument3
* iface
,
2693 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2694 HRESULT hr
= E_FAIL
;
2695 IXMLDOMSchemaCollection2
* new_schema
= NULL
;
2697 FIXME("(%p)->(%s): semi-stub\n", This
, debugstr_variant(&schema
));
2698 switch(V_VT(&schema
))
2701 if (V_UNKNOWN(&schema
))
2703 hr
= IUnknown_QueryInterface(V_UNKNOWN(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2708 if (V_DISPATCH(&schema
))
2710 hr
= IDispatch_QueryInterface(V_DISPATCH(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2720 WARN("Can't get schema from vt %x\n", V_VT(&schema
));
2725 IXMLDOMSchemaCollection2
* old_schema
= InterlockedExchangePointer((void**)&This
->properties
->schemaCache
, new_schema
);
2726 if(old_schema
) IXMLDOMSchemaCollection2_Release(old_schema
);
2732 static inline BOOL
is_wellformed(xmlDocPtr doc
)
2734 #ifdef HAVE_XMLDOC_PROPERTIES
2735 return doc
->properties
& XML_DOC_WELLFORMED
;
2737 /* Not a full check, but catches the worst violations */
2741 for (child
= doc
->children
; child
!= NULL
; child
= child
->next
)
2743 switch (child
->type
)
2745 case XML_ELEMENT_NODE
:
2750 case XML_CDATA_SECTION_NODE
:
2762 static void LIBXML2_LOG_CALLBACK
validate_error(void* ctx
, char const* msg
, ...)
2766 LIBXML2_CALLBACK_ERR(domdoc_validateNode
, msg
, ap
);
2770 static void LIBXML2_LOG_CALLBACK
validate_warning(void* ctx
, char const* msg
, ...)
2774 LIBXML2_CALLBACK_WARN(domdoc_validateNode
, msg
, ap
);
2778 static HRESULT WINAPI
domdoc_validateNode(
2779 IXMLDOMDocument3
* iface
,
2781 IXMLDOMParseError
** err
)
2783 domdoc
* This
= impl_from_IXMLDOMDocument3(iface
);
2784 LONG state
, err_code
= 0;
2788 TRACE("(%p)->(%p, %p)\n", This
, node
, err
);
2789 IXMLDOMDocument3_get_readyState(iface
, &state
);
2790 if (state
!= READYSTATE_COMPLETE
)
2793 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2800 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2804 if (!get_node_obj(node
)->node
|| get_node_obj(node
)->node
->doc
!= get_doc(This
))
2807 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2811 if (!is_wellformed(get_doc(This
)))
2813 ERR("doc not well-formed\n");
2815 *err
= create_parseError(E_XML_NOTWF
, NULL
, NULL
, NULL
, 0, 0, 0);
2819 /* DTD validation */
2820 if (get_doc(This
)->intSubset
|| get_doc(This
)->extSubset
)
2822 xmlValidCtxtPtr vctx
= xmlNewValidCtxt();
2823 vctx
->error
= validate_error
;
2824 vctx
->warning
= validate_warning
;
2827 if (!((node
== (IXMLDOMNode
*)iface
)?
2828 xmlValidateDocument(vctx
, get_doc(This
)) :
2829 xmlValidateElement(vctx
, get_doc(This
), get_node_obj(node
)->node
)))
2831 /* TODO: get a real error code here */
2832 TRACE("DTD validation failed\n");
2833 err_code
= E_XML_INVALID
;
2836 xmlFreeValidCtxt(vctx
);
2839 /* Schema validation */
2840 if (hr
== S_OK
&& This
->properties
->schemaCache
!= NULL
)
2843 hr
= SchemaCache_validate_tree(This
->properties
->schemaCache
, get_node_obj(node
)->node
);
2847 /* TODO: get a real error code here */
2850 TRACE("schema validation succeeded\n");
2854 ERR("schema validation failed\n");
2855 err_code
= E_XML_INVALID
;
2860 /* not really OK, just didn't find a schema for the ns */
2867 ERR("no DTD or schema found\n");
2868 err_code
= E_XML_NODTD
;
2873 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2878 static HRESULT WINAPI
domdoc_validate(
2879 IXMLDOMDocument3
* iface
,
2880 IXMLDOMParseError
** err
)
2882 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2883 TRACE("(%p)->(%p)\n", This
, err
);
2884 return IXMLDOMDocument3_validateNode(iface
, (IXMLDOMNode
*)iface
, err
);
2887 static HRESULT WINAPI
domdoc_setProperty(
2888 IXMLDOMDocument3
* iface
,
2892 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2894 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(p
), debugstr_variant(&value
));
2896 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
2902 V_VT(&varStr
) = VT_EMPTY
;
2903 if (V_VT(&value
) != VT_BSTR
)
2905 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2907 bstr
= V_BSTR(&varStr
);
2910 bstr
= V_BSTR(&value
);
2913 if (lstrcmpiW(bstr
, PropValueXPathW
) == 0)
2914 This
->properties
->XPath
= TRUE
;
2915 else if (lstrcmpiW(bstr
, PropValueXSLPatternW
) == 0)
2916 This
->properties
->XPath
= FALSE
;
2920 VariantClear(&varStr
);
2923 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
2925 xmlChar
*nsStr
= (xmlChar
*)This
->properties
->selectNsStr
;
2926 struct list
*pNsList
;
2931 V_VT(&varStr
) = VT_EMPTY
;
2932 if (V_VT(&value
) != VT_BSTR
)
2934 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2936 bstr
= V_BSTR(&varStr
);
2939 bstr
= V_BSTR(&value
);
2943 pNsList
= &(This
->properties
->selectNsList
);
2944 clear_selectNsList(pNsList
);
2946 nsStr
= xmlchar_from_wchar(bstr
);
2948 TRACE("property value: \"%s\"\n", debugstr_w(bstr
));
2950 This
->properties
->selectNsStr
= nsStr
;
2951 This
->properties
->selectNsStr_len
= xmlStrlen(nsStr
);
2954 xmlChar
*pTokBegin
, *pTokEnd
, *pTokInner
;
2955 select_ns_entry
* ns_entry
= NULL
;
2956 xmlXPathContextPtr ctx
;
2958 ctx
= xmlXPathNewContext(This
->node
.node
->doc
);
2961 /* skip leading spaces */
2962 while (*pTokBegin
== ' ' || *pTokBegin
== '\n' ||
2963 *pTokBegin
== '\t' || *pTokBegin
== '\r')
2966 for (; *pTokBegin
; pTokBegin
= pTokEnd
)
2969 memset(ns_entry
, 0, sizeof(select_ns_entry
));
2971 ns_entry
= heap_alloc_zero(sizeof(select_ns_entry
));
2973 while (*pTokBegin
== ' ')
2975 pTokEnd
= pTokBegin
;
2976 while (*pTokEnd
!= ' ' && *pTokEnd
!= 0)
2979 /* so it failed to advance which means we've got some trailing spaces */
2980 if (pTokEnd
== pTokBegin
) break;
2982 if (xmlStrncmp(pTokBegin
, (xmlChar
const*)"xmlns", 5) != 0)
2985 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2986 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2991 if (*pTokBegin
== '=')
2993 /*valid for XSLPattern?*/
2994 FIXME("Setting default xmlns not supported - skipping.\n");
2997 else if (*pTokBegin
== ':')
2999 ns_entry
->prefix
= ++pTokBegin
;
3000 for (pTokInner
= pTokBegin
; pTokInner
!= pTokEnd
&& *pTokInner
!= '='; ++pTokInner
)
3003 if (pTokInner
== pTokEnd
)
3006 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3007 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
3011 ns_entry
->prefix_end
= *pTokInner
;
3015 if (pTokEnd
-pTokInner
> 1 &&
3016 ((*pTokInner
== '\'' && *(pTokEnd
-1) == '\'') ||
3017 (*pTokInner
== '"' && *(pTokEnd
-1) == '"')))
3019 ns_entry
->href
= ++pTokInner
;
3020 ns_entry
->href_end
= *(pTokEnd
-1);
3022 list_add_tail(pNsList
, &ns_entry
->entry
);
3023 /*let libxml figure out if they're valid from here ;)*/
3024 if (xmlXPathRegisterNs(ctx
, ns_entry
->prefix
, ns_entry
->href
) != 0)
3033 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3034 debugstr_w(bstr
), debugstr_an((const char*)pTokInner
, pTokEnd
-pTokInner
));
3035 list_add_tail(pNsList
, &ns_entry
->entry
);
3048 heap_free(ns_entry
);
3049 xmlXPathFreeContext(ctx
);
3052 VariantClear(&varStr
);
3055 else if (lstrcmpiW(p
, PropertyProhibitDTDW
) == 0 ||
3056 lstrcmpiW(p
, PropertyNewParserW
) == 0 ||
3057 lstrcmpiW(p
, PropertyResolveExternalsW
) == 0 ||
3058 lstrcmpiW(p
, PropertyAllowXsltScriptW
) == 0 ||
3059 lstrcmpiW(p
, PropertyAllowDocumentFunctionW
) == 0)
3062 FIXME("Ignoring property %s, value %s\n", debugstr_w(p
), debugstr_variant(&value
));
3066 FIXME("Unknown property %s\n", debugstr_w(p
));
3070 static HRESULT WINAPI
domdoc_getProperty(
3071 IXMLDOMDocument3
* iface
,
3075 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3077 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
3080 return E_INVALIDARG
;
3082 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
3084 V_VT(var
) = VT_BSTR
;
3085 V_BSTR(var
) = This
->properties
->XPath
?
3086 SysAllocString(PropValueXPathW
) :
3087 SysAllocString(PropValueXSLPatternW
);
3088 return V_BSTR(var
) ? S_OK
: E_OUTOFMEMORY
;
3090 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3093 BSTR rebuiltStr
, cur
;
3094 const xmlChar
*nsStr
;
3095 struct list
*pNsList
;
3096 select_ns_entry
* pNsEntry
;
3098 V_VT(var
) = VT_BSTR
;
3099 nsStr
= This
->properties
->selectNsStr
;
3100 pNsList
= &This
->properties
->selectNsList
;
3101 lenA
= This
->properties
->selectNsStr_len
;
3102 lenW
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, NULL
, 0);
3103 rebuiltStr
= heap_alloc(lenW
*sizeof(WCHAR
));
3104 MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, rebuiltStr
, lenW
);
3106 /* this is fine because all of the chars that end tokens are ASCII*/
3107 LIST_FOR_EACH_ENTRY(pNsEntry
, pNsList
, select_ns_entry
, entry
)
3109 while (*cur
!= 0) ++cur
;
3110 if (pNsEntry
->prefix_end
)
3112 *cur
= pNsEntry
->prefix_end
;
3113 while (*cur
!= 0) ++cur
;
3116 if (pNsEntry
->href_end
)
3118 *cur
= pNsEntry
->href_end
;
3121 V_BSTR(var
) = SysAllocString(rebuiltStr
);
3122 heap_free(rebuiltStr
);
3126 FIXME("Unknown property %s\n", debugstr_w(p
));
3130 static HRESULT WINAPI
domdoc_importNode(
3131 IXMLDOMDocument3
* iface
,
3134 IXMLDOMNode
** clone
)
3136 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3137 FIXME("(%p)->(%p %d %p): stub\n", This
, node
, deep
, clone
);
3141 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl
=
3143 domdoc_QueryInterface
,
3146 domdoc_GetTypeInfoCount
,
3148 domdoc_GetIDsOfNames
,
3150 domdoc_get_nodeName
,
3151 domdoc_get_nodeValue
,
3152 domdoc_put_nodeValue
,
3153 domdoc_get_nodeType
,
3154 domdoc_get_parentNode
,
3155 domdoc_get_childNodes
,
3156 domdoc_get_firstChild
,
3157 domdoc_get_lastChild
,
3158 domdoc_get_previousSibling
,
3159 domdoc_get_nextSibling
,
3160 domdoc_get_attributes
,
3161 domdoc_insertBefore
,
3162 domdoc_replaceChild
,
3165 domdoc_hasChildNodes
,
3166 domdoc_get_ownerDocument
,
3168 domdoc_get_nodeTypeString
,
3171 domdoc_get_specified
,
3172 domdoc_get_definition
,
3173 domdoc_get_nodeTypedValue
,
3174 domdoc_put_nodeTypedValue
,
3175 domdoc_get_dataType
,
3176 domdoc_put_dataType
,
3178 domdoc_transformNode
,
3180 domdoc_selectSingleNode
,
3182 domdoc_get_namespaceURI
,
3184 domdoc_get_baseName
,
3185 domdoc_transformNodeToObject
,
3187 domdoc_get_implementation
,
3188 domdoc_get_documentElement
,
3189 domdoc_put_documentElement
,
3190 domdoc_createElement
,
3191 domdoc_createDocumentFragment
,
3192 domdoc_createTextNode
,
3193 domdoc_createComment
,
3194 domdoc_createCDATASection
,
3195 domdoc_createProcessingInstruction
,
3196 domdoc_createAttribute
,
3197 domdoc_createEntityReference
,
3198 domdoc_getElementsByTagName
,
3202 domdoc_get_readyState
,
3203 domdoc_get_parseError
,
3210 domdoc_get_validateOnParse
,
3211 domdoc_put_validateOnParse
,
3212 domdoc_get_resolveExternals
,
3213 domdoc_put_resolveExternals
,
3214 domdoc_get_preserveWhiteSpace
,
3215 domdoc_put_preserveWhiteSpace
,
3216 domdoc_put_onreadystatechange
,
3217 domdoc_put_onDataAvailable
,
3218 domdoc_put_onTransformNode
,
3219 domdoc_get_namespaces
,
3221 domdoc_putref_schemas
,
3225 domdoc_validateNode
,
3229 /* IConnectionPointContainer */
3230 static HRESULT WINAPI
ConnectionPointContainer_QueryInterface(IConnectionPointContainer
*iface
,
3231 REFIID riid
, void **ppv
)
3233 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3234 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3237 static ULONG WINAPI
ConnectionPointContainer_AddRef(IConnectionPointContainer
*iface
)
3239 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3240 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3243 static ULONG WINAPI
ConnectionPointContainer_Release(IConnectionPointContainer
*iface
)
3245 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3246 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3249 static HRESULT WINAPI
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer
*iface
,
3250 IEnumConnectionPoints
**ppEnum
)
3252 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3253 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3257 static HRESULT WINAPI
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer
*iface
,
3258 REFIID riid
, IConnectionPoint
**cp
)
3260 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3261 ConnectionPoint
*iter
;
3263 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), cp
);
3267 for(iter
= This
->cp_list
; iter
; iter
= iter
->next
)
3269 if (IsEqualGUID(iter
->iid
, riid
))
3270 *cp
= &iter
->IConnectionPoint_iface
;
3275 IConnectionPoint_AddRef(*cp
);
3279 FIXME("unsupported riid %s\n", debugstr_guid(riid
));
3280 return CONNECT_E_NOCONNECTION
;
3284 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl
=
3286 ConnectionPointContainer_QueryInterface
,
3287 ConnectionPointContainer_AddRef
,
3288 ConnectionPointContainer_Release
,
3289 ConnectionPointContainer_EnumConnectionPoints
,
3290 ConnectionPointContainer_FindConnectionPoint
3293 /* IConnectionPoint */
3294 static HRESULT WINAPI
ConnectionPoint_QueryInterface(IConnectionPoint
*iface
,
3295 REFIID riid
, void **ppv
)
3297 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3299 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
3303 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
3304 IsEqualGUID(&IID_IConnectionPoint
, riid
))
3311 IConnectionPoint_AddRef(iface
);
3315 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
3316 return E_NOINTERFACE
;
3319 static ULONG WINAPI
ConnectionPoint_AddRef(IConnectionPoint
*iface
)
3321 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3322 return IConnectionPointContainer_AddRef(This
->container
);
3325 static ULONG WINAPI
ConnectionPoint_Release(IConnectionPoint
*iface
)
3327 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3328 return IConnectionPointContainer_Release(This
->container
);
3331 static HRESULT WINAPI
ConnectionPoint_GetConnectionInterface(IConnectionPoint
*iface
, IID
*iid
)
3333 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3335 TRACE("(%p)->(%p)\n", This
, iid
);
3337 if (!iid
) return E_POINTER
;
3343 static HRESULT WINAPI
ConnectionPoint_GetConnectionPointContainer(IConnectionPoint
*iface
,
3344 IConnectionPointContainer
**container
)
3346 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3348 TRACE("(%p)->(%p)\n", This
, container
);
3350 if (!container
) return E_POINTER
;
3352 *container
= This
->container
;
3353 IConnectionPointContainer_AddRef(*container
);
3357 static HRESULT WINAPI
ConnectionPoint_Advise(IConnectionPoint
*iface
, IUnknown
*unk_sink
,
3360 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3365 TRACE("(%p)->(%p %p)\n", This
, unk_sink
, cookie
);
3367 hr
= IUnknown_QueryInterface(unk_sink
, This
->iid
, (void**)&sink
);
3368 if(FAILED(hr
) && !IsEqualGUID(&IID_IPropertyNotifySink
, This
->iid
))
3369 hr
= IUnknown_QueryInterface(unk_sink
, &IID_IDispatch
, (void**)&sink
);
3371 return CONNECT_E_CANNOTCONNECT
;
3375 for (i
= 0; i
< This
->sinks_size
; i
++)
3376 if (!This
->sinks
[i
].unk
)
3379 if (i
== This
->sinks_size
)
3380 This
->sinks
= heap_realloc(This
->sinks
,(++This
->sinks_size
)*sizeof(*This
->sinks
));
3384 This
->sinks
= heap_alloc(sizeof(*This
->sinks
));
3385 This
->sinks_size
= 1;
3389 This
->sinks
[i
].unk
= sink
;
3396 static HRESULT WINAPI
ConnectionPoint_Unadvise(IConnectionPoint
*iface
, DWORD cookie
)
3398 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3400 TRACE("(%p)->(%d)\n", This
, cookie
);
3402 if (cookie
== 0 || cookie
> This
->sinks_size
|| !This
->sinks
[cookie
-1].unk
)
3403 return CONNECT_E_NOCONNECTION
;
3405 IUnknown_Release(This
->sinks
[cookie
-1].unk
);
3406 This
->sinks
[cookie
-1].unk
= NULL
;
3411 static HRESULT WINAPI
ConnectionPoint_EnumConnections(IConnectionPoint
*iface
,
3412 IEnumConnections
**ppEnum
)
3414 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3415 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3419 static const IConnectionPointVtbl ConnectionPointVtbl
=
3421 ConnectionPoint_QueryInterface
,
3422 ConnectionPoint_AddRef
,
3423 ConnectionPoint_Release
,
3424 ConnectionPoint_GetConnectionInterface
,
3425 ConnectionPoint_GetConnectionPointContainer
,
3426 ConnectionPoint_Advise
,
3427 ConnectionPoint_Unadvise
,
3428 ConnectionPoint_EnumConnections
3431 static void ConnectionPoint_Init(ConnectionPoint
*cp
, struct domdoc
*doc
, REFIID riid
)
3433 cp
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointVtbl
;
3439 cp
->next
= doc
->cp_list
;
3442 cp
->container
= &doc
->IConnectionPointContainer_iface
;
3445 /* domdoc implementation of IObjectWithSite */
3446 static HRESULT WINAPI
3447 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
3449 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3450 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObject
);
3453 static ULONG WINAPI
domdoc_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
3455 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3456 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3459 static ULONG WINAPI
domdoc_ObjectWithSite_Release( IObjectWithSite
* iface
)
3461 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3462 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3465 static HRESULT WINAPI
domdoc_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
3467 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3469 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
3474 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
3477 static HRESULT WINAPI
domdoc_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
3479 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3481 TRACE("(%p)->(%p)\n", iface
, punk
);
3487 IUnknown_Release( This
->site
);
3494 IUnknown_AddRef( punk
);
3497 IUnknown_Release( This
->site
);
3504 static const IObjectWithSiteVtbl domdocObjectSite
=
3506 domdoc_ObjectWithSite_QueryInterface
,
3507 domdoc_ObjectWithSite_AddRef
,
3508 domdoc_ObjectWithSite_Release
,
3509 domdoc_ObjectWithSite_SetSite
,
3510 domdoc_ObjectWithSite_GetSite
3513 static HRESULT WINAPI
domdoc_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
3515 domdoc
*This
= impl_from_IObjectSafety(iface
);
3516 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3519 static ULONG WINAPI
domdoc_Safety_AddRef(IObjectSafety
*iface
)
3521 domdoc
*This
= impl_from_IObjectSafety(iface
);
3522 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3525 static ULONG WINAPI
domdoc_Safety_Release(IObjectSafety
*iface
)
3527 domdoc
*This
= impl_from_IObjectSafety(iface
);
3528 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3531 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3533 static HRESULT WINAPI
domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3534 DWORD
*supported
, DWORD
*enabled
)
3536 domdoc
*This
= impl_from_IObjectSafety(iface
);
3538 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
3540 if(!supported
|| !enabled
) return E_POINTER
;
3542 *supported
= SAFETY_SUPPORTED_OPTIONS
;
3543 *enabled
= This
->safeopt
;
3548 static HRESULT WINAPI
domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3549 DWORD mask
, DWORD enabled
)
3551 domdoc
*This
= impl_from_IObjectSafety(iface
);
3552 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
3554 if ((mask
& ~SAFETY_SUPPORTED_OPTIONS
) != 0)
3557 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
3562 #undef SAFETY_SUPPORTED_OPTIONS
3564 static const IObjectSafetyVtbl domdocObjectSafetyVtbl
= {
3565 domdoc_Safety_QueryInterface
,
3566 domdoc_Safety_AddRef
,
3567 domdoc_Safety_Release
,
3568 domdoc_Safety_GetInterfaceSafetyOptions
,
3569 domdoc_Safety_SetInterfaceSafetyOptions
3572 static const tid_t domdoc_iface_tids
[] = {
3573 IXMLDOMDocument3_tid
,
3577 static dispex_static_data_t domdoc_dispex
= {
3579 IXMLDOMDocument3_tid
,
3584 HRESULT
get_domdoc_from_xmldoc(xmlDocPtr xmldoc
, IXMLDOMDocument3
**document
)
3588 doc
= heap_alloc( sizeof (*doc
) );
3590 return E_OUTOFMEMORY
;
3592 doc
->IXMLDOMDocument3_iface
.lpVtbl
= &XMLDOMDocument3Vtbl
;
3593 doc
->IPersistStreamInit_iface
.lpVtbl
= &xmldoc_IPersistStreamInit_VTable
;
3594 doc
->IObjectWithSite_iface
.lpVtbl
= &domdocObjectSite
;
3595 doc
->IObjectSafety_iface
.lpVtbl
= &domdocObjectSafetyVtbl
;
3596 doc
->IConnectionPointContainer_iface
.lpVtbl
= &ConnectionPointContainerVtbl
;
3598 doc
->async
= VARIANT_TRUE
;
3599 doc
->validating
= 0;
3601 doc
->properties
= properties_from_xmlDocPtr(xmldoc
);
3605 doc
->cp_list
= NULL
;
3606 doc
->namespaces
= NULL
;
3607 memset(doc
->events
, 0, sizeof(doc
->events
));
3609 /* events connection points */
3610 ConnectionPoint_Init(&doc
->cp_dispatch
, doc
, &IID_IDispatch
);
3611 ConnectionPoint_Init(&doc
->cp_propnotif
, doc
, &IID_IPropertyNotifySink
);
3612 ConnectionPoint_Init(&doc
->cp_domdocevents
, doc
, &DIID_XMLDOMDocumentEvents
);
3614 init_xmlnode(&doc
->node
, (xmlNodePtr
)xmldoc
, (IXMLDOMNode
*)&doc
->IXMLDOMDocument3_iface
,
3617 *document
= &doc
->IXMLDOMDocument3_iface
;
3619 TRACE("returning iface %p\n", *document
);
3623 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3628 TRACE("(%d, %p)\n", version
, ppObj
);
3630 xmldoc
= xmlNewDoc(NULL
);
3632 return E_OUTOFMEMORY
;
3634 xmldoc_init(xmldoc
, version
);
3636 hr
= get_domdoc_from_xmldoc(xmldoc
, (IXMLDOMDocument3
**)ppObj
);
3639 free_properties(properties_from_xmlDocPtr(xmldoc
));
3640 heap_free(xmldoc
->_private
);
3648 IUnknown
* create_domdoc( xmlNodePtr document
)
3650 IUnknown
*obj
= NULL
;
3653 TRACE("(%p)\n", document
);
3655 hr
= get_domdoc_from_xmldoc((xmlDocPtr
)document
, (IXMLDOMDocument3
**)&obj
);
3664 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3666 MESSAGE("This program tried to use a DOMDocument object, but\n"
3667 "libxml2 support was not present at compile time.\n");