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
))
432 /* Keep information about ignorable whitespace text node in previous or parent node */
433 if (ctxt
->node
->last
)
434 *(DWORD
*)&ctxt
->node
->last
->_private
|= NODE_PRIV_TRAILING_IGNORABLE_WS
;
435 else if (ctxt
->node
->type
!= XML_DOCUMENT_NODE
)
436 *(DWORD
*)&ctxt
->node
->_private
|= NODE_PRIV_CHILD_IGNORABLE_WS
;
441 xmlSAX2Characters(ctxt
, ch
, len
);
444 static void LIBXML2_LOG_CALLBACK
sax_error(void* ctx
, char const* msg
, ...)
448 LIBXML2_CALLBACK_ERR(doparse
, msg
, ap
);
452 static void LIBXML2_LOG_CALLBACK
sax_warning(void* ctx
, char const* msg
, ...)
456 LIBXML2_CALLBACK_WARN(doparse
, msg
, ap
);
460 static void sax_serror(void* ctx
, xmlErrorPtr err
)
462 LIBXML2_CALLBACK_SERROR(doparse
, err
);
465 static xmlDocPtr
doparse(domdoc
* This
, char const* ptr
, int len
, xmlCharEncoding encoding
)
467 xmlDocPtr doc
= NULL
;
468 xmlParserCtxtPtr pctx
;
469 static xmlSAXHandler sax_handler
= {
470 xmlSAX2InternalSubset
, /* internalSubset */
471 xmlSAX2IsStandalone
, /* isStandalone */
472 xmlSAX2HasInternalSubset
, /* hasInternalSubset */
473 xmlSAX2HasExternalSubset
, /* hasExternalSubset */
474 xmlSAX2ResolveEntity
, /* resolveEntity */
475 xmlSAX2GetEntity
, /* getEntity */
476 xmlSAX2EntityDecl
, /* entityDecl */
477 xmlSAX2NotationDecl
, /* notationDecl */
478 xmlSAX2AttributeDecl
, /* attributeDecl */
479 xmlSAX2ElementDecl
, /* elementDecl */
480 xmlSAX2UnparsedEntityDecl
, /* unparsedEntityDecl */
481 xmlSAX2SetDocumentLocator
, /* setDocumentLocator */
482 xmlSAX2StartDocument
, /* startDocument */
483 xmlSAX2EndDocument
, /* endDocument */
484 xmlSAX2StartElement
, /* startElement */
485 xmlSAX2EndElement
, /* endElement */
486 xmlSAX2Reference
, /* reference */
487 sax_characters
, /* characters */
488 sax_characters
, /* ignorableWhitespace */
489 xmlSAX2ProcessingInstruction
, /* processingInstruction */
490 xmlSAX2Comment
, /* comment */
491 sax_warning
, /* warning */
492 sax_error
, /* error */
493 sax_error
, /* fatalError */
494 xmlSAX2GetParameterEntity
, /* getParameterEntity */
495 xmlSAX2CDataBlock
, /* cdataBlock */
496 xmlSAX2ExternalSubset
, /* externalSubset */
499 xmlSAX2StartElementNs
, /* startElementNs */
500 xmlSAX2EndElementNs
, /* endElementNs */
501 sax_serror
/* serror */
504 pctx
= xmlCreateMemoryParserCtxt(ptr
, len
);
507 ERR("Failed to create parser context\n");
511 if (pctx
->sax
) xmlFree(pctx
->sax
);
512 pctx
->sax
= &sax_handler
;
513 pctx
->_private
= This
;
516 if (encoding
!= XML_CHAR_ENCODING_NONE
)
517 xmlSwitchEncoding(pctx
, encoding
);
519 xmlParseDocument(pctx
);
521 if (pctx
->wellFormed
)
527 xmlFreeDoc(pctx
->myDoc
);
531 xmlFreeParserCtxt(pctx
);
533 /* TODO: put this in one of the SAX callbacks */
534 /* create first child as a <?xml...?> */
535 if (doc
&& doc
->standalone
!= -1)
539 xmlChar
*xmlbuff
= (xmlChar
*)buff
;
541 node
= xmlNewDocPI( doc
, (xmlChar
*)"xml", NULL
);
543 /* version attribute can't be omitted */
544 sprintf(buff
, "version=\"%s\"", doc
->version
? (char*)doc
->version
: "1.0");
545 xmlNodeAddContent( node
, xmlbuff
);
549 sprintf(buff
, " encoding=\"%s\"", doc
->encoding
);
550 xmlNodeAddContent( node
, xmlbuff
);
553 if (doc
->standalone
!= -2)
555 sprintf(buff
, " standalone=\"%s\"", doc
->standalone
== 0 ? "no" : "yes");
556 xmlNodeAddContent( node
, xmlbuff
);
559 xmldoc_link_xmldecl( doc
, node
);
565 void xmldoc_init(xmlDocPtr doc
, MSXML_VERSION version
)
567 doc
->_private
= create_priv();
568 priv_from_xmlDocPtr(doc
)->properties
= create_properties(version
);
571 LONG
xmldoc_add_refs(xmlDocPtr doc
, LONG refs
)
573 LONG ref
= InterlockedExchangeAdd(&priv_from_xmlDocPtr(doc
)->refs
, refs
) + refs
;
574 TRACE("(%p)->(%d)\n", doc
, ref
);
578 LONG
xmldoc_add_ref(xmlDocPtr doc
)
580 return xmldoc_add_refs(doc
, 1);
583 LONG
xmldoc_release_refs(xmlDocPtr doc
, LONG refs
)
585 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
586 LONG ref
= InterlockedExchangeAdd(&priv
->refs
, -refs
) - refs
;
587 TRACE("(%p)->(%d)\n", doc
, ref
);
590 WARN("negative refcount, expect troubles\n");
594 orphan_entry
*orphan
, *orphan2
;
595 TRACE("freeing docptr %p\n", doc
);
597 LIST_FOR_EACH_ENTRY_SAFE( orphan
, orphan2
, &priv
->orphans
, orphan_entry
, entry
)
599 xmlFreeNode( orphan
->node
);
602 free_properties(priv
->properties
);
603 heap_free(doc
->_private
);
611 LONG
xmldoc_release(xmlDocPtr doc
)
613 return xmldoc_release_refs(doc
, 1);
616 HRESULT
xmldoc_add_orphan(xmlDocPtr doc
, xmlNodePtr node
)
618 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
621 entry
= heap_alloc( sizeof (*entry
) );
623 return E_OUTOFMEMORY
;
626 list_add_head( &priv
->orphans
, &entry
->entry
);
630 HRESULT
xmldoc_remove_orphan(xmlDocPtr doc
, xmlNodePtr node
)
632 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
633 orphan_entry
*entry
, *entry2
;
635 LIST_FOR_EACH_ENTRY_SAFE( entry
, entry2
, &priv
->orphans
, orphan_entry
, entry
)
637 if( entry
->node
== node
)
639 list_remove( &entry
->entry
);
648 static inline xmlDocPtr
get_doc( domdoc
*This
)
650 return This
->node
.node
->doc
;
653 static HRESULT
attach_xmldoc(domdoc
*This
, xmlDocPtr xml
)
655 release_namespaces(This
);
659 priv_from_xmlDocPtr(get_doc(This
))->properties
= NULL
;
660 if (xmldoc_release(get_doc(This
)) != 0)
661 priv_from_xmlDocPtr(get_doc(This
))->properties
=
662 copy_properties(This
->properties
);
665 This
->node
.node
= (xmlNodePtr
) xml
;
669 xmldoc_add_ref(get_doc(This
));
670 priv_from_xmlDocPtr(get_doc(This
))->properties
= This
->properties
;
676 static inline domdoc
*impl_from_IXMLDOMDocument3( IXMLDOMDocument3
*iface
)
678 return CONTAINING_RECORD(iface
, domdoc
, IXMLDOMDocument3_iface
);
681 static inline domdoc
*impl_from_IPersistStreamInit(IPersistStreamInit
*iface
)
683 return CONTAINING_RECORD(iface
, domdoc
, IPersistStreamInit_iface
);
686 static inline domdoc
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
688 return CONTAINING_RECORD(iface
, domdoc
, IObjectWithSite_iface
);
691 static inline domdoc
*impl_from_IObjectSafety(IObjectSafety
*iface
)
693 return CONTAINING_RECORD(iface
, domdoc
, IObjectSafety_iface
);
696 static inline domdoc
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
698 return CONTAINING_RECORD(iface
, domdoc
, IConnectionPointContainer_iface
);
701 /************************************************************************
702 * domdoc implementation of IPersistStream.
704 static HRESULT WINAPI
PersistStreamInit_QueryInterface(
705 IPersistStreamInit
*iface
, REFIID riid
, void **ppvObj
)
707 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
708 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObj
);
711 static ULONG WINAPI
PersistStreamInit_AddRef(
712 IPersistStreamInit
*iface
)
714 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
715 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
718 static ULONG WINAPI
PersistStreamInit_Release(
719 IPersistStreamInit
*iface
)
721 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
722 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
725 static HRESULT WINAPI
PersistStreamInit_GetClassID(
726 IPersistStreamInit
*iface
, CLSID
*classid
)
728 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
729 TRACE("(%p)->(%p)\n", This
, classid
);
734 *classid
= *DOMDocument_version(This
->properties
->version
);
739 static HRESULT WINAPI
PersistStreamInit_IsDirty(
740 IPersistStreamInit
*iface
)
742 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
743 FIXME("(%p): stub!\n", This
);
747 static HRESULT
domdoc_load_from_stream(domdoc
*doc
, ISequentialStream
*stream
)
749 DWORD read
, written
, len
;
750 xmlDocPtr xmldoc
= NULL
;
758 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &hstream
);
764 ISequentialStream_Read(stream
, buf
, sizeof(buf
), &read
);
765 hr
= IStream_Write(hstream
, buf
, read
, &written
);
766 } while(SUCCEEDED(hr
) && written
!= 0 && read
!= 0);
770 ERR("failed to copy stream 0x%08x\n", hr
);
771 IStream_Release(hstream
);
775 hr
= GetHGlobalFromStream(hstream
, &hglobal
);
779 len
= GlobalSize(hglobal
);
780 ptr
= GlobalLock(hglobal
);
782 xmldoc
= doparse(doc
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
783 GlobalUnlock(hglobal
);
787 ERR("Failed to parse xml\n");
791 xmldoc
->_private
= create_priv();
793 return attach_xmldoc(doc
, xmldoc
);
796 static HRESULT WINAPI
PersistStreamInit_Load(IPersistStreamInit
*iface
, IStream
*stream
)
798 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
800 TRACE("(%p)->(%p)\n", This
, stream
);
805 return domdoc_load_from_stream(This
, (ISequentialStream
*)stream
);
808 static HRESULT WINAPI
PersistStreamInit_Save(
809 IPersistStreamInit
*iface
, IStream
*stream
, BOOL clr_dirty
)
811 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
815 TRACE("(%p)->(%p %d)\n", This
, stream
, clr_dirty
);
817 hr
= IXMLDOMDocument3_get_xml(&This
->IXMLDOMDocument3_iface
, &xmlString
);
820 DWORD len
= SysStringLen(xmlString
) * sizeof(WCHAR
);
822 hr
= IStream_Write( stream
, xmlString
, len
, NULL
);
823 SysFreeString(xmlString
);
826 TRACE("ret 0x%08x\n", hr
);
831 static HRESULT WINAPI
PersistStreamInit_GetSizeMax(
832 IPersistStreamInit
*iface
, ULARGE_INTEGER
*pcbSize
)
834 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
835 TRACE("(%p)->(%p)\n", This
, pcbSize
);
839 static HRESULT WINAPI
PersistStreamInit_InitNew(
840 IPersistStreamInit
*iface
)
842 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
843 TRACE("(%p)\n", This
);
847 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable
=
849 PersistStreamInit_QueryInterface
,
850 PersistStreamInit_AddRef
,
851 PersistStreamInit_Release
,
852 PersistStreamInit_GetClassID
,
853 PersistStreamInit_IsDirty
,
854 PersistStreamInit_Load
,
855 PersistStreamInit_Save
,
856 PersistStreamInit_GetSizeMax
,
857 PersistStreamInit_InitNew
860 /* IXMLDOMDocument3 interface */
862 static const tid_t domdoc_se_tids
[] = {
865 IXMLDOMDocument2_tid
,
866 IXMLDOMDocument3_tid
,
870 static HRESULT WINAPI
domdoc_QueryInterface( IXMLDOMDocument3
*iface
, REFIID riid
, void** ppvObject
)
872 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
874 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( riid
), ppvObject
);
878 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
879 IsEqualGUID( riid
, &IID_IDispatch
) ||
880 IsEqualGUID( riid
, &IID_IXMLDOMNode
) ||
881 IsEqualGUID( riid
, &IID_IXMLDOMDocument
) ||
882 IsEqualGUID( riid
, &IID_IXMLDOMDocument2
)||
883 IsEqualGUID( riid
, &IID_IXMLDOMDocument3
))
887 else if (IsEqualGUID(&IID_IPersistStream
, riid
) ||
888 IsEqualGUID(&IID_IPersistStreamInit
, riid
))
890 *ppvObject
= &This
->IPersistStreamInit_iface
;
892 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
894 *ppvObject
= &This
->IObjectWithSite_iface
;
896 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
898 *ppvObject
= &This
->IObjectSafety_iface
;
900 else if( IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
902 return node_create_supporterrorinfo(domdoc_se_tids
, ppvObject
);
904 else if(node_query_interface(&This
->node
, riid
, ppvObject
))
906 return *ppvObject
? S_OK
: E_NOINTERFACE
;
908 else if (IsEqualGUID( riid
, &IID_IConnectionPointContainer
))
910 *ppvObject
= &This
->IConnectionPointContainer_iface
;
914 TRACE("interface %s not implemented\n", debugstr_guid(riid
));
915 return E_NOINTERFACE
;
918 IUnknown_AddRef((IUnknown
*)*ppvObject
);
923 static ULONG WINAPI
domdoc_AddRef( IXMLDOMDocument3
*iface
)
925 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
926 ULONG ref
= InterlockedIncrement( &This
->ref
);
927 TRACE("(%p)->(%d)\n", This
, ref
);
931 static ULONG WINAPI
domdoc_Release( IXMLDOMDocument3
*iface
)
933 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
934 LONG ref
= InterlockedDecrement( &This
->ref
);
936 TRACE("(%p)->(%d)\n", This
, ref
);
943 IUnknown_Release( This
->site
);
944 destroy_xmlnode(&This
->node
);
946 for (eid
= 0; eid
< EVENTID_LAST
; eid
++)
947 if (This
->events
[eid
]) IDispatch_Release(This
->events
[eid
]);
949 release_namespaces(This
);
956 static HRESULT WINAPI
domdoc_GetTypeInfoCount( IXMLDOMDocument3
*iface
, UINT
* pctinfo
)
958 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
959 return IDispatchEx_GetTypeInfoCount(&This
->node
.dispex
.IDispatchEx_iface
, pctinfo
);
962 static HRESULT WINAPI
domdoc_GetTypeInfo(
963 IXMLDOMDocument3
*iface
,
964 UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
966 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
967 return IDispatchEx_GetTypeInfo(&This
->node
.dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
970 static HRESULT WINAPI
domdoc_GetIDsOfNames(
971 IXMLDOMDocument3
*iface
,
978 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
979 return IDispatchEx_GetIDsOfNames(&This
->node
.dispex
.IDispatchEx_iface
,
980 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
983 static HRESULT WINAPI
domdoc_Invoke(
984 IXMLDOMDocument3
*iface
,
989 DISPPARAMS
* pDispParams
,
991 EXCEPINFO
* pExcepInfo
,
994 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
995 return IDispatchEx_Invoke(&This
->node
.dispex
.IDispatchEx_iface
,
996 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
999 static HRESULT WINAPI
domdoc_get_nodeName(
1000 IXMLDOMDocument3
*iface
,
1003 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1005 static const WCHAR documentW
[] = {'#','d','o','c','u','m','e','n','t',0};
1007 TRACE("(%p)->(%p)\n", This
, name
);
1009 return return_bstr(documentW
, name
);
1013 static HRESULT WINAPI
domdoc_get_nodeValue(
1014 IXMLDOMDocument3
*iface
,
1017 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1019 TRACE("(%p)->(%p)\n", This
, value
);
1022 return E_INVALIDARG
;
1024 V_VT(value
) = VT_NULL
;
1025 V_BSTR(value
) = NULL
; /* tests show that we should do this */
1030 static HRESULT WINAPI
domdoc_put_nodeValue(
1031 IXMLDOMDocument3
*iface
,
1034 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1035 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&value
));
1040 static HRESULT WINAPI
domdoc_get_nodeType(
1041 IXMLDOMDocument3
*iface
,
1044 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1046 TRACE("(%p)->(%p)\n", This
, type
);
1048 *type
= NODE_DOCUMENT
;
1053 static HRESULT WINAPI
domdoc_get_parentNode(
1054 IXMLDOMDocument3
*iface
,
1055 IXMLDOMNode
** parent
)
1057 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1059 TRACE("(%p)->(%p)\n", This
, parent
);
1061 return node_get_parent(&This
->node
, parent
);
1065 static HRESULT WINAPI
domdoc_get_childNodes(
1066 IXMLDOMDocument3
*iface
,
1067 IXMLDOMNodeList
** childList
)
1069 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1071 TRACE("(%p)->(%p)\n", This
, childList
);
1073 return node_get_child_nodes(&This
->node
, childList
);
1077 static HRESULT WINAPI
domdoc_get_firstChild(
1078 IXMLDOMDocument3
*iface
,
1079 IXMLDOMNode
** firstChild
)
1081 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1083 TRACE("(%p)->(%p)\n", This
, firstChild
);
1085 return node_get_first_child(&This
->node
, firstChild
);
1089 static HRESULT WINAPI
domdoc_get_lastChild(
1090 IXMLDOMDocument3
*iface
,
1091 IXMLDOMNode
** lastChild
)
1093 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1095 TRACE("(%p)->(%p)\n", This
, lastChild
);
1097 return node_get_last_child(&This
->node
, lastChild
);
1101 static HRESULT WINAPI
domdoc_get_previousSibling(
1102 IXMLDOMDocument3
*iface
,
1103 IXMLDOMNode
** previousSibling
)
1105 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1107 TRACE("(%p)->(%p)\n", This
, previousSibling
);
1109 return return_null_node(previousSibling
);
1113 static HRESULT WINAPI
domdoc_get_nextSibling(
1114 IXMLDOMDocument3
*iface
,
1115 IXMLDOMNode
** nextSibling
)
1117 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1119 TRACE("(%p)->(%p)\n", This
, nextSibling
);
1121 return return_null_node(nextSibling
);
1125 static HRESULT WINAPI
domdoc_get_attributes(
1126 IXMLDOMDocument3
*iface
,
1127 IXMLDOMNamedNodeMap
** attributeMap
)
1129 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1131 TRACE("(%p)->(%p)\n", This
, attributeMap
);
1133 return return_null_ptr((void**)attributeMap
);
1137 static HRESULT WINAPI
domdoc_insertBefore(
1138 IXMLDOMDocument3
*iface
,
1139 IXMLDOMNode
* newChild
,
1141 IXMLDOMNode
** outNewChild
)
1143 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1147 TRACE("(%p)->(%p %s %p)\n", This
, newChild
, debugstr_variant(&refChild
), outNewChild
);
1149 hr
= IXMLDOMNode_get_nodeType(newChild
, &type
);
1150 if (hr
!= S_OK
) return hr
;
1152 TRACE("new node type %d\n", type
);
1155 case NODE_ATTRIBUTE
:
1157 case NODE_CDATA_SECTION
:
1158 if (outNewChild
) *outNewChild
= NULL
;
1161 return node_insert_before(&This
->node
, newChild
, &refChild
, outNewChild
);
1165 static HRESULT WINAPI
domdoc_replaceChild(
1166 IXMLDOMDocument3
*iface
,
1167 IXMLDOMNode
* newChild
,
1168 IXMLDOMNode
* oldChild
,
1169 IXMLDOMNode
** outOldChild
)
1171 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1173 TRACE("(%p)->(%p %p %p)\n", This
, newChild
, oldChild
, outOldChild
);
1175 return node_replace_child(&This
->node
, newChild
, oldChild
, outOldChild
);
1179 static HRESULT WINAPI
domdoc_removeChild(
1180 IXMLDOMDocument3
*iface
,
1182 IXMLDOMNode
**oldChild
)
1184 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1185 TRACE("(%p)->(%p %p)\n", This
, child
, oldChild
);
1186 return node_remove_child(&This
->node
, child
, oldChild
);
1190 static HRESULT WINAPI
domdoc_appendChild(
1191 IXMLDOMDocument3
*iface
,
1193 IXMLDOMNode
**outChild
)
1195 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1196 TRACE("(%p)->(%p %p)\n", This
, child
, outChild
);
1197 return node_append_child(&This
->node
, child
, outChild
);
1201 static HRESULT WINAPI
domdoc_hasChildNodes(
1202 IXMLDOMDocument3
*iface
,
1205 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1206 TRACE("(%p)->(%p)\n", This
, ret
);
1207 return node_has_childnodes(&This
->node
, ret
);
1211 static HRESULT WINAPI
domdoc_get_ownerDocument(
1212 IXMLDOMDocument3
*iface
,
1213 IXMLDOMDocument
**doc
)
1215 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1216 TRACE("(%p)->(%p)\n", This
, doc
);
1217 return node_get_owner_doc(&This
->node
, doc
);
1221 static HRESULT WINAPI
domdoc_cloneNode(
1222 IXMLDOMDocument3
*iface
,
1224 IXMLDOMNode
** outNode
)
1226 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1229 TRACE("(%p)->(%d %p)\n", This
, deep
, outNode
);
1232 return E_INVALIDARG
;
1236 clone
= xmlCopyNode((xmlNodePtr
)get_doc(This
), deep
? 1 : 2);
1240 clone
->doc
->_private
= create_priv();
1241 xmldoc_add_orphan(clone
->doc
, clone
);
1242 xmldoc_add_ref(clone
->doc
);
1244 priv_from_xmlDocPtr(clone
->doc
)->properties
= copy_properties(This
->properties
);
1245 if (!(*outNode
= (IXMLDOMNode
*)create_domdoc(clone
)))
1247 xmldoc_release(clone
->doc
);
1255 static HRESULT WINAPI
domdoc_get_nodeTypeString(
1256 IXMLDOMDocument3
*iface
,
1259 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1260 static const WCHAR documentW
[] = {'d','o','c','u','m','e','n','t',0};
1262 TRACE("(%p)->(%p)\n", This
, p
);
1264 return return_bstr(documentW
, p
);
1268 static HRESULT WINAPI
domdoc_get_text(
1269 IXMLDOMDocument3
*iface
,
1272 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1273 TRACE("(%p)->(%p)\n", This
, p
);
1274 return node_get_text(&This
->node
, p
);
1278 static HRESULT WINAPI
domdoc_put_text(
1279 IXMLDOMDocument3
*iface
,
1282 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1283 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
1288 static HRESULT WINAPI
domdoc_get_specified(
1289 IXMLDOMDocument3
*iface
,
1290 VARIANT_BOOL
* isSpecified
)
1292 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1293 FIXME("(%p)->(%p) stub!\n", This
, isSpecified
);
1294 *isSpecified
= VARIANT_TRUE
;
1299 static HRESULT WINAPI
domdoc_get_definition(
1300 IXMLDOMDocument3
*iface
,
1301 IXMLDOMNode
** definitionNode
)
1303 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1304 FIXME("(%p)->(%p)\n", This
, definitionNode
);
1309 static HRESULT WINAPI
domdoc_get_nodeTypedValue(
1310 IXMLDOMDocument3
*iface
,
1313 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1314 TRACE("(%p)->(%p)\n", This
, v
);
1315 return return_null_var(v
);
1318 static HRESULT WINAPI
domdoc_put_nodeTypedValue(
1319 IXMLDOMDocument3
*iface
,
1320 VARIANT typedValue
)
1322 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1323 FIXME("(%p)->(%s)\n", This
, debugstr_variant(&typedValue
));
1328 static HRESULT WINAPI
domdoc_get_dataType(
1329 IXMLDOMDocument3
*iface
,
1332 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1333 TRACE("(%p)->(%p)\n", This
, typename
);
1334 return return_null_var( typename
);
1338 static HRESULT WINAPI
domdoc_put_dataType(
1339 IXMLDOMDocument3
*iface
,
1342 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1344 FIXME("(%p)->(%s)\n", This
, debugstr_w(dataTypeName
));
1347 return E_INVALIDARG
;
1352 static int XMLCALL
domdoc_get_xml_writecallback(void *ctx
, const char *data
, int len
)
1354 return xmlBufferAdd((xmlBufferPtr
)ctx
, (xmlChar
*)data
, len
) == 0 ? len
: 0;
1357 static HRESULT WINAPI
domdoc_get_xml(
1358 IXMLDOMDocument3
*iface
,
1361 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1362 xmlSaveCtxtPtr ctxt
;
1367 TRACE("(%p)->(%p)\n", This
, p
);
1370 return E_INVALIDARG
;
1374 buf
= xmlBufferCreate();
1376 return E_OUTOFMEMORY
;
1378 options
= XML_SAVE_FORMAT
| XML_SAVE_NO_DECL
;
1379 ctxt
= xmlSaveToIO(domdoc_get_xml_writecallback
, NULL
, buf
, "UTF-8", options
);
1384 return E_OUTOFMEMORY
;
1387 ret
= xmlSaveDoc(ctxt
, get_doc(This
));
1388 /* flushes on close */
1391 TRACE("%ld, len=%d\n", ret
, xmlBufferLength(buf
));
1392 if(ret
!= -1 && xmlBufferLength(buf
) > 0)
1396 content
= bstr_from_xmlChar(xmlBufferContent(buf
));
1397 content
= EnsureCorrectEOL(content
);
1403 *p
= SysAllocStringLen(NULL
, 0);
1408 return *p
? S_OK
: E_OUTOFMEMORY
;
1412 static HRESULT WINAPI
domdoc_transformNode(
1413 IXMLDOMDocument3
*iface
,
1417 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1418 TRACE("(%p)->(%p %p)\n", This
, node
, p
);
1419 return node_transform_node(&This
->node
, node
, p
);
1423 static HRESULT WINAPI
domdoc_selectNodes(
1424 IXMLDOMDocument3
*iface
,
1426 IXMLDOMNodeList
**outList
)
1428 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1429 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outList
);
1430 return node_select_nodes(&This
->node
, p
, outList
);
1434 static HRESULT WINAPI
domdoc_selectSingleNode(
1435 IXMLDOMDocument3
*iface
,
1437 IXMLDOMNode
**outNode
)
1439 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1440 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outNode
);
1441 return node_select_singlenode(&This
->node
, p
, outNode
);
1445 static HRESULT WINAPI
domdoc_get_parsed(
1446 IXMLDOMDocument3
*iface
,
1447 VARIANT_BOOL
* isParsed
)
1449 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1450 FIXME("(%p)->(%p) stub!\n", This
, isParsed
);
1451 *isParsed
= VARIANT_TRUE
;
1455 static HRESULT WINAPI
domdoc_get_namespaceURI(
1456 IXMLDOMDocument3
*iface
,
1457 BSTR
* namespaceURI
)
1459 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1460 TRACE("(%p)->(%p)\n", This
, namespaceURI
);
1461 return return_null_bstr( namespaceURI
);
1464 static HRESULT WINAPI
domdoc_get_prefix(
1465 IXMLDOMDocument3
*iface
,
1468 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1469 TRACE("(%p)->(%p)\n", This
, prefix
);
1470 return return_null_bstr( prefix
);
1474 static HRESULT WINAPI
domdoc_get_baseName(
1475 IXMLDOMDocument3
*iface
,
1478 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1479 TRACE("(%p)->(%p)\n", This
, name
);
1480 return return_null_bstr( name
);
1484 static HRESULT WINAPI
domdoc_transformNodeToObject(
1485 IXMLDOMDocument3
*iface
,
1486 IXMLDOMNode
* stylesheet
,
1487 VARIANT outputObject
)
1489 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1490 FIXME("(%p)->(%p %s)\n", This
, stylesheet
, debugstr_variant(&outputObject
));
1495 static HRESULT WINAPI
domdoc_get_doctype(
1496 IXMLDOMDocument3
*iface
,
1497 IXMLDOMDocumentType
** doctype
)
1499 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1504 TRACE("(%p)->(%p)\n", This
, doctype
);
1506 if (!doctype
) return E_INVALIDARG
;
1510 dtd
= xmlGetIntSubset(get_doc(This
));
1511 if (!dtd
) return S_FALSE
;
1513 node
= create_node((xmlNodePtr
)dtd
);
1514 if (!node
) return S_FALSE
;
1516 hr
= IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentType
, (void**)doctype
);
1517 IXMLDOMNode_Release(node
);
1523 static HRESULT WINAPI
domdoc_get_implementation(
1524 IXMLDOMDocument3
*iface
,
1525 IXMLDOMImplementation
** impl
)
1527 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1529 TRACE("(%p)->(%p)\n", This
, impl
);
1532 return E_INVALIDARG
;
1534 *impl
= (IXMLDOMImplementation
*)create_doc_Implementation();
1539 static HRESULT WINAPI
domdoc_get_documentElement(
1540 IXMLDOMDocument3
*iface
,
1541 IXMLDOMElement
** DOMElement
)
1543 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1544 IXMLDOMNode
*element_node
;
1548 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1551 return E_INVALIDARG
;
1555 root
= xmlDocGetRootElement( get_doc(This
) );
1559 element_node
= create_node( root
);
1560 if(!element_node
) return S_FALSE
;
1562 hr
= IXMLDOMNode_QueryInterface(element_node
, &IID_IXMLDOMElement
, (void**)DOMElement
);
1563 IXMLDOMNode_Release(element_node
);
1569 static HRESULT WINAPI
domdoc_put_documentElement(
1570 IXMLDOMDocument3
*iface
,
1571 IXMLDOMElement
* DOMElement
)
1573 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1574 IXMLDOMNode
*elementNode
;
1581 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1583 hr
= IXMLDOMElement_QueryInterface( DOMElement
, &IID_IXMLDOMNode
, (void**)&elementNode
);
1587 xmlNode
= get_node_obj( elementNode
);
1588 if(!xmlNode
) return E_FAIL
;
1590 if(!xmlNode
->node
->parent
)
1591 if(xmldoc_remove_orphan(xmlNode
->node
->doc
, xmlNode
->node
) != S_OK
)
1592 WARN("%p is not an orphan of %p\n", xmlNode
->node
->doc
, xmlNode
->node
);
1594 old_doc
= xmlNode
->node
->doc
;
1595 if (old_doc
!= get_doc(This
))
1596 refcount
= xmlnode_get_inst_cnt(xmlNode
);
1598 /* old root is still orphaned by its document, update refcount from new root */
1599 if (refcount
) xmldoc_add_refs(get_doc(This
), refcount
);
1600 oldRoot
= xmlDocSetRootElement( get_doc(This
), xmlNode
->node
);
1601 if (refcount
) xmldoc_release_refs(old_doc
, refcount
);
1602 IXMLDOMNode_Release( elementNode
);
1605 xmldoc_add_orphan(oldRoot
->doc
, oldRoot
);
1611 static HRESULT WINAPI
domdoc_createElement(
1612 IXMLDOMDocument3
*iface
,
1614 IXMLDOMElement
** element
)
1616 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1621 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(tagname
), element
);
1623 if (!element
|| !tagname
) return E_INVALIDARG
;
1625 V_VT(&type
) = VT_I1
;
1626 V_I1(&type
) = NODE_ELEMENT
;
1628 hr
= IXMLDOMDocument3_createNode(iface
, type
, tagname
, NULL
, &node
);
1631 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMElement
, (void**)element
);
1632 IXMLDOMNode_Release(node
);
1639 static HRESULT WINAPI
domdoc_createDocumentFragment(
1640 IXMLDOMDocument3
*iface
,
1641 IXMLDOMDocumentFragment
** frag
)
1643 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1648 TRACE("(%p)->(%p)\n", This
, frag
);
1650 if (!frag
) return E_INVALIDARG
;
1654 V_VT(&type
) = VT_I1
;
1655 V_I1(&type
) = NODE_DOCUMENT_FRAGMENT
;
1657 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1660 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentFragment
, (void**)frag
);
1661 IXMLDOMNode_Release(node
);
1668 static HRESULT WINAPI
domdoc_createTextNode(
1669 IXMLDOMDocument3
*iface
,
1671 IXMLDOMText
** text
)
1673 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1678 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), text
);
1680 if (!text
) return E_INVALIDARG
;
1684 V_VT(&type
) = VT_I1
;
1685 V_I1(&type
) = NODE_TEXT
;
1687 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1690 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMText
, (void**)text
);
1691 IXMLDOMNode_Release(node
);
1692 hr
= IXMLDOMText_put_data(*text
, data
);
1699 static HRESULT WINAPI
domdoc_createComment(
1700 IXMLDOMDocument3
*iface
,
1702 IXMLDOMComment
** comment
)
1704 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1709 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), comment
);
1711 if (!comment
) return E_INVALIDARG
;
1715 V_VT(&type
) = VT_I1
;
1716 V_I1(&type
) = NODE_COMMENT
;
1718 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1721 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMComment
, (void**)comment
);
1722 IXMLDOMNode_Release(node
);
1723 hr
= IXMLDOMComment_put_data(*comment
, data
);
1730 static HRESULT WINAPI
domdoc_createCDATASection(
1731 IXMLDOMDocument3
*iface
,
1733 IXMLDOMCDATASection
** cdata
)
1735 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1740 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), cdata
);
1742 if (!cdata
) return E_INVALIDARG
;
1746 V_VT(&type
) = VT_I1
;
1747 V_I1(&type
) = NODE_CDATA_SECTION
;
1749 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1752 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMCDATASection
, (void**)cdata
);
1753 IXMLDOMNode_Release(node
);
1754 hr
= IXMLDOMCDATASection_put_data(*cdata
, data
);
1761 static HRESULT WINAPI
domdoc_createProcessingInstruction(
1762 IXMLDOMDocument3
*iface
,
1765 IXMLDOMProcessingInstruction
** pi
)
1767 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1772 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_w(target
), debugstr_w(data
), pi
);
1774 if (!pi
) return E_INVALIDARG
;
1778 V_VT(&type
) = VT_I1
;
1779 V_I1(&type
) = NODE_PROCESSING_INSTRUCTION
;
1781 hr
= IXMLDOMDocument3_createNode(iface
, type
, target
, NULL
, &node
);
1786 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1787 node_obj
= get_node_obj(node
);
1788 hr
= node_set_content(node_obj
, data
);
1790 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMProcessingInstruction
, (void**)pi
);
1791 IXMLDOMNode_Release(node
);
1798 static HRESULT WINAPI
domdoc_createAttribute(
1799 IXMLDOMDocument3
*iface
,
1801 IXMLDOMAttribute
** attribute
)
1803 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1808 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), attribute
);
1810 if (!attribute
|| !name
) return E_INVALIDARG
;
1812 V_VT(&type
) = VT_I1
;
1813 V_I1(&type
) = NODE_ATTRIBUTE
;
1815 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1818 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMAttribute
, (void**)attribute
);
1819 IXMLDOMNode_Release(node
);
1826 static HRESULT WINAPI
domdoc_createEntityReference(
1827 IXMLDOMDocument3
*iface
,
1829 IXMLDOMEntityReference
** entityref
)
1831 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1836 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), entityref
);
1838 if (!entityref
) return E_INVALIDARG
;
1842 V_VT(&type
) = VT_I1
;
1843 V_I1(&type
) = NODE_ENTITY_REFERENCE
;
1845 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1848 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMEntityReference
, (void**)entityref
);
1849 IXMLDOMNode_Release(node
);
1855 xmlChar
* tagName_to_XPath(const BSTR tagName
)
1857 xmlChar
*query
, *tmp
;
1858 static const xmlChar everything
[] = "/descendant::node()";
1859 static const xmlChar mod_pre
[] = "*[local-name()='";
1860 static const xmlChar mod_post
[] = "']";
1861 static const xmlChar prefix
[] = "descendant::";
1862 const WCHAR
*tokBegin
, *tokEnd
;
1865 /* Special case - empty tagname - means select all nodes,
1866 except document itself. */
1868 return xmlStrdup(everything
);
1870 query
= xmlStrdup(prefix
);
1873 while (tokBegin
&& *tokBegin
)
1878 query
= xmlStrcat(query
, BAD_CAST
"/");
1882 query
= xmlStrcat(query
, BAD_CAST
"*");
1886 query
= xmlStrcat(query
, mod_pre
);
1888 while (*tokEnd
&& *tokEnd
!= '/')
1890 len
= WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, NULL
, 0, NULL
, NULL
);
1891 tmp
= xmlMalloc(len
);
1892 WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, (char*)tmp
, len
, NULL
, NULL
);
1893 query
= xmlStrncat(query
, tmp
, len
);
1896 query
= xmlStrcat(query
, mod_post
);
1903 static HRESULT WINAPI
domdoc_getElementsByTagName(
1904 IXMLDOMDocument3
*iface
,
1906 IXMLDOMNodeList
** resultList
)
1908 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1913 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(tagName
), resultList
);
1915 if (!tagName
|| !resultList
) return E_INVALIDARG
;
1917 XPath
= This
->properties
->XPath
;
1918 This
->properties
->XPath
= TRUE
;
1919 query
= tagName_to_XPath(tagName
);
1920 hr
= create_selection((xmlNodePtr
)get_doc(This
), query
, resultList
);
1922 This
->properties
->XPath
= XPath
;
1927 static HRESULT
get_node_type(VARIANT Type
, DOMNodeType
* type
)
1933 hr
= VariantChangeType(&tmp
, &Type
, 0, VT_I4
);
1935 return E_INVALIDARG
;
1942 static HRESULT WINAPI
domdoc_createNode(
1943 IXMLDOMDocument3
*iface
,
1947 IXMLDOMNode
** node
)
1949 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1950 DOMNodeType node_type
;
1952 xmlChar
*xml_name
, *href
;
1955 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_variant(&Type
), debugstr_w(name
), debugstr_w(namespaceURI
), node
);
1957 if(!node
) return E_INVALIDARG
;
1959 hr
= get_node_type(Type
, &node_type
);
1960 if(FAILED(hr
)) return hr
;
1962 TRACE("node_type %d\n", node_type
);
1964 /* exit earlier for types that need name */
1968 case NODE_ATTRIBUTE
:
1969 case NODE_ENTITY_REFERENCE
:
1970 case NODE_PROCESSING_INSTRUCTION
:
1971 if (!name
|| *name
== 0) return E_FAIL
;
1977 xml_name
= xmlchar_from_wchar(name
);
1978 /* prevent empty href from being allocated */
1979 href
= namespaceURI
? xmlchar_from_wchar(namespaceURI
) : NULL
;
1985 xmlChar
*local
, *prefix
;
1987 local
= xmlSplitQName2(xml_name
, &prefix
);
1989 xmlnode
= xmlNewDocNode(get_doc(This
), NULL
, local
? local
: xml_name
, NULL
);
1991 /* allow creating the default namespace xmlns= */
1992 if (local
|| (href
&& *href
))
1994 xmlNsPtr ns
= xmlNewNs(xmlnode
, href
, prefix
);
1995 xmlSetNs(xmlnode
, ns
);
2003 case NODE_ATTRIBUTE
:
2005 xmlChar
*local
, *prefix
;
2007 local
= xmlSplitQName2(xml_name
, &prefix
);
2009 xmlnode
= (xmlNodePtr
)xmlNewDocProp(get_doc(This
), local
? local
: xml_name
, NULL
);
2011 if (local
|| (href
&& *href
))
2013 /* we need a floating namespace here, it can't be created linked to attribute from
2015 xmlNsPtr ns
= xmlNewNs(NULL
, href
, prefix
);
2016 xmlSetNs(xmlnode
, ns
);
2025 xmlnode
= (xmlNodePtr
)xmlNewDocText(get_doc(This
), NULL
);
2027 case NODE_CDATA_SECTION
:
2028 xmlnode
= xmlNewCDataBlock(get_doc(This
), NULL
, 0);
2030 case NODE_ENTITY_REFERENCE
:
2031 xmlnode
= xmlNewReference(get_doc(This
), xml_name
);
2033 case NODE_PROCESSING_INSTRUCTION
:
2034 #ifdef HAVE_XMLNEWDOCPI
2035 xmlnode
= xmlNewDocPI(get_doc(This
), xml_name
, NULL
);
2037 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2042 xmlnode
= xmlNewDocComment(get_doc(This
), NULL
);
2044 case NODE_DOCUMENT_FRAGMENT
:
2045 xmlnode
= xmlNewDocFragment(get_doc(This
));
2047 /* unsupported types */
2049 case NODE_DOCUMENT_TYPE
:
2052 heap_free(xml_name
);
2053 return E_INVALIDARG
;
2055 FIXME("unhandled node type %d\n", node_type
);
2060 *node
= create_node(xmlnode
);
2061 heap_free(xml_name
);
2066 TRACE("created node (%d, %p, %p)\n", node_type
, *node
, xmlnode
);
2067 xmldoc_add_orphan(xmlnode
->doc
, xmlnode
);
2074 static HRESULT WINAPI
domdoc_nodeFromID(
2075 IXMLDOMDocument3
*iface
,
2077 IXMLDOMNode
** node
)
2079 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2080 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(idString
), node
);
2084 static HRESULT
domdoc_onDataAvailable(void *obj
, char *ptr
, DWORD len
)
2089 xmldoc
= doparse(This
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
2091 xmldoc
->_private
= create_priv();
2092 return attach_xmldoc(This
, xmldoc
);
2098 static HRESULT
domdoc_load_moniker(domdoc
*This
, IMoniker
*mon
)
2103 hr
= bind_url(mon
, domdoc_onDataAvailable
, This
, &bsc
);
2107 return detach_bsc(bsc
);
2110 static HRESULT WINAPI
domdoc_load(
2111 IXMLDOMDocument3
*iface
,
2113 VARIANT_BOOL
* isSuccessful
)
2115 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2116 LPWSTR filename
= NULL
;
2117 HRESULT hr
= S_FALSE
;
2120 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&source
));
2124 *isSuccessful
= VARIANT_FALSE
;
2126 assert( &This
->node
);
2128 switch( V_VT(&source
) )
2131 filename
= V_BSTR(&source
);
2133 case VT_BSTR
|VT_BYREF
:
2134 if (!V_BSTRREF(&source
)) return E_INVALIDARG
;
2135 filename
= *V_BSTRREF(&source
);
2137 case VT_ARRAY
|VT_UI1
:
2139 SAFEARRAY
*psa
= V_ARRAY(&source
);
2142 UINT dim
= SafeArrayGetDim(psa
);
2147 ERR("SAFEARRAY == NULL\n");
2148 hr
= This
->error
= E_INVALIDARG
;
2151 /* Only takes UTF-8 strings.
2152 * NOT NULL-terminated. */
2153 hr
= SafeArrayAccessData(psa
, (void**)&str
);
2157 WARN("failed to access array data, 0x%08x\n", hr
);
2160 SafeArrayGetUBound(psa
, 1, &len
);
2162 if ((xmldoc
= doparse(This
, str
, ++len
, XML_CHAR_ENCODING_UTF8
)))
2164 hr
= This
->error
= S_OK
;
2165 *isSuccessful
= VARIANT_TRUE
;
2166 TRACE("parsed document %p\n", xmldoc
);
2170 This
->error
= E_FAIL
;
2171 TRACE("failed to parse document\n");
2174 SafeArrayUnaccessData(psa
);
2178 xmldoc
->_private
= create_priv();
2179 return attach_xmldoc(This
, xmldoc
);
2183 FIXME("unhandled SAFEARRAY dim: %d\n", dim
);
2184 hr
= This
->error
= E_NOTIMPL
;
2190 ISequentialStream
*stream
= NULL
;
2191 IXMLDOMDocument3
*newdoc
= NULL
;
2193 if (!V_UNKNOWN(&source
)) return E_INVALIDARG
;
2195 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IXMLDOMDocument3
, (void**)&newdoc
);
2200 domdoc
*newDoc
= impl_from_IXMLDOMDocument3( newdoc
);
2202 xmldoc
= xmlCopyDoc(get_doc(newDoc
), 1);
2203 xmldoc
->_private
= create_priv();
2204 hr
= attach_xmldoc(This
, xmldoc
);
2207 *isSuccessful
= VARIANT_TRUE
;
2213 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IStream
, (void**)&stream
);
2215 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_ISequentialStream
, (void**)&stream
);
2219 hr
= domdoc_load_from_stream(This
, stream
);
2221 *isSuccessful
= VARIANT_TRUE
;
2222 ISequentialStream_Release(stream
);
2226 FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr
, V_UNKNOWN(&source
)->lpVtbl
);
2230 FIXME("VT type not supported (%d)\n", V_VT(&source
));
2237 CoTaskMemFree(This
->properties
->url
);
2238 This
->properties
->url
= NULL
;
2240 hr
= create_moniker_from_url( filename
, &mon
);
2241 if ( SUCCEEDED(hr
) )
2243 hr
= domdoc_load_moniker( This
, mon
);
2245 IMoniker_GetDisplayName(mon
, NULL
, NULL
, &This
->properties
->url
);
2246 IMoniker_Release(mon
);
2250 This
->error
= E_FAIL
;
2253 hr
= This
->error
= S_OK
;
2254 *isSuccessful
= VARIANT_TRUE
;
2258 if(!filename
|| FAILED(hr
)) {
2259 xmldoc
= xmlNewDoc(NULL
);
2260 xmldoc
->_private
= create_priv();
2261 hr
= attach_xmldoc(This
, xmldoc
);
2266 TRACE("ret (%d)\n", hr
);
2272 static HRESULT WINAPI
domdoc_get_readyState(
2273 IXMLDOMDocument3
*iface
,
2276 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2277 FIXME("stub! (%p)->(%p)\n", This
, value
);
2280 return E_INVALIDARG
;
2282 *value
= READYSTATE_COMPLETE
;
2287 static HRESULT WINAPI
domdoc_get_parseError(
2288 IXMLDOMDocument3
*iface
,
2289 IXMLDOMParseError
** errorObj
)
2291 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2292 static const WCHAR err
[] = {'e','r','r','o','r',0};
2293 BSTR error_string
= NULL
;
2295 FIXME("(%p)->(%p): creating a dummy parseError\n", iface
, errorObj
);
2298 error_string
= SysAllocString(err
);
2300 *errorObj
= create_parseError(This
->error
, NULL
, error_string
, NULL
, 0, 0, 0);
2301 if(!*errorObj
) return E_OUTOFMEMORY
;
2306 static HRESULT WINAPI
domdoc_get_url(
2307 IXMLDOMDocument3
*iface
,
2310 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2312 TRACE("(%p)->(%p)\n", This
, url
);
2315 return E_INVALIDARG
;
2317 if (This
->properties
->url
)
2319 *url
= SysAllocString(This
->properties
->url
);
2321 return E_OUTOFMEMORY
;
2326 return return_null_bstr(url
);
2330 static HRESULT WINAPI
domdoc_get_async(
2331 IXMLDOMDocument3
*iface
,
2332 VARIANT_BOOL
* isAsync
)
2334 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2336 TRACE("(%p)->(%p: %d)\n", This
, isAsync
, This
->async
);
2337 *isAsync
= This
->async
;
2342 static HRESULT WINAPI
domdoc_put_async(
2343 IXMLDOMDocument3
*iface
,
2344 VARIANT_BOOL isAsync
)
2346 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2348 TRACE("(%p)->(%d)\n", This
, isAsync
);
2349 This
->async
= isAsync
;
2354 static HRESULT WINAPI
domdoc_abort(
2355 IXMLDOMDocument3
*iface
)
2357 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2358 FIXME("%p\n", This
);
2362 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2363 static HRESULT WINAPI
domdoc_loadXML(
2364 IXMLDOMDocument3
*iface
,
2366 VARIANT_BOOL
* isSuccessful
)
2368 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2369 xmlDocPtr xmldoc
= NULL
;
2370 HRESULT hr
= S_FALSE
, hr2
;
2372 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), isSuccessful
);
2374 assert ( &This
->node
);
2378 *isSuccessful
= VARIANT_FALSE
;
2384 /* skip leading spaces if needed */
2385 if (This
->properties
->version
== MSXML_DEFAULT
|| This
->properties
->version
== MSXML26
)
2386 while (*ptr
&& isspaceW(*ptr
)) ptr
++;
2388 xmldoc
= doparse(This
, (char*)ptr
, strlenW(ptr
)*sizeof(WCHAR
), XML_CHAR_ENCODING_UTF16LE
);
2391 This
->error
= E_FAIL
;
2392 TRACE("failed to parse document\n");
2396 hr
= This
->error
= S_OK
;
2397 *isSuccessful
= VARIANT_TRUE
;
2398 TRACE("parsed document %p\n", xmldoc
);
2404 xmldoc
= xmlNewDoc(NULL
);
2405 xmldoc
->_private
= create_priv();
2406 hr2
= attach_xmldoc(This
, xmldoc
);
2413 static int XMLCALL
domdoc_save_writecallback(void *ctx
, const char *buffer
, int len
)
2417 if(!WriteFile(ctx
, buffer
, len
, &written
, NULL
))
2419 WARN("write error\n");
2426 static int XMLCALL
domdoc_save_closecallback(void *ctx
)
2428 return CloseHandle(ctx
) ? 0 : -1;
2431 static int XMLCALL
domdoc_stream_save_writecallback(void *ctx
, const char *buffer
, int len
)
2436 hr
= IStream_Write((IStream
*)ctx
, buffer
, len
, &written
);
2437 TRACE("0x%08x %p %d %u\n", hr
, buffer
, len
, written
);
2440 WARN("stream write error: 0x%08x\n", hr
);
2447 static int XMLCALL
domdoc_stream_save_closecallback(void *ctx
)
2449 IStream_Release((IStream
*)ctx
);
2453 static HRESULT WINAPI
domdoc_save(
2454 IXMLDOMDocument3
*iface
,
2455 VARIANT destination
)
2457 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2458 xmlSaveCtxtPtr ctx
= NULL
;
2462 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&destination
));
2464 switch (V_VT(&destination
))
2468 IUnknown
*pUnk
= V_UNKNOWN(&destination
);
2469 IXMLDOMDocument3
*document
;
2472 ret
= IUnknown_QueryInterface(pUnk
, &IID_IXMLDOMDocument3
, (void**)&document
);
2475 VARIANT_BOOL success
;
2478 ret
= IXMLDOMDocument3_get_xml(iface
, &xml
);
2481 ret
= IXMLDOMDocument3_loadXML(document
, xml
, &success
);
2485 IXMLDOMDocument3_Release(document
);
2489 ret
= IUnknown_QueryInterface(pUnk
, &IID_IStream
, (void**)&stream
);
2492 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2493 ctx
= xmlSaveToIO(domdoc_stream_save_writecallback
,
2494 domdoc_stream_save_closecallback
, stream
, NULL
, options
);
2498 IStream_Release(stream
);
2506 case VT_BSTR
| VT_BYREF
:
2508 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2510 /* save with file path */
2511 HANDLE handle
= CreateFileW( (V_VT(&destination
) & VT_BYREF
)? *V_BSTRREF(&destination
) : V_BSTR(&destination
),
2512 GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2513 if( handle
== INVALID_HANDLE_VALUE
)
2515 WARN("failed to create file\n");
2519 /* disable top XML declaration */
2520 ctx
= xmlSaveToIO(domdoc_save_writecallback
, domdoc_save_closecallback
,
2521 handle
, NULL
, options
);
2524 CloseHandle(handle
);
2531 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination
));
2535 xmldecl
= xmldoc_unlink_xmldecl(get_doc(This
));
2536 if (xmlSaveDoc(ctx
, get_doc(This
)) == -1) ret
= S_FALSE
;
2537 xmldoc_link_xmldecl(get_doc(This
), xmldecl
);
2539 /* will release resources through close callback */
2545 static HRESULT WINAPI
domdoc_get_validateOnParse(
2546 IXMLDOMDocument3
*iface
,
2547 VARIANT_BOOL
* isValidating
)
2549 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2550 TRACE("(%p)->(%p: %d)\n", This
, isValidating
, This
->validating
);
2551 *isValidating
= This
->validating
;
2556 static HRESULT WINAPI
domdoc_put_validateOnParse(
2557 IXMLDOMDocument3
*iface
,
2558 VARIANT_BOOL isValidating
)
2560 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2561 TRACE("(%p)->(%d)\n", This
, isValidating
);
2562 This
->validating
= isValidating
;
2567 static HRESULT WINAPI
domdoc_get_resolveExternals(
2568 IXMLDOMDocument3
*iface
,
2569 VARIANT_BOOL
* isResolving
)
2571 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2572 TRACE("(%p)->(%p: %d)\n", This
, isResolving
, This
->resolving
);
2573 *isResolving
= This
->resolving
;
2578 static HRESULT WINAPI
domdoc_put_resolveExternals(
2579 IXMLDOMDocument3
*iface
,
2580 VARIANT_BOOL isResolving
)
2582 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2583 TRACE("(%p)->(%d)\n", This
, isResolving
);
2584 This
->resolving
= isResolving
;
2589 static HRESULT WINAPI
domdoc_get_preserveWhiteSpace(
2590 IXMLDOMDocument3
*iface
,
2591 VARIANT_BOOL
* isPreserving
)
2593 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2594 TRACE("(%p)->(%p: %d)\n", This
, isPreserving
, This
->properties
->preserving
);
2595 *isPreserving
= This
->properties
->preserving
;
2600 static HRESULT WINAPI
domdoc_put_preserveWhiteSpace(
2601 IXMLDOMDocument3
*iface
,
2602 VARIANT_BOOL isPreserving
)
2604 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2605 TRACE("(%p)->(%d)\n", This
, isPreserving
);
2606 This
->properties
->preserving
= isPreserving
;
2611 static HRESULT WINAPI
domdoc_put_onreadystatechange(
2612 IXMLDOMDocument3
*iface
,
2615 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2617 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&event
));
2618 return set_doc_event(This
, EVENTID_READYSTATECHANGE
, &event
);
2622 static HRESULT WINAPI
domdoc_put_onDataAvailable(IXMLDOMDocument3
*iface
, VARIANT sink
)
2624 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2625 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2629 static HRESULT WINAPI
domdoc_put_onTransformNode(IXMLDOMDocument3
*iface
, VARIANT sink
)
2631 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2632 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2636 static HRESULT WINAPI
domdoc_get_namespaces(
2637 IXMLDOMDocument3
* iface
,
2638 IXMLDOMSchemaCollection
** collection
)
2640 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2643 FIXME("(%p)->(%p): semi-stub\n", This
, collection
);
2645 if (!collection
) return E_POINTER
;
2647 if (!This
->namespaces
)
2649 hr
= SchemaCache_create(This
->properties
->version
, (void**)&This
->namespaces
);
2650 if (hr
!= S_OK
) return hr
;
2652 hr
= cache_from_doc_ns(This
->namespaces
, &This
->node
);
2654 release_namespaces(This
);
2657 if (This
->namespaces
)
2658 return IXMLDOMSchemaCollection2_QueryInterface(This
->namespaces
,
2659 &IID_IXMLDOMSchemaCollection
, (void**)collection
);
2664 static HRESULT WINAPI
domdoc_get_schemas(
2665 IXMLDOMDocument3
* iface
,
2668 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2669 IXMLDOMSchemaCollection2
* cur_schema
= This
->properties
->schemaCache
;
2670 HRESULT hr
= S_FALSE
;
2672 TRACE("(%p)->(%p)\n", This
, schema
);
2674 V_VT(schema
) = VT_NULL
;
2675 /* just to reset pointer part, cause that's what application is expected to use */
2676 V_DISPATCH(schema
) = NULL
;
2680 hr
= IXMLDOMSchemaCollection2_QueryInterface(cur_schema
, &IID_IDispatch
, (void**)&V_DISPATCH(schema
));
2682 V_VT(schema
) = VT_DISPATCH
;
2687 static HRESULT WINAPI
domdoc_putref_schemas(
2688 IXMLDOMDocument3
* iface
,
2691 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2692 HRESULT hr
= E_FAIL
;
2693 IXMLDOMSchemaCollection2
* new_schema
= NULL
;
2695 FIXME("(%p)->(%s): semi-stub\n", This
, debugstr_variant(&schema
));
2696 switch(V_VT(&schema
))
2699 if (V_UNKNOWN(&schema
))
2701 hr
= IUnknown_QueryInterface(V_UNKNOWN(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2706 if (V_DISPATCH(&schema
))
2708 hr
= IDispatch_QueryInterface(V_DISPATCH(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2718 WARN("Can't get schema from vt %x\n", V_VT(&schema
));
2723 IXMLDOMSchemaCollection2
* old_schema
= InterlockedExchangePointer((void**)&This
->properties
->schemaCache
, new_schema
);
2724 if(old_schema
) IXMLDOMSchemaCollection2_Release(old_schema
);
2730 static inline BOOL
is_wellformed(xmlDocPtr doc
)
2732 #ifdef HAVE_XMLDOC_PROPERTIES
2733 return doc
->properties
& XML_DOC_WELLFORMED
;
2735 /* Not a full check, but catches the worst violations */
2739 for (child
= doc
->children
; child
!= NULL
; child
= child
->next
)
2741 switch (child
->type
)
2743 case XML_ELEMENT_NODE
:
2748 case XML_CDATA_SECTION_NODE
:
2760 static void LIBXML2_LOG_CALLBACK
validate_error(void* ctx
, char const* msg
, ...)
2764 LIBXML2_CALLBACK_ERR(domdoc_validateNode
, msg
, ap
);
2768 static void LIBXML2_LOG_CALLBACK
validate_warning(void* ctx
, char const* msg
, ...)
2772 LIBXML2_CALLBACK_WARN(domdoc_validateNode
, msg
, ap
);
2776 static HRESULT WINAPI
domdoc_validateNode(
2777 IXMLDOMDocument3
* iface
,
2779 IXMLDOMParseError
** err
)
2781 domdoc
* This
= impl_from_IXMLDOMDocument3(iface
);
2782 LONG state
, err_code
= 0;
2786 TRACE("(%p)->(%p, %p)\n", This
, node
, err
);
2787 IXMLDOMDocument3_get_readyState(iface
, &state
);
2788 if (state
!= READYSTATE_COMPLETE
)
2791 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2798 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2802 if (!get_node_obj(node
)->node
|| get_node_obj(node
)->node
->doc
!= get_doc(This
))
2805 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2809 if (!is_wellformed(get_doc(This
)))
2811 ERR("doc not well-formed\n");
2813 *err
= create_parseError(E_XML_NOTWF
, NULL
, NULL
, NULL
, 0, 0, 0);
2817 /* DTD validation */
2818 if (get_doc(This
)->intSubset
|| get_doc(This
)->extSubset
)
2820 xmlValidCtxtPtr vctx
= xmlNewValidCtxt();
2821 vctx
->error
= validate_error
;
2822 vctx
->warning
= validate_warning
;
2825 if (!((node
== (IXMLDOMNode
*)iface
)?
2826 xmlValidateDocument(vctx
, get_doc(This
)) :
2827 xmlValidateElement(vctx
, get_doc(This
), get_node_obj(node
)->node
)))
2829 /* TODO: get a real error code here */
2830 TRACE("DTD validation failed\n");
2831 err_code
= E_XML_INVALID
;
2834 xmlFreeValidCtxt(vctx
);
2837 /* Schema validation */
2838 if (hr
== S_OK
&& This
->properties
->schemaCache
!= NULL
)
2841 hr
= SchemaCache_validate_tree(This
->properties
->schemaCache
, get_node_obj(node
)->node
);
2845 /* TODO: get a real error code here */
2848 TRACE("schema validation succeeded\n");
2852 ERR("schema validation failed\n");
2853 err_code
= E_XML_INVALID
;
2858 /* not really OK, just didn't find a schema for the ns */
2865 ERR("no DTD or schema found\n");
2866 err_code
= E_XML_NODTD
;
2871 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2876 static HRESULT WINAPI
domdoc_validate(
2877 IXMLDOMDocument3
* iface
,
2878 IXMLDOMParseError
** err
)
2880 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2881 TRACE("(%p)->(%p)\n", This
, err
);
2882 return IXMLDOMDocument3_validateNode(iface
, (IXMLDOMNode
*)iface
, err
);
2885 static HRESULT WINAPI
domdoc_setProperty(
2886 IXMLDOMDocument3
* iface
,
2890 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2892 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(p
), debugstr_variant(&value
));
2894 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
2900 V_VT(&varStr
) = VT_EMPTY
;
2901 if (V_VT(&value
) != VT_BSTR
)
2903 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2905 bstr
= V_BSTR(&varStr
);
2908 bstr
= V_BSTR(&value
);
2911 if (lstrcmpiW(bstr
, PropValueXPathW
) == 0)
2912 This
->properties
->XPath
= TRUE
;
2913 else if (lstrcmpiW(bstr
, PropValueXSLPatternW
) == 0)
2914 This
->properties
->XPath
= FALSE
;
2918 VariantClear(&varStr
);
2921 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
2923 xmlChar
*nsStr
= (xmlChar
*)This
->properties
->selectNsStr
;
2924 struct list
*pNsList
;
2929 V_VT(&varStr
) = VT_EMPTY
;
2930 if (V_VT(&value
) != VT_BSTR
)
2932 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2934 bstr
= V_BSTR(&varStr
);
2937 bstr
= V_BSTR(&value
);
2941 pNsList
= &(This
->properties
->selectNsList
);
2942 clear_selectNsList(pNsList
);
2944 nsStr
= xmlchar_from_wchar(bstr
);
2946 TRACE("property value: \"%s\"\n", debugstr_w(bstr
));
2948 This
->properties
->selectNsStr
= nsStr
;
2949 This
->properties
->selectNsStr_len
= xmlStrlen(nsStr
);
2952 xmlChar
*pTokBegin
, *pTokEnd
, *pTokInner
;
2953 select_ns_entry
* ns_entry
= NULL
;
2954 xmlXPathContextPtr ctx
;
2956 ctx
= xmlXPathNewContext(This
->node
.node
->doc
);
2959 /* skip leading spaces */
2960 while (*pTokBegin
== ' ' || *pTokBegin
== '\n' ||
2961 *pTokBegin
== '\t' || *pTokBegin
== '\r')
2964 for (; *pTokBegin
; pTokBegin
= pTokEnd
)
2967 memset(ns_entry
, 0, sizeof(select_ns_entry
));
2969 ns_entry
= heap_alloc_zero(sizeof(select_ns_entry
));
2971 while (*pTokBegin
== ' ')
2973 pTokEnd
= pTokBegin
;
2974 while (*pTokEnd
!= ' ' && *pTokEnd
!= 0)
2977 /* so it failed to advance which means we've got some trailing spaces */
2978 if (pTokEnd
== pTokBegin
) break;
2980 if (xmlStrncmp(pTokBegin
, (xmlChar
const*)"xmlns", 5) != 0)
2983 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2984 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2989 if (*pTokBegin
== '=')
2991 /*valid for XSLPattern?*/
2992 FIXME("Setting default xmlns not supported - skipping.\n");
2995 else if (*pTokBegin
== ':')
2997 ns_entry
->prefix
= ++pTokBegin
;
2998 for (pTokInner
= pTokBegin
; pTokInner
!= pTokEnd
&& *pTokInner
!= '='; ++pTokInner
)
3001 if (pTokInner
== pTokEnd
)
3004 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3005 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
3009 ns_entry
->prefix_end
= *pTokInner
;
3013 if (pTokEnd
-pTokInner
> 1 &&
3014 ((*pTokInner
== '\'' && *(pTokEnd
-1) == '\'') ||
3015 (*pTokInner
== '"' && *(pTokEnd
-1) == '"')))
3017 ns_entry
->href
= ++pTokInner
;
3018 ns_entry
->href_end
= *(pTokEnd
-1);
3020 list_add_tail(pNsList
, &ns_entry
->entry
);
3021 /*let libxml figure out if they're valid from here ;)*/
3022 if (xmlXPathRegisterNs(ctx
, ns_entry
->prefix
, ns_entry
->href
) != 0)
3031 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3032 debugstr_w(bstr
), debugstr_an((const char*)pTokInner
, pTokEnd
-pTokInner
));
3033 list_add_tail(pNsList
, &ns_entry
->entry
);
3046 heap_free(ns_entry
);
3047 xmlXPathFreeContext(ctx
);
3050 VariantClear(&varStr
);
3053 else if (lstrcmpiW(p
, PropertyProhibitDTDW
) == 0 ||
3054 lstrcmpiW(p
, PropertyNewParserW
) == 0 ||
3055 lstrcmpiW(p
, PropertyResolveExternalsW
) == 0)
3058 FIXME("Ignoring property %s, value %s\n", debugstr_w(p
), debugstr_variant(&value
));
3062 FIXME("Unknown property %s\n", debugstr_w(p
));
3066 static HRESULT WINAPI
domdoc_getProperty(
3067 IXMLDOMDocument3
* iface
,
3071 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3073 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
3076 return E_INVALIDARG
;
3078 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
3080 V_VT(var
) = VT_BSTR
;
3081 V_BSTR(var
) = This
->properties
->XPath
?
3082 SysAllocString(PropValueXPathW
) :
3083 SysAllocString(PropValueXSLPatternW
);
3084 return V_BSTR(var
) ? S_OK
: E_OUTOFMEMORY
;
3086 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3089 BSTR rebuiltStr
, cur
;
3090 const xmlChar
*nsStr
;
3091 struct list
*pNsList
;
3092 select_ns_entry
* pNsEntry
;
3094 V_VT(var
) = VT_BSTR
;
3095 nsStr
= This
->properties
->selectNsStr
;
3096 pNsList
= &This
->properties
->selectNsList
;
3097 lenA
= This
->properties
->selectNsStr_len
;
3098 lenW
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, NULL
, 0);
3099 rebuiltStr
= heap_alloc(lenW
*sizeof(WCHAR
));
3100 MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, rebuiltStr
, lenW
);
3102 /* this is fine because all of the chars that end tokens are ASCII*/
3103 LIST_FOR_EACH_ENTRY(pNsEntry
, pNsList
, select_ns_entry
, entry
)
3105 while (*cur
!= 0) ++cur
;
3106 if (pNsEntry
->prefix_end
)
3108 *cur
= pNsEntry
->prefix_end
;
3109 while (*cur
!= 0) ++cur
;
3112 if (pNsEntry
->href_end
)
3114 *cur
= pNsEntry
->href_end
;
3117 V_BSTR(var
) = SysAllocString(rebuiltStr
);
3118 heap_free(rebuiltStr
);
3122 FIXME("Unknown property %s\n", debugstr_w(p
));
3126 static HRESULT WINAPI
domdoc_importNode(
3127 IXMLDOMDocument3
* iface
,
3130 IXMLDOMNode
** clone
)
3132 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3133 FIXME("(%p)->(%p %d %p): stub\n", This
, node
, deep
, clone
);
3137 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl
=
3139 domdoc_QueryInterface
,
3142 domdoc_GetTypeInfoCount
,
3144 domdoc_GetIDsOfNames
,
3146 domdoc_get_nodeName
,
3147 domdoc_get_nodeValue
,
3148 domdoc_put_nodeValue
,
3149 domdoc_get_nodeType
,
3150 domdoc_get_parentNode
,
3151 domdoc_get_childNodes
,
3152 domdoc_get_firstChild
,
3153 domdoc_get_lastChild
,
3154 domdoc_get_previousSibling
,
3155 domdoc_get_nextSibling
,
3156 domdoc_get_attributes
,
3157 domdoc_insertBefore
,
3158 domdoc_replaceChild
,
3161 domdoc_hasChildNodes
,
3162 domdoc_get_ownerDocument
,
3164 domdoc_get_nodeTypeString
,
3167 domdoc_get_specified
,
3168 domdoc_get_definition
,
3169 domdoc_get_nodeTypedValue
,
3170 domdoc_put_nodeTypedValue
,
3171 domdoc_get_dataType
,
3172 domdoc_put_dataType
,
3174 domdoc_transformNode
,
3176 domdoc_selectSingleNode
,
3178 domdoc_get_namespaceURI
,
3180 domdoc_get_baseName
,
3181 domdoc_transformNodeToObject
,
3183 domdoc_get_implementation
,
3184 domdoc_get_documentElement
,
3185 domdoc_put_documentElement
,
3186 domdoc_createElement
,
3187 domdoc_createDocumentFragment
,
3188 domdoc_createTextNode
,
3189 domdoc_createComment
,
3190 domdoc_createCDATASection
,
3191 domdoc_createProcessingInstruction
,
3192 domdoc_createAttribute
,
3193 domdoc_createEntityReference
,
3194 domdoc_getElementsByTagName
,
3198 domdoc_get_readyState
,
3199 domdoc_get_parseError
,
3206 domdoc_get_validateOnParse
,
3207 domdoc_put_validateOnParse
,
3208 domdoc_get_resolveExternals
,
3209 domdoc_put_resolveExternals
,
3210 domdoc_get_preserveWhiteSpace
,
3211 domdoc_put_preserveWhiteSpace
,
3212 domdoc_put_onreadystatechange
,
3213 domdoc_put_onDataAvailable
,
3214 domdoc_put_onTransformNode
,
3215 domdoc_get_namespaces
,
3217 domdoc_putref_schemas
,
3221 domdoc_validateNode
,
3225 /* IConnectionPointContainer */
3226 static HRESULT WINAPI
ConnectionPointContainer_QueryInterface(IConnectionPointContainer
*iface
,
3227 REFIID riid
, void **ppv
)
3229 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3230 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3233 static ULONG WINAPI
ConnectionPointContainer_AddRef(IConnectionPointContainer
*iface
)
3235 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3236 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3239 static ULONG WINAPI
ConnectionPointContainer_Release(IConnectionPointContainer
*iface
)
3241 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3242 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3245 static HRESULT WINAPI
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer
*iface
,
3246 IEnumConnectionPoints
**ppEnum
)
3248 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3249 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3253 static HRESULT WINAPI
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer
*iface
,
3254 REFIID riid
, IConnectionPoint
**cp
)
3256 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3257 ConnectionPoint
*iter
;
3259 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), cp
);
3263 for(iter
= This
->cp_list
; iter
; iter
= iter
->next
)
3265 if (IsEqualGUID(iter
->iid
, riid
))
3266 *cp
= &iter
->IConnectionPoint_iface
;
3271 IConnectionPoint_AddRef(*cp
);
3275 FIXME("unsupported riid %s\n", debugstr_guid(riid
));
3276 return CONNECT_E_NOCONNECTION
;
3280 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl
=
3282 ConnectionPointContainer_QueryInterface
,
3283 ConnectionPointContainer_AddRef
,
3284 ConnectionPointContainer_Release
,
3285 ConnectionPointContainer_EnumConnectionPoints
,
3286 ConnectionPointContainer_FindConnectionPoint
3289 /* IConnectionPoint */
3290 static HRESULT WINAPI
ConnectionPoint_QueryInterface(IConnectionPoint
*iface
,
3291 REFIID riid
, void **ppv
)
3293 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3295 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
3299 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
3300 IsEqualGUID(&IID_IConnectionPoint
, riid
))
3307 IConnectionPoint_AddRef(iface
);
3311 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
3312 return E_NOINTERFACE
;
3315 static ULONG WINAPI
ConnectionPoint_AddRef(IConnectionPoint
*iface
)
3317 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3318 return IConnectionPointContainer_AddRef(This
->container
);
3321 static ULONG WINAPI
ConnectionPoint_Release(IConnectionPoint
*iface
)
3323 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3324 return IConnectionPointContainer_Release(This
->container
);
3327 static HRESULT WINAPI
ConnectionPoint_GetConnectionInterface(IConnectionPoint
*iface
, IID
*iid
)
3329 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3331 TRACE("(%p)->(%p)\n", This
, iid
);
3333 if (!iid
) return E_POINTER
;
3339 static HRESULT WINAPI
ConnectionPoint_GetConnectionPointContainer(IConnectionPoint
*iface
,
3340 IConnectionPointContainer
**container
)
3342 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3344 TRACE("(%p)->(%p)\n", This
, container
);
3346 if (!container
) return E_POINTER
;
3348 *container
= This
->container
;
3349 IConnectionPointContainer_AddRef(*container
);
3353 static HRESULT WINAPI
ConnectionPoint_Advise(IConnectionPoint
*iface
, IUnknown
*unk_sink
,
3356 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3361 TRACE("(%p)->(%p %p)\n", This
, unk_sink
, cookie
);
3363 hr
= IUnknown_QueryInterface(unk_sink
, This
->iid
, (void**)&sink
);
3364 if(FAILED(hr
) && !IsEqualGUID(&IID_IPropertyNotifySink
, This
->iid
))
3365 hr
= IUnknown_QueryInterface(unk_sink
, &IID_IDispatch
, (void**)&sink
);
3367 return CONNECT_E_CANNOTCONNECT
;
3371 for (i
= 0; i
< This
->sinks_size
; i
++)
3372 if (!This
->sinks
[i
].unk
)
3375 if (i
== This
->sinks_size
)
3376 This
->sinks
= heap_realloc(This
->sinks
,(++This
->sinks_size
)*sizeof(*This
->sinks
));
3380 This
->sinks
= heap_alloc(sizeof(*This
->sinks
));
3381 This
->sinks_size
= 1;
3385 This
->sinks
[i
].unk
= sink
;
3392 static HRESULT WINAPI
ConnectionPoint_Unadvise(IConnectionPoint
*iface
, DWORD cookie
)
3394 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3396 TRACE("(%p)->(%d)\n", This
, cookie
);
3398 if (cookie
== 0 || cookie
> This
->sinks_size
|| !This
->sinks
[cookie
-1].unk
)
3399 return CONNECT_E_NOCONNECTION
;
3401 IUnknown_Release(This
->sinks
[cookie
-1].unk
);
3402 This
->sinks
[cookie
-1].unk
= NULL
;
3407 static HRESULT WINAPI
ConnectionPoint_EnumConnections(IConnectionPoint
*iface
,
3408 IEnumConnections
**ppEnum
)
3410 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3411 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3415 static const IConnectionPointVtbl ConnectionPointVtbl
=
3417 ConnectionPoint_QueryInterface
,
3418 ConnectionPoint_AddRef
,
3419 ConnectionPoint_Release
,
3420 ConnectionPoint_GetConnectionInterface
,
3421 ConnectionPoint_GetConnectionPointContainer
,
3422 ConnectionPoint_Advise
,
3423 ConnectionPoint_Unadvise
,
3424 ConnectionPoint_EnumConnections
3427 static void ConnectionPoint_Init(ConnectionPoint
*cp
, struct domdoc
*doc
, REFIID riid
)
3429 cp
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointVtbl
;
3435 cp
->next
= doc
->cp_list
;
3438 cp
->container
= &doc
->IConnectionPointContainer_iface
;
3441 /* domdoc implementation of IObjectWithSite */
3442 static HRESULT WINAPI
3443 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
3445 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3446 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObject
);
3449 static ULONG WINAPI
domdoc_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
3451 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3452 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3455 static ULONG WINAPI
domdoc_ObjectWithSite_Release( IObjectWithSite
* iface
)
3457 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3458 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3461 static HRESULT WINAPI
domdoc_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
3463 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3465 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
3470 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
3473 static HRESULT WINAPI
domdoc_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
3475 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3477 TRACE("(%p)->(%p)\n", iface
, punk
);
3483 IUnknown_Release( This
->site
);
3490 IUnknown_AddRef( punk
);
3493 IUnknown_Release( This
->site
);
3500 static const IObjectWithSiteVtbl domdocObjectSite
=
3502 domdoc_ObjectWithSite_QueryInterface
,
3503 domdoc_ObjectWithSite_AddRef
,
3504 domdoc_ObjectWithSite_Release
,
3505 domdoc_ObjectWithSite_SetSite
,
3506 domdoc_ObjectWithSite_GetSite
3509 static HRESULT WINAPI
domdoc_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
3511 domdoc
*This
= impl_from_IObjectSafety(iface
);
3512 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3515 static ULONG WINAPI
domdoc_Safety_AddRef(IObjectSafety
*iface
)
3517 domdoc
*This
= impl_from_IObjectSafety(iface
);
3518 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3521 static ULONG WINAPI
domdoc_Safety_Release(IObjectSafety
*iface
)
3523 domdoc
*This
= impl_from_IObjectSafety(iface
);
3524 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3527 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3529 static HRESULT WINAPI
domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3530 DWORD
*supported
, DWORD
*enabled
)
3532 domdoc
*This
= impl_from_IObjectSafety(iface
);
3534 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
3536 if(!supported
|| !enabled
) return E_POINTER
;
3538 *supported
= SAFETY_SUPPORTED_OPTIONS
;
3539 *enabled
= This
->safeopt
;
3544 static HRESULT WINAPI
domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3545 DWORD mask
, DWORD enabled
)
3547 domdoc
*This
= impl_from_IObjectSafety(iface
);
3548 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
3550 if ((mask
& ~SAFETY_SUPPORTED_OPTIONS
) != 0)
3553 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
3558 #undef SAFETY_SUPPORTED_OPTIONS
3560 static const IObjectSafetyVtbl domdocObjectSafetyVtbl
= {
3561 domdoc_Safety_QueryInterface
,
3562 domdoc_Safety_AddRef
,
3563 domdoc_Safety_Release
,
3564 domdoc_Safety_GetInterfaceSafetyOptions
,
3565 domdoc_Safety_SetInterfaceSafetyOptions
3568 static const tid_t domdoc_iface_tids
[] = {
3569 IXMLDOMDocument3_tid
,
3573 static dispex_static_data_t domdoc_dispex
= {
3575 IXMLDOMDocument3_tid
,
3580 HRESULT
get_domdoc_from_xmldoc(xmlDocPtr xmldoc
, IXMLDOMDocument3
**document
)
3584 doc
= heap_alloc( sizeof (*doc
) );
3586 return E_OUTOFMEMORY
;
3588 doc
->IXMLDOMDocument3_iface
.lpVtbl
= &XMLDOMDocument3Vtbl
;
3589 doc
->IPersistStreamInit_iface
.lpVtbl
= &xmldoc_IPersistStreamInit_VTable
;
3590 doc
->IObjectWithSite_iface
.lpVtbl
= &domdocObjectSite
;
3591 doc
->IObjectSafety_iface
.lpVtbl
= &domdocObjectSafetyVtbl
;
3592 doc
->IConnectionPointContainer_iface
.lpVtbl
= &ConnectionPointContainerVtbl
;
3594 doc
->async
= VARIANT_TRUE
;
3595 doc
->validating
= 0;
3597 doc
->properties
= properties_from_xmlDocPtr(xmldoc
);
3601 doc
->cp_list
= NULL
;
3602 doc
->namespaces
= NULL
;
3603 memset(doc
->events
, 0, sizeof(doc
->events
));
3605 /* events connection points */
3606 ConnectionPoint_Init(&doc
->cp_dispatch
, doc
, &IID_IDispatch
);
3607 ConnectionPoint_Init(&doc
->cp_propnotif
, doc
, &IID_IPropertyNotifySink
);
3608 ConnectionPoint_Init(&doc
->cp_domdocevents
, doc
, &DIID_XMLDOMDocumentEvents
);
3610 init_xmlnode(&doc
->node
, (xmlNodePtr
)xmldoc
, (IXMLDOMNode
*)&doc
->IXMLDOMDocument3_iface
,
3613 *document
= &doc
->IXMLDOMDocument3_iface
;
3615 TRACE("returning iface %p\n", *document
);
3619 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3624 TRACE("(%d, %p)\n", version
, ppObj
);
3626 xmldoc
= xmlNewDoc(NULL
);
3628 return E_OUTOFMEMORY
;
3630 xmldoc_init(xmldoc
, version
);
3632 hr
= get_domdoc_from_xmldoc(xmldoc
, (IXMLDOMDocument3
**)ppObj
);
3635 free_properties(properties_from_xmlDocPtr(xmldoc
));
3636 heap_free(xmldoc
->_private
);
3644 IUnknown
* create_domdoc( xmlNodePtr document
)
3646 IUnknown
*obj
= NULL
;
3649 TRACE("(%p)\n", document
);
3651 hr
= get_domdoc_from_xmldoc((xmlDocPtr
)document
, (IXMLDOMDocument3
**)&obj
);
3660 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3662 MESSAGE("This program tried to use a DOMDocument object, but\n"
3663 "libxml2 support was not present at compile time.\n");