2 * DOM Document implementation
4 * Copyright 2005 Mike McCormack
5 * Copyright 2010-2011 Adam Martinson for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 # include <libxml/parser.h>
30 # include <libxml/xmlerror.h>
31 # include <libxml/xpathInternals.h>
32 # include <libxml/xmlsave.h>
33 # include <libxml/SAX2.h>
34 # include <libxml/parserInternals.h>
50 #include "wine/debug.h"
52 #include "msxml_private.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
58 /* not defined in older versions */
59 #define XML_SAVE_FORMAT 1
60 #define XML_SAVE_NO_DECL 2
61 #define XML_SAVE_NO_EMPTY 4
62 #define XML_SAVE_NO_XHTML 8
63 #define XML_SAVE_XHTML 16
64 #define XML_SAVE_AS_XML 32
65 #define XML_SAVE_AS_HTML 64
67 static const WCHAR PropertySelectionLanguageW
[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
68 static const WCHAR PropertySelectionNamespacesW
[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
69 static const WCHAR PropertyProhibitDTDW
[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
70 static const WCHAR PropertyNewParserW
[] = {'N','e','w','P','a','r','s','e','r',0};
71 static const WCHAR PropValueXPathW
[] = {'X','P','a','t','h',0};
72 static const WCHAR PropValueXSLPatternW
[] = {'X','S','L','P','a','t','t','e','r','n',0};
73 static const WCHAR PropertyResolveExternalsW
[] = {'R','e','s','o','l','v','e','E','x','t','e','r','n','a','l','s',0};
74 static const WCHAR PropertyAllowXsltScriptW
[] = {'A','l','l','o','w','X','s','l','t','S','c','r','i','p','t',0};
75 static const WCHAR PropertyAllowDocumentFunctionW
[] = {'A','l','l','o','w','D','o','c','u','m','e','n','t','F','u','n','c','t','i','o','n',0};
76 static const WCHAR PropertyNormalizeAttributeValuesW
[] = {'N','o','r','m','a','l','i','z','e','A','t','t','r','i','b','u','t','e','V','a','l','u','e','s',0};
78 /* Anything that passes the test_get_ownerDocument()
79 * tests can go here (data shared between all instances).
80 * We need to preserve this when reloading a document,
81 * and also need access to it from the libxml backend. */
83 MSXML_VERSION version
;
84 VARIANT_BOOL preserving
;
85 IXMLDOMSchemaCollection2
* schemaCache
;
86 struct list selectNsList
;
87 xmlChar
const* selectNsStr
;
93 typedef struct ConnectionPoint ConnectionPoint
;
94 typedef struct domdoc domdoc
;
96 struct ConnectionPoint
98 IConnectionPoint IConnectionPoint_iface
;
101 ConnectionPoint
*next
;
102 IConnectionPointContainer
*container
;
109 IPropertyNotifySink
*propnotif
;
115 EVENTID_READYSTATECHANGE
= 0,
116 EVENTID_DATAAVAILABLE
,
117 EVENTID_TRANSFORMNODE
,
124 IXMLDOMDocument3 IXMLDOMDocument3_iface
;
125 IPersistStreamInit IPersistStreamInit_iface
;
126 IObjectWithSite IObjectWithSite_iface
;
127 IObjectSafety IObjectSafety_iface
;
128 IConnectionPointContainer IConnectionPointContainer_iface
;
131 VARIANT_BOOL validating
;
132 VARIANT_BOOL resolving
;
133 domdoc_properties
* properties
;
136 /* IObjectWithSite */
142 /* connection list */
143 ConnectionPoint
*cp_list
;
144 ConnectionPoint cp_domdocevents
;
145 ConnectionPoint cp_propnotif
;
146 ConnectionPoint cp_dispatch
;
149 IDispatch
*events
[EVENTID_LAST
];
151 IXMLDOMSchemaCollection2
*namespaces
;
154 static HRESULT
set_doc_event(domdoc
*doc
, eventid_t eid
, const VARIANT
*v
)
162 IUnknown_QueryInterface(V_UNKNOWN(v
), &IID_IDispatch
, (void**)&disp
);
167 disp
= V_DISPATCH(v
);
168 if (disp
) IDispatch_AddRef(disp
);
171 return DISP_E_TYPEMISMATCH
;
174 if (doc
->events
[eid
]) IDispatch_Release(doc
->events
[eid
]);
175 doc
->events
[eid
] = disp
;
180 static inline ConnectionPoint
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
182 return CONTAINING_RECORD(iface
, ConnectionPoint
, IConnectionPoint_iface
);
186 In native windows, the whole lifetime management of XMLDOMNodes is
187 managed automatically using reference counts. Wine emulates that by
188 maintaining a reference count to the document that is increased for
189 each IXMLDOMNode pointer passed out for this document. If all these
190 pointers are gone, the document is unreachable and gets freed, that
191 is, all nodes in the tree of the document get freed.
193 You are able to create nodes that are associated to a document (in
194 fact, in msxml's XMLDOM model, all nodes are associated to a document),
195 but not in the tree of that document, for example using the createFoo
196 functions from IXMLDOMDocument. These nodes do not get cleaned up
197 by libxml, so we have to do it ourselves.
199 To catch these nodes, a list of "orphan nodes" is introduced.
200 It contains pointers to all roots of node trees that are
201 associated with the document without being part of the document
202 tree. All nodes with parent==NULL (except for the document root nodes)
203 should be in the orphan node list of their document. All orphan nodes
204 get freed together with the document itself.
207 typedef struct _xmldoc_priv
{
210 domdoc_properties
* properties
;
213 typedef struct _orphan_entry
{
218 typedef struct _select_ns_entry
{
220 xmlChar
const* prefix
;
226 static inline xmldoc_priv
* priv_from_xmlDocPtr(const xmlDocPtr doc
)
228 return doc
->_private
;
231 static inline domdoc_properties
* properties_from_xmlDocPtr(xmlDocPtr doc
)
233 return priv_from_xmlDocPtr(doc
)->properties
;
236 BOOL
is_xpathmode(const xmlDocPtr doc
)
238 return properties_from_xmlDocPtr(doc
)->XPath
;
241 void set_xpathmode(xmlDocPtr doc
, BOOL xpath
)
243 properties_from_xmlDocPtr(doc
)->XPath
= xpath
;
246 int registerNamespaces(xmlXPathContextPtr ctxt
)
249 const select_ns_entry
* ns
= NULL
;
250 const struct list
* pNsList
= &properties_from_xmlDocPtr(ctxt
->doc
)->selectNsList
;
252 TRACE("(%p)\n", ctxt
);
254 LIST_FOR_EACH_ENTRY( ns
, pNsList
, select_ns_entry
, entry
)
256 xmlXPathRegisterNs(ctxt
, ns
->prefix
, ns
->href
);
263 static inline void clear_selectNsList(struct list
* pNsList
)
265 select_ns_entry
*ns
, *ns2
;
266 LIST_FOR_EACH_ENTRY_SAFE( ns
, ns2
, pNsList
, select_ns_entry
, entry
)
273 static xmldoc_priv
* create_priv(void)
276 priv
= heap_alloc( sizeof (*priv
) );
281 list_init( &priv
->orphans
);
282 priv
->properties
= NULL
;
288 static domdoc_properties
*create_properties(MSXML_VERSION version
)
290 domdoc_properties
*properties
= heap_alloc(sizeof(domdoc_properties
));
292 list_init(&properties
->selectNsList
);
293 properties
->preserving
= VARIANT_FALSE
;
294 properties
->schemaCache
= NULL
;
295 properties
->selectNsStr
= heap_alloc_zero(sizeof(xmlChar
));
296 properties
->selectNsStr_len
= 0;
298 /* properties that are dependent on object versions */
299 properties
->version
= version
;
300 properties
->XPath
= (version
== MSXML4
|| version
== MSXML6
);
303 properties
->uri
= NULL
;
308 static domdoc_properties
* copy_properties(domdoc_properties
const* properties
)
310 domdoc_properties
* pcopy
= heap_alloc(sizeof(domdoc_properties
));
311 select_ns_entry
const* ns
= NULL
;
312 select_ns_entry
* new_ns
= NULL
;
313 int len
= (properties
->selectNsStr_len
+1)*sizeof(xmlChar
);
318 pcopy
->version
= properties
->version
;
319 pcopy
->preserving
= properties
->preserving
;
320 pcopy
->schemaCache
= properties
->schemaCache
;
321 if (pcopy
->schemaCache
)
322 IXMLDOMSchemaCollection2_AddRef(pcopy
->schemaCache
);
323 pcopy
->XPath
= properties
->XPath
;
324 pcopy
->selectNsStr_len
= properties
->selectNsStr_len
;
325 list_init( &pcopy
->selectNsList
);
326 pcopy
->selectNsStr
= heap_alloc(len
);
327 memcpy((xmlChar
*)pcopy
->selectNsStr
, properties
->selectNsStr
, len
);
328 offset
= pcopy
->selectNsStr
- properties
->selectNsStr
;
330 LIST_FOR_EACH_ENTRY( ns
, (&properties
->selectNsList
), select_ns_entry
, entry
)
332 new_ns
= heap_alloc(sizeof(select_ns_entry
));
333 memcpy(new_ns
, ns
, sizeof(select_ns_entry
));
334 new_ns
->href
+= offset
;
335 new_ns
->prefix
+= offset
;
336 list_add_tail(&pcopy
->selectNsList
, &new_ns
->entry
);
339 pcopy
->uri
= properties
->uri
;
341 IUri_AddRef(pcopy
->uri
);
347 static void free_properties(domdoc_properties
* properties
)
351 if (properties
->schemaCache
)
352 IXMLDOMSchemaCollection2_Release(properties
->schemaCache
);
353 clear_selectNsList(&properties
->selectNsList
);
354 heap_free((xmlChar
*)properties
->selectNsStr
);
356 IUri_Release(properties
->uri
);
357 heap_free(properties
);
361 static void release_namespaces(domdoc
*This
)
363 if (This
->namespaces
)
365 IXMLDOMSchemaCollection2_Release(This
->namespaces
);
366 This
->namespaces
= NULL
;
370 /* links a "<?xml" node as a first child */
371 void xmldoc_link_xmldecl(xmlDocPtr doc
, xmlNodePtr node
)
374 if (doc
->standalone
!= -1) xmlAddPrevSibling( doc
->children
, node
);
377 /* unlinks a first "<?xml" child if it was created */
378 xmlNodePtr
xmldoc_unlink_xmldecl(xmlDocPtr doc
)
380 static const xmlChar xmlA
[] = "xml";
381 xmlNodePtr node
, first_child
;
385 /* xml declaration node could be created automatically after parsing or added
387 first_child
= doc
->children
;
388 if (first_child
&& first_child
->type
== XML_PI_NODE
&& xmlStrEqual(first_child
->name
, xmlA
))
391 xmlUnlinkNode( node
);
399 MSXML_VERSION
xmldoc_version(xmlDocPtr doc
)
401 return properties_from_xmlDocPtr(doc
)->version
;
404 BOOL
is_preserving_whitespace(xmlNodePtr node
)
406 domdoc_properties
* properties
= NULL
;
407 /* during parsing the xmlDoc._private stuff is not there */
408 if (priv_from_xmlDocPtr(node
->doc
))
409 properties
= properties_from_xmlDocPtr(node
->doc
);
410 return ((properties
&& properties
->preserving
== VARIANT_TRUE
) ||
411 xmlNodeGetSpacePreserve(node
) == 1);
414 static inline BOOL
strn_isspace(xmlChar
const* str
, int len
)
416 for (; str
&& len
> 0 && *str
; ++str
, --len
)
423 static void sax_characters(void *ctx
, const xmlChar
*ch
, int len
)
425 xmlParserCtxtPtr ctxt
;
428 ctxt
= (xmlParserCtxtPtr
) ctx
;
429 This
= (const domdoc
*) ctxt
->_private
;
433 xmlChar cur
= *(ctxt
->input
->cur
);
435 /* Characters are reported with multiple calls, for example each charref is reported with a separate
436 call and then parser appends it to a single text node or creates a new node if not created.
437 It's not possible to tell if it's ignorable data or not just looking at data itself cause it could be
438 space chars that separate charrefs or similar case. We only need to skip leading and trailing spaces,
439 or whole node if it has nothing but space chars, so to detect leading space node->last is checked that
440 contains text node pointer if already created, trailing spaces are detected directly looking at parser input
441 for next '<' opening bracket - similar logic is used by libxml2 itself. Basically 'cur' == '<' means the last
442 chunk of char data, in case it's not the last chunk we check for previously added node type and if it's not
443 a text node it's safe to ignore.
445 Note that during domdoc_loadXML() the xmlDocPtr->_private data is not available. */
447 if (!This
->properties
->preserving
&&
448 !is_preserving_whitespace(ctxt
->node
) &&
449 strn_isspace(ch
, len
) &&
450 (!ctxt
->node
->last
||
451 ((ctxt
->node
->last
&& (cur
== '<' || ctxt
->node
->last
->type
!= XML_TEXT_NODE
))
454 /* Keep information about ignorable whitespace text node in previous or parent node */
455 if (ctxt
->node
->last
)
456 *(DWORD
*)&ctxt
->node
->last
->_private
|= NODE_PRIV_TRAILING_IGNORABLE_WS
;
457 else if (ctxt
->node
->type
!= XML_DOCUMENT_NODE
)
458 *(DWORD
*)&ctxt
->node
->_private
|= NODE_PRIV_CHILD_IGNORABLE_WS
;
463 xmlSAX2Characters(ctxt
, ch
, len
);
466 static void LIBXML2_LOG_CALLBACK
sax_error(void* ctx
, char const* msg
, ...)
470 LIBXML2_CALLBACK_ERR(doparse
, msg
, ap
);
474 static void LIBXML2_LOG_CALLBACK
sax_warning(void* ctx
, char const* msg
, ...)
478 LIBXML2_CALLBACK_WARN(doparse
, msg
, ap
);
482 static void sax_serror(void* ctx
, xmlErrorPtr err
)
484 LIBXML2_CALLBACK_SERROR(doparse
, err
);
487 static xmlDocPtr
doparse(domdoc
* This
, char const* ptr
, int len
, xmlCharEncoding encoding
)
489 xmlDocPtr doc
= NULL
;
490 xmlParserCtxtPtr pctx
;
491 static xmlSAXHandler sax_handler
= {
492 xmlSAX2InternalSubset
, /* internalSubset */
493 xmlSAX2IsStandalone
, /* isStandalone */
494 xmlSAX2HasInternalSubset
, /* hasInternalSubset */
495 xmlSAX2HasExternalSubset
, /* hasExternalSubset */
496 xmlSAX2ResolveEntity
, /* resolveEntity */
497 xmlSAX2GetEntity
, /* getEntity */
498 xmlSAX2EntityDecl
, /* entityDecl */
499 xmlSAX2NotationDecl
, /* notationDecl */
500 xmlSAX2AttributeDecl
, /* attributeDecl */
501 xmlSAX2ElementDecl
, /* elementDecl */
502 xmlSAX2UnparsedEntityDecl
, /* unparsedEntityDecl */
503 xmlSAX2SetDocumentLocator
, /* setDocumentLocator */
504 xmlSAX2StartDocument
, /* startDocument */
505 xmlSAX2EndDocument
, /* endDocument */
506 xmlSAX2StartElement
, /* startElement */
507 xmlSAX2EndElement
, /* endElement */
508 xmlSAX2Reference
, /* reference */
509 sax_characters
, /* characters */
510 sax_characters
, /* ignorableWhitespace */
511 xmlSAX2ProcessingInstruction
, /* processingInstruction */
512 xmlSAX2Comment
, /* comment */
513 sax_warning
, /* warning */
514 sax_error
, /* error */
515 sax_error
, /* fatalError */
516 xmlSAX2GetParameterEntity
, /* getParameterEntity */
517 xmlSAX2CDataBlock
, /* cdataBlock */
518 xmlSAX2ExternalSubset
, /* externalSubset */
521 xmlSAX2StartElementNs
, /* startElementNs */
522 xmlSAX2EndElementNs
, /* endElementNs */
523 sax_serror
/* serror */
526 pctx
= xmlCreateMemoryParserCtxt(ptr
, len
);
529 ERR("Failed to create parser context\n");
533 if (pctx
->sax
) xmlFree(pctx
->sax
);
534 pctx
->sax
= &sax_handler
;
535 pctx
->_private
= This
;
538 if (encoding
!= XML_CHAR_ENCODING_NONE
)
539 xmlSwitchEncoding(pctx
, encoding
);
541 xmlParseDocument(pctx
);
543 if (pctx
->wellFormed
)
549 xmlFreeDoc(pctx
->myDoc
);
553 xmlFreeParserCtxt(pctx
);
555 /* TODO: put this in one of the SAX callbacks */
556 /* create first child as a <?xml...?> */
557 if (doc
&& doc
->standalone
!= -1)
561 xmlChar
*xmlbuff
= (xmlChar
*)buff
;
563 node
= xmlNewDocPI( doc
, (xmlChar
*)"xml", NULL
);
565 /* version attribute can't be omitted */
566 sprintf(buff
, "version=\"%s\"", doc
->version
? (char*)doc
->version
: "1.0");
567 xmlNodeAddContent( node
, xmlbuff
);
571 sprintf(buff
, " encoding=\"%s\"", doc
->encoding
);
572 xmlNodeAddContent( node
, xmlbuff
);
575 if (doc
->standalone
!= -2)
577 sprintf(buff
, " standalone=\"%s\"", doc
->standalone
== 0 ? "no" : "yes");
578 xmlNodeAddContent( node
, xmlbuff
);
581 xmldoc_link_xmldecl( doc
, node
);
587 void xmldoc_init(xmlDocPtr doc
, MSXML_VERSION version
)
589 doc
->_private
= create_priv();
590 priv_from_xmlDocPtr(doc
)->properties
= create_properties(version
);
593 LONG
xmldoc_add_refs(xmlDocPtr doc
, LONG refs
)
595 LONG ref
= InterlockedExchangeAdd(&priv_from_xmlDocPtr(doc
)->refs
, refs
) + refs
;
596 TRACE("(%p)->(%d)\n", doc
, ref
);
600 LONG
xmldoc_add_ref(xmlDocPtr doc
)
602 return xmldoc_add_refs(doc
, 1);
605 LONG
xmldoc_release_refs(xmlDocPtr doc
, LONG refs
)
607 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
608 LONG ref
= InterlockedExchangeAdd(&priv
->refs
, -refs
) - refs
;
609 TRACE("(%p)->(%d)\n", doc
, ref
);
612 WARN("negative refcount, expect troubles\n");
616 orphan_entry
*orphan
, *orphan2
;
617 TRACE("freeing docptr %p\n", doc
);
619 LIST_FOR_EACH_ENTRY_SAFE( orphan
, orphan2
, &priv
->orphans
, orphan_entry
, entry
)
621 xmlFreeNode( orphan
->node
);
624 free_properties(priv
->properties
);
625 heap_free(doc
->_private
);
633 LONG
xmldoc_release(xmlDocPtr doc
)
635 return xmldoc_release_refs(doc
, 1);
638 HRESULT
xmldoc_add_orphan(xmlDocPtr doc
, xmlNodePtr node
)
640 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
643 entry
= heap_alloc( sizeof (*entry
) );
645 return E_OUTOFMEMORY
;
648 list_add_head( &priv
->orphans
, &entry
->entry
);
652 HRESULT
xmldoc_remove_orphan(xmlDocPtr doc
, xmlNodePtr node
)
654 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
655 orphan_entry
*entry
, *entry2
;
657 LIST_FOR_EACH_ENTRY_SAFE( entry
, entry2
, &priv
->orphans
, orphan_entry
, entry
)
659 if( entry
->node
== node
)
661 list_remove( &entry
->entry
);
670 static inline xmlDocPtr
get_doc( domdoc
*This
)
672 return This
->node
.node
->doc
;
675 static HRESULT
attach_xmldoc(domdoc
*This
, xmlDocPtr xml
)
677 release_namespaces(This
);
681 priv_from_xmlDocPtr(get_doc(This
))->properties
= NULL
;
682 if (xmldoc_release(get_doc(This
)) != 0)
683 priv_from_xmlDocPtr(get_doc(This
))->properties
=
684 copy_properties(This
->properties
);
687 This
->node
.node
= (xmlNodePtr
) xml
;
691 xmldoc_add_ref(get_doc(This
));
692 priv_from_xmlDocPtr(get_doc(This
))->properties
= This
->properties
;
698 static inline domdoc
*impl_from_IXMLDOMDocument3( IXMLDOMDocument3
*iface
)
700 return CONTAINING_RECORD(iface
, domdoc
, IXMLDOMDocument3_iface
);
703 static inline domdoc
*impl_from_IPersistStreamInit(IPersistStreamInit
*iface
)
705 return CONTAINING_RECORD(iface
, domdoc
, IPersistStreamInit_iface
);
708 static inline domdoc
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
710 return CONTAINING_RECORD(iface
, domdoc
, IObjectWithSite_iface
);
713 static inline domdoc
*impl_from_IObjectSafety(IObjectSafety
*iface
)
715 return CONTAINING_RECORD(iface
, domdoc
, IObjectSafety_iface
);
718 static inline domdoc
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
720 return CONTAINING_RECORD(iface
, domdoc
, IConnectionPointContainer_iface
);
723 /************************************************************************
724 * domdoc implementation of IPersistStream.
726 static HRESULT WINAPI
PersistStreamInit_QueryInterface(
727 IPersistStreamInit
*iface
, REFIID riid
, void **ppvObj
)
729 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
730 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObj
);
733 static ULONG WINAPI
PersistStreamInit_AddRef(
734 IPersistStreamInit
*iface
)
736 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
737 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
740 static ULONG WINAPI
PersistStreamInit_Release(
741 IPersistStreamInit
*iface
)
743 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
744 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
747 static HRESULT WINAPI
PersistStreamInit_GetClassID(
748 IPersistStreamInit
*iface
, CLSID
*classid
)
750 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
751 TRACE("(%p)->(%p)\n", This
, classid
);
756 *classid
= *DOMDocument_version(This
->properties
->version
);
761 static HRESULT WINAPI
PersistStreamInit_IsDirty(
762 IPersistStreamInit
*iface
)
764 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
765 FIXME("(%p): stub!\n", This
);
769 static HRESULT
domdoc_load_from_stream(domdoc
*doc
, ISequentialStream
*stream
)
771 DWORD read
, written
, len
;
772 xmlDocPtr xmldoc
= NULL
;
780 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &hstream
);
786 ISequentialStream_Read(stream
, buf
, sizeof(buf
), &read
);
787 hr
= IStream_Write(hstream
, buf
, read
, &written
);
788 } while(SUCCEEDED(hr
) && written
!= 0 && read
!= 0);
792 ERR("failed to copy stream 0x%08x\n", hr
);
793 IStream_Release(hstream
);
797 hr
= GetHGlobalFromStream(hstream
, &hglobal
);
801 len
= GlobalSize(hglobal
);
802 ptr
= GlobalLock(hglobal
);
804 xmldoc
= doparse(doc
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
805 GlobalUnlock(hglobal
);
809 ERR("Failed to parse xml\n");
813 xmldoc
->_private
= create_priv();
815 return attach_xmldoc(doc
, xmldoc
);
818 static HRESULT WINAPI
PersistStreamInit_Load(IPersistStreamInit
*iface
, IStream
*stream
)
820 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
822 TRACE("(%p)->(%p)\n", This
, stream
);
827 return domdoc_load_from_stream(This
, (ISequentialStream
*)stream
);
830 static HRESULT WINAPI
PersistStreamInit_Save(
831 IPersistStreamInit
*iface
, IStream
*stream
, BOOL clr_dirty
)
833 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
837 TRACE("(%p)->(%p %d)\n", This
, stream
, clr_dirty
);
839 hr
= IXMLDOMDocument3_get_xml(&This
->IXMLDOMDocument3_iface
, &xmlString
);
842 DWORD len
= SysStringLen(xmlString
) * sizeof(WCHAR
);
844 hr
= IStream_Write( stream
, xmlString
, len
, NULL
);
845 SysFreeString(xmlString
);
848 TRACE("ret 0x%08x\n", hr
);
853 static HRESULT WINAPI
PersistStreamInit_GetSizeMax(
854 IPersistStreamInit
*iface
, ULARGE_INTEGER
*pcbSize
)
856 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
857 TRACE("(%p)->(%p)\n", This
, pcbSize
);
861 static HRESULT WINAPI
PersistStreamInit_InitNew(
862 IPersistStreamInit
*iface
)
864 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
865 TRACE("(%p)\n", This
);
869 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable
=
871 PersistStreamInit_QueryInterface
,
872 PersistStreamInit_AddRef
,
873 PersistStreamInit_Release
,
874 PersistStreamInit_GetClassID
,
875 PersistStreamInit_IsDirty
,
876 PersistStreamInit_Load
,
877 PersistStreamInit_Save
,
878 PersistStreamInit_GetSizeMax
,
879 PersistStreamInit_InitNew
882 /* IXMLDOMDocument3 interface */
884 static const tid_t domdoc_se_tids
[] = {
887 IXMLDOMDocument2_tid
,
888 IXMLDOMDocument3_tid
,
892 static HRESULT WINAPI
domdoc_QueryInterface( IXMLDOMDocument3
*iface
, REFIID riid
, void** ppvObject
)
894 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
896 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( riid
), ppvObject
);
900 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
901 IsEqualGUID( riid
, &IID_IDispatch
) ||
902 IsEqualGUID( riid
, &IID_IXMLDOMNode
) ||
903 IsEqualGUID( riid
, &IID_IXMLDOMDocument
) ||
904 IsEqualGUID( riid
, &IID_IXMLDOMDocument2
)||
905 IsEqualGUID( riid
, &IID_IXMLDOMDocument3
))
909 else if (IsEqualGUID(&IID_IPersistStream
, riid
) ||
910 IsEqualGUID(&IID_IPersistStreamInit
, riid
))
912 *ppvObject
= &This
->IPersistStreamInit_iface
;
914 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
916 *ppvObject
= &This
->IObjectWithSite_iface
;
918 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
920 *ppvObject
= &This
->IObjectSafety_iface
;
922 else if( IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
924 return node_create_supporterrorinfo(domdoc_se_tids
, ppvObject
);
926 else if(node_query_interface(&This
->node
, riid
, ppvObject
))
928 return *ppvObject
? S_OK
: E_NOINTERFACE
;
930 else if (IsEqualGUID( riid
, &IID_IConnectionPointContainer
))
932 *ppvObject
= &This
->IConnectionPointContainer_iface
;
936 TRACE("interface %s not implemented\n", debugstr_guid(riid
));
937 return E_NOINTERFACE
;
940 IUnknown_AddRef((IUnknown
*)*ppvObject
);
945 static ULONG WINAPI
domdoc_AddRef( IXMLDOMDocument3
*iface
)
947 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
948 ULONG ref
= InterlockedIncrement( &This
->ref
);
949 TRACE("(%p)->(%d)\n", This
, ref
);
953 static ULONG WINAPI
domdoc_Release( IXMLDOMDocument3
*iface
)
955 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
956 LONG ref
= InterlockedDecrement( &This
->ref
);
958 TRACE("(%p)->(%d)\n", This
, ref
);
965 IUnknown_Release( This
->site
);
966 destroy_xmlnode(&This
->node
);
968 for (eid
= 0; eid
< EVENTID_LAST
; eid
++)
969 if (This
->events
[eid
]) IDispatch_Release(This
->events
[eid
]);
971 release_namespaces(This
);
978 static HRESULT WINAPI
domdoc_GetTypeInfoCount( IXMLDOMDocument3
*iface
, UINT
* pctinfo
)
980 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
981 return IDispatchEx_GetTypeInfoCount(&This
->node
.dispex
.IDispatchEx_iface
, pctinfo
);
984 static HRESULT WINAPI
domdoc_GetTypeInfo(
985 IXMLDOMDocument3
*iface
,
986 UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
988 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
989 return IDispatchEx_GetTypeInfo(&This
->node
.dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
992 static HRESULT WINAPI
domdoc_GetIDsOfNames(
993 IXMLDOMDocument3
*iface
,
1000 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1001 return IDispatchEx_GetIDsOfNames(&This
->node
.dispex
.IDispatchEx_iface
,
1002 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
1005 static HRESULT WINAPI
domdoc_Invoke(
1006 IXMLDOMDocument3
*iface
,
1007 DISPID dispIdMember
,
1011 DISPPARAMS
* pDispParams
,
1012 VARIANT
* pVarResult
,
1013 EXCEPINFO
* pExcepInfo
,
1016 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1017 return IDispatchEx_Invoke(&This
->node
.dispex
.IDispatchEx_iface
,
1018 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1021 static HRESULT WINAPI
domdoc_get_nodeName(
1022 IXMLDOMDocument3
*iface
,
1025 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1027 static const WCHAR documentW
[] = {'#','d','o','c','u','m','e','n','t',0};
1029 TRACE("(%p)->(%p)\n", This
, name
);
1031 return return_bstr(documentW
, name
);
1035 static HRESULT WINAPI
domdoc_get_nodeValue(
1036 IXMLDOMDocument3
*iface
,
1039 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1041 TRACE("(%p)->(%p)\n", This
, value
);
1044 return E_INVALIDARG
;
1046 V_VT(value
) = VT_NULL
;
1047 V_BSTR(value
) = NULL
; /* tests show that we should do this */
1052 static HRESULT WINAPI
domdoc_put_nodeValue(
1053 IXMLDOMDocument3
*iface
,
1056 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1057 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&value
));
1062 static HRESULT WINAPI
domdoc_get_nodeType(
1063 IXMLDOMDocument3
*iface
,
1066 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1068 TRACE("(%p)->(%p)\n", This
, type
);
1070 *type
= NODE_DOCUMENT
;
1075 static HRESULT WINAPI
domdoc_get_parentNode(
1076 IXMLDOMDocument3
*iface
,
1077 IXMLDOMNode
** parent
)
1079 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1081 TRACE("(%p)->(%p)\n", This
, parent
);
1083 return node_get_parent(&This
->node
, parent
);
1087 static HRESULT WINAPI
domdoc_get_childNodes(
1088 IXMLDOMDocument3
*iface
,
1089 IXMLDOMNodeList
** childList
)
1091 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1093 TRACE("(%p)->(%p)\n", This
, childList
);
1095 return node_get_child_nodes(&This
->node
, childList
);
1099 static HRESULT WINAPI
domdoc_get_firstChild(
1100 IXMLDOMDocument3
*iface
,
1101 IXMLDOMNode
** firstChild
)
1103 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1105 TRACE("(%p)->(%p)\n", This
, firstChild
);
1107 return node_get_first_child(&This
->node
, firstChild
);
1111 static HRESULT WINAPI
domdoc_get_lastChild(
1112 IXMLDOMDocument3
*iface
,
1113 IXMLDOMNode
** lastChild
)
1115 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1117 TRACE("(%p)->(%p)\n", This
, lastChild
);
1119 return node_get_last_child(&This
->node
, lastChild
);
1123 static HRESULT WINAPI
domdoc_get_previousSibling(
1124 IXMLDOMDocument3
*iface
,
1125 IXMLDOMNode
** previousSibling
)
1127 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1129 TRACE("(%p)->(%p)\n", This
, previousSibling
);
1131 return return_null_node(previousSibling
);
1135 static HRESULT WINAPI
domdoc_get_nextSibling(
1136 IXMLDOMDocument3
*iface
,
1137 IXMLDOMNode
** nextSibling
)
1139 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1141 TRACE("(%p)->(%p)\n", This
, nextSibling
);
1143 return return_null_node(nextSibling
);
1147 static HRESULT WINAPI
domdoc_get_attributes(
1148 IXMLDOMDocument3
*iface
,
1149 IXMLDOMNamedNodeMap
** attributeMap
)
1151 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1153 TRACE("(%p)->(%p)\n", This
, attributeMap
);
1155 return return_null_ptr((void**)attributeMap
);
1159 static HRESULT WINAPI
domdoc_insertBefore(
1160 IXMLDOMDocument3
*iface
,
1161 IXMLDOMNode
* newChild
,
1163 IXMLDOMNode
** outNewChild
)
1165 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1169 TRACE("(%p)->(%p %s %p)\n", This
, newChild
, debugstr_variant(&refChild
), outNewChild
);
1171 hr
= IXMLDOMNode_get_nodeType(newChild
, &type
);
1172 if (hr
!= S_OK
) return hr
;
1174 TRACE("new node type %d\n", type
);
1177 case NODE_ATTRIBUTE
:
1179 case NODE_CDATA_SECTION
:
1180 if (outNewChild
) *outNewChild
= NULL
;
1183 return node_insert_before(&This
->node
, newChild
, &refChild
, outNewChild
);
1187 static HRESULT WINAPI
domdoc_replaceChild(
1188 IXMLDOMDocument3
*iface
,
1189 IXMLDOMNode
* newChild
,
1190 IXMLDOMNode
* oldChild
,
1191 IXMLDOMNode
** outOldChild
)
1193 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1195 TRACE("(%p)->(%p %p %p)\n", This
, newChild
, oldChild
, outOldChild
);
1197 return node_replace_child(&This
->node
, newChild
, oldChild
, outOldChild
);
1201 static HRESULT WINAPI
domdoc_removeChild(
1202 IXMLDOMDocument3
*iface
,
1204 IXMLDOMNode
**oldChild
)
1206 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1207 TRACE("(%p)->(%p %p)\n", This
, child
, oldChild
);
1208 return node_remove_child(&This
->node
, child
, oldChild
);
1212 static HRESULT WINAPI
domdoc_appendChild(
1213 IXMLDOMDocument3
*iface
,
1215 IXMLDOMNode
**outChild
)
1217 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1218 TRACE("(%p)->(%p %p)\n", This
, child
, outChild
);
1219 return node_append_child(&This
->node
, child
, outChild
);
1223 static HRESULT WINAPI
domdoc_hasChildNodes(
1224 IXMLDOMDocument3
*iface
,
1227 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1228 TRACE("(%p)->(%p)\n", This
, ret
);
1229 return node_has_childnodes(&This
->node
, ret
);
1233 static HRESULT WINAPI
domdoc_get_ownerDocument(
1234 IXMLDOMDocument3
*iface
,
1235 IXMLDOMDocument
**doc
)
1237 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1238 TRACE("(%p)->(%p)\n", This
, doc
);
1239 return node_get_owner_doc(&This
->node
, doc
);
1243 static HRESULT WINAPI
domdoc_cloneNode(
1244 IXMLDOMDocument3
*iface
,
1246 IXMLDOMNode
** outNode
)
1248 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1251 TRACE("(%p)->(%d %p)\n", This
, deep
, outNode
);
1254 return E_INVALIDARG
;
1258 clone
= xmlCopyNode((xmlNodePtr
)get_doc(This
), deep
? 1 : 2);
1262 clone
->doc
->_private
= create_priv();
1263 xmldoc_add_orphan(clone
->doc
, clone
);
1264 xmldoc_add_ref(clone
->doc
);
1266 priv_from_xmlDocPtr(clone
->doc
)->properties
= copy_properties(This
->properties
);
1267 if (!(*outNode
= (IXMLDOMNode
*)create_domdoc(clone
)))
1269 xmldoc_release(clone
->doc
);
1277 static HRESULT WINAPI
domdoc_get_nodeTypeString(
1278 IXMLDOMDocument3
*iface
,
1281 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1282 static const WCHAR documentW
[] = {'d','o','c','u','m','e','n','t',0};
1284 TRACE("(%p)->(%p)\n", This
, p
);
1286 return return_bstr(documentW
, p
);
1290 static HRESULT WINAPI
domdoc_get_text(
1291 IXMLDOMDocument3
*iface
,
1294 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1295 TRACE("(%p)->(%p)\n", This
, p
);
1296 return node_get_text(&This
->node
, p
);
1300 static HRESULT WINAPI
domdoc_put_text(
1301 IXMLDOMDocument3
*iface
,
1304 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1305 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
1310 static HRESULT WINAPI
domdoc_get_specified(
1311 IXMLDOMDocument3
*iface
,
1312 VARIANT_BOOL
* isSpecified
)
1314 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1315 FIXME("(%p)->(%p) stub!\n", This
, isSpecified
);
1316 *isSpecified
= VARIANT_TRUE
;
1321 static HRESULT WINAPI
domdoc_get_definition(
1322 IXMLDOMDocument3
*iface
,
1323 IXMLDOMNode
** definitionNode
)
1325 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1326 FIXME("(%p)->(%p)\n", This
, definitionNode
);
1331 static HRESULT WINAPI
domdoc_get_nodeTypedValue(
1332 IXMLDOMDocument3
*iface
,
1335 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1336 TRACE("(%p)->(%p)\n", This
, v
);
1337 return return_null_var(v
);
1340 static HRESULT WINAPI
domdoc_put_nodeTypedValue(
1341 IXMLDOMDocument3
*iface
,
1342 VARIANT typedValue
)
1344 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1345 FIXME("(%p)->(%s)\n", This
, debugstr_variant(&typedValue
));
1350 static HRESULT WINAPI
domdoc_get_dataType(
1351 IXMLDOMDocument3
*iface
,
1354 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1355 TRACE("(%p)->(%p)\n", This
, typename
);
1356 return return_null_var( typename
);
1360 static HRESULT WINAPI
domdoc_put_dataType(
1361 IXMLDOMDocument3
*iface
,
1364 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1366 FIXME("(%p)->(%s)\n", This
, debugstr_w(dataTypeName
));
1369 return E_INVALIDARG
;
1374 static int XMLCALL
domdoc_get_xml_writecallback(void *ctx
, const char *data
, int len
)
1376 return xmlBufferAdd((xmlBufferPtr
)ctx
, (xmlChar
*)data
, len
) == 0 ? len
: 0;
1379 static HRESULT WINAPI
domdoc_get_xml(
1380 IXMLDOMDocument3
*iface
,
1383 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1384 xmlSaveCtxtPtr ctxt
;
1389 TRACE("(%p)->(%p)\n", This
, p
);
1392 return E_INVALIDARG
;
1396 buf
= xmlBufferCreate();
1398 return E_OUTOFMEMORY
;
1400 options
= XML_SAVE_FORMAT
| XML_SAVE_NO_DECL
;
1401 ctxt
= xmlSaveToIO(domdoc_get_xml_writecallback
, NULL
, buf
, "UTF-8", options
);
1406 return E_OUTOFMEMORY
;
1409 ret
= xmlSaveDoc(ctxt
, get_doc(This
));
1410 /* flushes on close */
1413 TRACE("%ld, len=%d\n", ret
, xmlBufferLength(buf
));
1414 if(ret
!= -1 && xmlBufferLength(buf
) > 0)
1418 content
= bstr_from_xmlChar(xmlBufferContent(buf
));
1419 content
= EnsureCorrectEOL(content
);
1425 *p
= SysAllocStringLen(NULL
, 0);
1430 return *p
? S_OK
: E_OUTOFMEMORY
;
1434 static HRESULT WINAPI
domdoc_transformNode(
1435 IXMLDOMDocument3
*iface
,
1439 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1440 TRACE("(%p)->(%p %p)\n", This
, node
, p
);
1441 return node_transform_node(&This
->node
, node
, p
);
1445 static HRESULT WINAPI
domdoc_selectNodes(
1446 IXMLDOMDocument3
*iface
,
1448 IXMLDOMNodeList
**outList
)
1450 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1451 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outList
);
1452 return node_select_nodes(&This
->node
, p
, outList
);
1456 static HRESULT WINAPI
domdoc_selectSingleNode(
1457 IXMLDOMDocument3
*iface
,
1459 IXMLDOMNode
**outNode
)
1461 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1462 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outNode
);
1463 return node_select_singlenode(&This
->node
, p
, outNode
);
1467 static HRESULT WINAPI
domdoc_get_parsed(
1468 IXMLDOMDocument3
*iface
,
1469 VARIANT_BOOL
* isParsed
)
1471 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1472 FIXME("(%p)->(%p) stub!\n", This
, isParsed
);
1473 *isParsed
= VARIANT_TRUE
;
1477 static HRESULT WINAPI
domdoc_get_namespaceURI(
1478 IXMLDOMDocument3
*iface
,
1479 BSTR
* namespaceURI
)
1481 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1482 TRACE("(%p)->(%p)\n", This
, namespaceURI
);
1483 return return_null_bstr( namespaceURI
);
1486 static HRESULT WINAPI
domdoc_get_prefix(
1487 IXMLDOMDocument3
*iface
,
1490 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1491 TRACE("(%p)->(%p)\n", This
, prefix
);
1492 return return_null_bstr( prefix
);
1496 static HRESULT WINAPI
domdoc_get_baseName(
1497 IXMLDOMDocument3
*iface
,
1500 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1501 TRACE("(%p)->(%p)\n", This
, name
);
1502 return return_null_bstr( name
);
1506 static HRESULT WINAPI
domdoc_transformNodeToObject(
1507 IXMLDOMDocument3
*iface
,
1508 IXMLDOMNode
* stylesheet
,
1511 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1513 TRACE("(%p)->(%p %s)\n", This
, stylesheet
, debugstr_variant(&output
));
1515 switch (V_VT(&output
))
1520 IXMLDOMDocument
*doc
;
1523 if (!V_UNKNOWN(&output
))
1524 return E_INVALIDARG
;
1526 /* FIXME: we're not supposed to query for document interface, should use IStream
1527 which we don't support currently. */
1528 if (IUnknown_QueryInterface(V_UNKNOWN(&output
), &IID_IXMLDOMDocument
, (void **)&doc
) == S_OK
)
1533 if (FAILED(hr
= node_transform_node(&This
->node
, stylesheet
, &str
)))
1536 hr
= IXMLDOMDocument_loadXML(doc
, str
, &b
);
1542 FIXME("Unsupported destination type.\n");
1543 return E_INVALIDARG
;
1547 FIXME("Output type %d not handled.\n", V_VT(&output
));
1555 static HRESULT WINAPI
domdoc_get_doctype(
1556 IXMLDOMDocument3
*iface
,
1557 IXMLDOMDocumentType
** doctype
)
1559 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1564 TRACE("(%p)->(%p)\n", This
, doctype
);
1566 if (!doctype
) return E_INVALIDARG
;
1570 dtd
= xmlGetIntSubset(get_doc(This
));
1571 if (!dtd
) return S_FALSE
;
1573 node
= create_node((xmlNodePtr
)dtd
);
1574 if (!node
) return S_FALSE
;
1576 hr
= IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentType
, (void**)doctype
);
1577 IXMLDOMNode_Release(node
);
1583 static HRESULT WINAPI
domdoc_get_implementation(
1584 IXMLDOMDocument3
*iface
,
1585 IXMLDOMImplementation
** impl
)
1587 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1589 TRACE("(%p)->(%p)\n", This
, impl
);
1592 return E_INVALIDARG
;
1594 *impl
= (IXMLDOMImplementation
*)create_doc_Implementation();
1599 static HRESULT WINAPI
domdoc_get_documentElement(
1600 IXMLDOMDocument3
*iface
,
1601 IXMLDOMElement
** DOMElement
)
1603 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1604 IXMLDOMNode
*element_node
;
1608 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1611 return E_INVALIDARG
;
1615 root
= xmlDocGetRootElement( get_doc(This
) );
1619 element_node
= create_node( root
);
1620 if(!element_node
) return S_FALSE
;
1622 hr
= IXMLDOMNode_QueryInterface(element_node
, &IID_IXMLDOMElement
, (void**)DOMElement
);
1623 IXMLDOMNode_Release(element_node
);
1629 static HRESULT WINAPI
domdoc_put_documentElement(
1630 IXMLDOMDocument3
*iface
,
1631 IXMLDOMElement
* DOMElement
)
1633 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1634 IXMLDOMNode
*elementNode
;
1641 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1643 hr
= IXMLDOMElement_QueryInterface( DOMElement
, &IID_IXMLDOMNode
, (void**)&elementNode
);
1647 xmlNode
= get_node_obj( elementNode
);
1648 if(!xmlNode
) return E_FAIL
;
1650 if(!xmlNode
->node
->parent
)
1651 if(xmldoc_remove_orphan(xmlNode
->node
->doc
, xmlNode
->node
) != S_OK
)
1652 WARN("%p is not an orphan of %p\n", xmlNode
->node
->doc
, xmlNode
->node
);
1654 old_doc
= xmlNode
->node
->doc
;
1655 if (old_doc
!= get_doc(This
))
1656 refcount
= xmlnode_get_inst_cnt(xmlNode
);
1658 /* old root is still orphaned by its document, update refcount from new root */
1659 if (refcount
) xmldoc_add_refs(get_doc(This
), refcount
);
1660 oldRoot
= xmlDocSetRootElement( get_doc(This
), xmlNode
->node
);
1661 if (refcount
) xmldoc_release_refs(old_doc
, refcount
);
1662 IXMLDOMNode_Release( elementNode
);
1665 xmldoc_add_orphan(oldRoot
->doc
, oldRoot
);
1671 static HRESULT WINAPI
domdoc_createElement(
1672 IXMLDOMDocument3
*iface
,
1674 IXMLDOMElement
** element
)
1676 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1681 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(tagname
), element
);
1683 if (!element
|| !tagname
) return E_INVALIDARG
;
1685 V_VT(&type
) = VT_I1
;
1686 V_I1(&type
) = NODE_ELEMENT
;
1688 hr
= IXMLDOMDocument3_createNode(iface
, type
, tagname
, NULL
, &node
);
1691 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMElement
, (void**)element
);
1692 IXMLDOMNode_Release(node
);
1699 static HRESULT WINAPI
domdoc_createDocumentFragment(
1700 IXMLDOMDocument3
*iface
,
1701 IXMLDOMDocumentFragment
** frag
)
1703 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1708 TRACE("(%p)->(%p)\n", This
, frag
);
1710 if (!frag
) return E_INVALIDARG
;
1714 V_VT(&type
) = VT_I1
;
1715 V_I1(&type
) = NODE_DOCUMENT_FRAGMENT
;
1717 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1720 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentFragment
, (void**)frag
);
1721 IXMLDOMNode_Release(node
);
1728 static HRESULT WINAPI
domdoc_createTextNode(
1729 IXMLDOMDocument3
*iface
,
1731 IXMLDOMText
** text
)
1733 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1738 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), text
);
1740 if (!text
) return E_INVALIDARG
;
1744 V_VT(&type
) = VT_I1
;
1745 V_I1(&type
) = NODE_TEXT
;
1747 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1750 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMText
, (void**)text
);
1751 IXMLDOMNode_Release(node
);
1752 hr
= IXMLDOMText_put_data(*text
, data
);
1759 static HRESULT WINAPI
domdoc_createComment(
1760 IXMLDOMDocument3
*iface
,
1762 IXMLDOMComment
** comment
)
1764 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1769 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), comment
);
1771 if (!comment
) return E_INVALIDARG
;
1775 V_VT(&type
) = VT_I1
;
1776 V_I1(&type
) = NODE_COMMENT
;
1778 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1781 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMComment
, (void**)comment
);
1782 IXMLDOMNode_Release(node
);
1783 hr
= IXMLDOMComment_put_data(*comment
, data
);
1790 static HRESULT WINAPI
domdoc_createCDATASection(
1791 IXMLDOMDocument3
*iface
,
1793 IXMLDOMCDATASection
** cdata
)
1795 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1800 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), cdata
);
1802 if (!cdata
) return E_INVALIDARG
;
1806 V_VT(&type
) = VT_I1
;
1807 V_I1(&type
) = NODE_CDATA_SECTION
;
1809 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1812 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMCDATASection
, (void**)cdata
);
1813 IXMLDOMNode_Release(node
);
1814 hr
= IXMLDOMCDATASection_put_data(*cdata
, data
);
1821 static HRESULT WINAPI
domdoc_createProcessingInstruction(
1822 IXMLDOMDocument3
*iface
,
1825 IXMLDOMProcessingInstruction
** pi
)
1827 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1832 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_w(target
), debugstr_w(data
), pi
);
1834 if (!pi
) return E_INVALIDARG
;
1838 V_VT(&type
) = VT_I1
;
1839 V_I1(&type
) = NODE_PROCESSING_INSTRUCTION
;
1841 hr
= IXMLDOMDocument3_createNode(iface
, type
, target
, NULL
, &node
);
1846 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1847 node_obj
= get_node_obj(node
);
1848 hr
= node_set_content(node_obj
, data
);
1850 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMProcessingInstruction
, (void**)pi
);
1851 IXMLDOMNode_Release(node
);
1858 static HRESULT WINAPI
domdoc_createAttribute(
1859 IXMLDOMDocument3
*iface
,
1861 IXMLDOMAttribute
** attribute
)
1863 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1868 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), attribute
);
1870 if (!attribute
|| !name
) return E_INVALIDARG
;
1872 V_VT(&type
) = VT_I1
;
1873 V_I1(&type
) = NODE_ATTRIBUTE
;
1875 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1878 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMAttribute
, (void**)attribute
);
1879 IXMLDOMNode_Release(node
);
1886 static HRESULT WINAPI
domdoc_createEntityReference(
1887 IXMLDOMDocument3
*iface
,
1889 IXMLDOMEntityReference
** entityref
)
1891 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1896 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), entityref
);
1898 if (!entityref
) return E_INVALIDARG
;
1902 V_VT(&type
) = VT_I1
;
1903 V_I1(&type
) = NODE_ENTITY_REFERENCE
;
1905 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1908 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMEntityReference
, (void**)entityref
);
1909 IXMLDOMNode_Release(node
);
1915 xmlChar
* tagName_to_XPath(const BSTR tagName
)
1917 xmlChar
*query
, *tmp
;
1918 static const xmlChar everything
[] = "/descendant::node()";
1919 static const xmlChar mod_pre
[] = "*[local-name()='";
1920 static const xmlChar mod_post
[] = "']";
1921 static const xmlChar prefix
[] = "descendant::";
1922 const WCHAR
*tokBegin
, *tokEnd
;
1925 /* Special case - empty tagname - means select all nodes,
1926 except document itself. */
1928 return xmlStrdup(everything
);
1930 query
= xmlStrdup(prefix
);
1933 while (tokBegin
&& *tokBegin
)
1938 query
= xmlStrcat(query
, BAD_CAST
"/");
1942 query
= xmlStrcat(query
, BAD_CAST
"*");
1946 query
= xmlStrcat(query
, mod_pre
);
1948 while (*tokEnd
&& *tokEnd
!= '/')
1950 len
= WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, NULL
, 0, NULL
, NULL
);
1951 tmp
= xmlMalloc(len
);
1952 WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, (char*)tmp
, len
, NULL
, NULL
);
1953 query
= xmlStrncat(query
, tmp
, len
);
1956 query
= xmlStrcat(query
, mod_post
);
1963 static HRESULT WINAPI
domdoc_getElementsByTagName(
1964 IXMLDOMDocument3
*iface
,
1966 IXMLDOMNodeList
** resultList
)
1968 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1973 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(tagName
), resultList
);
1975 if (!tagName
|| !resultList
) return E_INVALIDARG
;
1977 XPath
= This
->properties
->XPath
;
1978 This
->properties
->XPath
= TRUE
;
1979 query
= tagName_to_XPath(tagName
);
1980 hr
= create_selection((xmlNodePtr
)get_doc(This
), query
, resultList
);
1982 This
->properties
->XPath
= XPath
;
1987 static HRESULT
get_node_type(VARIANT Type
, DOMNodeType
* type
)
1993 hr
= VariantChangeType(&tmp
, &Type
, 0, VT_I4
);
1995 return E_INVALIDARG
;
2002 static HRESULT WINAPI
domdoc_createNode(
2003 IXMLDOMDocument3
*iface
,
2007 IXMLDOMNode
** node
)
2009 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2010 DOMNodeType node_type
;
2012 xmlChar
*xml_name
, *href
;
2015 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_variant(&Type
), debugstr_w(name
), debugstr_w(namespaceURI
), node
);
2017 if(!node
) return E_INVALIDARG
;
2019 hr
= get_node_type(Type
, &node_type
);
2020 if(FAILED(hr
)) return hr
;
2022 TRACE("node_type %d\n", node_type
);
2024 /* exit earlier for types that need name */
2028 case NODE_ATTRIBUTE
:
2029 case NODE_ENTITY_REFERENCE
:
2030 case NODE_PROCESSING_INSTRUCTION
:
2031 if (!name
|| *name
== 0) return E_FAIL
;
2037 xml_name
= xmlchar_from_wchar(name
);
2038 /* prevent empty href from being allocated */
2039 href
= namespaceURI
? xmlchar_from_wchar(namespaceURI
) : NULL
;
2045 xmlChar
*local
, *prefix
;
2047 local
= xmlSplitQName2(xml_name
, &prefix
);
2049 xmlnode
= xmlNewDocNode(get_doc(This
), NULL
, local
? local
: xml_name
, NULL
);
2051 /* allow creating the default namespace xmlns= */
2052 if (local
|| (href
&& *href
))
2054 xmlNsPtr ns
= xmlNewNs(xmlnode
, href
, prefix
);
2055 xmlSetNs(xmlnode
, ns
);
2063 case NODE_ATTRIBUTE
:
2065 xmlChar
*local
, *prefix
;
2067 local
= xmlSplitQName2(xml_name
, &prefix
);
2069 xmlnode
= (xmlNodePtr
)xmlNewDocProp(get_doc(This
), local
? local
: xml_name
, NULL
);
2071 if (local
|| (href
&& *href
))
2073 /* we need a floating namespace here, it can't be created linked to attribute from
2075 xmlNsPtr ns
= xmlNewNs(NULL
, href
, prefix
);
2076 xmlSetNs(xmlnode
, ns
);
2085 xmlnode
= (xmlNodePtr
)xmlNewDocText(get_doc(This
), NULL
);
2087 case NODE_CDATA_SECTION
:
2088 xmlnode
= xmlNewCDataBlock(get_doc(This
), NULL
, 0);
2090 case NODE_ENTITY_REFERENCE
:
2091 xmlnode
= xmlNewReference(get_doc(This
), xml_name
);
2093 case NODE_PROCESSING_INSTRUCTION
:
2094 #ifdef HAVE_XMLNEWDOCPI
2095 xmlnode
= xmlNewDocPI(get_doc(This
), xml_name
, NULL
);
2097 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2102 xmlnode
= xmlNewDocComment(get_doc(This
), NULL
);
2104 case NODE_DOCUMENT_FRAGMENT
:
2105 xmlnode
= xmlNewDocFragment(get_doc(This
));
2107 /* unsupported types */
2109 case NODE_DOCUMENT_TYPE
:
2112 heap_free(xml_name
);
2113 return E_INVALIDARG
;
2115 FIXME("unhandled node type %d\n", node_type
);
2120 *node
= create_node(xmlnode
);
2121 heap_free(xml_name
);
2126 TRACE("created node (%d, %p, %p)\n", node_type
, *node
, xmlnode
);
2127 xmldoc_add_orphan(xmlnode
->doc
, xmlnode
);
2134 static HRESULT WINAPI
domdoc_nodeFromID(
2135 IXMLDOMDocument3
*iface
,
2137 IXMLDOMNode
** node
)
2139 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2140 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(idString
), node
);
2144 static HRESULT
domdoc_onDataAvailable(void *obj
, char *ptr
, DWORD len
)
2149 xmldoc
= doparse(This
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
2151 xmldoc
->_private
= create_priv();
2152 return attach_xmldoc(This
, xmldoc
);
2158 static HRESULT
domdoc_load_moniker(domdoc
*This
, IMoniker
*mon
)
2163 hr
= bind_url(mon
, domdoc_onDataAvailable
, This
, &bsc
);
2167 return detach_bsc(bsc
);
2170 static HRESULT WINAPI
domdoc_load(
2171 IXMLDOMDocument3
*iface
,
2173 VARIANT_BOOL
* isSuccessful
)
2175 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2176 LPWSTR filename
= NULL
;
2177 HRESULT hr
= S_FALSE
;
2180 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&source
));
2184 *isSuccessful
= VARIANT_FALSE
;
2186 assert( &This
->node
);
2188 switch( V_VT(&source
) )
2191 filename
= V_BSTR(&source
);
2193 case VT_BSTR
|VT_BYREF
:
2194 if (!V_BSTRREF(&source
)) return E_INVALIDARG
;
2195 filename
= *V_BSTRREF(&source
);
2197 case VT_ARRAY
|VT_UI1
:
2199 SAFEARRAY
*psa
= V_ARRAY(&source
);
2202 UINT dim
= SafeArrayGetDim(psa
);
2207 ERR("SAFEARRAY == NULL\n");
2208 hr
= This
->error
= E_INVALIDARG
;
2211 /* Only takes UTF-8 strings.
2212 * NOT NULL-terminated. */
2213 hr
= SafeArrayAccessData(psa
, (void**)&str
);
2217 WARN("failed to access array data, 0x%08x\n", hr
);
2220 SafeArrayGetUBound(psa
, 1, &len
);
2222 if ((xmldoc
= doparse(This
, str
, ++len
, XML_CHAR_ENCODING_UTF8
)))
2224 hr
= This
->error
= S_OK
;
2225 *isSuccessful
= VARIANT_TRUE
;
2226 TRACE("parsed document %p\n", xmldoc
);
2230 This
->error
= E_FAIL
;
2231 TRACE("failed to parse document\n");
2234 SafeArrayUnaccessData(psa
);
2238 xmldoc
->_private
= create_priv();
2239 return attach_xmldoc(This
, xmldoc
);
2243 FIXME("unhandled SAFEARRAY dim: %d\n", dim
);
2244 hr
= This
->error
= E_NOTIMPL
;
2250 ISequentialStream
*stream
= NULL
;
2251 IXMLDOMDocument3
*newdoc
= NULL
;
2253 if (!V_UNKNOWN(&source
)) return E_INVALIDARG
;
2255 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IXMLDOMDocument3
, (void**)&newdoc
);
2260 domdoc
*newDoc
= impl_from_IXMLDOMDocument3( newdoc
);
2262 xmldoc
= xmlCopyDoc(get_doc(newDoc
), 1);
2263 xmldoc
->_private
= create_priv();
2264 hr
= attach_xmldoc(This
, xmldoc
);
2267 *isSuccessful
= VARIANT_TRUE
;
2273 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IStream
, (void**)&stream
);
2275 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_ISequentialStream
, (void**)&stream
);
2279 hr
= domdoc_load_from_stream(This
, stream
);
2281 *isSuccessful
= VARIANT_TRUE
;
2282 ISequentialStream_Release(stream
);
2286 FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr
, V_UNKNOWN(&source
)->lpVtbl
);
2290 FIXME("VT type not supported (%d)\n", V_VT(&source
));
2298 if (This
->properties
->uri
)
2300 IUri_Release(This
->properties
->uri
);
2301 This
->properties
->uri
= NULL
;
2304 hr
= create_uri(filename
, &uri
);
2306 hr
= CreateURLMonikerEx2(NULL
, uri
, &mon
, 0);
2307 if ( SUCCEEDED(hr
) )
2309 hr
= domdoc_load_moniker( This
, mon
);
2310 IMoniker_Release(mon
);
2315 get_doc(This
)->name
= (char *)xmlchar_from_wcharn(filename
, -1, TRUE
);
2316 This
->properties
->uri
= uri
;
2317 hr
= This
->error
= S_OK
;
2318 *isSuccessful
= VARIANT_TRUE
;
2324 This
->error
= E_FAIL
;
2328 if(!filename
|| FAILED(hr
)) {
2329 xmldoc
= xmlNewDoc(NULL
);
2330 xmldoc
->_private
= create_priv();
2331 hr
= attach_xmldoc(This
, xmldoc
);
2336 TRACE("ret (%d)\n", hr
);
2342 static HRESULT WINAPI
domdoc_get_readyState(
2343 IXMLDOMDocument3
*iface
,
2346 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2347 FIXME("stub! (%p)->(%p)\n", This
, value
);
2350 return E_INVALIDARG
;
2352 *value
= READYSTATE_COMPLETE
;
2357 static HRESULT WINAPI
domdoc_get_parseError(
2358 IXMLDOMDocument3
*iface
,
2359 IXMLDOMParseError
** errorObj
)
2361 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2362 static const WCHAR err
[] = {'e','r','r','o','r',0};
2363 BSTR error_string
= NULL
;
2365 FIXME("(%p)->(%p): creating a dummy parseError\n", iface
, errorObj
);
2368 error_string
= SysAllocString(err
);
2370 *errorObj
= create_parseError(This
->error
, NULL
, error_string
, NULL
, 0, 0, 0);
2371 if(!*errorObj
) return E_OUTOFMEMORY
;
2376 static HRESULT WINAPI
domdoc_get_url(
2377 IXMLDOMDocument3
*iface
,
2380 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2382 TRACE("(%p)->(%p)\n", This
, url
);
2385 return E_INVALIDARG
;
2387 if (!This
->properties
->uri
)
2388 return return_null_bstr(url
);
2390 return IUri_GetPropertyBSTR(This
->properties
->uri
, Uri_PROPERTY_DISPLAY_URI
, url
, 0);
2394 static HRESULT WINAPI
domdoc_get_async(
2395 IXMLDOMDocument3
*iface
,
2396 VARIANT_BOOL
* isAsync
)
2398 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2400 TRACE("(%p)->(%p: %d)\n", This
, isAsync
, This
->async
);
2401 *isAsync
= This
->async
;
2406 static HRESULT WINAPI
domdoc_put_async(
2407 IXMLDOMDocument3
*iface
,
2408 VARIANT_BOOL isAsync
)
2410 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2412 TRACE("(%p)->(%d)\n", This
, isAsync
);
2413 This
->async
= isAsync
;
2418 static HRESULT WINAPI
domdoc_abort(
2419 IXMLDOMDocument3
*iface
)
2421 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2422 FIXME("%p\n", This
);
2426 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2427 static HRESULT WINAPI
domdoc_loadXML(
2428 IXMLDOMDocument3
*iface
,
2430 VARIANT_BOOL
* isSuccessful
)
2432 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2433 xmlDocPtr xmldoc
= NULL
;
2434 HRESULT hr
= S_FALSE
, hr2
;
2436 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), isSuccessful
);
2438 assert ( &This
->node
);
2442 *isSuccessful
= VARIANT_FALSE
;
2448 /* skip leading spaces if needed */
2449 if (This
->properties
->version
== MSXML_DEFAULT
|| This
->properties
->version
== MSXML26
)
2450 while (*ptr
&& isspaceW(*ptr
)) ptr
++;
2452 xmldoc
= doparse(This
, (char*)ptr
, strlenW(ptr
)*sizeof(WCHAR
), XML_CHAR_ENCODING_UTF16LE
);
2455 This
->error
= E_FAIL
;
2456 TRACE("failed to parse document\n");
2460 hr
= This
->error
= S_OK
;
2461 *isSuccessful
= VARIANT_TRUE
;
2462 TRACE("parsed document %p\n", xmldoc
);
2468 xmldoc
= xmlNewDoc(NULL
);
2469 xmldoc
->_private
= create_priv();
2470 hr2
= attach_xmldoc(This
, xmldoc
);
2477 static int XMLCALL
domdoc_save_writecallback(void *ctx
, const char *buffer
, int len
)
2481 if(!WriteFile(ctx
, buffer
, len
, &written
, NULL
))
2483 WARN("write error\n");
2490 static int XMLCALL
domdoc_save_closecallback(void *ctx
)
2492 return CloseHandle(ctx
) ? 0 : -1;
2495 static int XMLCALL
domdoc_stream_save_writecallback(void *ctx
, const char *buffer
, int len
)
2500 hr
= IStream_Write((IStream
*)ctx
, buffer
, len
, &written
);
2501 TRACE("0x%08x %p %d %u\n", hr
, buffer
, len
, written
);
2504 WARN("stream write error: 0x%08x\n", hr
);
2511 static int XMLCALL
domdoc_stream_save_closecallback(void *ctx
)
2513 IStream_Release((IStream
*)ctx
);
2517 static HRESULT WINAPI
domdoc_save(
2518 IXMLDOMDocument3
*iface
,
2519 VARIANT destination
)
2521 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2522 xmlSaveCtxtPtr ctx
= NULL
;
2526 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&destination
));
2528 switch (V_VT(&destination
))
2532 IUnknown
*pUnk
= V_UNKNOWN(&destination
);
2533 IXMLDOMDocument3
*document
;
2536 ret
= IUnknown_QueryInterface(pUnk
, &IID_IXMLDOMDocument3
, (void**)&document
);
2539 VARIANT_BOOL success
;
2542 ret
= IXMLDOMDocument3_get_xml(iface
, &xml
);
2545 ret
= IXMLDOMDocument3_loadXML(document
, xml
, &success
);
2549 IXMLDOMDocument3_Release(document
);
2553 ret
= IUnknown_QueryInterface(pUnk
, &IID_IStream
, (void**)&stream
);
2556 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2557 ctx
= xmlSaveToIO(domdoc_stream_save_writecallback
,
2558 domdoc_stream_save_closecallback
, stream
, NULL
, options
);
2562 IStream_Release(stream
);
2570 case VT_BSTR
| VT_BYREF
:
2572 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2574 /* save with file path */
2575 HANDLE handle
= CreateFileW( (V_VT(&destination
) & VT_BYREF
)? *V_BSTRREF(&destination
) : V_BSTR(&destination
),
2576 GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2577 if( handle
== INVALID_HANDLE_VALUE
)
2579 WARN("failed to create file\n");
2583 /* disable top XML declaration */
2584 ctx
= xmlSaveToIO(domdoc_save_writecallback
, domdoc_save_closecallback
,
2585 handle
, NULL
, options
);
2588 CloseHandle(handle
);
2595 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination
));
2599 xmldecl
= xmldoc_unlink_xmldecl(get_doc(This
));
2600 if (xmlSaveDoc(ctx
, get_doc(This
)) == -1) ret
= S_FALSE
;
2601 xmldoc_link_xmldecl(get_doc(This
), xmldecl
);
2603 /* will release resources through close callback */
2609 static HRESULT WINAPI
domdoc_get_validateOnParse(
2610 IXMLDOMDocument3
*iface
,
2611 VARIANT_BOOL
* isValidating
)
2613 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2614 TRACE("(%p)->(%p: %d)\n", This
, isValidating
, This
->validating
);
2615 *isValidating
= This
->validating
;
2620 static HRESULT WINAPI
domdoc_put_validateOnParse(
2621 IXMLDOMDocument3
*iface
,
2622 VARIANT_BOOL isValidating
)
2624 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2625 TRACE("(%p)->(%d)\n", This
, isValidating
);
2626 This
->validating
= isValidating
;
2631 static HRESULT WINAPI
domdoc_get_resolveExternals(
2632 IXMLDOMDocument3
*iface
,
2633 VARIANT_BOOL
* isResolving
)
2635 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2636 TRACE("(%p)->(%p: %d)\n", This
, isResolving
, This
->resolving
);
2637 *isResolving
= This
->resolving
;
2642 static HRESULT WINAPI
domdoc_put_resolveExternals(
2643 IXMLDOMDocument3
*iface
,
2644 VARIANT_BOOL isResolving
)
2646 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2647 TRACE("(%p)->(%d)\n", This
, isResolving
);
2648 This
->resolving
= isResolving
;
2653 static HRESULT WINAPI
domdoc_get_preserveWhiteSpace(
2654 IXMLDOMDocument3
*iface
,
2655 VARIANT_BOOL
* isPreserving
)
2657 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2658 TRACE("(%p)->(%p: %d)\n", This
, isPreserving
, This
->properties
->preserving
);
2659 *isPreserving
= This
->properties
->preserving
;
2664 static HRESULT WINAPI
domdoc_put_preserveWhiteSpace(
2665 IXMLDOMDocument3
*iface
,
2666 VARIANT_BOOL isPreserving
)
2668 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2669 TRACE("(%p)->(%d)\n", This
, isPreserving
);
2670 This
->properties
->preserving
= isPreserving
;
2675 static HRESULT WINAPI
domdoc_put_onreadystatechange(
2676 IXMLDOMDocument3
*iface
,
2679 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2681 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&event
));
2682 return set_doc_event(This
, EVENTID_READYSTATECHANGE
, &event
);
2686 static HRESULT WINAPI
domdoc_put_onDataAvailable(IXMLDOMDocument3
*iface
, VARIANT sink
)
2688 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2689 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2693 static HRESULT WINAPI
domdoc_put_onTransformNode(IXMLDOMDocument3
*iface
, VARIANT sink
)
2695 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2696 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2700 static HRESULT WINAPI
domdoc_get_namespaces(
2701 IXMLDOMDocument3
* iface
,
2702 IXMLDOMSchemaCollection
** collection
)
2704 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2707 FIXME("(%p)->(%p): semi-stub\n", This
, collection
);
2709 if (!collection
) return E_POINTER
;
2711 if (!This
->namespaces
)
2713 hr
= SchemaCache_create(This
->properties
->version
, (void**)&This
->namespaces
);
2714 if (hr
!= S_OK
) return hr
;
2716 hr
= cache_from_doc_ns(This
->namespaces
, &This
->node
);
2718 release_namespaces(This
);
2721 if (This
->namespaces
)
2722 return IXMLDOMSchemaCollection2_QueryInterface(This
->namespaces
,
2723 &IID_IXMLDOMSchemaCollection
, (void**)collection
);
2728 static HRESULT WINAPI
domdoc_get_schemas(
2729 IXMLDOMDocument3
* iface
,
2732 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2733 IXMLDOMSchemaCollection2
* cur_schema
= This
->properties
->schemaCache
;
2734 HRESULT hr
= S_FALSE
;
2736 TRACE("(%p)->(%p)\n", This
, schema
);
2738 V_VT(schema
) = VT_NULL
;
2739 /* just to reset pointer part, cause that's what application is expected to use */
2740 V_DISPATCH(schema
) = NULL
;
2744 hr
= IXMLDOMSchemaCollection2_QueryInterface(cur_schema
, &IID_IDispatch
, (void**)&V_DISPATCH(schema
));
2746 V_VT(schema
) = VT_DISPATCH
;
2751 static HRESULT WINAPI
domdoc_putref_schemas(
2752 IXMLDOMDocument3
* iface
,
2755 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2756 HRESULT hr
= E_FAIL
;
2757 IXMLDOMSchemaCollection2
* new_schema
= NULL
;
2759 FIXME("(%p)->(%s): semi-stub\n", This
, debugstr_variant(&schema
));
2760 switch(V_VT(&schema
))
2763 if (V_UNKNOWN(&schema
))
2765 hr
= IUnknown_QueryInterface(V_UNKNOWN(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2770 if (V_DISPATCH(&schema
))
2772 hr
= IDispatch_QueryInterface(V_DISPATCH(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2782 WARN("Can't get schema from vt %x\n", V_VT(&schema
));
2787 IXMLDOMSchemaCollection2
* old_schema
= InterlockedExchangePointer((void**)&This
->properties
->schemaCache
, new_schema
);
2788 if(old_schema
) IXMLDOMSchemaCollection2_Release(old_schema
);
2794 static inline BOOL
is_wellformed(xmlDocPtr doc
)
2796 #ifdef HAVE_XMLDOC_PROPERTIES
2797 return doc
->properties
& XML_DOC_WELLFORMED
;
2799 /* Not a full check, but catches the worst violations */
2803 for (child
= doc
->children
; child
!= NULL
; child
= child
->next
)
2805 switch (child
->type
)
2807 case XML_ELEMENT_NODE
:
2812 case XML_CDATA_SECTION_NODE
:
2824 static void LIBXML2_LOG_CALLBACK
validate_error(void* ctx
, char const* msg
, ...)
2828 LIBXML2_CALLBACK_ERR(domdoc_validateNode
, msg
, ap
);
2832 static void LIBXML2_LOG_CALLBACK
validate_warning(void* ctx
, char const* msg
, ...)
2836 LIBXML2_CALLBACK_WARN(domdoc_validateNode
, msg
, ap
);
2840 static HRESULT WINAPI
domdoc_validateNode(
2841 IXMLDOMDocument3
* iface
,
2843 IXMLDOMParseError
** err
)
2845 domdoc
* This
= impl_from_IXMLDOMDocument3(iface
);
2846 LONG state
, err_code
= 0;
2850 TRACE("(%p)->(%p, %p)\n", This
, node
, err
);
2851 IXMLDOMDocument3_get_readyState(iface
, &state
);
2852 if (state
!= READYSTATE_COMPLETE
)
2855 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2862 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2866 if (!get_node_obj(node
)->node
|| get_node_obj(node
)->node
->doc
!= get_doc(This
))
2869 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2873 if (!is_wellformed(get_doc(This
)))
2875 ERR("doc not well-formed\n");
2877 *err
= create_parseError(E_XML_NOTWF
, NULL
, NULL
, NULL
, 0, 0, 0);
2881 /* DTD validation */
2882 if (get_doc(This
)->intSubset
|| get_doc(This
)->extSubset
)
2884 xmlValidCtxtPtr vctx
= xmlNewValidCtxt();
2885 vctx
->error
= validate_error
;
2886 vctx
->warning
= validate_warning
;
2889 if (!((node
== (IXMLDOMNode
*)iface
)?
2890 xmlValidateDocument(vctx
, get_doc(This
)) :
2891 xmlValidateElement(vctx
, get_doc(This
), get_node_obj(node
)->node
)))
2893 /* TODO: get a real error code here */
2894 TRACE("DTD validation failed\n");
2895 err_code
= E_XML_INVALID
;
2898 xmlFreeValidCtxt(vctx
);
2901 /* Schema validation */
2902 if (hr
== S_OK
&& This
->properties
->schemaCache
!= NULL
)
2905 hr
= SchemaCache_validate_tree(This
->properties
->schemaCache
, get_node_obj(node
)->node
);
2909 /* TODO: get a real error code here */
2912 TRACE("schema validation succeeded\n");
2916 ERR("schema validation failed\n");
2917 err_code
= E_XML_INVALID
;
2922 /* not really OK, just didn't find a schema for the ns */
2929 ERR("no DTD or schema found\n");
2930 err_code
= E_XML_NODTD
;
2935 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2940 static HRESULT WINAPI
domdoc_validate(
2941 IXMLDOMDocument3
* iface
,
2942 IXMLDOMParseError
** err
)
2944 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2945 TRACE("(%p)->(%p)\n", This
, err
);
2946 return IXMLDOMDocument3_validateNode(iface
, (IXMLDOMNode
*)iface
, err
);
2949 static HRESULT WINAPI
domdoc_setProperty(
2950 IXMLDOMDocument3
* iface
,
2954 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2956 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(p
), debugstr_variant(&value
));
2958 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
2964 V_VT(&varStr
) = VT_EMPTY
;
2965 if (V_VT(&value
) != VT_BSTR
)
2967 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2969 bstr
= V_BSTR(&varStr
);
2972 bstr
= V_BSTR(&value
);
2975 if (lstrcmpiW(bstr
, PropValueXPathW
) == 0)
2976 This
->properties
->XPath
= TRUE
;
2977 else if (lstrcmpiW(bstr
, PropValueXSLPatternW
) == 0)
2978 This
->properties
->XPath
= FALSE
;
2982 VariantClear(&varStr
);
2985 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
2987 xmlChar
*nsStr
= (xmlChar
*)This
->properties
->selectNsStr
;
2988 struct list
*pNsList
;
2993 V_VT(&varStr
) = VT_EMPTY
;
2994 if (V_VT(&value
) != VT_BSTR
)
2996 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2998 bstr
= V_BSTR(&varStr
);
3001 bstr
= V_BSTR(&value
);
3005 pNsList
= &(This
->properties
->selectNsList
);
3006 clear_selectNsList(pNsList
);
3008 nsStr
= xmlchar_from_wchar(bstr
);
3010 TRACE("property value: \"%s\"\n", debugstr_w(bstr
));
3012 This
->properties
->selectNsStr
= nsStr
;
3013 This
->properties
->selectNsStr_len
= xmlStrlen(nsStr
);
3016 xmlChar
*pTokBegin
, *pTokEnd
, *pTokInner
;
3017 select_ns_entry
* ns_entry
= NULL
;
3018 xmlXPathContextPtr ctx
;
3020 ctx
= xmlXPathNewContext(This
->node
.node
->doc
);
3023 /* skip leading spaces */
3024 while (*pTokBegin
== ' ' || *pTokBegin
== '\n' ||
3025 *pTokBegin
== '\t' || *pTokBegin
== '\r')
3028 for (; *pTokBegin
; pTokBegin
= pTokEnd
)
3031 memset(ns_entry
, 0, sizeof(select_ns_entry
));
3033 ns_entry
= heap_alloc_zero(sizeof(select_ns_entry
));
3035 while (*pTokBegin
== ' ')
3037 pTokEnd
= pTokBegin
;
3038 while (*pTokEnd
!= ' ' && *pTokEnd
!= 0)
3041 /* so it failed to advance which means we've got some trailing spaces */
3042 if (pTokEnd
== pTokBegin
) break;
3044 if (xmlStrncmp(pTokBegin
, (xmlChar
const*)"xmlns", 5) != 0)
3047 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3048 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
3053 if (*pTokBegin
== '=')
3055 /*valid for XSLPattern?*/
3056 FIXME("Setting default xmlns not supported - skipping.\n");
3059 else if (*pTokBegin
== ':')
3061 ns_entry
->prefix
= ++pTokBegin
;
3062 for (pTokInner
= pTokBegin
; pTokInner
!= pTokEnd
&& *pTokInner
!= '='; ++pTokInner
)
3065 if (pTokInner
== pTokEnd
)
3068 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3069 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
3073 ns_entry
->prefix_end
= *pTokInner
;
3077 if (pTokEnd
-pTokInner
> 1 &&
3078 ((*pTokInner
== '\'' && *(pTokEnd
-1) == '\'') ||
3079 (*pTokInner
== '"' && *(pTokEnd
-1) == '"')))
3081 ns_entry
->href
= ++pTokInner
;
3082 ns_entry
->href_end
= *(pTokEnd
-1);
3084 list_add_tail(pNsList
, &ns_entry
->entry
);
3085 /*let libxml figure out if they're valid from here ;)*/
3086 if (xmlXPathRegisterNs(ctx
, ns_entry
->prefix
, ns_entry
->href
) != 0)
3095 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3096 debugstr_w(bstr
), debugstr_an((const char*)pTokInner
, pTokEnd
-pTokInner
));
3097 list_add_tail(pNsList
, &ns_entry
->entry
);
3110 heap_free(ns_entry
);
3111 xmlXPathFreeContext(ctx
);
3114 VariantClear(&varStr
);
3117 else if (lstrcmpiW(p
, PropertyProhibitDTDW
) == 0 ||
3118 lstrcmpiW(p
, PropertyNewParserW
) == 0 ||
3119 lstrcmpiW(p
, PropertyResolveExternalsW
) == 0 ||
3120 lstrcmpiW(p
, PropertyAllowXsltScriptW
) == 0 ||
3121 lstrcmpiW(p
, PropertyNormalizeAttributeValuesW
) == 0 ||
3122 lstrcmpiW(p
, PropertyAllowDocumentFunctionW
) == 0)
3125 FIXME("Ignoring property %s, value %s\n", debugstr_w(p
), debugstr_variant(&value
));
3129 FIXME("Unknown property %s\n", debugstr_w(p
));
3133 static HRESULT WINAPI
domdoc_getProperty(
3134 IXMLDOMDocument3
* iface
,
3138 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3140 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
3143 return E_INVALIDARG
;
3145 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
3147 V_VT(var
) = VT_BSTR
;
3148 V_BSTR(var
) = This
->properties
->XPath
?
3149 SysAllocString(PropValueXPathW
) :
3150 SysAllocString(PropValueXSLPatternW
);
3151 return V_BSTR(var
) ? S_OK
: E_OUTOFMEMORY
;
3153 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3156 BSTR rebuiltStr
, cur
;
3157 const xmlChar
*nsStr
;
3158 struct list
*pNsList
;
3159 select_ns_entry
* pNsEntry
;
3161 V_VT(var
) = VT_BSTR
;
3162 nsStr
= This
->properties
->selectNsStr
;
3163 pNsList
= &This
->properties
->selectNsList
;
3164 lenA
= This
->properties
->selectNsStr_len
;
3165 lenW
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, NULL
, 0);
3166 rebuiltStr
= heap_alloc(lenW
*sizeof(WCHAR
));
3167 MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, rebuiltStr
, lenW
);
3169 /* this is fine because all of the chars that end tokens are ASCII*/
3170 LIST_FOR_EACH_ENTRY(pNsEntry
, pNsList
, select_ns_entry
, entry
)
3172 while (*cur
!= 0) ++cur
;
3173 if (pNsEntry
->prefix_end
)
3175 *cur
= pNsEntry
->prefix_end
;
3176 while (*cur
!= 0) ++cur
;
3179 if (pNsEntry
->href_end
)
3181 *cur
= pNsEntry
->href_end
;
3184 V_BSTR(var
) = SysAllocString(rebuiltStr
);
3185 heap_free(rebuiltStr
);
3189 FIXME("Unknown property %s\n", debugstr_w(p
));
3193 static HRESULT WINAPI
domdoc_importNode(
3194 IXMLDOMDocument3
* iface
,
3197 IXMLDOMNode
** clone
)
3199 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3200 FIXME("(%p)->(%p %d %p): stub\n", This
, node
, deep
, clone
);
3204 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl
=
3206 domdoc_QueryInterface
,
3209 domdoc_GetTypeInfoCount
,
3211 domdoc_GetIDsOfNames
,
3213 domdoc_get_nodeName
,
3214 domdoc_get_nodeValue
,
3215 domdoc_put_nodeValue
,
3216 domdoc_get_nodeType
,
3217 domdoc_get_parentNode
,
3218 domdoc_get_childNodes
,
3219 domdoc_get_firstChild
,
3220 domdoc_get_lastChild
,
3221 domdoc_get_previousSibling
,
3222 domdoc_get_nextSibling
,
3223 domdoc_get_attributes
,
3224 domdoc_insertBefore
,
3225 domdoc_replaceChild
,
3228 domdoc_hasChildNodes
,
3229 domdoc_get_ownerDocument
,
3231 domdoc_get_nodeTypeString
,
3234 domdoc_get_specified
,
3235 domdoc_get_definition
,
3236 domdoc_get_nodeTypedValue
,
3237 domdoc_put_nodeTypedValue
,
3238 domdoc_get_dataType
,
3239 domdoc_put_dataType
,
3241 domdoc_transformNode
,
3243 domdoc_selectSingleNode
,
3245 domdoc_get_namespaceURI
,
3247 domdoc_get_baseName
,
3248 domdoc_transformNodeToObject
,
3250 domdoc_get_implementation
,
3251 domdoc_get_documentElement
,
3252 domdoc_put_documentElement
,
3253 domdoc_createElement
,
3254 domdoc_createDocumentFragment
,
3255 domdoc_createTextNode
,
3256 domdoc_createComment
,
3257 domdoc_createCDATASection
,
3258 domdoc_createProcessingInstruction
,
3259 domdoc_createAttribute
,
3260 domdoc_createEntityReference
,
3261 domdoc_getElementsByTagName
,
3265 domdoc_get_readyState
,
3266 domdoc_get_parseError
,
3273 domdoc_get_validateOnParse
,
3274 domdoc_put_validateOnParse
,
3275 domdoc_get_resolveExternals
,
3276 domdoc_put_resolveExternals
,
3277 domdoc_get_preserveWhiteSpace
,
3278 domdoc_put_preserveWhiteSpace
,
3279 domdoc_put_onreadystatechange
,
3280 domdoc_put_onDataAvailable
,
3281 domdoc_put_onTransformNode
,
3282 domdoc_get_namespaces
,
3284 domdoc_putref_schemas
,
3288 domdoc_validateNode
,
3292 /* IConnectionPointContainer */
3293 static HRESULT WINAPI
ConnectionPointContainer_QueryInterface(IConnectionPointContainer
*iface
,
3294 REFIID riid
, void **ppv
)
3296 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3297 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3300 static ULONG WINAPI
ConnectionPointContainer_AddRef(IConnectionPointContainer
*iface
)
3302 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3303 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3306 static ULONG WINAPI
ConnectionPointContainer_Release(IConnectionPointContainer
*iface
)
3308 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3309 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3312 static HRESULT WINAPI
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer
*iface
,
3313 IEnumConnectionPoints
**ppEnum
)
3315 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3316 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3320 static HRESULT WINAPI
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer
*iface
,
3321 REFIID riid
, IConnectionPoint
**cp
)
3323 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3324 ConnectionPoint
*iter
;
3326 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), cp
);
3330 for(iter
= This
->cp_list
; iter
; iter
= iter
->next
)
3332 if (IsEqualGUID(iter
->iid
, riid
))
3333 *cp
= &iter
->IConnectionPoint_iface
;
3338 IConnectionPoint_AddRef(*cp
);
3342 FIXME("unsupported riid %s\n", debugstr_guid(riid
));
3343 return CONNECT_E_NOCONNECTION
;
3347 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl
=
3349 ConnectionPointContainer_QueryInterface
,
3350 ConnectionPointContainer_AddRef
,
3351 ConnectionPointContainer_Release
,
3352 ConnectionPointContainer_EnumConnectionPoints
,
3353 ConnectionPointContainer_FindConnectionPoint
3356 /* IConnectionPoint */
3357 static HRESULT WINAPI
ConnectionPoint_QueryInterface(IConnectionPoint
*iface
,
3358 REFIID riid
, void **ppv
)
3360 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3362 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
3366 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
3367 IsEqualGUID(&IID_IConnectionPoint
, riid
))
3374 IConnectionPoint_AddRef(iface
);
3378 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
3379 return E_NOINTERFACE
;
3382 static ULONG WINAPI
ConnectionPoint_AddRef(IConnectionPoint
*iface
)
3384 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3385 return IConnectionPointContainer_AddRef(This
->container
);
3388 static ULONG WINAPI
ConnectionPoint_Release(IConnectionPoint
*iface
)
3390 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3391 return IConnectionPointContainer_Release(This
->container
);
3394 static HRESULT WINAPI
ConnectionPoint_GetConnectionInterface(IConnectionPoint
*iface
, IID
*iid
)
3396 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3398 TRACE("(%p)->(%p)\n", This
, iid
);
3400 if (!iid
) return E_POINTER
;
3406 static HRESULT WINAPI
ConnectionPoint_GetConnectionPointContainer(IConnectionPoint
*iface
,
3407 IConnectionPointContainer
**container
)
3409 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3411 TRACE("(%p)->(%p)\n", This
, container
);
3413 if (!container
) return E_POINTER
;
3415 *container
= This
->container
;
3416 IConnectionPointContainer_AddRef(*container
);
3420 static HRESULT WINAPI
ConnectionPoint_Advise(IConnectionPoint
*iface
, IUnknown
*unk_sink
,
3423 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3428 TRACE("(%p)->(%p %p)\n", This
, unk_sink
, cookie
);
3430 hr
= IUnknown_QueryInterface(unk_sink
, This
->iid
, (void**)&sink
);
3431 if(FAILED(hr
) && !IsEqualGUID(&IID_IPropertyNotifySink
, This
->iid
))
3432 hr
= IUnknown_QueryInterface(unk_sink
, &IID_IDispatch
, (void**)&sink
);
3434 return CONNECT_E_CANNOTCONNECT
;
3438 for (i
= 0; i
< This
->sinks_size
; i
++)
3439 if (!This
->sinks
[i
].unk
)
3442 if (i
== This
->sinks_size
)
3443 This
->sinks
= heap_realloc(This
->sinks
,(++This
->sinks_size
)*sizeof(*This
->sinks
));
3447 This
->sinks
= heap_alloc(sizeof(*This
->sinks
));
3448 This
->sinks_size
= 1;
3452 This
->sinks
[i
].unk
= sink
;
3459 static HRESULT WINAPI
ConnectionPoint_Unadvise(IConnectionPoint
*iface
, DWORD cookie
)
3461 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3463 TRACE("(%p)->(%d)\n", This
, cookie
);
3465 if (cookie
== 0 || cookie
> This
->sinks_size
|| !This
->sinks
[cookie
-1].unk
)
3466 return CONNECT_E_NOCONNECTION
;
3468 IUnknown_Release(This
->sinks
[cookie
-1].unk
);
3469 This
->sinks
[cookie
-1].unk
= NULL
;
3474 static HRESULT WINAPI
ConnectionPoint_EnumConnections(IConnectionPoint
*iface
,
3475 IEnumConnections
**ppEnum
)
3477 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3478 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3482 static const IConnectionPointVtbl ConnectionPointVtbl
=
3484 ConnectionPoint_QueryInterface
,
3485 ConnectionPoint_AddRef
,
3486 ConnectionPoint_Release
,
3487 ConnectionPoint_GetConnectionInterface
,
3488 ConnectionPoint_GetConnectionPointContainer
,
3489 ConnectionPoint_Advise
,
3490 ConnectionPoint_Unadvise
,
3491 ConnectionPoint_EnumConnections
3494 static void ConnectionPoint_Init(ConnectionPoint
*cp
, struct domdoc
*doc
, REFIID riid
)
3496 cp
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointVtbl
;
3502 cp
->next
= doc
->cp_list
;
3505 cp
->container
= &doc
->IConnectionPointContainer_iface
;
3508 /* domdoc implementation of IObjectWithSite */
3509 static HRESULT WINAPI
3510 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
3512 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3513 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObject
);
3516 static ULONG WINAPI
domdoc_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
3518 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3519 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3522 static ULONG WINAPI
domdoc_ObjectWithSite_Release( IObjectWithSite
* iface
)
3524 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3525 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3528 static HRESULT WINAPI
domdoc_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
3530 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3532 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
3537 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
3540 static HRESULT WINAPI
domdoc_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
3542 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3544 TRACE("(%p)->(%p)\n", iface
, punk
);
3550 IUnknown_Release( This
->site
);
3557 IUnknown_AddRef( punk
);
3560 IUnknown_Release( This
->site
);
3567 static const IObjectWithSiteVtbl domdocObjectSite
=
3569 domdoc_ObjectWithSite_QueryInterface
,
3570 domdoc_ObjectWithSite_AddRef
,
3571 domdoc_ObjectWithSite_Release
,
3572 domdoc_ObjectWithSite_SetSite
,
3573 domdoc_ObjectWithSite_GetSite
3576 static HRESULT WINAPI
domdoc_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
3578 domdoc
*This
= impl_from_IObjectSafety(iface
);
3579 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3582 static ULONG WINAPI
domdoc_Safety_AddRef(IObjectSafety
*iface
)
3584 domdoc
*This
= impl_from_IObjectSafety(iface
);
3585 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3588 static ULONG WINAPI
domdoc_Safety_Release(IObjectSafety
*iface
)
3590 domdoc
*This
= impl_from_IObjectSafety(iface
);
3591 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3594 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3596 static HRESULT WINAPI
domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3597 DWORD
*supported
, DWORD
*enabled
)
3599 domdoc
*This
= impl_from_IObjectSafety(iface
);
3601 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
3603 if(!supported
|| !enabled
) return E_POINTER
;
3605 *supported
= SAFETY_SUPPORTED_OPTIONS
;
3606 *enabled
= This
->safeopt
;
3611 static HRESULT WINAPI
domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3612 DWORD mask
, DWORD enabled
)
3614 domdoc
*This
= impl_from_IObjectSafety(iface
);
3615 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
3617 if ((mask
& ~SAFETY_SUPPORTED_OPTIONS
) != 0)
3620 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
3625 #undef SAFETY_SUPPORTED_OPTIONS
3627 static const IObjectSafetyVtbl domdocObjectSafetyVtbl
= {
3628 domdoc_Safety_QueryInterface
,
3629 domdoc_Safety_AddRef
,
3630 domdoc_Safety_Release
,
3631 domdoc_Safety_GetInterfaceSafetyOptions
,
3632 domdoc_Safety_SetInterfaceSafetyOptions
3635 static const tid_t domdoc_iface_tids
[] = {
3636 IXMLDOMDocument3_tid
,
3640 static dispex_static_data_t domdoc_dispex
= {
3642 IXMLDOMDocument3_tid
,
3647 HRESULT
get_domdoc_from_xmldoc(xmlDocPtr xmldoc
, IXMLDOMDocument3
**document
)
3651 doc
= heap_alloc( sizeof (*doc
) );
3653 return E_OUTOFMEMORY
;
3655 doc
->IXMLDOMDocument3_iface
.lpVtbl
= &XMLDOMDocument3Vtbl
;
3656 doc
->IPersistStreamInit_iface
.lpVtbl
= &xmldoc_IPersistStreamInit_VTable
;
3657 doc
->IObjectWithSite_iface
.lpVtbl
= &domdocObjectSite
;
3658 doc
->IObjectSafety_iface
.lpVtbl
= &domdocObjectSafetyVtbl
;
3659 doc
->IConnectionPointContainer_iface
.lpVtbl
= &ConnectionPointContainerVtbl
;
3661 doc
->async
= VARIANT_TRUE
;
3662 doc
->validating
= 0;
3664 doc
->properties
= properties_from_xmlDocPtr(xmldoc
);
3668 doc
->cp_list
= NULL
;
3669 doc
->namespaces
= NULL
;
3670 memset(doc
->events
, 0, sizeof(doc
->events
));
3672 /* events connection points */
3673 ConnectionPoint_Init(&doc
->cp_dispatch
, doc
, &IID_IDispatch
);
3674 ConnectionPoint_Init(&doc
->cp_propnotif
, doc
, &IID_IPropertyNotifySink
);
3675 ConnectionPoint_Init(&doc
->cp_domdocevents
, doc
, &DIID_XMLDOMDocumentEvents
);
3677 init_xmlnode(&doc
->node
, (xmlNodePtr
)xmldoc
, (IXMLDOMNode
*)&doc
->IXMLDOMDocument3_iface
,
3680 *document
= &doc
->IXMLDOMDocument3_iface
;
3682 TRACE("returning iface %p\n", *document
);
3686 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3691 TRACE("(%d, %p)\n", version
, ppObj
);
3693 xmldoc
= xmlNewDoc(NULL
);
3695 return E_OUTOFMEMORY
;
3697 xmldoc_init(xmldoc
, version
);
3699 hr
= get_domdoc_from_xmldoc(xmldoc
, (IXMLDOMDocument3
**)ppObj
);
3702 free_properties(properties_from_xmlDocPtr(xmldoc
));
3703 heap_free(xmldoc
->_private
);
3711 IUnknown
* create_domdoc( xmlNodePtr document
)
3713 IUnknown
*obj
= NULL
;
3716 TRACE("(%p)\n", document
);
3718 hr
= get_domdoc_from_xmldoc((xmlDocPtr
)document
, (IXMLDOMDocument3
**)&obj
);
3727 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3729 MESSAGE("This program tried to use a DOMDocument object, but\n"
3730 "libxml2 support was not present at compile time.\n");