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};
55 /* Anything that passes the test_get_ownerDocument()
56 * tests can go here (data shared between all instances).
57 * We need to preserve this when reloading a document,
58 * and also need access to it from the libxml backend. */
60 MSXML_VERSION version
;
61 VARIANT_BOOL preserving
;
62 IXMLDOMSchemaCollection2
* schemaCache
;
63 struct list selectNsList
;
64 xmlChar
const* selectNsStr
;
70 typedef struct ConnectionPoint ConnectionPoint
;
71 typedef struct domdoc domdoc
;
73 struct ConnectionPoint
75 IConnectionPoint IConnectionPoint_iface
;
78 ConnectionPoint
*next
;
79 IConnectionPointContainer
*container
;
86 IPropertyNotifySink
*propnotif
;
92 EVENTID_READYSTATECHANGE
= 0,
93 EVENTID_DATAAVAILABLE
,
94 EVENTID_TRANSFORMNODE
,
101 IXMLDOMDocument3 IXMLDOMDocument3_iface
;
102 IPersistStreamInit IPersistStreamInit_iface
;
103 IObjectWithSite IObjectWithSite_iface
;
104 IObjectSafety IObjectSafety_iface
;
105 IConnectionPointContainer IConnectionPointContainer_iface
;
108 VARIANT_BOOL validating
;
109 VARIANT_BOOL resolving
;
110 domdoc_properties
* properties
;
113 /* IObjectWithSite */
119 /* connection list */
120 ConnectionPoint
*cp_list
;
121 ConnectionPoint cp_domdocevents
;
122 ConnectionPoint cp_propnotif
;
123 ConnectionPoint cp_dispatch
;
126 IDispatch
*events
[EVENTID_LAST
];
128 IXMLDOMSchemaCollection2
*namespaces
;
131 static HRESULT
set_doc_event(domdoc
*doc
, eventid_t eid
, const VARIANT
*v
)
139 IUnknown_QueryInterface(V_UNKNOWN(v
), &IID_IDispatch
, (void**)&disp
);
144 disp
= V_DISPATCH(v
);
145 if (disp
) IDispatch_AddRef(disp
);
148 return DISP_E_TYPEMISMATCH
;
151 if (doc
->events
[eid
]) IDispatch_Release(doc
->events
[eid
]);
152 doc
->events
[eid
] = disp
;
157 static inline ConnectionPoint
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
159 return CONTAINING_RECORD(iface
, ConnectionPoint
, IConnectionPoint_iface
);
163 In native windows, the whole lifetime management of XMLDOMNodes is
164 managed automatically using reference counts. Wine emulates that by
165 maintaining a reference count to the document that is increased for
166 each IXMLDOMNode pointer passed out for this document. If all these
167 pointers are gone, the document is unreachable and gets freed, that
168 is, all nodes in the tree of the document get freed.
170 You are able to create nodes that are associated to a document (in
171 fact, in msxml's XMLDOM model, all nodes are associated to a document),
172 but not in the tree of that document, for example using the createFoo
173 functions from IXMLDOMDocument. These nodes do not get cleaned up
174 by libxml, so we have to do it ourselves.
176 To catch these nodes, a list of "orphan nodes" is introduced.
177 It contains pointers to all roots of node trees that are
178 associated with the document without being part of the document
179 tree. All nodes with parent==NULL (except for the document root nodes)
180 should be in the orphan node list of their document. All orphan nodes
181 get freed together with the document itself.
184 typedef struct _xmldoc_priv
{
187 domdoc_properties
* properties
;
190 typedef struct _orphan_entry
{
195 typedef struct _select_ns_entry
{
197 xmlChar
const* prefix
;
203 static inline xmldoc_priv
* priv_from_xmlDocPtr(const xmlDocPtr doc
)
205 return doc
->_private
;
208 static inline domdoc_properties
* properties_from_xmlDocPtr(xmlDocPtr doc
)
210 return priv_from_xmlDocPtr(doc
)->properties
;
213 BOOL
is_xpathmode(const xmlDocPtr doc
)
215 return properties_from_xmlDocPtr(doc
)->XPath
;
218 void set_xpathmode(xmlDocPtr doc
, BOOL xpath
)
220 properties_from_xmlDocPtr(doc
)->XPath
= xpath
;
223 int registerNamespaces(xmlXPathContextPtr ctxt
)
226 const select_ns_entry
* ns
= NULL
;
227 const struct list
* pNsList
= &properties_from_xmlDocPtr(ctxt
->doc
)->selectNsList
;
229 TRACE("(%p)\n", ctxt
);
231 LIST_FOR_EACH_ENTRY( ns
, pNsList
, select_ns_entry
, entry
)
233 xmlXPathRegisterNs(ctxt
, ns
->prefix
, ns
->href
);
240 static inline void clear_selectNsList(struct list
* pNsList
)
242 select_ns_entry
*ns
, *ns2
;
243 LIST_FOR_EACH_ENTRY_SAFE( ns
, ns2
, pNsList
, select_ns_entry
, entry
)
250 static xmldoc_priv
* create_priv(void)
253 priv
= heap_alloc( sizeof (*priv
) );
258 list_init( &priv
->orphans
);
259 priv
->properties
= NULL
;
265 static domdoc_properties
*create_properties(MSXML_VERSION version
)
267 domdoc_properties
*properties
= heap_alloc(sizeof(domdoc_properties
));
269 list_init(&properties
->selectNsList
);
270 properties
->preserving
= VARIANT_FALSE
;
271 properties
->schemaCache
= NULL
;
272 properties
->selectNsStr
= heap_alloc_zero(sizeof(xmlChar
));
273 properties
->selectNsStr_len
= 0;
275 /* properties that are dependent on object versions */
276 properties
->version
= version
;
277 properties
->XPath
= (version
== MSXML4
|| version
== MSXML6
);
280 properties
->url
= NULL
;
285 static domdoc_properties
* copy_properties(domdoc_properties
const* properties
)
287 domdoc_properties
* pcopy
= heap_alloc(sizeof(domdoc_properties
));
288 select_ns_entry
const* ns
= NULL
;
289 select_ns_entry
* new_ns
= NULL
;
290 int len
= (properties
->selectNsStr_len
+1)*sizeof(xmlChar
);
295 pcopy
->version
= properties
->version
;
296 pcopy
->preserving
= properties
->preserving
;
297 pcopy
->schemaCache
= properties
->schemaCache
;
298 if (pcopy
->schemaCache
)
299 IXMLDOMSchemaCollection2_AddRef(pcopy
->schemaCache
);
300 pcopy
->XPath
= properties
->XPath
;
301 pcopy
->selectNsStr_len
= properties
->selectNsStr_len
;
302 list_init( &pcopy
->selectNsList
);
303 pcopy
->selectNsStr
= heap_alloc(len
);
304 memcpy((xmlChar
*)pcopy
->selectNsStr
, properties
->selectNsStr
, len
);
305 offset
= pcopy
->selectNsStr
- properties
->selectNsStr
;
307 LIST_FOR_EACH_ENTRY( ns
, (&properties
->selectNsList
), select_ns_entry
, entry
)
309 new_ns
= heap_alloc(sizeof(select_ns_entry
));
310 memcpy(new_ns
, ns
, sizeof(select_ns_entry
));
311 new_ns
->href
+= offset
;
312 new_ns
->prefix
+= offset
;
313 list_add_tail(&pcopy
->selectNsList
, &new_ns
->entry
);
318 int len
= strlenW(properties
->url
);
320 pcopy
->url
= CoTaskMemAlloc((len
+1)*sizeof(WCHAR
));
321 memcpy(pcopy
->url
, properties
->url
, len
*sizeof(WCHAR
));
331 static void free_properties(domdoc_properties
* properties
)
335 if (properties
->schemaCache
)
336 IXMLDOMSchemaCollection2_Release(properties
->schemaCache
);
337 clear_selectNsList(&properties
->selectNsList
);
338 heap_free((xmlChar
*)properties
->selectNsStr
);
339 CoTaskMemFree(properties
->url
);
340 heap_free(properties
);
344 static void release_namespaces(domdoc
*This
)
346 if (This
->namespaces
)
348 IXMLDOMSchemaCollection2_Release(This
->namespaces
);
349 This
->namespaces
= NULL
;
353 /* links a "<?xml" node as a first child */
354 void xmldoc_link_xmldecl(xmlDocPtr doc
, xmlNodePtr node
)
357 if (doc
->standalone
!= -1) xmlAddPrevSibling( doc
->children
, node
);
360 /* unlinks a first "<?xml" child if it was created */
361 xmlNodePtr
xmldoc_unlink_xmldecl(xmlDocPtr doc
)
363 static const xmlChar xmlA
[] = "xml";
364 xmlNodePtr node
, first_child
;
368 /* xml declaration node could be created automatically after parsing or added
370 first_child
= doc
->children
;
371 if (first_child
&& first_child
->type
== XML_PI_NODE
&& xmlStrEqual(first_child
->name
, xmlA
))
374 xmlUnlinkNode( node
);
382 BOOL
is_preserving_whitespace(xmlNodePtr node
)
384 domdoc_properties
* properties
= NULL
;
385 /* during parsing the xmlDoc._private stuff is not there */
386 if (priv_from_xmlDocPtr(node
->doc
))
387 properties
= properties_from_xmlDocPtr(node
->doc
);
388 return ((properties
&& properties
->preserving
== VARIANT_TRUE
) ||
389 xmlNodeGetSpacePreserve(node
) == 1);
392 static inline BOOL
strn_isspace(xmlChar
const* str
, int len
)
394 for (; str
&& len
> 0 && *str
; ++str
, --len
)
401 static void sax_characters(void *ctx
, const xmlChar
*ch
, int len
)
403 xmlParserCtxtPtr ctxt
;
406 ctxt
= (xmlParserCtxtPtr
) ctx
;
407 This
= (const domdoc
*) ctxt
->_private
;
411 xmlChar cur
= *(ctxt
->input
->cur
);
413 /* Characters are reported with multiple calls, for example each charref is reported with a separate
414 call and then parser appends it to a single text node or creates a new node if not created.
415 It's not possible to tell if it's ignorable data or not just looking at data itself cause it could be
416 space chars that separate charrefs or similar case. We only need to skip leading and trailing spaces,
417 or whole node if it has nothing but space chars, so to detect leading space node->last is checked that
418 contains text node pointer if already created, trailing spaces are detected directly looking at parser input
419 for next '<' opening bracket - similar logic is used by libxml2 itself. Basically 'cur' == '<' means the last
420 chunk of char data, in case it's not the last chunk we check for previously added node type and if it's not
421 a text node it's safe to ignore.
423 Note that during domdoc_loadXML() the xmlDocPtr->_private data is not available. */
425 if (!This
->properties
->preserving
&&
426 !is_preserving_whitespace(ctxt
->node
) &&
427 strn_isspace(ch
, len
) &&
428 (!ctxt
->node
->last
||
429 ((ctxt
->node
->last
&& (cur
== '<' || ctxt
->node
->last
->type
!= XML_TEXT_NODE
))
434 xmlSAX2Characters(ctxt
, ch
, len
);
437 static void LIBXML2_LOG_CALLBACK
sax_error(void* ctx
, char const* msg
, ...)
441 LIBXML2_CALLBACK_ERR(doparse
, msg
, ap
);
445 static void LIBXML2_LOG_CALLBACK
sax_warning(void* ctx
, char const* msg
, ...)
449 LIBXML2_CALLBACK_WARN(doparse
, msg
, ap
);
453 static void sax_serror(void* ctx
, xmlErrorPtr err
)
455 LIBXML2_CALLBACK_SERROR(doparse
, err
);
458 static xmlDocPtr
doparse(domdoc
* This
, char const* ptr
, int len
, xmlCharEncoding encoding
)
460 xmlDocPtr doc
= NULL
;
461 xmlParserCtxtPtr pctx
;
462 static xmlSAXHandler sax_handler
= {
463 xmlSAX2InternalSubset
, /* internalSubset */
464 xmlSAX2IsStandalone
, /* isStandalone */
465 xmlSAX2HasInternalSubset
, /* hasInternalSubset */
466 xmlSAX2HasExternalSubset
, /* hasExternalSubset */
467 xmlSAX2ResolveEntity
, /* resolveEntity */
468 xmlSAX2GetEntity
, /* getEntity */
469 xmlSAX2EntityDecl
, /* entityDecl */
470 xmlSAX2NotationDecl
, /* notationDecl */
471 xmlSAX2AttributeDecl
, /* attributeDecl */
472 xmlSAX2ElementDecl
, /* elementDecl */
473 xmlSAX2UnparsedEntityDecl
, /* unparsedEntityDecl */
474 xmlSAX2SetDocumentLocator
, /* setDocumentLocator */
475 xmlSAX2StartDocument
, /* startDocument */
476 xmlSAX2EndDocument
, /* endDocument */
477 xmlSAX2StartElement
, /* startElement */
478 xmlSAX2EndElement
, /* endElement */
479 xmlSAX2Reference
, /* reference */
480 sax_characters
, /* characters */
481 sax_characters
, /* ignorableWhitespace */
482 xmlSAX2ProcessingInstruction
, /* processingInstruction */
483 xmlSAX2Comment
, /* comment */
484 sax_warning
, /* warning */
485 sax_error
, /* error */
486 sax_error
, /* fatalError */
487 xmlSAX2GetParameterEntity
, /* getParameterEntity */
488 xmlSAX2CDataBlock
, /* cdataBlock */
489 xmlSAX2ExternalSubset
, /* externalSubset */
492 xmlSAX2StartElementNs
, /* startElementNs */
493 xmlSAX2EndElementNs
, /* endElementNs */
494 sax_serror
/* serror */
497 pctx
= xmlCreateMemoryParserCtxt(ptr
, len
);
500 ERR("Failed to create parser context\n");
504 if (pctx
->sax
) xmlFree(pctx
->sax
);
505 pctx
->sax
= &sax_handler
;
506 pctx
->_private
= This
;
509 if (encoding
!= XML_CHAR_ENCODING_NONE
)
510 xmlSwitchEncoding(pctx
, encoding
);
512 xmlParseDocument(pctx
);
514 if (pctx
->wellFormed
)
520 xmlFreeDoc(pctx
->myDoc
);
524 xmlFreeParserCtxt(pctx
);
526 /* TODO: put this in one of the SAX callbacks */
527 /* create first child as a <?xml...?> */
528 if (doc
&& doc
->standalone
!= -1)
532 xmlChar
*xmlbuff
= (xmlChar
*)buff
;
534 node
= xmlNewDocPI( doc
, (xmlChar
*)"xml", NULL
);
536 /* version attribute can't be omitted */
537 sprintf(buff
, "version=\"%s\"", doc
->version
? (char*)doc
->version
: "1.0");
538 xmlNodeAddContent( node
, xmlbuff
);
542 sprintf(buff
, " encoding=\"%s\"", doc
->encoding
);
543 xmlNodeAddContent( node
, xmlbuff
);
546 if (doc
->standalone
!= -2)
548 sprintf(buff
, " standalone=\"%s\"", doc
->standalone
== 0 ? "no" : "yes");
549 xmlNodeAddContent( node
, xmlbuff
);
552 xmldoc_link_xmldecl( doc
, node
);
558 void xmldoc_init(xmlDocPtr doc
, MSXML_VERSION version
)
560 doc
->_private
= create_priv();
561 priv_from_xmlDocPtr(doc
)->properties
= create_properties(version
);
564 LONG
xmldoc_add_refs(xmlDocPtr doc
, LONG refs
)
566 LONG ref
= InterlockedExchangeAdd(&priv_from_xmlDocPtr(doc
)->refs
, refs
) + refs
;
567 TRACE("(%p)->(%d)\n", doc
, ref
);
571 LONG
xmldoc_add_ref(xmlDocPtr doc
)
573 return xmldoc_add_refs(doc
, 1);
576 LONG
xmldoc_release_refs(xmlDocPtr doc
, LONG refs
)
578 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
579 LONG ref
= InterlockedExchangeAdd(&priv
->refs
, -refs
) - refs
;
580 TRACE("(%p)->(%d)\n", doc
, ref
);
583 WARN("negative refcount, expect troubles\n");
587 orphan_entry
*orphan
, *orphan2
;
588 TRACE("freeing docptr %p\n", doc
);
590 LIST_FOR_EACH_ENTRY_SAFE( orphan
, orphan2
, &priv
->orphans
, orphan_entry
, entry
)
592 xmlFreeNode( orphan
->node
);
595 free_properties(priv
->properties
);
596 heap_free(doc
->_private
);
604 LONG
xmldoc_release(xmlDocPtr doc
)
606 return xmldoc_release_refs(doc
, 1);
609 HRESULT
xmldoc_add_orphan(xmlDocPtr doc
, xmlNodePtr node
)
611 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
614 entry
= heap_alloc( sizeof (*entry
) );
616 return E_OUTOFMEMORY
;
619 list_add_head( &priv
->orphans
, &entry
->entry
);
623 HRESULT
xmldoc_remove_orphan(xmlDocPtr doc
, xmlNodePtr node
)
625 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
626 orphan_entry
*entry
, *entry2
;
628 LIST_FOR_EACH_ENTRY_SAFE( entry
, entry2
, &priv
->orphans
, orphan_entry
, entry
)
630 if( entry
->node
== node
)
632 list_remove( &entry
->entry
);
641 static inline xmlDocPtr
get_doc( domdoc
*This
)
643 return This
->node
.node
->doc
;
646 static HRESULT
attach_xmldoc(domdoc
*This
, xmlDocPtr xml
)
648 release_namespaces(This
);
652 priv_from_xmlDocPtr(get_doc(This
))->properties
= NULL
;
653 if (xmldoc_release(get_doc(This
)) != 0)
654 priv_from_xmlDocPtr(get_doc(This
))->properties
=
655 copy_properties(This
->properties
);
658 This
->node
.node
= (xmlNodePtr
) xml
;
662 xmldoc_add_ref(get_doc(This
));
663 priv_from_xmlDocPtr(get_doc(This
))->properties
= This
->properties
;
669 static inline domdoc
*impl_from_IXMLDOMDocument3( IXMLDOMDocument3
*iface
)
671 return CONTAINING_RECORD(iface
, domdoc
, IXMLDOMDocument3_iface
);
674 static inline domdoc
*impl_from_IPersistStreamInit(IPersistStreamInit
*iface
)
676 return CONTAINING_RECORD(iface
, domdoc
, IPersistStreamInit_iface
);
679 static inline domdoc
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
681 return CONTAINING_RECORD(iface
, domdoc
, IObjectWithSite_iface
);
684 static inline domdoc
*impl_from_IObjectSafety(IObjectSafety
*iface
)
686 return CONTAINING_RECORD(iface
, domdoc
, IObjectSafety_iface
);
689 static inline domdoc
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
691 return CONTAINING_RECORD(iface
, domdoc
, IConnectionPointContainer_iface
);
694 /************************************************************************
695 * domdoc implementation of IPersistStream.
697 static HRESULT WINAPI
PersistStreamInit_QueryInterface(
698 IPersistStreamInit
*iface
, REFIID riid
, void **ppvObj
)
700 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
701 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObj
);
704 static ULONG WINAPI
PersistStreamInit_AddRef(
705 IPersistStreamInit
*iface
)
707 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
708 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
711 static ULONG WINAPI
PersistStreamInit_Release(
712 IPersistStreamInit
*iface
)
714 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
715 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
718 static HRESULT WINAPI
PersistStreamInit_GetClassID(
719 IPersistStreamInit
*iface
, CLSID
*classid
)
721 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
722 TRACE("(%p)->(%p)\n", This
, classid
);
727 *classid
= *DOMDocument_version(This
->properties
->version
);
732 static HRESULT WINAPI
PersistStreamInit_IsDirty(
733 IPersistStreamInit
*iface
)
735 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
736 FIXME("(%p): stub!\n", This
);
740 static HRESULT
domdoc_load_from_stream(domdoc
*doc
, ISequentialStream
*stream
)
742 DWORD read
, written
, len
;
743 xmlDocPtr xmldoc
= NULL
;
751 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &hstream
);
757 ISequentialStream_Read(stream
, buf
, sizeof(buf
), &read
);
758 hr
= IStream_Write(hstream
, buf
, read
, &written
);
759 } while(SUCCEEDED(hr
) && written
!= 0 && read
!= 0);
763 ERR("failed to copy stream 0x%08x\n", hr
);
764 IStream_Release(hstream
);
768 hr
= GetHGlobalFromStream(hstream
, &hglobal
);
772 len
= GlobalSize(hglobal
);
773 ptr
= GlobalLock(hglobal
);
775 xmldoc
= doparse(doc
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
776 GlobalUnlock(hglobal
);
780 ERR("Failed to parse xml\n");
784 xmldoc
->_private
= create_priv();
786 return attach_xmldoc(doc
, xmldoc
);
789 static HRESULT WINAPI
PersistStreamInit_Load(IPersistStreamInit
*iface
, IStream
*stream
)
791 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
793 TRACE("(%p)->(%p)\n", This
, stream
);
798 return domdoc_load_from_stream(This
, (ISequentialStream
*)stream
);
801 static HRESULT WINAPI
PersistStreamInit_Save(
802 IPersistStreamInit
*iface
, IStream
*stream
, BOOL clr_dirty
)
804 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
808 TRACE("(%p)->(%p %d)\n", This
, stream
, clr_dirty
);
810 hr
= IXMLDOMDocument3_get_xml(&This
->IXMLDOMDocument3_iface
, &xmlString
);
813 DWORD len
= SysStringLen(xmlString
) * sizeof(WCHAR
);
815 hr
= IStream_Write( stream
, xmlString
, len
, NULL
);
816 SysFreeString(xmlString
);
819 TRACE("ret 0x%08x\n", hr
);
824 static HRESULT WINAPI
PersistStreamInit_GetSizeMax(
825 IPersistStreamInit
*iface
, ULARGE_INTEGER
*pcbSize
)
827 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
828 TRACE("(%p)->(%p)\n", This
, pcbSize
);
832 static HRESULT WINAPI
PersistStreamInit_InitNew(
833 IPersistStreamInit
*iface
)
835 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
836 TRACE("(%p)\n", This
);
840 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable
=
842 PersistStreamInit_QueryInterface
,
843 PersistStreamInit_AddRef
,
844 PersistStreamInit_Release
,
845 PersistStreamInit_GetClassID
,
846 PersistStreamInit_IsDirty
,
847 PersistStreamInit_Load
,
848 PersistStreamInit_Save
,
849 PersistStreamInit_GetSizeMax
,
850 PersistStreamInit_InitNew
853 /* IXMLDOMDocument3 interface */
855 static const tid_t domdoc_se_tids
[] = {
858 IXMLDOMDocument2_tid
,
859 IXMLDOMDocument3_tid
,
863 static HRESULT WINAPI
domdoc_QueryInterface( IXMLDOMDocument3
*iface
, REFIID riid
, void** ppvObject
)
865 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
867 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( riid
), ppvObject
);
871 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
872 IsEqualGUID( riid
, &IID_IDispatch
) ||
873 IsEqualGUID( riid
, &IID_IXMLDOMNode
) ||
874 IsEqualGUID( riid
, &IID_IXMLDOMDocument
) ||
875 IsEqualGUID( riid
, &IID_IXMLDOMDocument2
)||
876 IsEqualGUID( riid
, &IID_IXMLDOMDocument3
))
880 else if (IsEqualGUID(&IID_IPersistStream
, riid
) ||
881 IsEqualGUID(&IID_IPersistStreamInit
, riid
))
883 *ppvObject
= &This
->IPersistStreamInit_iface
;
885 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
887 *ppvObject
= &This
->IObjectWithSite_iface
;
889 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
891 *ppvObject
= &This
->IObjectSafety_iface
;
893 else if( IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
895 return node_create_supporterrorinfo(domdoc_se_tids
, ppvObject
);
897 else if(node_query_interface(&This
->node
, riid
, ppvObject
))
899 return *ppvObject
? S_OK
: E_NOINTERFACE
;
901 else if (IsEqualGUID( riid
, &IID_IConnectionPointContainer
))
903 *ppvObject
= &This
->IConnectionPointContainer_iface
;
907 TRACE("interface %s not implemented\n", debugstr_guid(riid
));
908 return E_NOINTERFACE
;
911 IUnknown_AddRef((IUnknown
*)*ppvObject
);
916 static ULONG WINAPI
domdoc_AddRef( IXMLDOMDocument3
*iface
)
918 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
919 ULONG ref
= InterlockedIncrement( &This
->ref
);
920 TRACE("(%p)->(%d)\n", This
, ref
);
924 static ULONG WINAPI
domdoc_Release( IXMLDOMDocument3
*iface
)
926 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
927 LONG ref
= InterlockedDecrement( &This
->ref
);
929 TRACE("(%p)->(%d)\n", This
, ref
);
936 IUnknown_Release( This
->site
);
937 destroy_xmlnode(&This
->node
);
939 for (eid
= 0; eid
< EVENTID_LAST
; eid
++)
940 if (This
->events
[eid
]) IDispatch_Release(This
->events
[eid
]);
942 release_namespaces(This
);
949 static HRESULT WINAPI
domdoc_GetTypeInfoCount( IXMLDOMDocument3
*iface
, UINT
* pctinfo
)
951 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
952 return IDispatchEx_GetTypeInfoCount(&This
->node
.dispex
.IDispatchEx_iface
, pctinfo
);
955 static HRESULT WINAPI
domdoc_GetTypeInfo(
956 IXMLDOMDocument3
*iface
,
957 UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
959 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
960 return IDispatchEx_GetTypeInfo(&This
->node
.dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
963 static HRESULT WINAPI
domdoc_GetIDsOfNames(
964 IXMLDOMDocument3
*iface
,
971 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
972 return IDispatchEx_GetIDsOfNames(&This
->node
.dispex
.IDispatchEx_iface
,
973 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
976 static HRESULT WINAPI
domdoc_Invoke(
977 IXMLDOMDocument3
*iface
,
982 DISPPARAMS
* pDispParams
,
984 EXCEPINFO
* pExcepInfo
,
987 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
988 return IDispatchEx_Invoke(&This
->node
.dispex
.IDispatchEx_iface
,
989 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
992 static HRESULT WINAPI
domdoc_get_nodeName(
993 IXMLDOMDocument3
*iface
,
996 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
998 static const WCHAR documentW
[] = {'#','d','o','c','u','m','e','n','t',0};
1000 TRACE("(%p)->(%p)\n", This
, name
);
1002 return return_bstr(documentW
, name
);
1006 static HRESULT WINAPI
domdoc_get_nodeValue(
1007 IXMLDOMDocument3
*iface
,
1010 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1012 TRACE("(%p)->(%p)\n", This
, value
);
1015 return E_INVALIDARG
;
1017 V_VT(value
) = VT_NULL
;
1018 V_BSTR(value
) = NULL
; /* tests show that we should do this */
1023 static HRESULT WINAPI
domdoc_put_nodeValue(
1024 IXMLDOMDocument3
*iface
,
1027 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1028 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&value
));
1033 static HRESULT WINAPI
domdoc_get_nodeType(
1034 IXMLDOMDocument3
*iface
,
1037 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1039 TRACE("(%p)->(%p)\n", This
, type
);
1041 *type
= NODE_DOCUMENT
;
1046 static HRESULT WINAPI
domdoc_get_parentNode(
1047 IXMLDOMDocument3
*iface
,
1048 IXMLDOMNode
** parent
)
1050 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1052 TRACE("(%p)->(%p)\n", This
, parent
);
1054 return node_get_parent(&This
->node
, parent
);
1058 static HRESULT WINAPI
domdoc_get_childNodes(
1059 IXMLDOMDocument3
*iface
,
1060 IXMLDOMNodeList
** childList
)
1062 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1064 TRACE("(%p)->(%p)\n", This
, childList
);
1066 return node_get_child_nodes(&This
->node
, childList
);
1070 static HRESULT WINAPI
domdoc_get_firstChild(
1071 IXMLDOMDocument3
*iface
,
1072 IXMLDOMNode
** firstChild
)
1074 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1076 TRACE("(%p)->(%p)\n", This
, firstChild
);
1078 return node_get_first_child(&This
->node
, firstChild
);
1082 static HRESULT WINAPI
domdoc_get_lastChild(
1083 IXMLDOMDocument3
*iface
,
1084 IXMLDOMNode
** lastChild
)
1086 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1088 TRACE("(%p)->(%p)\n", This
, lastChild
);
1090 return node_get_last_child(&This
->node
, lastChild
);
1094 static HRESULT WINAPI
domdoc_get_previousSibling(
1095 IXMLDOMDocument3
*iface
,
1096 IXMLDOMNode
** previousSibling
)
1098 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1100 TRACE("(%p)->(%p)\n", This
, previousSibling
);
1102 return return_null_node(previousSibling
);
1106 static HRESULT WINAPI
domdoc_get_nextSibling(
1107 IXMLDOMDocument3
*iface
,
1108 IXMLDOMNode
** nextSibling
)
1110 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1112 TRACE("(%p)->(%p)\n", This
, nextSibling
);
1114 return return_null_node(nextSibling
);
1118 static HRESULT WINAPI
domdoc_get_attributes(
1119 IXMLDOMDocument3
*iface
,
1120 IXMLDOMNamedNodeMap
** attributeMap
)
1122 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1124 TRACE("(%p)->(%p)\n", This
, attributeMap
);
1126 return return_null_ptr((void**)attributeMap
);
1130 static HRESULT WINAPI
domdoc_insertBefore(
1131 IXMLDOMDocument3
*iface
,
1132 IXMLDOMNode
* newChild
,
1134 IXMLDOMNode
** outNewChild
)
1136 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1140 TRACE("(%p)->(%p %s %p)\n", This
, newChild
, debugstr_variant(&refChild
), outNewChild
);
1142 hr
= IXMLDOMNode_get_nodeType(newChild
, &type
);
1143 if (hr
!= S_OK
) return hr
;
1145 TRACE("new node type %d\n", type
);
1148 case NODE_ATTRIBUTE
:
1150 case NODE_CDATA_SECTION
:
1151 if (outNewChild
) *outNewChild
= NULL
;
1154 return node_insert_before(&This
->node
, newChild
, &refChild
, outNewChild
);
1158 static HRESULT WINAPI
domdoc_replaceChild(
1159 IXMLDOMDocument3
*iface
,
1160 IXMLDOMNode
* newChild
,
1161 IXMLDOMNode
* oldChild
,
1162 IXMLDOMNode
** outOldChild
)
1164 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1166 TRACE("(%p)->(%p %p %p)\n", This
, newChild
, oldChild
, outOldChild
);
1168 return node_replace_child(&This
->node
, newChild
, oldChild
, outOldChild
);
1172 static HRESULT WINAPI
domdoc_removeChild(
1173 IXMLDOMDocument3
*iface
,
1175 IXMLDOMNode
**oldChild
)
1177 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1178 TRACE("(%p)->(%p %p)\n", This
, child
, oldChild
);
1179 return node_remove_child(&This
->node
, child
, oldChild
);
1183 static HRESULT WINAPI
domdoc_appendChild(
1184 IXMLDOMDocument3
*iface
,
1186 IXMLDOMNode
**outChild
)
1188 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1189 TRACE("(%p)->(%p %p)\n", This
, child
, outChild
);
1190 return node_append_child(&This
->node
, child
, outChild
);
1194 static HRESULT WINAPI
domdoc_hasChildNodes(
1195 IXMLDOMDocument3
*iface
,
1198 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1199 TRACE("(%p)->(%p)\n", This
, ret
);
1200 return node_has_childnodes(&This
->node
, ret
);
1204 static HRESULT WINAPI
domdoc_get_ownerDocument(
1205 IXMLDOMDocument3
*iface
,
1206 IXMLDOMDocument
**doc
)
1208 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1209 TRACE("(%p)->(%p)\n", This
, doc
);
1210 return node_get_owner_doc(&This
->node
, doc
);
1214 static HRESULT WINAPI
domdoc_cloneNode(
1215 IXMLDOMDocument3
*iface
,
1217 IXMLDOMNode
** outNode
)
1219 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1220 TRACE("(%p)->(%d %p)\n", This
, deep
, outNode
);
1221 return node_clone( &This
->node
, deep
, outNode
);
1225 static HRESULT WINAPI
domdoc_get_nodeTypeString(
1226 IXMLDOMDocument3
*iface
,
1229 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1230 static const WCHAR documentW
[] = {'d','o','c','u','m','e','n','t',0};
1232 TRACE("(%p)->(%p)\n", This
, p
);
1234 return return_bstr(documentW
, p
);
1238 static HRESULT WINAPI
domdoc_get_text(
1239 IXMLDOMDocument3
*iface
,
1242 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1243 TRACE("(%p)->(%p)\n", This
, p
);
1244 return node_get_text(&This
->node
, p
);
1248 static HRESULT WINAPI
domdoc_put_text(
1249 IXMLDOMDocument3
*iface
,
1252 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1253 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
1258 static HRESULT WINAPI
domdoc_get_specified(
1259 IXMLDOMDocument3
*iface
,
1260 VARIANT_BOOL
* isSpecified
)
1262 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1263 FIXME("(%p)->(%p) stub!\n", This
, isSpecified
);
1264 *isSpecified
= VARIANT_TRUE
;
1269 static HRESULT WINAPI
domdoc_get_definition(
1270 IXMLDOMDocument3
*iface
,
1271 IXMLDOMNode
** definitionNode
)
1273 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1274 FIXME("(%p)->(%p)\n", This
, definitionNode
);
1279 static HRESULT WINAPI
domdoc_get_nodeTypedValue(
1280 IXMLDOMDocument3
*iface
,
1283 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1284 TRACE("(%p)->(%p)\n", This
, v
);
1285 return return_null_var(v
);
1288 static HRESULT WINAPI
domdoc_put_nodeTypedValue(
1289 IXMLDOMDocument3
*iface
,
1290 VARIANT typedValue
)
1292 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1293 FIXME("(%p)->(%s)\n", This
, debugstr_variant(&typedValue
));
1298 static HRESULT WINAPI
domdoc_get_dataType(
1299 IXMLDOMDocument3
*iface
,
1302 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1303 TRACE("(%p)->(%p)\n", This
, typename
);
1304 return return_null_var( typename
);
1308 static HRESULT WINAPI
domdoc_put_dataType(
1309 IXMLDOMDocument3
*iface
,
1312 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1314 FIXME("(%p)->(%s)\n", This
, debugstr_w(dataTypeName
));
1317 return E_INVALIDARG
;
1322 static int XMLCALL
domdoc_get_xml_writecallback(void *ctx
, const char *data
, int len
)
1324 return xmlBufferAdd((xmlBufferPtr
)ctx
, (xmlChar
*)data
, len
) == 0 ? len
: 0;
1327 static HRESULT WINAPI
domdoc_get_xml(
1328 IXMLDOMDocument3
*iface
,
1331 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1332 xmlSaveCtxtPtr ctxt
;
1337 TRACE("(%p)->(%p)\n", This
, p
);
1340 return E_INVALIDARG
;
1344 buf
= xmlBufferCreate();
1346 return E_OUTOFMEMORY
;
1348 options
= XML_SAVE_FORMAT
| XML_SAVE_NO_DECL
;
1349 ctxt
= xmlSaveToIO(domdoc_get_xml_writecallback
, NULL
, buf
, "UTF-8", options
);
1354 return E_OUTOFMEMORY
;
1357 ret
= xmlSaveDoc(ctxt
, get_doc(This
));
1358 /* flushes on close */
1361 TRACE("%ld, len=%d\n", ret
, xmlBufferLength(buf
));
1362 if(ret
!= -1 && xmlBufferLength(buf
) > 0)
1366 content
= bstr_from_xmlChar(xmlBufferContent(buf
));
1367 content
= EnsureCorrectEOL(content
);
1373 *p
= SysAllocStringLen(NULL
, 0);
1378 return *p
? S_OK
: E_OUTOFMEMORY
;
1382 static HRESULT WINAPI
domdoc_transformNode(
1383 IXMLDOMDocument3
*iface
,
1387 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1388 TRACE("(%p)->(%p %p)\n", This
, node
, p
);
1389 return node_transform_node(&This
->node
, node
, p
);
1393 static HRESULT WINAPI
domdoc_selectNodes(
1394 IXMLDOMDocument3
*iface
,
1396 IXMLDOMNodeList
**outList
)
1398 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1399 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outList
);
1400 return node_select_nodes(&This
->node
, p
, outList
);
1404 static HRESULT WINAPI
domdoc_selectSingleNode(
1405 IXMLDOMDocument3
*iface
,
1407 IXMLDOMNode
**outNode
)
1409 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1410 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outNode
);
1411 return node_select_singlenode(&This
->node
, p
, outNode
);
1415 static HRESULT WINAPI
domdoc_get_parsed(
1416 IXMLDOMDocument3
*iface
,
1417 VARIANT_BOOL
* isParsed
)
1419 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1420 FIXME("(%p)->(%p) stub!\n", This
, isParsed
);
1421 *isParsed
= VARIANT_TRUE
;
1425 static HRESULT WINAPI
domdoc_get_namespaceURI(
1426 IXMLDOMDocument3
*iface
,
1427 BSTR
* namespaceURI
)
1429 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1430 TRACE("(%p)->(%p)\n", This
, namespaceURI
);
1431 return return_null_bstr( namespaceURI
);
1434 static HRESULT WINAPI
domdoc_get_prefix(
1435 IXMLDOMDocument3
*iface
,
1438 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1439 TRACE("(%p)->(%p)\n", This
, prefix
);
1440 return return_null_bstr( prefix
);
1444 static HRESULT WINAPI
domdoc_get_baseName(
1445 IXMLDOMDocument3
*iface
,
1448 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1449 TRACE("(%p)->(%p)\n", This
, name
);
1450 return return_null_bstr( name
);
1454 static HRESULT WINAPI
domdoc_transformNodeToObject(
1455 IXMLDOMDocument3
*iface
,
1456 IXMLDOMNode
* stylesheet
,
1457 VARIANT outputObject
)
1459 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1460 FIXME("(%p)->(%p %s)\n", This
, stylesheet
, debugstr_variant(&outputObject
));
1465 static HRESULT WINAPI
domdoc_get_doctype(
1466 IXMLDOMDocument3
*iface
,
1467 IXMLDOMDocumentType
** doctype
)
1469 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1474 TRACE("(%p)->(%p)\n", This
, doctype
);
1476 if (!doctype
) return E_INVALIDARG
;
1480 dtd
= xmlGetIntSubset(get_doc(This
));
1481 if (!dtd
) return S_FALSE
;
1483 node
= create_node((xmlNodePtr
)dtd
);
1484 if (!node
) return S_FALSE
;
1486 hr
= IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentType
, (void**)doctype
);
1487 IXMLDOMNode_Release(node
);
1493 static HRESULT WINAPI
domdoc_get_implementation(
1494 IXMLDOMDocument3
*iface
,
1495 IXMLDOMImplementation
** impl
)
1497 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1499 TRACE("(%p)->(%p)\n", This
, impl
);
1502 return E_INVALIDARG
;
1504 *impl
= (IXMLDOMImplementation
*)create_doc_Implementation();
1509 static HRESULT WINAPI
domdoc_get_documentElement(
1510 IXMLDOMDocument3
*iface
,
1511 IXMLDOMElement
** DOMElement
)
1513 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1514 IXMLDOMNode
*element_node
;
1518 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1521 return E_INVALIDARG
;
1525 root
= xmlDocGetRootElement( get_doc(This
) );
1529 element_node
= create_node( root
);
1530 if(!element_node
) return S_FALSE
;
1532 hr
= IXMLDOMNode_QueryInterface(element_node
, &IID_IXMLDOMElement
, (void**)DOMElement
);
1533 IXMLDOMNode_Release(element_node
);
1539 static HRESULT WINAPI
domdoc_put_documentElement(
1540 IXMLDOMDocument3
*iface
,
1541 IXMLDOMElement
* DOMElement
)
1543 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1544 IXMLDOMNode
*elementNode
;
1551 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1553 hr
= IXMLDOMElement_QueryInterface( DOMElement
, &IID_IXMLDOMNode
, (void**)&elementNode
);
1557 xmlNode
= get_node_obj( elementNode
);
1558 if(!xmlNode
) return E_FAIL
;
1560 if(!xmlNode
->node
->parent
)
1561 if(xmldoc_remove_orphan(xmlNode
->node
->doc
, xmlNode
->node
) != S_OK
)
1562 WARN("%p is not an orphan of %p\n", xmlNode
->node
->doc
, xmlNode
->node
);
1564 old_doc
= xmlNode
->node
->doc
;
1565 if (old_doc
!= get_doc(This
))
1566 refcount
= xmlnode_get_inst_cnt(xmlNode
);
1568 /* old root is still orphaned by its document, update refcount from new root */
1569 if (refcount
) xmldoc_add_refs(get_doc(This
), refcount
);
1570 oldRoot
= xmlDocSetRootElement( get_doc(This
), xmlNode
->node
);
1571 if (refcount
) xmldoc_release_refs(old_doc
, refcount
);
1572 IXMLDOMNode_Release( elementNode
);
1575 xmldoc_add_orphan(oldRoot
->doc
, oldRoot
);
1581 static HRESULT WINAPI
domdoc_createElement(
1582 IXMLDOMDocument3
*iface
,
1584 IXMLDOMElement
** element
)
1586 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1591 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(tagname
), element
);
1593 if (!element
|| !tagname
) return E_INVALIDARG
;
1595 V_VT(&type
) = VT_I1
;
1596 V_I1(&type
) = NODE_ELEMENT
;
1598 hr
= IXMLDOMDocument3_createNode(iface
, type
, tagname
, NULL
, &node
);
1601 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMElement
, (void**)element
);
1602 IXMLDOMNode_Release(node
);
1609 static HRESULT WINAPI
domdoc_createDocumentFragment(
1610 IXMLDOMDocument3
*iface
,
1611 IXMLDOMDocumentFragment
** frag
)
1613 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1618 TRACE("(%p)->(%p)\n", This
, frag
);
1620 if (!frag
) return E_INVALIDARG
;
1624 V_VT(&type
) = VT_I1
;
1625 V_I1(&type
) = NODE_DOCUMENT_FRAGMENT
;
1627 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1630 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentFragment
, (void**)frag
);
1631 IXMLDOMNode_Release(node
);
1638 static HRESULT WINAPI
domdoc_createTextNode(
1639 IXMLDOMDocument3
*iface
,
1641 IXMLDOMText
** text
)
1643 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1648 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), text
);
1650 if (!text
) return E_INVALIDARG
;
1654 V_VT(&type
) = VT_I1
;
1655 V_I1(&type
) = NODE_TEXT
;
1657 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1660 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMText
, (void**)text
);
1661 IXMLDOMNode_Release(node
);
1662 hr
= IXMLDOMText_put_data(*text
, data
);
1669 static HRESULT WINAPI
domdoc_createComment(
1670 IXMLDOMDocument3
*iface
,
1672 IXMLDOMComment
** comment
)
1674 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1679 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), comment
);
1681 if (!comment
) return E_INVALIDARG
;
1685 V_VT(&type
) = VT_I1
;
1686 V_I1(&type
) = NODE_COMMENT
;
1688 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1691 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMComment
, (void**)comment
);
1692 IXMLDOMNode_Release(node
);
1693 hr
= IXMLDOMComment_put_data(*comment
, data
);
1700 static HRESULT WINAPI
domdoc_createCDATASection(
1701 IXMLDOMDocument3
*iface
,
1703 IXMLDOMCDATASection
** cdata
)
1705 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1710 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), cdata
);
1712 if (!cdata
) return E_INVALIDARG
;
1716 V_VT(&type
) = VT_I1
;
1717 V_I1(&type
) = NODE_CDATA_SECTION
;
1719 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1722 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMCDATASection
, (void**)cdata
);
1723 IXMLDOMNode_Release(node
);
1724 hr
= IXMLDOMCDATASection_put_data(*cdata
, data
);
1731 static HRESULT WINAPI
domdoc_createProcessingInstruction(
1732 IXMLDOMDocument3
*iface
,
1735 IXMLDOMProcessingInstruction
** pi
)
1737 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1742 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_w(target
), debugstr_w(data
), pi
);
1744 if (!pi
) return E_INVALIDARG
;
1748 V_VT(&type
) = VT_I1
;
1749 V_I1(&type
) = NODE_PROCESSING_INSTRUCTION
;
1751 hr
= IXMLDOMDocument3_createNode(iface
, type
, target
, NULL
, &node
);
1756 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1757 node_obj
= get_node_obj(node
);
1758 hr
= node_set_content(node_obj
, data
);
1760 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMProcessingInstruction
, (void**)pi
);
1761 IXMLDOMNode_Release(node
);
1768 static HRESULT WINAPI
domdoc_createAttribute(
1769 IXMLDOMDocument3
*iface
,
1771 IXMLDOMAttribute
** attribute
)
1773 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1778 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), attribute
);
1780 if (!attribute
|| !name
) return E_INVALIDARG
;
1782 V_VT(&type
) = VT_I1
;
1783 V_I1(&type
) = NODE_ATTRIBUTE
;
1785 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1788 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMAttribute
, (void**)attribute
);
1789 IXMLDOMNode_Release(node
);
1796 static HRESULT WINAPI
domdoc_createEntityReference(
1797 IXMLDOMDocument3
*iface
,
1799 IXMLDOMEntityReference
** entityref
)
1801 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1806 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), entityref
);
1808 if (!entityref
) return E_INVALIDARG
;
1812 V_VT(&type
) = VT_I1
;
1813 V_I1(&type
) = NODE_ENTITY_REFERENCE
;
1815 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1818 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMEntityReference
, (void**)entityref
);
1819 IXMLDOMNode_Release(node
);
1825 xmlChar
* tagName_to_XPath(const BSTR tagName
)
1827 xmlChar
*query
, *tmp
;
1828 static const xmlChar everything
[] = "/descendant::node()";
1829 static const xmlChar mod_pre
[] = "*[local-name()='";
1830 static const xmlChar mod_post
[] = "']";
1831 static const xmlChar prefix
[] = "descendant::";
1832 const WCHAR
*tokBegin
, *tokEnd
;
1835 /* Special case - empty tagname - means select all nodes,
1836 except document itself. */
1838 return xmlStrdup(everything
);
1840 query
= xmlStrdup(prefix
);
1843 while (tokBegin
&& *tokBegin
)
1848 query
= xmlStrcat(query
, BAD_CAST
"/");
1852 query
= xmlStrcat(query
, BAD_CAST
"*");
1856 query
= xmlStrcat(query
, mod_pre
);
1858 while (*tokEnd
&& *tokEnd
!= '/')
1860 len
= WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, NULL
, 0, NULL
, NULL
);
1861 tmp
= xmlMalloc(len
);
1862 WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, (char*)tmp
, len
, NULL
, NULL
);
1863 query
= xmlStrncat(query
, tmp
, len
);
1866 query
= xmlStrcat(query
, mod_post
);
1873 static HRESULT WINAPI
domdoc_getElementsByTagName(
1874 IXMLDOMDocument3
*iface
,
1876 IXMLDOMNodeList
** resultList
)
1878 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1883 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(tagName
), resultList
);
1885 if (!tagName
|| !resultList
) return E_INVALIDARG
;
1887 XPath
= This
->properties
->XPath
;
1888 This
->properties
->XPath
= TRUE
;
1889 query
= tagName_to_XPath(tagName
);
1890 hr
= create_selection((xmlNodePtr
)get_doc(This
), query
, resultList
);
1892 This
->properties
->XPath
= XPath
;
1897 static HRESULT
get_node_type(VARIANT Type
, DOMNodeType
* type
)
1903 hr
= VariantChangeType(&tmp
, &Type
, 0, VT_I4
);
1905 return E_INVALIDARG
;
1912 static HRESULT WINAPI
domdoc_createNode(
1913 IXMLDOMDocument3
*iface
,
1917 IXMLDOMNode
** node
)
1919 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1920 DOMNodeType node_type
;
1922 xmlChar
*xml_name
, *href
;
1925 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_variant(&Type
), debugstr_w(name
), debugstr_w(namespaceURI
), node
);
1927 if(!node
) return E_INVALIDARG
;
1929 hr
= get_node_type(Type
, &node_type
);
1930 if(FAILED(hr
)) return hr
;
1932 TRACE("node_type %d\n", node_type
);
1934 /* exit earlier for types that need name */
1938 case NODE_ATTRIBUTE
:
1939 case NODE_ENTITY_REFERENCE
:
1940 case NODE_PROCESSING_INSTRUCTION
:
1941 if (!name
|| *name
== 0) return E_FAIL
;
1947 xml_name
= xmlchar_from_wchar(name
);
1948 /* prevent empty href to be allocated */
1949 href
= namespaceURI
? xmlchar_from_wchar(namespaceURI
) : NULL
;
1955 xmlChar
*local
, *prefix
;
1957 local
= xmlSplitQName2(xml_name
, &prefix
);
1959 xmlnode
= xmlNewDocNode(get_doc(This
), NULL
, local
? local
: xml_name
, NULL
);
1961 /* allow to create default namespace xmlns= */
1962 if (local
|| (href
&& *href
))
1964 xmlNsPtr ns
= xmlNewNs(xmlnode
, href
, prefix
);
1965 xmlSetNs(xmlnode
, ns
);
1973 case NODE_ATTRIBUTE
:
1975 xmlChar
*local
, *prefix
;
1977 local
= xmlSplitQName2(xml_name
, &prefix
);
1979 xmlnode
= (xmlNodePtr
)xmlNewDocProp(get_doc(This
), local
? local
: xml_name
, NULL
);
1981 if (local
|| (href
&& *href
))
1983 /* we need a floating namespace here, it can't be created linked to attribute from
1985 xmlNsPtr ns
= xmlNewNs(NULL
, href
, prefix
);
1986 xmlSetNs(xmlnode
, ns
);
1995 xmlnode
= (xmlNodePtr
)xmlNewDocText(get_doc(This
), NULL
);
1997 case NODE_CDATA_SECTION
:
1998 xmlnode
= xmlNewCDataBlock(get_doc(This
), NULL
, 0);
2000 case NODE_ENTITY_REFERENCE
:
2001 xmlnode
= xmlNewReference(get_doc(This
), xml_name
);
2003 case NODE_PROCESSING_INSTRUCTION
:
2004 #ifdef HAVE_XMLNEWDOCPI
2005 xmlnode
= xmlNewDocPI(get_doc(This
), xml_name
, NULL
);
2007 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2012 xmlnode
= xmlNewDocComment(get_doc(This
), NULL
);
2014 case NODE_DOCUMENT_FRAGMENT
:
2015 xmlnode
= xmlNewDocFragment(get_doc(This
));
2017 /* unsupported types */
2019 case NODE_DOCUMENT_TYPE
:
2022 heap_free(xml_name
);
2023 return E_INVALIDARG
;
2025 FIXME("unhandled node type %d\n", node_type
);
2030 *node
= create_node(xmlnode
);
2031 heap_free(xml_name
);
2036 TRACE("created node (%d, %p, %p)\n", node_type
, *node
, xmlnode
);
2037 xmldoc_add_orphan(xmlnode
->doc
, xmlnode
);
2044 static HRESULT WINAPI
domdoc_nodeFromID(
2045 IXMLDOMDocument3
*iface
,
2047 IXMLDOMNode
** node
)
2049 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2050 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(idString
), node
);
2054 static HRESULT
domdoc_onDataAvailable(void *obj
, char *ptr
, DWORD len
)
2059 xmldoc
= doparse(This
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
2061 xmldoc
->_private
= create_priv();
2062 return attach_xmldoc(This
, xmldoc
);
2068 static HRESULT
domdoc_load_moniker(domdoc
*This
, IMoniker
*mon
)
2073 hr
= bind_url(mon
, domdoc_onDataAvailable
, This
, &bsc
);
2077 return detach_bsc(bsc
);
2080 static HRESULT WINAPI
domdoc_load(
2081 IXMLDOMDocument3
*iface
,
2083 VARIANT_BOOL
* isSuccessful
)
2085 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2086 LPWSTR filename
= NULL
;
2087 HRESULT hr
= S_FALSE
;
2090 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&source
));
2094 *isSuccessful
= VARIANT_FALSE
;
2096 assert( &This
->node
);
2098 switch( V_VT(&source
) )
2101 filename
= V_BSTR(&source
);
2103 case VT_BSTR
|VT_BYREF
:
2104 if (!V_BSTRREF(&source
)) return E_INVALIDARG
;
2105 filename
= *V_BSTRREF(&source
);
2107 case VT_ARRAY
|VT_UI1
:
2109 SAFEARRAY
*psa
= V_ARRAY(&source
);
2112 UINT dim
= SafeArrayGetDim(psa
);
2117 ERR("SAFEARRAY == NULL\n");
2118 hr
= This
->error
= E_INVALIDARG
;
2121 /* Only takes UTF-8 strings.
2122 * NOT NULL-terminated. */
2123 SafeArrayAccessData(psa
, (void**)&str
);
2124 SafeArrayGetUBound(psa
, 1, &len
);
2126 if ((xmldoc
= doparse(This
, str
, ++len
, XML_CHAR_ENCODING_UTF8
)))
2128 hr
= This
->error
= S_OK
;
2129 *isSuccessful
= VARIANT_TRUE
;
2130 TRACE("parsed document %p\n", xmldoc
);
2134 This
->error
= E_FAIL
;
2135 TRACE("failed to parse document\n");
2138 SafeArrayUnaccessData(psa
);
2142 xmldoc
->_private
= create_priv();
2143 return attach_xmldoc(This
, xmldoc
);
2147 FIXME("unhandled SAFEARRAY dim: %d\n", dim
);
2148 hr
= This
->error
= E_NOTIMPL
;
2154 ISequentialStream
*stream
= NULL
;
2155 IXMLDOMDocument3
*newdoc
= NULL
;
2157 if (!V_UNKNOWN(&source
)) return E_INVALIDARG
;
2159 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IXMLDOMDocument3
, (void**)&newdoc
);
2164 domdoc
*newDoc
= impl_from_IXMLDOMDocument3( newdoc
);
2166 xmldoc
= xmlCopyDoc(get_doc(newDoc
), 1);
2167 xmldoc
->_private
= create_priv();
2168 hr
= attach_xmldoc(This
, xmldoc
);
2171 *isSuccessful
= VARIANT_TRUE
;
2177 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IStream
, (void**)&stream
);
2179 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_ISequentialStream
, (void**)&stream
);
2183 hr
= domdoc_load_from_stream(This
, stream
);
2185 *isSuccessful
= VARIANT_TRUE
;
2186 ISequentialStream_Release(stream
);
2190 FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr
, V_UNKNOWN(&source
)->lpVtbl
);
2194 FIXME("VT type not supported (%d)\n", V_VT(&source
));
2201 CoTaskMemFree(This
->properties
->url
);
2202 This
->properties
->url
= NULL
;
2204 hr
= create_moniker_from_url( filename
, &mon
);
2205 if ( SUCCEEDED(hr
) )
2207 hr
= domdoc_load_moniker( This
, mon
);
2209 IMoniker_GetDisplayName(mon
, NULL
, NULL
, &This
->properties
->url
);
2210 IMoniker_Release(mon
);
2214 This
->error
= E_FAIL
;
2217 hr
= This
->error
= S_OK
;
2218 *isSuccessful
= VARIANT_TRUE
;
2222 if(!filename
|| FAILED(hr
)) {
2223 xmldoc
= xmlNewDoc(NULL
);
2224 xmldoc
->_private
= create_priv();
2225 hr
= attach_xmldoc(This
, xmldoc
);
2230 TRACE("ret (%d)\n", hr
);
2236 static HRESULT WINAPI
domdoc_get_readyState(
2237 IXMLDOMDocument3
*iface
,
2240 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2241 FIXME("stub! (%p)->(%p)\n", This
, value
);
2244 return E_INVALIDARG
;
2246 *value
= READYSTATE_COMPLETE
;
2251 static HRESULT WINAPI
domdoc_get_parseError(
2252 IXMLDOMDocument3
*iface
,
2253 IXMLDOMParseError
** errorObj
)
2255 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2256 static const WCHAR err
[] = {'e','r','r','o','r',0};
2257 BSTR error_string
= NULL
;
2259 FIXME("(%p)->(%p): creating a dummy parseError\n", iface
, errorObj
);
2262 error_string
= SysAllocString(err
);
2264 *errorObj
= create_parseError(This
->error
, NULL
, error_string
, NULL
, 0, 0, 0);
2265 if(!*errorObj
) return E_OUTOFMEMORY
;
2270 static HRESULT WINAPI
domdoc_get_url(
2271 IXMLDOMDocument3
*iface
,
2274 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2276 TRACE("(%p)->(%p)\n", This
, url
);
2279 return E_INVALIDARG
;
2281 if (This
->properties
->url
)
2283 *url
= SysAllocString(This
->properties
->url
);
2285 return E_OUTOFMEMORY
;
2290 return return_null_bstr(url
);
2294 static HRESULT WINAPI
domdoc_get_async(
2295 IXMLDOMDocument3
*iface
,
2296 VARIANT_BOOL
* isAsync
)
2298 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2300 TRACE("(%p)->(%p: %d)\n", This
, isAsync
, This
->async
);
2301 *isAsync
= This
->async
;
2306 static HRESULT WINAPI
domdoc_put_async(
2307 IXMLDOMDocument3
*iface
,
2308 VARIANT_BOOL isAsync
)
2310 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2312 TRACE("(%p)->(%d)\n", This
, isAsync
);
2313 This
->async
= isAsync
;
2318 static HRESULT WINAPI
domdoc_abort(
2319 IXMLDOMDocument3
*iface
)
2321 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2322 FIXME("%p\n", This
);
2326 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2327 static HRESULT WINAPI
domdoc_loadXML(
2328 IXMLDOMDocument3
*iface
,
2330 VARIANT_BOOL
* isSuccessful
)
2332 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2333 xmlDocPtr xmldoc
= NULL
;
2334 HRESULT hr
= S_FALSE
, hr2
;
2336 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), isSuccessful
);
2338 assert ( &This
->node
);
2342 *isSuccessful
= VARIANT_FALSE
;
2348 /* skip leading spaces if needed */
2349 if (This
->properties
->version
== MSXML_DEFAULT
|| This
->properties
->version
== MSXML26
)
2350 while (*ptr
&& isspaceW(*ptr
)) ptr
++;
2352 xmldoc
= doparse(This
, (char*)ptr
, strlenW(ptr
)*sizeof(WCHAR
), XML_CHAR_ENCODING_UTF16LE
);
2355 This
->error
= E_FAIL
;
2356 TRACE("failed to parse document\n");
2360 hr
= This
->error
= S_OK
;
2361 *isSuccessful
= VARIANT_TRUE
;
2362 TRACE("parsed document %p\n", xmldoc
);
2368 xmldoc
= xmlNewDoc(NULL
);
2369 xmldoc
->_private
= create_priv();
2370 hr2
= attach_xmldoc(This
, xmldoc
);
2377 static int XMLCALL
domdoc_save_writecallback(void *ctx
, const char *buffer
, int len
)
2381 if(!WriteFile(ctx
, buffer
, len
, &written
, NULL
))
2383 WARN("write error\n");
2390 static int XMLCALL
domdoc_save_closecallback(void *ctx
)
2392 return CloseHandle(ctx
) ? 0 : -1;
2395 static int XMLCALL
domdoc_stream_save_writecallback(void *ctx
, const char *buffer
, int len
)
2400 hr
= IStream_Write((IStream
*)ctx
, buffer
, len
, &written
);
2401 TRACE("0x%08x %p %d %u\n", hr
, buffer
, len
, written
);
2404 WARN("stream write error: 0x%08x\n", hr
);
2411 static int XMLCALL
domdoc_stream_save_closecallback(void *ctx
)
2413 IStream_Release((IStream
*)ctx
);
2417 static HRESULT WINAPI
domdoc_save(
2418 IXMLDOMDocument3
*iface
,
2419 VARIANT destination
)
2421 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2422 xmlSaveCtxtPtr ctx
= NULL
;
2426 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&destination
));
2428 switch (V_VT(&destination
))
2432 IUnknown
*pUnk
= V_UNKNOWN(&destination
);
2433 IXMLDOMDocument3
*document
;
2436 ret
= IUnknown_QueryInterface(pUnk
, &IID_IXMLDOMDocument3
, (void**)&document
);
2439 VARIANT_BOOL success
;
2442 ret
= IXMLDOMDocument3_get_xml(iface
, &xml
);
2445 ret
= IXMLDOMDocument3_loadXML(document
, xml
, &success
);
2449 IXMLDOMDocument3_Release(document
);
2453 ret
= IUnknown_QueryInterface(pUnk
, &IID_IStream
, (void**)&stream
);
2456 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2457 ctx
= xmlSaveToIO(domdoc_stream_save_writecallback
,
2458 domdoc_stream_save_closecallback
, stream
, NULL
, options
);
2462 IStream_Release(stream
);
2470 case VT_BSTR
| VT_BYREF
:
2472 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2474 /* save with file path */
2475 HANDLE handle
= CreateFileW( (V_VT(&destination
) & VT_BYREF
)? *V_BSTRREF(&destination
) : V_BSTR(&destination
),
2476 GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2477 if( handle
== INVALID_HANDLE_VALUE
)
2479 WARN("failed to create file\n");
2483 /* disable top XML declaration */
2484 ctx
= xmlSaveToIO(domdoc_save_writecallback
, domdoc_save_closecallback
,
2485 handle
, NULL
, options
);
2488 CloseHandle(handle
);
2495 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination
));
2499 xmldecl
= xmldoc_unlink_xmldecl(get_doc(This
));
2500 if (xmlSaveDoc(ctx
, get_doc(This
)) == -1) ret
= S_FALSE
;
2501 xmldoc_link_xmldecl(get_doc(This
), xmldecl
);
2503 /* will release resources through close callback */
2509 static HRESULT WINAPI
domdoc_get_validateOnParse(
2510 IXMLDOMDocument3
*iface
,
2511 VARIANT_BOOL
* isValidating
)
2513 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2514 TRACE("(%p)->(%p: %d)\n", This
, isValidating
, This
->validating
);
2515 *isValidating
= This
->validating
;
2520 static HRESULT WINAPI
domdoc_put_validateOnParse(
2521 IXMLDOMDocument3
*iface
,
2522 VARIANT_BOOL isValidating
)
2524 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2525 TRACE("(%p)->(%d)\n", This
, isValidating
);
2526 This
->validating
= isValidating
;
2531 static HRESULT WINAPI
domdoc_get_resolveExternals(
2532 IXMLDOMDocument3
*iface
,
2533 VARIANT_BOOL
* isResolving
)
2535 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2536 TRACE("(%p)->(%p: %d)\n", This
, isResolving
, This
->resolving
);
2537 *isResolving
= This
->resolving
;
2542 static HRESULT WINAPI
domdoc_put_resolveExternals(
2543 IXMLDOMDocument3
*iface
,
2544 VARIANT_BOOL isResolving
)
2546 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2547 TRACE("(%p)->(%d)\n", This
, isResolving
);
2548 This
->resolving
= isResolving
;
2553 static HRESULT WINAPI
domdoc_get_preserveWhiteSpace(
2554 IXMLDOMDocument3
*iface
,
2555 VARIANT_BOOL
* isPreserving
)
2557 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2558 TRACE("(%p)->(%p: %d)\n", This
, isPreserving
, This
->properties
->preserving
);
2559 *isPreserving
= This
->properties
->preserving
;
2564 static HRESULT WINAPI
domdoc_put_preserveWhiteSpace(
2565 IXMLDOMDocument3
*iface
,
2566 VARIANT_BOOL isPreserving
)
2568 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2569 TRACE("(%p)->(%d)\n", This
, isPreserving
);
2570 This
->properties
->preserving
= isPreserving
;
2575 static HRESULT WINAPI
domdoc_put_onreadystatechange(
2576 IXMLDOMDocument3
*iface
,
2579 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2581 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&event
));
2582 return set_doc_event(This
, EVENTID_READYSTATECHANGE
, &event
);
2586 static HRESULT WINAPI
domdoc_put_onDataAvailable(IXMLDOMDocument3
*iface
, VARIANT sink
)
2588 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2589 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2593 static HRESULT WINAPI
domdoc_put_onTransformNode(IXMLDOMDocument3
*iface
, VARIANT sink
)
2595 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2596 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2600 static HRESULT WINAPI
domdoc_get_namespaces(
2601 IXMLDOMDocument3
* iface
,
2602 IXMLDOMSchemaCollection
** collection
)
2604 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2607 FIXME("(%p)->(%p): semi-stub\n", This
, collection
);
2609 if (!collection
) return E_POINTER
;
2611 if (!This
->namespaces
)
2613 hr
= SchemaCache_create(This
->properties
->version
, (void**)&This
->namespaces
);
2614 if (hr
!= S_OK
) return hr
;
2616 hr
= cache_from_doc_ns(This
->namespaces
, &This
->node
);
2618 release_namespaces(This
);
2621 if (This
->namespaces
)
2622 return IXMLDOMSchemaCollection2_QueryInterface(This
->namespaces
,
2623 &IID_IXMLDOMSchemaCollection
, (void**)collection
);
2628 static HRESULT WINAPI
domdoc_get_schemas(
2629 IXMLDOMDocument3
* iface
,
2632 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2633 IXMLDOMSchemaCollection2
* cur_schema
= This
->properties
->schemaCache
;
2634 HRESULT hr
= S_FALSE
;
2636 TRACE("(%p)->(%p)\n", This
, schema
);
2638 V_VT(schema
) = VT_NULL
;
2639 /* just to reset pointer part, cause that's what application is expected to use */
2640 V_DISPATCH(schema
) = NULL
;
2644 hr
= IXMLDOMSchemaCollection2_QueryInterface(cur_schema
, &IID_IDispatch
, (void**)&V_DISPATCH(schema
));
2646 V_VT(schema
) = VT_DISPATCH
;
2651 static HRESULT WINAPI
domdoc_putref_schemas(
2652 IXMLDOMDocument3
* iface
,
2655 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2656 HRESULT hr
= E_FAIL
;
2657 IXMLDOMSchemaCollection2
* new_schema
= NULL
;
2659 FIXME("(%p)->(%s): semi-stub\n", This
, debugstr_variant(&schema
));
2660 switch(V_VT(&schema
))
2663 if (V_UNKNOWN(&schema
))
2665 hr
= IUnknown_QueryInterface(V_UNKNOWN(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2670 if (V_DISPATCH(&schema
))
2672 hr
= IDispatch_QueryInterface(V_DISPATCH(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2682 WARN("Can't get schema from vt %x\n", V_VT(&schema
));
2687 IXMLDOMSchemaCollection2
* old_schema
= InterlockedExchangePointer((void**)&This
->properties
->schemaCache
, new_schema
);
2688 if(old_schema
) IXMLDOMSchemaCollection2_Release(old_schema
);
2694 static inline BOOL
is_wellformed(xmlDocPtr doc
)
2696 #ifdef HAVE_XMLDOC_PROPERTIES
2697 return doc
->properties
& XML_DOC_WELLFORMED
;
2699 /* Not a full check, but catches the worst violations */
2703 for (child
= doc
->children
; child
!= NULL
; child
= child
->next
)
2705 switch (child
->type
)
2707 case XML_ELEMENT_NODE
:
2712 case XML_CDATA_SECTION_NODE
:
2724 static void LIBXML2_LOG_CALLBACK
validate_error(void* ctx
, char const* msg
, ...)
2728 LIBXML2_CALLBACK_ERR(domdoc_validateNode
, msg
, ap
);
2732 static void LIBXML2_LOG_CALLBACK
validate_warning(void* ctx
, char const* msg
, ...)
2736 LIBXML2_CALLBACK_WARN(domdoc_validateNode
, msg
, ap
);
2740 static HRESULT WINAPI
domdoc_validateNode(
2741 IXMLDOMDocument3
* iface
,
2743 IXMLDOMParseError
** err
)
2745 domdoc
* This
= impl_from_IXMLDOMDocument3(iface
);
2746 LONG state
, err_code
= 0;
2750 TRACE("(%p)->(%p, %p)\n", This
, node
, err
);
2751 IXMLDOMDocument3_get_readyState(iface
, &state
);
2752 if (state
!= READYSTATE_COMPLETE
)
2755 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2762 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2766 if (!get_node_obj(node
)->node
|| get_node_obj(node
)->node
->doc
!= get_doc(This
))
2769 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2773 if (!is_wellformed(get_doc(This
)))
2775 ERR("doc not well-formed\n");
2777 *err
= create_parseError(E_XML_NOTWF
, NULL
, NULL
, NULL
, 0, 0, 0);
2781 /* DTD validation */
2782 if (get_doc(This
)->intSubset
|| get_doc(This
)->extSubset
)
2784 xmlValidCtxtPtr vctx
= xmlNewValidCtxt();
2785 vctx
->error
= validate_error
;
2786 vctx
->warning
= validate_warning
;
2789 if (!((node
== (IXMLDOMNode
*)iface
)?
2790 xmlValidateDocument(vctx
, get_doc(This
)) :
2791 xmlValidateElement(vctx
, get_doc(This
), get_node_obj(node
)->node
)))
2793 /* TODO: get a real error code here */
2794 TRACE("DTD validation failed\n");
2795 err_code
= E_XML_INVALID
;
2798 xmlFreeValidCtxt(vctx
);
2801 /* Schema validation */
2802 if (hr
== S_OK
&& This
->properties
->schemaCache
!= NULL
)
2805 hr
= SchemaCache_validate_tree(This
->properties
->schemaCache
, get_node_obj(node
)->node
);
2809 /* TODO: get a real error code here */
2812 TRACE("schema validation succeeded\n");
2816 ERR("schema validation failed\n");
2817 err_code
= E_XML_INVALID
;
2822 /* not really OK, just didn't find a schema for the ns */
2829 ERR("no DTD or schema found\n");
2830 err_code
= E_XML_NODTD
;
2835 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2840 static HRESULT WINAPI
domdoc_validate(
2841 IXMLDOMDocument3
* iface
,
2842 IXMLDOMParseError
** err
)
2844 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2845 TRACE("(%p)->(%p)\n", This
, err
);
2846 return IXMLDOMDocument3_validateNode(iface
, (IXMLDOMNode
*)iface
, err
);
2849 static HRESULT WINAPI
domdoc_setProperty(
2850 IXMLDOMDocument3
* iface
,
2854 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2856 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(p
), debugstr_variant(&value
));
2858 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
2864 V_VT(&varStr
) = VT_EMPTY
;
2865 if (V_VT(&value
) != VT_BSTR
)
2867 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2869 bstr
= V_BSTR(&varStr
);
2872 bstr
= V_BSTR(&value
);
2875 if (lstrcmpiW(bstr
, PropValueXPathW
) == 0)
2876 This
->properties
->XPath
= TRUE
;
2877 else if (lstrcmpiW(bstr
, PropValueXSLPatternW
) == 0)
2878 This
->properties
->XPath
= FALSE
;
2882 VariantClear(&varStr
);
2885 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
2887 xmlChar
*nsStr
= (xmlChar
*)This
->properties
->selectNsStr
;
2888 struct list
*pNsList
;
2893 V_VT(&varStr
) = VT_EMPTY
;
2894 if (V_VT(&value
) != VT_BSTR
)
2896 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2898 bstr
= V_BSTR(&varStr
);
2901 bstr
= V_BSTR(&value
);
2905 pNsList
= &(This
->properties
->selectNsList
);
2906 clear_selectNsList(pNsList
);
2908 nsStr
= xmlchar_from_wchar(bstr
);
2910 TRACE("property value: \"%s\"\n", debugstr_w(bstr
));
2912 This
->properties
->selectNsStr
= nsStr
;
2913 This
->properties
->selectNsStr_len
= xmlStrlen(nsStr
);
2916 xmlChar
*pTokBegin
, *pTokEnd
, *pTokInner
;
2917 select_ns_entry
* ns_entry
= NULL
;
2918 xmlXPathContextPtr ctx
;
2920 ctx
= xmlXPathNewContext(This
->node
.node
->doc
);
2923 /* skip leading spaces */
2924 while (*pTokBegin
== ' ' || *pTokBegin
== '\n' ||
2925 *pTokBegin
== '\t' || *pTokBegin
== '\r')
2928 for (; *pTokBegin
; pTokBegin
= pTokEnd
)
2931 memset(ns_entry
, 0, sizeof(select_ns_entry
));
2933 ns_entry
= heap_alloc_zero(sizeof(select_ns_entry
));
2935 while (*pTokBegin
== ' ')
2937 pTokEnd
= pTokBegin
;
2938 while (*pTokEnd
!= ' ' && *pTokEnd
!= 0)
2941 /* so it failed to advance which means we've got some trailing spaces */
2942 if (pTokEnd
== pTokBegin
) break;
2944 if (xmlStrncmp(pTokBegin
, (xmlChar
const*)"xmlns", 5) != 0)
2947 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2948 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2953 if (*pTokBegin
== '=')
2955 /*valid for XSLPattern?*/
2956 FIXME("Setting default xmlns not supported - skipping.\n");
2959 else if (*pTokBegin
== ':')
2961 ns_entry
->prefix
= ++pTokBegin
;
2962 for (pTokInner
= pTokBegin
; pTokInner
!= pTokEnd
&& *pTokInner
!= '='; ++pTokInner
)
2965 if (pTokInner
== pTokEnd
)
2968 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2969 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2973 ns_entry
->prefix_end
= *pTokInner
;
2977 if (pTokEnd
-pTokInner
> 1 &&
2978 ((*pTokInner
== '\'' && *(pTokEnd
-1) == '\'') ||
2979 (*pTokInner
== '"' && *(pTokEnd
-1) == '"')))
2981 ns_entry
->href
= ++pTokInner
;
2982 ns_entry
->href_end
= *(pTokEnd
-1);
2984 list_add_tail(pNsList
, &ns_entry
->entry
);
2985 /*let libxml figure out if they're valid from here ;)*/
2986 if (xmlXPathRegisterNs(ctx
, ns_entry
->prefix
, ns_entry
->href
) != 0)
2995 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2996 debugstr_w(bstr
), debugstr_an((const char*)pTokInner
, pTokEnd
-pTokInner
));
2997 list_add_tail(pNsList
, &ns_entry
->entry
);
3010 heap_free(ns_entry
);
3011 xmlXPathFreeContext(ctx
);
3014 VariantClear(&varStr
);
3017 else if (lstrcmpiW(p
, PropertyProhibitDTDW
) == 0 ||
3018 lstrcmpiW(p
, PropertyNewParserW
) == 0 ||
3019 lstrcmpiW(p
, PropertyResolveExternalsW
) == 0)
3022 FIXME("Ignoring property %s, value %s\n", debugstr_w(p
), debugstr_variant(&value
));
3026 FIXME("Unknown property %s\n", debugstr_w(p
));
3030 static HRESULT WINAPI
domdoc_getProperty(
3031 IXMLDOMDocument3
* iface
,
3035 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3037 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
3040 return E_INVALIDARG
;
3042 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
3044 V_VT(var
) = VT_BSTR
;
3045 V_BSTR(var
) = This
->properties
->XPath
?
3046 SysAllocString(PropValueXPathW
) :
3047 SysAllocString(PropValueXSLPatternW
);
3048 return V_BSTR(var
) ? S_OK
: E_OUTOFMEMORY
;
3050 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3053 BSTR rebuiltStr
, cur
;
3054 const xmlChar
*nsStr
;
3055 struct list
*pNsList
;
3056 select_ns_entry
* pNsEntry
;
3058 V_VT(var
) = VT_BSTR
;
3059 nsStr
= This
->properties
->selectNsStr
;
3060 pNsList
= &This
->properties
->selectNsList
;
3061 lenA
= This
->properties
->selectNsStr_len
;
3062 lenW
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, NULL
, 0);
3063 rebuiltStr
= heap_alloc(lenW
*sizeof(WCHAR
));
3064 MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, rebuiltStr
, lenW
);
3066 /* this is fine because all of the chars that end tokens are ASCII*/
3067 LIST_FOR_EACH_ENTRY(pNsEntry
, pNsList
, select_ns_entry
, entry
)
3069 while (*cur
!= 0) ++cur
;
3070 if (pNsEntry
->prefix_end
)
3072 *cur
= pNsEntry
->prefix_end
;
3073 while (*cur
!= 0) ++cur
;
3076 if (pNsEntry
->href_end
)
3078 *cur
= pNsEntry
->href_end
;
3081 V_BSTR(var
) = SysAllocString(rebuiltStr
);
3082 heap_free(rebuiltStr
);
3086 FIXME("Unknown property %s\n", debugstr_w(p
));
3090 static HRESULT WINAPI
domdoc_importNode(
3091 IXMLDOMDocument3
* iface
,
3094 IXMLDOMNode
** clone
)
3096 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3097 FIXME("(%p)->(%p %d %p): stub\n", This
, node
, deep
, clone
);
3101 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl
=
3103 domdoc_QueryInterface
,
3106 domdoc_GetTypeInfoCount
,
3108 domdoc_GetIDsOfNames
,
3110 domdoc_get_nodeName
,
3111 domdoc_get_nodeValue
,
3112 domdoc_put_nodeValue
,
3113 domdoc_get_nodeType
,
3114 domdoc_get_parentNode
,
3115 domdoc_get_childNodes
,
3116 domdoc_get_firstChild
,
3117 domdoc_get_lastChild
,
3118 domdoc_get_previousSibling
,
3119 domdoc_get_nextSibling
,
3120 domdoc_get_attributes
,
3121 domdoc_insertBefore
,
3122 domdoc_replaceChild
,
3125 domdoc_hasChildNodes
,
3126 domdoc_get_ownerDocument
,
3128 domdoc_get_nodeTypeString
,
3131 domdoc_get_specified
,
3132 domdoc_get_definition
,
3133 domdoc_get_nodeTypedValue
,
3134 domdoc_put_nodeTypedValue
,
3135 domdoc_get_dataType
,
3136 domdoc_put_dataType
,
3138 domdoc_transformNode
,
3140 domdoc_selectSingleNode
,
3142 domdoc_get_namespaceURI
,
3144 domdoc_get_baseName
,
3145 domdoc_transformNodeToObject
,
3147 domdoc_get_implementation
,
3148 domdoc_get_documentElement
,
3149 domdoc_put_documentElement
,
3150 domdoc_createElement
,
3151 domdoc_createDocumentFragment
,
3152 domdoc_createTextNode
,
3153 domdoc_createComment
,
3154 domdoc_createCDATASection
,
3155 domdoc_createProcessingInstruction
,
3156 domdoc_createAttribute
,
3157 domdoc_createEntityReference
,
3158 domdoc_getElementsByTagName
,
3162 domdoc_get_readyState
,
3163 domdoc_get_parseError
,
3170 domdoc_get_validateOnParse
,
3171 domdoc_put_validateOnParse
,
3172 domdoc_get_resolveExternals
,
3173 domdoc_put_resolveExternals
,
3174 domdoc_get_preserveWhiteSpace
,
3175 domdoc_put_preserveWhiteSpace
,
3176 domdoc_put_onreadystatechange
,
3177 domdoc_put_onDataAvailable
,
3178 domdoc_put_onTransformNode
,
3179 domdoc_get_namespaces
,
3181 domdoc_putref_schemas
,
3185 domdoc_validateNode
,
3189 /* IConnectionPointContainer */
3190 static HRESULT WINAPI
ConnectionPointContainer_QueryInterface(IConnectionPointContainer
*iface
,
3191 REFIID riid
, void **ppv
)
3193 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3194 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3197 static ULONG WINAPI
ConnectionPointContainer_AddRef(IConnectionPointContainer
*iface
)
3199 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3200 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3203 static ULONG WINAPI
ConnectionPointContainer_Release(IConnectionPointContainer
*iface
)
3205 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3206 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3209 static HRESULT WINAPI
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer
*iface
,
3210 IEnumConnectionPoints
**ppEnum
)
3212 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3213 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3217 static HRESULT WINAPI
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer
*iface
,
3218 REFIID riid
, IConnectionPoint
**cp
)
3220 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3221 ConnectionPoint
*iter
;
3223 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), cp
);
3227 for(iter
= This
->cp_list
; iter
; iter
= iter
->next
)
3229 if (IsEqualGUID(iter
->iid
, riid
))
3230 *cp
= &iter
->IConnectionPoint_iface
;
3235 IConnectionPoint_AddRef(*cp
);
3239 FIXME("unsupported riid %s\n", debugstr_guid(riid
));
3240 return CONNECT_E_NOCONNECTION
;
3244 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl
=
3246 ConnectionPointContainer_QueryInterface
,
3247 ConnectionPointContainer_AddRef
,
3248 ConnectionPointContainer_Release
,
3249 ConnectionPointContainer_EnumConnectionPoints
,
3250 ConnectionPointContainer_FindConnectionPoint
3253 /* IConnectionPoint */
3254 static HRESULT WINAPI
ConnectionPoint_QueryInterface(IConnectionPoint
*iface
,
3255 REFIID riid
, void **ppv
)
3257 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3259 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
3263 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
3264 IsEqualGUID(&IID_IConnectionPoint
, riid
))
3271 IConnectionPoint_AddRef(iface
);
3275 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
3276 return E_NOINTERFACE
;
3279 static ULONG WINAPI
ConnectionPoint_AddRef(IConnectionPoint
*iface
)
3281 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3282 return IConnectionPointContainer_AddRef(This
->container
);
3285 static ULONG WINAPI
ConnectionPoint_Release(IConnectionPoint
*iface
)
3287 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3288 return IConnectionPointContainer_Release(This
->container
);
3291 static HRESULT WINAPI
ConnectionPoint_GetConnectionInterface(IConnectionPoint
*iface
, IID
*iid
)
3293 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3295 TRACE("(%p)->(%p)\n", This
, iid
);
3297 if (!iid
) return E_POINTER
;
3303 static HRESULT WINAPI
ConnectionPoint_GetConnectionPointContainer(IConnectionPoint
*iface
,
3304 IConnectionPointContainer
**container
)
3306 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3308 TRACE("(%p)->(%p)\n", This
, container
);
3310 if (!container
) return E_POINTER
;
3312 *container
= This
->container
;
3313 IConnectionPointContainer_AddRef(*container
);
3317 static HRESULT WINAPI
ConnectionPoint_Advise(IConnectionPoint
*iface
, IUnknown
*unk_sink
,
3320 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3325 TRACE("(%p)->(%p %p)\n", This
, unk_sink
, cookie
);
3327 hr
= IUnknown_QueryInterface(unk_sink
, This
->iid
, (void**)&sink
);
3328 if(FAILED(hr
) && !IsEqualGUID(&IID_IPropertyNotifySink
, This
->iid
))
3329 hr
= IUnknown_QueryInterface(unk_sink
, &IID_IDispatch
, (void**)&sink
);
3331 return CONNECT_E_CANNOTCONNECT
;
3335 for (i
= 0; i
< This
->sinks_size
; i
++)
3336 if (!This
->sinks
[i
].unk
)
3339 if (i
== This
->sinks_size
)
3340 This
->sinks
= heap_realloc(This
->sinks
,(++This
->sinks_size
)*sizeof(*This
->sinks
));
3344 This
->sinks
= heap_alloc(sizeof(*This
->sinks
));
3345 This
->sinks_size
= 1;
3349 This
->sinks
[i
].unk
= sink
;
3356 static HRESULT WINAPI
ConnectionPoint_Unadvise(IConnectionPoint
*iface
, DWORD cookie
)
3358 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3360 TRACE("(%p)->(%d)\n", This
, cookie
);
3362 if (cookie
== 0 || cookie
> This
->sinks_size
|| !This
->sinks
[cookie
-1].unk
)
3363 return CONNECT_E_NOCONNECTION
;
3365 IUnknown_Release(This
->sinks
[cookie
-1].unk
);
3366 This
->sinks
[cookie
-1].unk
= NULL
;
3371 static HRESULT WINAPI
ConnectionPoint_EnumConnections(IConnectionPoint
*iface
,
3372 IEnumConnections
**ppEnum
)
3374 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3375 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3379 static const IConnectionPointVtbl ConnectionPointVtbl
=
3381 ConnectionPoint_QueryInterface
,
3382 ConnectionPoint_AddRef
,
3383 ConnectionPoint_Release
,
3384 ConnectionPoint_GetConnectionInterface
,
3385 ConnectionPoint_GetConnectionPointContainer
,
3386 ConnectionPoint_Advise
,
3387 ConnectionPoint_Unadvise
,
3388 ConnectionPoint_EnumConnections
3391 static void ConnectionPoint_Init(ConnectionPoint
*cp
, struct domdoc
*doc
, REFIID riid
)
3393 cp
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointVtbl
;
3399 cp
->next
= doc
->cp_list
;
3402 cp
->container
= &doc
->IConnectionPointContainer_iface
;
3405 /* domdoc implementation of IObjectWithSite */
3406 static HRESULT WINAPI
3407 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
3409 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3410 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObject
);
3413 static ULONG WINAPI
domdoc_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
3415 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3416 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3419 static ULONG WINAPI
domdoc_ObjectWithSite_Release( IObjectWithSite
* iface
)
3421 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3422 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3425 static HRESULT WINAPI
domdoc_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
3427 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3429 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
3434 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
3437 static HRESULT WINAPI
domdoc_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
3439 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3441 TRACE("(%p)->(%p)\n", iface
, punk
);
3447 IUnknown_Release( This
->site
);
3454 IUnknown_AddRef( punk
);
3457 IUnknown_Release( This
->site
);
3464 static const IObjectWithSiteVtbl domdocObjectSite
=
3466 domdoc_ObjectWithSite_QueryInterface
,
3467 domdoc_ObjectWithSite_AddRef
,
3468 domdoc_ObjectWithSite_Release
,
3469 domdoc_ObjectWithSite_SetSite
,
3470 domdoc_ObjectWithSite_GetSite
3473 static HRESULT WINAPI
domdoc_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
3475 domdoc
*This
= impl_from_IObjectSafety(iface
);
3476 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3479 static ULONG WINAPI
domdoc_Safety_AddRef(IObjectSafety
*iface
)
3481 domdoc
*This
= impl_from_IObjectSafety(iface
);
3482 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3485 static ULONG WINAPI
domdoc_Safety_Release(IObjectSafety
*iface
)
3487 domdoc
*This
= impl_from_IObjectSafety(iface
);
3488 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3491 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3493 static HRESULT WINAPI
domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3494 DWORD
*supported
, DWORD
*enabled
)
3496 domdoc
*This
= impl_from_IObjectSafety(iface
);
3498 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
3500 if(!supported
|| !enabled
) return E_POINTER
;
3502 *supported
= SAFETY_SUPPORTED_OPTIONS
;
3503 *enabled
= This
->safeopt
;
3508 static HRESULT WINAPI
domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3509 DWORD mask
, DWORD enabled
)
3511 domdoc
*This
= impl_from_IObjectSafety(iface
);
3512 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
3514 if ((mask
& ~SAFETY_SUPPORTED_OPTIONS
) != 0)
3517 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
3522 #undef SAFETY_SUPPORTED_OPTIONS
3524 static const IObjectSafetyVtbl domdocObjectSafetyVtbl
= {
3525 domdoc_Safety_QueryInterface
,
3526 domdoc_Safety_AddRef
,
3527 domdoc_Safety_Release
,
3528 domdoc_Safety_GetInterfaceSafetyOptions
,
3529 domdoc_Safety_SetInterfaceSafetyOptions
3532 static const tid_t domdoc_iface_tids
[] = {
3533 IXMLDOMDocument3_tid
,
3537 static dispex_static_data_t domdoc_dispex
= {
3539 IXMLDOMDocument3_tid
,
3544 HRESULT
get_domdoc_from_xmldoc(xmlDocPtr xmldoc
, IXMLDOMDocument3
**document
)
3548 doc
= heap_alloc( sizeof (*doc
) );
3550 return E_OUTOFMEMORY
;
3552 doc
->IXMLDOMDocument3_iface
.lpVtbl
= &XMLDOMDocument3Vtbl
;
3553 doc
->IPersistStreamInit_iface
.lpVtbl
= &xmldoc_IPersistStreamInit_VTable
;
3554 doc
->IObjectWithSite_iface
.lpVtbl
= &domdocObjectSite
;
3555 doc
->IObjectSafety_iface
.lpVtbl
= &domdocObjectSafetyVtbl
;
3556 doc
->IConnectionPointContainer_iface
.lpVtbl
= &ConnectionPointContainerVtbl
;
3558 doc
->async
= VARIANT_TRUE
;
3559 doc
->validating
= 0;
3561 doc
->properties
= properties_from_xmlDocPtr(xmldoc
);
3565 doc
->cp_list
= NULL
;
3566 doc
->namespaces
= NULL
;
3567 memset(doc
->events
, 0, sizeof(doc
->events
));
3569 /* events connection points */
3570 ConnectionPoint_Init(&doc
->cp_dispatch
, doc
, &IID_IDispatch
);
3571 ConnectionPoint_Init(&doc
->cp_propnotif
, doc
, &IID_IPropertyNotifySink
);
3572 ConnectionPoint_Init(&doc
->cp_domdocevents
, doc
, &DIID_XMLDOMDocumentEvents
);
3574 init_xmlnode(&doc
->node
, (xmlNodePtr
)xmldoc
, (IXMLDOMNode
*)&doc
->IXMLDOMDocument3_iface
,
3577 *document
= &doc
->IXMLDOMDocument3_iface
;
3579 TRACE("returning iface %p\n", *document
);
3583 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3588 TRACE("(%d, %p)\n", version
, ppObj
);
3590 xmldoc
= xmlNewDoc(NULL
);
3592 return E_OUTOFMEMORY
;
3594 xmldoc_init(xmldoc
, version
);
3596 hr
= get_domdoc_from_xmldoc(xmldoc
, (IXMLDOMDocument3
**)ppObj
);
3599 free_properties(properties_from_xmlDocPtr(xmldoc
));
3600 heap_free(xmldoc
->_private
);
3608 IUnknown
* create_domdoc( xmlNodePtr document
)
3613 TRACE("(%p)\n", document
);
3615 hr
= get_domdoc_from_xmldoc((xmlDocPtr
)document
, (IXMLDOMDocument3
**)&pObj
);
3624 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3626 MESSAGE("This program tried to use a DOMDocument object, but\n"
3627 "libxml2 support was not present at compile time.\n");