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 hr
= SafeArrayAccessData(psa
, (void**)&str
);
2127 WARN("failed to access array data, 0x%08x\n", hr
);
2130 SafeArrayGetUBound(psa
, 1, &len
);
2132 if ((xmldoc
= doparse(This
, str
, ++len
, XML_CHAR_ENCODING_UTF8
)))
2134 hr
= This
->error
= S_OK
;
2135 *isSuccessful
= VARIANT_TRUE
;
2136 TRACE("parsed document %p\n", xmldoc
);
2140 This
->error
= E_FAIL
;
2141 TRACE("failed to parse document\n");
2144 SafeArrayUnaccessData(psa
);
2148 xmldoc
->_private
= create_priv();
2149 return attach_xmldoc(This
, xmldoc
);
2153 FIXME("unhandled SAFEARRAY dim: %d\n", dim
);
2154 hr
= This
->error
= E_NOTIMPL
;
2160 ISequentialStream
*stream
= NULL
;
2161 IXMLDOMDocument3
*newdoc
= NULL
;
2163 if (!V_UNKNOWN(&source
)) return E_INVALIDARG
;
2165 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IXMLDOMDocument3
, (void**)&newdoc
);
2170 domdoc
*newDoc
= impl_from_IXMLDOMDocument3( newdoc
);
2172 xmldoc
= xmlCopyDoc(get_doc(newDoc
), 1);
2173 xmldoc
->_private
= create_priv();
2174 hr
= attach_xmldoc(This
, xmldoc
);
2177 *isSuccessful
= VARIANT_TRUE
;
2183 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IStream
, (void**)&stream
);
2185 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_ISequentialStream
, (void**)&stream
);
2189 hr
= domdoc_load_from_stream(This
, stream
);
2191 *isSuccessful
= VARIANT_TRUE
;
2192 ISequentialStream_Release(stream
);
2196 FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr
, V_UNKNOWN(&source
)->lpVtbl
);
2200 FIXME("VT type not supported (%d)\n", V_VT(&source
));
2207 CoTaskMemFree(This
->properties
->url
);
2208 This
->properties
->url
= NULL
;
2210 hr
= create_moniker_from_url( filename
, &mon
);
2211 if ( SUCCEEDED(hr
) )
2213 hr
= domdoc_load_moniker( This
, mon
);
2215 IMoniker_GetDisplayName(mon
, NULL
, NULL
, &This
->properties
->url
);
2216 IMoniker_Release(mon
);
2220 This
->error
= E_FAIL
;
2223 hr
= This
->error
= S_OK
;
2224 *isSuccessful
= VARIANT_TRUE
;
2228 if(!filename
|| FAILED(hr
)) {
2229 xmldoc
= xmlNewDoc(NULL
);
2230 xmldoc
->_private
= create_priv();
2231 hr
= attach_xmldoc(This
, xmldoc
);
2236 TRACE("ret (%d)\n", hr
);
2242 static HRESULT WINAPI
domdoc_get_readyState(
2243 IXMLDOMDocument3
*iface
,
2246 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2247 FIXME("stub! (%p)->(%p)\n", This
, value
);
2250 return E_INVALIDARG
;
2252 *value
= READYSTATE_COMPLETE
;
2257 static HRESULT WINAPI
domdoc_get_parseError(
2258 IXMLDOMDocument3
*iface
,
2259 IXMLDOMParseError
** errorObj
)
2261 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2262 static const WCHAR err
[] = {'e','r','r','o','r',0};
2263 BSTR error_string
= NULL
;
2265 FIXME("(%p)->(%p): creating a dummy parseError\n", iface
, errorObj
);
2268 error_string
= SysAllocString(err
);
2270 *errorObj
= create_parseError(This
->error
, NULL
, error_string
, NULL
, 0, 0, 0);
2271 if(!*errorObj
) return E_OUTOFMEMORY
;
2276 static HRESULT WINAPI
domdoc_get_url(
2277 IXMLDOMDocument3
*iface
,
2280 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2282 TRACE("(%p)->(%p)\n", This
, url
);
2285 return E_INVALIDARG
;
2287 if (This
->properties
->url
)
2289 *url
= SysAllocString(This
->properties
->url
);
2291 return E_OUTOFMEMORY
;
2296 return return_null_bstr(url
);
2300 static HRESULT WINAPI
domdoc_get_async(
2301 IXMLDOMDocument3
*iface
,
2302 VARIANT_BOOL
* isAsync
)
2304 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2306 TRACE("(%p)->(%p: %d)\n", This
, isAsync
, This
->async
);
2307 *isAsync
= This
->async
;
2312 static HRESULT WINAPI
domdoc_put_async(
2313 IXMLDOMDocument3
*iface
,
2314 VARIANT_BOOL isAsync
)
2316 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2318 TRACE("(%p)->(%d)\n", This
, isAsync
);
2319 This
->async
= isAsync
;
2324 static HRESULT WINAPI
domdoc_abort(
2325 IXMLDOMDocument3
*iface
)
2327 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2328 FIXME("%p\n", This
);
2332 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2333 static HRESULT WINAPI
domdoc_loadXML(
2334 IXMLDOMDocument3
*iface
,
2336 VARIANT_BOOL
* isSuccessful
)
2338 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2339 xmlDocPtr xmldoc
= NULL
;
2340 HRESULT hr
= S_FALSE
, hr2
;
2342 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), isSuccessful
);
2344 assert ( &This
->node
);
2348 *isSuccessful
= VARIANT_FALSE
;
2354 /* skip leading spaces if needed */
2355 if (This
->properties
->version
== MSXML_DEFAULT
|| This
->properties
->version
== MSXML26
)
2356 while (*ptr
&& isspaceW(*ptr
)) ptr
++;
2358 xmldoc
= doparse(This
, (char*)ptr
, strlenW(ptr
)*sizeof(WCHAR
), XML_CHAR_ENCODING_UTF16LE
);
2361 This
->error
= E_FAIL
;
2362 TRACE("failed to parse document\n");
2366 hr
= This
->error
= S_OK
;
2367 *isSuccessful
= VARIANT_TRUE
;
2368 TRACE("parsed document %p\n", xmldoc
);
2374 xmldoc
= xmlNewDoc(NULL
);
2375 xmldoc
->_private
= create_priv();
2376 hr2
= attach_xmldoc(This
, xmldoc
);
2383 static int XMLCALL
domdoc_save_writecallback(void *ctx
, const char *buffer
, int len
)
2387 if(!WriteFile(ctx
, buffer
, len
, &written
, NULL
))
2389 WARN("write error\n");
2396 static int XMLCALL
domdoc_save_closecallback(void *ctx
)
2398 return CloseHandle(ctx
) ? 0 : -1;
2401 static int XMLCALL
domdoc_stream_save_writecallback(void *ctx
, const char *buffer
, int len
)
2406 hr
= IStream_Write((IStream
*)ctx
, buffer
, len
, &written
);
2407 TRACE("0x%08x %p %d %u\n", hr
, buffer
, len
, written
);
2410 WARN("stream write error: 0x%08x\n", hr
);
2417 static int XMLCALL
domdoc_stream_save_closecallback(void *ctx
)
2419 IStream_Release((IStream
*)ctx
);
2423 static HRESULT WINAPI
domdoc_save(
2424 IXMLDOMDocument3
*iface
,
2425 VARIANT destination
)
2427 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2428 xmlSaveCtxtPtr ctx
= NULL
;
2432 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&destination
));
2434 switch (V_VT(&destination
))
2438 IUnknown
*pUnk
= V_UNKNOWN(&destination
);
2439 IXMLDOMDocument3
*document
;
2442 ret
= IUnknown_QueryInterface(pUnk
, &IID_IXMLDOMDocument3
, (void**)&document
);
2445 VARIANT_BOOL success
;
2448 ret
= IXMLDOMDocument3_get_xml(iface
, &xml
);
2451 ret
= IXMLDOMDocument3_loadXML(document
, xml
, &success
);
2455 IXMLDOMDocument3_Release(document
);
2459 ret
= IUnknown_QueryInterface(pUnk
, &IID_IStream
, (void**)&stream
);
2462 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2463 ctx
= xmlSaveToIO(domdoc_stream_save_writecallback
,
2464 domdoc_stream_save_closecallback
, stream
, NULL
, options
);
2468 IStream_Release(stream
);
2476 case VT_BSTR
| VT_BYREF
:
2478 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2480 /* save with file path */
2481 HANDLE handle
= CreateFileW( (V_VT(&destination
) & VT_BYREF
)? *V_BSTRREF(&destination
) : V_BSTR(&destination
),
2482 GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2483 if( handle
== INVALID_HANDLE_VALUE
)
2485 WARN("failed to create file\n");
2489 /* disable top XML declaration */
2490 ctx
= xmlSaveToIO(domdoc_save_writecallback
, domdoc_save_closecallback
,
2491 handle
, NULL
, options
);
2494 CloseHandle(handle
);
2501 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination
));
2505 xmldecl
= xmldoc_unlink_xmldecl(get_doc(This
));
2506 if (xmlSaveDoc(ctx
, get_doc(This
)) == -1) ret
= S_FALSE
;
2507 xmldoc_link_xmldecl(get_doc(This
), xmldecl
);
2509 /* will release resources through close callback */
2515 static HRESULT WINAPI
domdoc_get_validateOnParse(
2516 IXMLDOMDocument3
*iface
,
2517 VARIANT_BOOL
* isValidating
)
2519 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2520 TRACE("(%p)->(%p: %d)\n", This
, isValidating
, This
->validating
);
2521 *isValidating
= This
->validating
;
2526 static HRESULT WINAPI
domdoc_put_validateOnParse(
2527 IXMLDOMDocument3
*iface
,
2528 VARIANT_BOOL isValidating
)
2530 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2531 TRACE("(%p)->(%d)\n", This
, isValidating
);
2532 This
->validating
= isValidating
;
2537 static HRESULT WINAPI
domdoc_get_resolveExternals(
2538 IXMLDOMDocument3
*iface
,
2539 VARIANT_BOOL
* isResolving
)
2541 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2542 TRACE("(%p)->(%p: %d)\n", This
, isResolving
, This
->resolving
);
2543 *isResolving
= This
->resolving
;
2548 static HRESULT WINAPI
domdoc_put_resolveExternals(
2549 IXMLDOMDocument3
*iface
,
2550 VARIANT_BOOL isResolving
)
2552 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2553 TRACE("(%p)->(%d)\n", This
, isResolving
);
2554 This
->resolving
= isResolving
;
2559 static HRESULT WINAPI
domdoc_get_preserveWhiteSpace(
2560 IXMLDOMDocument3
*iface
,
2561 VARIANT_BOOL
* isPreserving
)
2563 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2564 TRACE("(%p)->(%p: %d)\n", This
, isPreserving
, This
->properties
->preserving
);
2565 *isPreserving
= This
->properties
->preserving
;
2570 static HRESULT WINAPI
domdoc_put_preserveWhiteSpace(
2571 IXMLDOMDocument3
*iface
,
2572 VARIANT_BOOL isPreserving
)
2574 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2575 TRACE("(%p)->(%d)\n", This
, isPreserving
);
2576 This
->properties
->preserving
= isPreserving
;
2581 static HRESULT WINAPI
domdoc_put_onreadystatechange(
2582 IXMLDOMDocument3
*iface
,
2585 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2587 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&event
));
2588 return set_doc_event(This
, EVENTID_READYSTATECHANGE
, &event
);
2592 static HRESULT WINAPI
domdoc_put_onDataAvailable(IXMLDOMDocument3
*iface
, VARIANT sink
)
2594 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2595 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2599 static HRESULT WINAPI
domdoc_put_onTransformNode(IXMLDOMDocument3
*iface
, VARIANT sink
)
2601 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2602 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2606 static HRESULT WINAPI
domdoc_get_namespaces(
2607 IXMLDOMDocument3
* iface
,
2608 IXMLDOMSchemaCollection
** collection
)
2610 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2613 FIXME("(%p)->(%p): semi-stub\n", This
, collection
);
2615 if (!collection
) return E_POINTER
;
2617 if (!This
->namespaces
)
2619 hr
= SchemaCache_create(This
->properties
->version
, (void**)&This
->namespaces
);
2620 if (hr
!= S_OK
) return hr
;
2622 hr
= cache_from_doc_ns(This
->namespaces
, &This
->node
);
2624 release_namespaces(This
);
2627 if (This
->namespaces
)
2628 return IXMLDOMSchemaCollection2_QueryInterface(This
->namespaces
,
2629 &IID_IXMLDOMSchemaCollection
, (void**)collection
);
2634 static HRESULT WINAPI
domdoc_get_schemas(
2635 IXMLDOMDocument3
* iface
,
2638 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2639 IXMLDOMSchemaCollection2
* cur_schema
= This
->properties
->schemaCache
;
2640 HRESULT hr
= S_FALSE
;
2642 TRACE("(%p)->(%p)\n", This
, schema
);
2644 V_VT(schema
) = VT_NULL
;
2645 /* just to reset pointer part, cause that's what application is expected to use */
2646 V_DISPATCH(schema
) = NULL
;
2650 hr
= IXMLDOMSchemaCollection2_QueryInterface(cur_schema
, &IID_IDispatch
, (void**)&V_DISPATCH(schema
));
2652 V_VT(schema
) = VT_DISPATCH
;
2657 static HRESULT WINAPI
domdoc_putref_schemas(
2658 IXMLDOMDocument3
* iface
,
2661 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2662 HRESULT hr
= E_FAIL
;
2663 IXMLDOMSchemaCollection2
* new_schema
= NULL
;
2665 FIXME("(%p)->(%s): semi-stub\n", This
, debugstr_variant(&schema
));
2666 switch(V_VT(&schema
))
2669 if (V_UNKNOWN(&schema
))
2671 hr
= IUnknown_QueryInterface(V_UNKNOWN(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2676 if (V_DISPATCH(&schema
))
2678 hr
= IDispatch_QueryInterface(V_DISPATCH(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2688 WARN("Can't get schema from vt %x\n", V_VT(&schema
));
2693 IXMLDOMSchemaCollection2
* old_schema
= InterlockedExchangePointer((void**)&This
->properties
->schemaCache
, new_schema
);
2694 if(old_schema
) IXMLDOMSchemaCollection2_Release(old_schema
);
2700 static inline BOOL
is_wellformed(xmlDocPtr doc
)
2702 #ifdef HAVE_XMLDOC_PROPERTIES
2703 return doc
->properties
& XML_DOC_WELLFORMED
;
2705 /* Not a full check, but catches the worst violations */
2709 for (child
= doc
->children
; child
!= NULL
; child
= child
->next
)
2711 switch (child
->type
)
2713 case XML_ELEMENT_NODE
:
2718 case XML_CDATA_SECTION_NODE
:
2730 static void LIBXML2_LOG_CALLBACK
validate_error(void* ctx
, char const* msg
, ...)
2734 LIBXML2_CALLBACK_ERR(domdoc_validateNode
, msg
, ap
);
2738 static void LIBXML2_LOG_CALLBACK
validate_warning(void* ctx
, char const* msg
, ...)
2742 LIBXML2_CALLBACK_WARN(domdoc_validateNode
, msg
, ap
);
2746 static HRESULT WINAPI
domdoc_validateNode(
2747 IXMLDOMDocument3
* iface
,
2749 IXMLDOMParseError
** err
)
2751 domdoc
* This
= impl_from_IXMLDOMDocument3(iface
);
2752 LONG state
, err_code
= 0;
2756 TRACE("(%p)->(%p, %p)\n", This
, node
, err
);
2757 IXMLDOMDocument3_get_readyState(iface
, &state
);
2758 if (state
!= READYSTATE_COMPLETE
)
2761 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2768 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2772 if (!get_node_obj(node
)->node
|| get_node_obj(node
)->node
->doc
!= get_doc(This
))
2775 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2779 if (!is_wellformed(get_doc(This
)))
2781 ERR("doc not well-formed\n");
2783 *err
= create_parseError(E_XML_NOTWF
, NULL
, NULL
, NULL
, 0, 0, 0);
2787 /* DTD validation */
2788 if (get_doc(This
)->intSubset
|| get_doc(This
)->extSubset
)
2790 xmlValidCtxtPtr vctx
= xmlNewValidCtxt();
2791 vctx
->error
= validate_error
;
2792 vctx
->warning
= validate_warning
;
2795 if (!((node
== (IXMLDOMNode
*)iface
)?
2796 xmlValidateDocument(vctx
, get_doc(This
)) :
2797 xmlValidateElement(vctx
, get_doc(This
), get_node_obj(node
)->node
)))
2799 /* TODO: get a real error code here */
2800 TRACE("DTD validation failed\n");
2801 err_code
= E_XML_INVALID
;
2804 xmlFreeValidCtxt(vctx
);
2807 /* Schema validation */
2808 if (hr
== S_OK
&& This
->properties
->schemaCache
!= NULL
)
2811 hr
= SchemaCache_validate_tree(This
->properties
->schemaCache
, get_node_obj(node
)->node
);
2815 /* TODO: get a real error code here */
2818 TRACE("schema validation succeeded\n");
2822 ERR("schema validation failed\n");
2823 err_code
= E_XML_INVALID
;
2828 /* not really OK, just didn't find a schema for the ns */
2835 ERR("no DTD or schema found\n");
2836 err_code
= E_XML_NODTD
;
2841 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2846 static HRESULT WINAPI
domdoc_validate(
2847 IXMLDOMDocument3
* iface
,
2848 IXMLDOMParseError
** err
)
2850 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2851 TRACE("(%p)->(%p)\n", This
, err
);
2852 return IXMLDOMDocument3_validateNode(iface
, (IXMLDOMNode
*)iface
, err
);
2855 static HRESULT WINAPI
domdoc_setProperty(
2856 IXMLDOMDocument3
* iface
,
2860 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2862 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(p
), debugstr_variant(&value
));
2864 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
2870 V_VT(&varStr
) = VT_EMPTY
;
2871 if (V_VT(&value
) != VT_BSTR
)
2873 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2875 bstr
= V_BSTR(&varStr
);
2878 bstr
= V_BSTR(&value
);
2881 if (lstrcmpiW(bstr
, PropValueXPathW
) == 0)
2882 This
->properties
->XPath
= TRUE
;
2883 else if (lstrcmpiW(bstr
, PropValueXSLPatternW
) == 0)
2884 This
->properties
->XPath
= FALSE
;
2888 VariantClear(&varStr
);
2891 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
2893 xmlChar
*nsStr
= (xmlChar
*)This
->properties
->selectNsStr
;
2894 struct list
*pNsList
;
2899 V_VT(&varStr
) = VT_EMPTY
;
2900 if (V_VT(&value
) != VT_BSTR
)
2902 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2904 bstr
= V_BSTR(&varStr
);
2907 bstr
= V_BSTR(&value
);
2911 pNsList
= &(This
->properties
->selectNsList
);
2912 clear_selectNsList(pNsList
);
2914 nsStr
= xmlchar_from_wchar(bstr
);
2916 TRACE("property value: \"%s\"\n", debugstr_w(bstr
));
2918 This
->properties
->selectNsStr
= nsStr
;
2919 This
->properties
->selectNsStr_len
= xmlStrlen(nsStr
);
2922 xmlChar
*pTokBegin
, *pTokEnd
, *pTokInner
;
2923 select_ns_entry
* ns_entry
= NULL
;
2924 xmlXPathContextPtr ctx
;
2926 ctx
= xmlXPathNewContext(This
->node
.node
->doc
);
2929 /* skip leading spaces */
2930 while (*pTokBegin
== ' ' || *pTokBegin
== '\n' ||
2931 *pTokBegin
== '\t' || *pTokBegin
== '\r')
2934 for (; *pTokBegin
; pTokBegin
= pTokEnd
)
2937 memset(ns_entry
, 0, sizeof(select_ns_entry
));
2939 ns_entry
= heap_alloc_zero(sizeof(select_ns_entry
));
2941 while (*pTokBegin
== ' ')
2943 pTokEnd
= pTokBegin
;
2944 while (*pTokEnd
!= ' ' && *pTokEnd
!= 0)
2947 /* so it failed to advance which means we've got some trailing spaces */
2948 if (pTokEnd
== pTokBegin
) break;
2950 if (xmlStrncmp(pTokBegin
, (xmlChar
const*)"xmlns", 5) != 0)
2953 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2954 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2959 if (*pTokBegin
== '=')
2961 /*valid for XSLPattern?*/
2962 FIXME("Setting default xmlns not supported - skipping.\n");
2965 else if (*pTokBegin
== ':')
2967 ns_entry
->prefix
= ++pTokBegin
;
2968 for (pTokInner
= pTokBegin
; pTokInner
!= pTokEnd
&& *pTokInner
!= '='; ++pTokInner
)
2971 if (pTokInner
== pTokEnd
)
2974 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2975 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2979 ns_entry
->prefix_end
= *pTokInner
;
2983 if (pTokEnd
-pTokInner
> 1 &&
2984 ((*pTokInner
== '\'' && *(pTokEnd
-1) == '\'') ||
2985 (*pTokInner
== '"' && *(pTokEnd
-1) == '"')))
2987 ns_entry
->href
= ++pTokInner
;
2988 ns_entry
->href_end
= *(pTokEnd
-1);
2990 list_add_tail(pNsList
, &ns_entry
->entry
);
2991 /*let libxml figure out if they're valid from here ;)*/
2992 if (xmlXPathRegisterNs(ctx
, ns_entry
->prefix
, ns_entry
->href
) != 0)
3001 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3002 debugstr_w(bstr
), debugstr_an((const char*)pTokInner
, pTokEnd
-pTokInner
));
3003 list_add_tail(pNsList
, &ns_entry
->entry
);
3016 heap_free(ns_entry
);
3017 xmlXPathFreeContext(ctx
);
3020 VariantClear(&varStr
);
3023 else if (lstrcmpiW(p
, PropertyProhibitDTDW
) == 0 ||
3024 lstrcmpiW(p
, PropertyNewParserW
) == 0 ||
3025 lstrcmpiW(p
, PropertyResolveExternalsW
) == 0)
3028 FIXME("Ignoring property %s, value %s\n", debugstr_w(p
), debugstr_variant(&value
));
3032 FIXME("Unknown property %s\n", debugstr_w(p
));
3036 static HRESULT WINAPI
domdoc_getProperty(
3037 IXMLDOMDocument3
* iface
,
3041 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3043 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
3046 return E_INVALIDARG
;
3048 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
3050 V_VT(var
) = VT_BSTR
;
3051 V_BSTR(var
) = This
->properties
->XPath
?
3052 SysAllocString(PropValueXPathW
) :
3053 SysAllocString(PropValueXSLPatternW
);
3054 return V_BSTR(var
) ? S_OK
: E_OUTOFMEMORY
;
3056 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3059 BSTR rebuiltStr
, cur
;
3060 const xmlChar
*nsStr
;
3061 struct list
*pNsList
;
3062 select_ns_entry
* pNsEntry
;
3064 V_VT(var
) = VT_BSTR
;
3065 nsStr
= This
->properties
->selectNsStr
;
3066 pNsList
= &This
->properties
->selectNsList
;
3067 lenA
= This
->properties
->selectNsStr_len
;
3068 lenW
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, NULL
, 0);
3069 rebuiltStr
= heap_alloc(lenW
*sizeof(WCHAR
));
3070 MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, rebuiltStr
, lenW
);
3072 /* this is fine because all of the chars that end tokens are ASCII*/
3073 LIST_FOR_EACH_ENTRY(pNsEntry
, pNsList
, select_ns_entry
, entry
)
3075 while (*cur
!= 0) ++cur
;
3076 if (pNsEntry
->prefix_end
)
3078 *cur
= pNsEntry
->prefix_end
;
3079 while (*cur
!= 0) ++cur
;
3082 if (pNsEntry
->href_end
)
3084 *cur
= pNsEntry
->href_end
;
3087 V_BSTR(var
) = SysAllocString(rebuiltStr
);
3088 heap_free(rebuiltStr
);
3092 FIXME("Unknown property %s\n", debugstr_w(p
));
3096 static HRESULT WINAPI
domdoc_importNode(
3097 IXMLDOMDocument3
* iface
,
3100 IXMLDOMNode
** clone
)
3102 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3103 FIXME("(%p)->(%p %d %p): stub\n", This
, node
, deep
, clone
);
3107 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl
=
3109 domdoc_QueryInterface
,
3112 domdoc_GetTypeInfoCount
,
3114 domdoc_GetIDsOfNames
,
3116 domdoc_get_nodeName
,
3117 domdoc_get_nodeValue
,
3118 domdoc_put_nodeValue
,
3119 domdoc_get_nodeType
,
3120 domdoc_get_parentNode
,
3121 domdoc_get_childNodes
,
3122 domdoc_get_firstChild
,
3123 domdoc_get_lastChild
,
3124 domdoc_get_previousSibling
,
3125 domdoc_get_nextSibling
,
3126 domdoc_get_attributes
,
3127 domdoc_insertBefore
,
3128 domdoc_replaceChild
,
3131 domdoc_hasChildNodes
,
3132 domdoc_get_ownerDocument
,
3134 domdoc_get_nodeTypeString
,
3137 domdoc_get_specified
,
3138 domdoc_get_definition
,
3139 domdoc_get_nodeTypedValue
,
3140 domdoc_put_nodeTypedValue
,
3141 domdoc_get_dataType
,
3142 domdoc_put_dataType
,
3144 domdoc_transformNode
,
3146 domdoc_selectSingleNode
,
3148 domdoc_get_namespaceURI
,
3150 domdoc_get_baseName
,
3151 domdoc_transformNodeToObject
,
3153 domdoc_get_implementation
,
3154 domdoc_get_documentElement
,
3155 domdoc_put_documentElement
,
3156 domdoc_createElement
,
3157 domdoc_createDocumentFragment
,
3158 domdoc_createTextNode
,
3159 domdoc_createComment
,
3160 domdoc_createCDATASection
,
3161 domdoc_createProcessingInstruction
,
3162 domdoc_createAttribute
,
3163 domdoc_createEntityReference
,
3164 domdoc_getElementsByTagName
,
3168 domdoc_get_readyState
,
3169 domdoc_get_parseError
,
3176 domdoc_get_validateOnParse
,
3177 domdoc_put_validateOnParse
,
3178 domdoc_get_resolveExternals
,
3179 domdoc_put_resolveExternals
,
3180 domdoc_get_preserveWhiteSpace
,
3181 domdoc_put_preserveWhiteSpace
,
3182 domdoc_put_onreadystatechange
,
3183 domdoc_put_onDataAvailable
,
3184 domdoc_put_onTransformNode
,
3185 domdoc_get_namespaces
,
3187 domdoc_putref_schemas
,
3191 domdoc_validateNode
,
3195 /* IConnectionPointContainer */
3196 static HRESULT WINAPI
ConnectionPointContainer_QueryInterface(IConnectionPointContainer
*iface
,
3197 REFIID riid
, void **ppv
)
3199 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3200 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3203 static ULONG WINAPI
ConnectionPointContainer_AddRef(IConnectionPointContainer
*iface
)
3205 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3206 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3209 static ULONG WINAPI
ConnectionPointContainer_Release(IConnectionPointContainer
*iface
)
3211 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3212 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3215 static HRESULT WINAPI
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer
*iface
,
3216 IEnumConnectionPoints
**ppEnum
)
3218 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3219 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3223 static HRESULT WINAPI
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer
*iface
,
3224 REFIID riid
, IConnectionPoint
**cp
)
3226 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3227 ConnectionPoint
*iter
;
3229 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), cp
);
3233 for(iter
= This
->cp_list
; iter
; iter
= iter
->next
)
3235 if (IsEqualGUID(iter
->iid
, riid
))
3236 *cp
= &iter
->IConnectionPoint_iface
;
3241 IConnectionPoint_AddRef(*cp
);
3245 FIXME("unsupported riid %s\n", debugstr_guid(riid
));
3246 return CONNECT_E_NOCONNECTION
;
3250 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl
=
3252 ConnectionPointContainer_QueryInterface
,
3253 ConnectionPointContainer_AddRef
,
3254 ConnectionPointContainer_Release
,
3255 ConnectionPointContainer_EnumConnectionPoints
,
3256 ConnectionPointContainer_FindConnectionPoint
3259 /* IConnectionPoint */
3260 static HRESULT WINAPI
ConnectionPoint_QueryInterface(IConnectionPoint
*iface
,
3261 REFIID riid
, void **ppv
)
3263 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3265 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
3269 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
3270 IsEqualGUID(&IID_IConnectionPoint
, riid
))
3277 IConnectionPoint_AddRef(iface
);
3281 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
3282 return E_NOINTERFACE
;
3285 static ULONG WINAPI
ConnectionPoint_AddRef(IConnectionPoint
*iface
)
3287 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3288 return IConnectionPointContainer_AddRef(This
->container
);
3291 static ULONG WINAPI
ConnectionPoint_Release(IConnectionPoint
*iface
)
3293 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3294 return IConnectionPointContainer_Release(This
->container
);
3297 static HRESULT WINAPI
ConnectionPoint_GetConnectionInterface(IConnectionPoint
*iface
, IID
*iid
)
3299 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3301 TRACE("(%p)->(%p)\n", This
, iid
);
3303 if (!iid
) return E_POINTER
;
3309 static HRESULT WINAPI
ConnectionPoint_GetConnectionPointContainer(IConnectionPoint
*iface
,
3310 IConnectionPointContainer
**container
)
3312 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3314 TRACE("(%p)->(%p)\n", This
, container
);
3316 if (!container
) return E_POINTER
;
3318 *container
= This
->container
;
3319 IConnectionPointContainer_AddRef(*container
);
3323 static HRESULT WINAPI
ConnectionPoint_Advise(IConnectionPoint
*iface
, IUnknown
*unk_sink
,
3326 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3331 TRACE("(%p)->(%p %p)\n", This
, unk_sink
, cookie
);
3333 hr
= IUnknown_QueryInterface(unk_sink
, This
->iid
, (void**)&sink
);
3334 if(FAILED(hr
) && !IsEqualGUID(&IID_IPropertyNotifySink
, This
->iid
))
3335 hr
= IUnknown_QueryInterface(unk_sink
, &IID_IDispatch
, (void**)&sink
);
3337 return CONNECT_E_CANNOTCONNECT
;
3341 for (i
= 0; i
< This
->sinks_size
; i
++)
3342 if (!This
->sinks
[i
].unk
)
3345 if (i
== This
->sinks_size
)
3346 This
->sinks
= heap_realloc(This
->sinks
,(++This
->sinks_size
)*sizeof(*This
->sinks
));
3350 This
->sinks
= heap_alloc(sizeof(*This
->sinks
));
3351 This
->sinks_size
= 1;
3355 This
->sinks
[i
].unk
= sink
;
3362 static HRESULT WINAPI
ConnectionPoint_Unadvise(IConnectionPoint
*iface
, DWORD cookie
)
3364 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3366 TRACE("(%p)->(%d)\n", This
, cookie
);
3368 if (cookie
== 0 || cookie
> This
->sinks_size
|| !This
->sinks
[cookie
-1].unk
)
3369 return CONNECT_E_NOCONNECTION
;
3371 IUnknown_Release(This
->sinks
[cookie
-1].unk
);
3372 This
->sinks
[cookie
-1].unk
= NULL
;
3377 static HRESULT WINAPI
ConnectionPoint_EnumConnections(IConnectionPoint
*iface
,
3378 IEnumConnections
**ppEnum
)
3380 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3381 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3385 static const IConnectionPointVtbl ConnectionPointVtbl
=
3387 ConnectionPoint_QueryInterface
,
3388 ConnectionPoint_AddRef
,
3389 ConnectionPoint_Release
,
3390 ConnectionPoint_GetConnectionInterface
,
3391 ConnectionPoint_GetConnectionPointContainer
,
3392 ConnectionPoint_Advise
,
3393 ConnectionPoint_Unadvise
,
3394 ConnectionPoint_EnumConnections
3397 static void ConnectionPoint_Init(ConnectionPoint
*cp
, struct domdoc
*doc
, REFIID riid
)
3399 cp
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointVtbl
;
3405 cp
->next
= doc
->cp_list
;
3408 cp
->container
= &doc
->IConnectionPointContainer_iface
;
3411 /* domdoc implementation of IObjectWithSite */
3412 static HRESULT WINAPI
3413 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
3415 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3416 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObject
);
3419 static ULONG WINAPI
domdoc_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
3421 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3422 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3425 static ULONG WINAPI
domdoc_ObjectWithSite_Release( IObjectWithSite
* iface
)
3427 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3428 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3431 static HRESULT WINAPI
domdoc_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
3433 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3435 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
3440 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
3443 static HRESULT WINAPI
domdoc_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
3445 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3447 TRACE("(%p)->(%p)\n", iface
, punk
);
3453 IUnknown_Release( This
->site
);
3460 IUnknown_AddRef( punk
);
3463 IUnknown_Release( This
->site
);
3470 static const IObjectWithSiteVtbl domdocObjectSite
=
3472 domdoc_ObjectWithSite_QueryInterface
,
3473 domdoc_ObjectWithSite_AddRef
,
3474 domdoc_ObjectWithSite_Release
,
3475 domdoc_ObjectWithSite_SetSite
,
3476 domdoc_ObjectWithSite_GetSite
3479 static HRESULT WINAPI
domdoc_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
3481 domdoc
*This
= impl_from_IObjectSafety(iface
);
3482 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3485 static ULONG WINAPI
domdoc_Safety_AddRef(IObjectSafety
*iface
)
3487 domdoc
*This
= impl_from_IObjectSafety(iface
);
3488 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3491 static ULONG WINAPI
domdoc_Safety_Release(IObjectSafety
*iface
)
3493 domdoc
*This
= impl_from_IObjectSafety(iface
);
3494 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3497 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3499 static HRESULT WINAPI
domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3500 DWORD
*supported
, DWORD
*enabled
)
3502 domdoc
*This
= impl_from_IObjectSafety(iface
);
3504 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
3506 if(!supported
|| !enabled
) return E_POINTER
;
3508 *supported
= SAFETY_SUPPORTED_OPTIONS
;
3509 *enabled
= This
->safeopt
;
3514 static HRESULT WINAPI
domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3515 DWORD mask
, DWORD enabled
)
3517 domdoc
*This
= impl_from_IObjectSafety(iface
);
3518 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
3520 if ((mask
& ~SAFETY_SUPPORTED_OPTIONS
) != 0)
3523 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
3528 #undef SAFETY_SUPPORTED_OPTIONS
3530 static const IObjectSafetyVtbl domdocObjectSafetyVtbl
= {
3531 domdoc_Safety_QueryInterface
,
3532 domdoc_Safety_AddRef
,
3533 domdoc_Safety_Release
,
3534 domdoc_Safety_GetInterfaceSafetyOptions
,
3535 domdoc_Safety_SetInterfaceSafetyOptions
3538 static const tid_t domdoc_iface_tids
[] = {
3539 IXMLDOMDocument3_tid
,
3543 static dispex_static_data_t domdoc_dispex
= {
3545 IXMLDOMDocument3_tid
,
3550 HRESULT
get_domdoc_from_xmldoc(xmlDocPtr xmldoc
, IXMLDOMDocument3
**document
)
3554 doc
= heap_alloc( sizeof (*doc
) );
3556 return E_OUTOFMEMORY
;
3558 doc
->IXMLDOMDocument3_iface
.lpVtbl
= &XMLDOMDocument3Vtbl
;
3559 doc
->IPersistStreamInit_iface
.lpVtbl
= &xmldoc_IPersistStreamInit_VTable
;
3560 doc
->IObjectWithSite_iface
.lpVtbl
= &domdocObjectSite
;
3561 doc
->IObjectSafety_iface
.lpVtbl
= &domdocObjectSafetyVtbl
;
3562 doc
->IConnectionPointContainer_iface
.lpVtbl
= &ConnectionPointContainerVtbl
;
3564 doc
->async
= VARIANT_TRUE
;
3565 doc
->validating
= 0;
3567 doc
->properties
= properties_from_xmlDocPtr(xmldoc
);
3571 doc
->cp_list
= NULL
;
3572 doc
->namespaces
= NULL
;
3573 memset(doc
->events
, 0, sizeof(doc
->events
));
3575 /* events connection points */
3576 ConnectionPoint_Init(&doc
->cp_dispatch
, doc
, &IID_IDispatch
);
3577 ConnectionPoint_Init(&doc
->cp_propnotif
, doc
, &IID_IPropertyNotifySink
);
3578 ConnectionPoint_Init(&doc
->cp_domdocevents
, doc
, &DIID_XMLDOMDocumentEvents
);
3580 init_xmlnode(&doc
->node
, (xmlNodePtr
)xmldoc
, (IXMLDOMNode
*)&doc
->IXMLDOMDocument3_iface
,
3583 *document
= &doc
->IXMLDOMDocument3_iface
;
3585 TRACE("returning iface %p\n", *document
);
3589 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3594 TRACE("(%d, %p)\n", version
, ppObj
);
3596 xmldoc
= xmlNewDoc(NULL
);
3598 return E_OUTOFMEMORY
;
3600 xmldoc_init(xmldoc
, version
);
3602 hr
= get_domdoc_from_xmldoc(xmldoc
, (IXMLDOMDocument3
**)ppObj
);
3605 free_properties(properties_from_xmlDocPtr(xmldoc
));
3606 heap_free(xmldoc
->_private
);
3614 IUnknown
* create_domdoc( xmlNodePtr document
)
3619 TRACE("(%p)\n", document
);
3621 hr
= get_domdoc_from_xmldoc((xmlDocPtr
)document
, (IXMLDOMDocument3
**)&pObj
);
3630 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3632 MESSAGE("This program tried to use a DOMDocument object, but\n"
3633 "libxml2 support was not present at compile time.\n");