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
26 #include <libxml/parser.h>
27 #include <libxml/xmlerror.h>
28 #include <libxml/xpathInternals.h>
29 # include <libxml/xmlsave.h>
30 #include <libxml/SAX2.h>
31 #include <libxml/parserInternals.h>
46 #include "wine/debug.h"
48 #include "msxml_private.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
52 /* not defined in older versions */
53 #define XML_SAVE_FORMAT 1
54 #define XML_SAVE_NO_DECL 2
55 #define XML_SAVE_NO_EMPTY 4
56 #define XML_SAVE_NO_XHTML 8
57 #define XML_SAVE_XHTML 16
58 #define XML_SAVE_AS_XML 32
59 #define XML_SAVE_AS_HTML 64
61 static const WCHAR PropertySelectionLanguageW
[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
62 static const WCHAR PropertySelectionNamespacesW
[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
63 static const WCHAR PropertyProhibitDTDW
[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
64 static const WCHAR PropertyNewParserW
[] = {'N','e','w','P','a','r','s','e','r',0};
65 static const WCHAR PropValueXPathW
[] = {'X','P','a','t','h',0};
66 static const WCHAR PropValueXSLPatternW
[] = {'X','S','L','P','a','t','t','e','r','n',0};
67 static const WCHAR PropertyResolveExternalsW
[] = {'R','e','s','o','l','v','e','E','x','t','e','r','n','a','l','s',0};
68 static const WCHAR PropertyAllowXsltScriptW
[] = {'A','l','l','o','w','X','s','l','t','S','c','r','i','p','t',0};
69 static const WCHAR PropertyAllowDocumentFunctionW
[] = {'A','l','l','o','w','D','o','c','u','m','e','n','t','F','u','n','c','t','i','o','n',0};
70 static const WCHAR PropertyNormalizeAttributeValuesW
[] = {'N','o','r','m','a','l','i','z','e','A','t','t','r','i','b','u','t','e','V','a','l','u','e','s',0};
71 static const WCHAR PropertyValidateOnParse
[] = L
"ValidateOnParse";
73 /* Anything that passes the test_get_ownerDocument()
74 * tests can go here (data shared between all instances).
75 * We need to preserve this when reloading a document,
76 * and also need access to it from the libxml backend. */
79 MSXML_VERSION version
;
80 VARIANT_BOOL preserving
;
81 VARIANT_BOOL validating
;
82 IXMLDOMSchemaCollection2
* schemaCache
;
83 struct list selectNsList
;
84 xmlChar
const* selectNsStr
;
90 typedef struct ConnectionPoint ConnectionPoint
;
91 typedef struct domdoc domdoc
;
93 struct ConnectionPoint
95 IConnectionPoint IConnectionPoint_iface
;
98 ConnectionPoint
*next
;
99 IConnectionPointContainer
*container
;
106 IPropertyNotifySink
*propnotif
;
112 EVENTID_READYSTATECHANGE
= 0,
113 EVENTID_DATAAVAILABLE
,
114 EVENTID_TRANSFORMNODE
,
121 IXMLDOMDocument3 IXMLDOMDocument3_iface
;
122 IPersistStreamInit IPersistStreamInit_iface
;
123 IObjectWithSite IObjectWithSite_iface
;
124 IObjectSafety IObjectSafety_iface
;
125 IConnectionPointContainer IConnectionPointContainer_iface
;
128 VARIANT_BOOL resolving
;
129 domdoc_properties
* properties
;
132 /* IObjectWithSite */
139 /* connection list */
140 ConnectionPoint
*cp_list
;
141 ConnectionPoint cp_domdocevents
;
142 ConnectionPoint cp_propnotif
;
143 ConnectionPoint cp_dispatch
;
146 IDispatch
*events
[EVENTID_LAST
];
148 IXMLDOMSchemaCollection2
*namespaces
;
151 static HRESULT
set_doc_event(domdoc
*doc
, eventid_t eid
, const VARIANT
*v
)
159 IUnknown_QueryInterface(V_UNKNOWN(v
), &IID_IDispatch
, (void**)&disp
);
164 disp
= V_DISPATCH(v
);
165 if (disp
) IDispatch_AddRef(disp
);
168 return DISP_E_TYPEMISMATCH
;
171 if (doc
->events
[eid
]) IDispatch_Release(doc
->events
[eid
]);
172 doc
->events
[eid
] = disp
;
177 static inline ConnectionPoint
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
179 return CONTAINING_RECORD(iface
, ConnectionPoint
, IConnectionPoint_iface
);
183 In native windows, the whole lifetime management of XMLDOMNodes is
184 managed automatically using reference counts. Wine emulates that by
185 maintaining a reference count to the document that is increased for
186 each IXMLDOMNode pointer passed out for this document. If all these
187 pointers are gone, the document is unreachable and gets freed, that
188 is, all nodes in the tree of the document get freed.
190 You are able to create nodes that are associated to a document (in
191 fact, in msxml's XMLDOM model, all nodes are associated to a document),
192 but not in the tree of that document, for example using the createFoo
193 functions from IXMLDOMDocument. These nodes do not get cleaned up
194 by libxml, so we have to do it ourselves.
196 To catch these nodes, a list of "orphan nodes" is introduced.
197 It contains pointers to all roots of node trees that are
198 associated with the document without being part of the document
199 tree. All nodes with parent==NULL (except for the document root nodes)
200 should be in the orphan node list of their document. All orphan nodes
201 get freed together with the document itself.
204 typedef struct _xmldoc_priv
{
207 domdoc_properties
* properties
;
210 typedef struct _orphan_entry
{
215 typedef struct _select_ns_entry
{
217 xmlChar
const* prefix
;
223 static inline xmldoc_priv
* priv_from_xmlDocPtr(const xmlDocPtr doc
)
225 return doc
->_private
;
228 static inline domdoc_properties
* properties_from_xmlDocPtr(xmlDocPtr doc
)
230 return priv_from_xmlDocPtr(doc
)->properties
;
233 BOOL
is_xpathmode(const xmlDocPtr doc
)
235 return properties_from_xmlDocPtr(doc
)->XPath
;
238 void set_xpathmode(xmlDocPtr doc
, BOOL xpath
)
240 properties_from_xmlDocPtr(doc
)->XPath
= xpath
;
243 int registerNamespaces(xmlXPathContextPtr ctxt
)
246 const select_ns_entry
* ns
= NULL
;
247 const struct list
* pNsList
= &properties_from_xmlDocPtr(ctxt
->doc
)->selectNsList
;
249 TRACE("(%p)\n", ctxt
);
251 LIST_FOR_EACH_ENTRY( ns
, pNsList
, select_ns_entry
, entry
)
253 xmlXPathRegisterNs(ctxt
, ns
->prefix
, ns
->href
);
260 static inline void clear_selectNsList(struct list
* pNsList
)
262 select_ns_entry
*ns
, *ns2
;
263 LIST_FOR_EACH_ENTRY_SAFE( ns
, ns2
, pNsList
, select_ns_entry
, entry
)
270 static xmldoc_priv
* create_priv(void)
273 priv
= heap_alloc( sizeof (*priv
) );
278 list_init( &priv
->orphans
);
279 priv
->properties
= NULL
;
285 static domdoc_properties
*create_properties(MSXML_VERSION version
)
287 domdoc_properties
*properties
= heap_alloc(sizeof(domdoc_properties
));
289 properties
->refs
= 1;
290 list_init(&properties
->selectNsList
);
291 properties
->preserving
= VARIANT_FALSE
;
292 properties
->validating
= VARIANT_TRUE
;
293 properties
->schemaCache
= NULL
;
294 properties
->selectNsStr
= heap_alloc_zero(sizeof(xmlChar
));
295 properties
->selectNsStr_len
= 0;
297 /* properties that are dependent on object versions */
298 properties
->version
= version
;
299 properties
->XPath
= (version
== MSXML4
|| version
== MSXML6
);
302 properties
->uri
= NULL
;
307 static domdoc_properties
* copy_properties(domdoc_properties
const* properties
)
309 domdoc_properties
* pcopy
= heap_alloc(sizeof(domdoc_properties
));
310 select_ns_entry
const* ns
= NULL
;
311 select_ns_entry
* new_ns
= NULL
;
312 int len
= (properties
->selectNsStr_len
+1)*sizeof(xmlChar
);
318 pcopy
->version
= properties
->version
;
319 pcopy
->preserving
= properties
->preserving
;
320 pcopy
->validating
= properties
->validating
;
321 pcopy
->schemaCache
= properties
->schemaCache
;
322 if (pcopy
->schemaCache
)
323 IXMLDOMSchemaCollection2_AddRef(pcopy
->schemaCache
);
324 pcopy
->XPath
= properties
->XPath
;
325 pcopy
->selectNsStr_len
= properties
->selectNsStr_len
;
326 list_init( &pcopy
->selectNsList
);
327 pcopy
->selectNsStr
= heap_alloc(len
);
328 memcpy((xmlChar
*)pcopy
->selectNsStr
, properties
->selectNsStr
, len
);
329 offset
= pcopy
->selectNsStr
- properties
->selectNsStr
;
331 LIST_FOR_EACH_ENTRY( ns
, (&properties
->selectNsList
), select_ns_entry
, entry
)
333 new_ns
= heap_alloc(sizeof(select_ns_entry
));
334 memcpy(new_ns
, ns
, sizeof(select_ns_entry
));
335 new_ns
->href
+= offset
;
336 new_ns
->prefix
+= offset
;
337 list_add_tail(&pcopy
->selectNsList
, &new_ns
->entry
);
340 pcopy
->uri
= properties
->uri
;
342 IUri_AddRef(pcopy
->uri
);
348 static domdoc_properties
* properties_add_ref(domdoc_properties
*properties
)
352 if (!properties
) return NULL
;
354 ref
= InterlockedIncrement(&properties
->refs
);
355 TRACE("%p, %ld.\n", properties
, ref
);
359 static void properties_release(domdoc_properties
*properties
)
363 if (!properties
) return;
365 ref
= InterlockedDecrement(&properties
->refs
);
367 TRACE("%p, %ld.\n", properties
, ref
);
370 WARN("negative refcount, expect troubles\n");
374 if (properties
->schemaCache
)
375 IXMLDOMSchemaCollection2_Release(properties
->schemaCache
);
376 clear_selectNsList(&properties
->selectNsList
);
377 heap_free((xmlChar
*)properties
->selectNsStr
);
379 IUri_Release(properties
->uri
);
380 heap_free(properties
);
384 static void release_namespaces(domdoc
*This
)
386 if (This
->namespaces
)
388 IXMLDOMSchemaCollection2_Release(This
->namespaces
);
389 This
->namespaces
= NULL
;
393 /* links a "<?xml" node as a first child */
394 void xmldoc_link_xmldecl(xmlDocPtr doc
, xmlNodePtr node
)
397 if (doc
->standalone
!= -1) xmlAddPrevSibling( doc
->children
, node
);
400 /* unlinks a first "<?xml" child if it was created */
401 xmlNodePtr
xmldoc_unlink_xmldecl(xmlDocPtr doc
)
403 static const xmlChar xmlA
[] = "xml";
404 xmlNodePtr node
, first_child
;
408 /* xml declaration node could be created automatically after parsing or added
410 first_child
= doc
->children
;
411 if (first_child
&& first_child
->type
== XML_PI_NODE
&& xmlStrEqual(first_child
->name
, xmlA
))
414 xmlUnlinkNode( node
);
422 MSXML_VERSION
xmldoc_version(xmlDocPtr doc
)
424 return properties_from_xmlDocPtr(doc
)->version
;
427 BOOL
is_preserving_whitespace(xmlNodePtr node
)
429 domdoc_properties
* properties
= NULL
;
430 /* during parsing the xmlDoc._private stuff is not there */
431 if (priv_from_xmlDocPtr(node
->doc
))
432 properties
= properties_from_xmlDocPtr(node
->doc
);
433 return ((properties
&& properties
->preserving
== VARIANT_TRUE
) ||
434 xmlNodeGetSpacePreserve(node
) == 1);
437 static inline BOOL
strn_isspace(xmlChar
const* str
, int len
)
439 for (; str
&& len
> 0 && *str
; ++str
, --len
)
446 static void sax_characters(void *ctx
, const xmlChar
*ch
, int len
)
448 xmlParserCtxtPtr ctxt
;
451 ctxt
= (xmlParserCtxtPtr
) ctx
;
452 This
= (const domdoc
*) ctxt
->_private
;
456 xmlChar cur
= *(ctxt
->input
->cur
);
458 /* Characters are reported with multiple calls, for example each charref is reported with a separate
459 call and then parser appends it to a single text node or creates a new node if not created.
460 It's not possible to tell if it's ignorable data or not just looking at data itself cause it could be
461 space chars that separate charrefs or similar case. We only need to skip leading and trailing spaces,
462 or whole node if it has nothing but space chars, so to detect leading space node->last is checked that
463 contains text node pointer if already created, trailing spaces are detected directly looking at parser input
464 for next '<' opening bracket - similar logic is used by libxml2 itself. Basically 'cur' == '<' means the last
465 chunk of char data, in case it's not the last chunk we check for previously added node type and if it's not
466 a text node it's safe to ignore.
468 Note that during domdoc_loadXML() the xmlDocPtr->_private data is not available. */
470 if (!This
->properties
->preserving
&&
471 !is_preserving_whitespace(ctxt
->node
) &&
472 strn_isspace(ch
, len
) &&
473 (!ctxt
->node
->last
||
474 ((ctxt
->node
->last
&& (cur
== '<' || ctxt
->node
->last
->type
!= XML_TEXT_NODE
))
477 /* Keep information about ignorable whitespace text node in previous or parent node */
478 if (ctxt
->node
->last
)
479 *(DWORD
*)&ctxt
->node
->last
->_private
|= NODE_PRIV_TRAILING_IGNORABLE_WS
;
480 else if (ctxt
->node
->type
!= XML_DOCUMENT_NODE
)
481 *(DWORD
*)&ctxt
->node
->_private
|= NODE_PRIV_CHILD_IGNORABLE_WS
;
486 xmlSAX2Characters(ctxt
, ch
, len
);
489 static void LIBXML2_LOG_CALLBACK
sax_error(void* ctx
, char const* msg
, ...)
493 LIBXML2_CALLBACK_ERR(doparse
, msg
, ap
);
497 static void LIBXML2_LOG_CALLBACK
sax_warning(void* ctx
, char const* msg
, ...)
501 LIBXML2_CALLBACK_WARN(doparse
, msg
, ap
);
505 static void sax_serror(void* ctx
, xmlErrorPtr err
)
507 LIBXML2_CALLBACK_SERROR(doparse
, err
);
510 static xmlDocPtr
doparse(domdoc
* This
, char const* ptr
, int len
, xmlCharEncoding encoding
)
512 xmlDocPtr doc
= NULL
;
513 xmlParserCtxtPtr pctx
;
514 static xmlSAXHandler sax_handler
= {
515 xmlSAX2InternalSubset
, /* internalSubset */
516 xmlSAX2IsStandalone
, /* isStandalone */
517 xmlSAX2HasInternalSubset
, /* hasInternalSubset */
518 xmlSAX2HasExternalSubset
, /* hasExternalSubset */
519 xmlSAX2ResolveEntity
, /* resolveEntity */
520 xmlSAX2GetEntity
, /* getEntity */
521 xmlSAX2EntityDecl
, /* entityDecl */
522 xmlSAX2NotationDecl
, /* notationDecl */
523 xmlSAX2AttributeDecl
, /* attributeDecl */
524 xmlSAX2ElementDecl
, /* elementDecl */
525 xmlSAX2UnparsedEntityDecl
, /* unparsedEntityDecl */
526 xmlSAX2SetDocumentLocator
, /* setDocumentLocator */
527 xmlSAX2StartDocument
, /* startDocument */
528 xmlSAX2EndDocument
, /* endDocument */
529 xmlSAX2StartElement
, /* startElement */
530 xmlSAX2EndElement
, /* endElement */
531 xmlSAX2Reference
, /* reference */
532 sax_characters
, /* characters */
533 sax_characters
, /* ignorableWhitespace */
534 xmlSAX2ProcessingInstruction
, /* processingInstruction */
535 xmlSAX2Comment
, /* comment */
536 sax_warning
, /* warning */
537 sax_error
, /* error */
538 sax_error
, /* fatalError */
539 xmlSAX2GetParameterEntity
, /* getParameterEntity */
540 xmlSAX2CDataBlock
, /* cdataBlock */
541 xmlSAX2ExternalSubset
, /* externalSubset */
544 xmlSAX2StartElementNs
, /* startElementNs */
545 xmlSAX2EndElementNs
, /* endElementNs */
546 sax_serror
/* serror */
549 pctx
= xmlCreateMemoryParserCtxt(ptr
, len
);
552 ERR("Failed to create parser context\n");
556 if (pctx
->sax
) xmlFree(pctx
->sax
);
557 pctx
->sax
= &sax_handler
;
558 pctx
->_private
= This
;
561 if (encoding
!= XML_CHAR_ENCODING_NONE
)
562 xmlSwitchEncoding(pctx
, encoding
);
564 xmlParseDocument(pctx
);
566 if (pctx
->wellFormed
)
572 xmlFreeDoc(pctx
->myDoc
);
576 xmlFreeParserCtxt(pctx
);
578 /* TODO: put this in one of the SAX callbacks */
579 /* create first child as a <?xml...?> */
580 if (doc
&& doc
->standalone
!= -1)
584 xmlChar
*xmlbuff
= (xmlChar
*)buff
;
586 node
= xmlNewDocPI( doc
, (xmlChar
*)"xml", NULL
);
588 /* version attribute can't be omitted */
589 sprintf(buff
, "version=\"%s\"", doc
->version
? (char*)doc
->version
: "1.0");
590 xmlNodeAddContent( node
, xmlbuff
);
594 sprintf(buff
, " encoding=\"%s\"", doc
->encoding
);
595 xmlNodeAddContent( node
, xmlbuff
);
598 if (doc
->standalone
!= -2)
600 sprintf(buff
, " standalone=\"%s\"", doc
->standalone
== 0 ? "no" : "yes");
601 xmlNodeAddContent( node
, xmlbuff
);
604 xmldoc_link_xmldecl( doc
, node
);
610 void xmldoc_init(xmlDocPtr doc
, MSXML_VERSION version
)
612 doc
->_private
= create_priv();
613 priv_from_xmlDocPtr(doc
)->properties
= create_properties(version
);
616 LONG
xmldoc_add_refs(xmlDocPtr doc
, LONG refs
)
618 LONG ref
= InterlockedExchangeAdd(&priv_from_xmlDocPtr(doc
)->refs
, refs
) + refs
;
619 TRACE("%p, refcount %ld.\n", doc
, ref
);
623 LONG
xmldoc_add_ref(xmlDocPtr doc
)
625 return xmldoc_add_refs(doc
, 1);
628 LONG
xmldoc_release_refs(xmlDocPtr doc
, LONG refs
)
630 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
631 LONG ref
= InterlockedExchangeAdd(&priv
->refs
, -refs
) - refs
;
633 TRACE("%p, refcount %ld.\n", doc
, ref
);
636 WARN("negative refcount, expect troubles\n");
640 orphan_entry
*orphan
, *orphan2
;
641 TRACE("freeing docptr %p\n", doc
);
643 LIST_FOR_EACH_ENTRY_SAFE( orphan
, orphan2
, &priv
->orphans
, orphan_entry
, entry
)
645 xmlFreeNode( orphan
->node
);
648 properties_release(priv
->properties
);
649 heap_free(doc
->_private
);
657 LONG
xmldoc_release(xmlDocPtr doc
)
659 return xmldoc_release_refs(doc
, 1);
662 HRESULT
xmldoc_add_orphan(xmlDocPtr doc
, xmlNodePtr node
)
664 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
667 entry
= heap_alloc( sizeof (*entry
) );
669 return E_OUTOFMEMORY
;
672 list_add_head( &priv
->orphans
, &entry
->entry
);
676 HRESULT
xmldoc_remove_orphan(xmlDocPtr doc
, xmlNodePtr node
)
678 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
679 orphan_entry
*entry
, *entry2
;
681 LIST_FOR_EACH_ENTRY_SAFE( entry
, entry2
, &priv
->orphans
, orphan_entry
, entry
)
683 if( entry
->node
== node
)
685 list_remove( &entry
->entry
);
694 static inline xmlDocPtr
get_doc( domdoc
*This
)
696 return This
->node
.node
->doc
;
699 static HRESULT
attach_xmldoc(domdoc
*This
, xmlDocPtr xml
)
701 release_namespaces(This
);
705 properties_release(properties_from_xmlDocPtr(get_doc(This
)));
706 priv_from_xmlDocPtr(get_doc(This
))->properties
= NULL
;
707 if (xmldoc_release(get_doc(This
)) != 0)
709 /* The xmlDocPtr object can no longer use the properties of this
710 * domdoc object. So give it its own copy.
712 priv_from_xmlDocPtr(get_doc(This
))->properties
=
713 copy_properties(This
->properties
);
717 This
->node
.node
= (xmlNodePtr
) xml
;
721 xmldoc_add_ref(get_doc(This
));
722 /* Only attach new xmlDocPtr objects, i.e. ones for which properties
725 priv_from_xmlDocPtr(get_doc(This
))->properties
= properties_add_ref(This
->properties
);
731 static inline domdoc
*impl_from_IXMLDOMDocument3( IXMLDOMDocument3
*iface
)
733 return CONTAINING_RECORD(iface
, domdoc
, IXMLDOMDocument3_iface
);
736 static inline domdoc
*impl_from_IPersistStreamInit(IPersistStreamInit
*iface
)
738 return CONTAINING_RECORD(iface
, domdoc
, IPersistStreamInit_iface
);
741 static inline domdoc
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
743 return CONTAINING_RECORD(iface
, domdoc
, IObjectWithSite_iface
);
746 static inline domdoc
*impl_from_IObjectSafety(IObjectSafety
*iface
)
748 return CONTAINING_RECORD(iface
, domdoc
, IObjectSafety_iface
);
751 static inline domdoc
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
753 return CONTAINING_RECORD(iface
, domdoc
, IConnectionPointContainer_iface
);
756 /************************************************************************
757 * domdoc implementation of IPersistStream.
759 static HRESULT WINAPI
PersistStreamInit_QueryInterface(
760 IPersistStreamInit
*iface
, REFIID riid
, void **ppvObj
)
762 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
763 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObj
);
766 static ULONG WINAPI
PersistStreamInit_AddRef(
767 IPersistStreamInit
*iface
)
769 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
770 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
773 static ULONG WINAPI
PersistStreamInit_Release(
774 IPersistStreamInit
*iface
)
776 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
777 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
780 static HRESULT WINAPI
PersistStreamInit_GetClassID(
781 IPersistStreamInit
*iface
, CLSID
*classid
)
783 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
784 TRACE("(%p)->(%p)\n", This
, classid
);
789 *classid
= *DOMDocument_version(This
->properties
->version
);
794 static HRESULT WINAPI
PersistStreamInit_IsDirty(
795 IPersistStreamInit
*iface
)
797 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
798 FIXME("(%p): stub!\n", This
);
802 static HRESULT
domdoc_load_from_stream(domdoc
*doc
, ISequentialStream
*stream
)
804 DWORD read
, written
, len
;
805 xmlDocPtr xmldoc
= NULL
;
813 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &hstream
);
819 ISequentialStream_Read(stream
, buf
, sizeof(buf
), &read
);
820 hr
= IStream_Write(hstream
, buf
, read
, &written
);
821 } while(SUCCEEDED(hr
) && written
!= 0 && read
!= 0);
825 ERR("failed to copy stream, hr %#lx.\n", hr
);
826 IStream_Release(hstream
);
830 hr
= GetHGlobalFromStream(hstream
, &hglobal
);
833 IStream_Release(hstream
);
837 len
= GlobalSize(hglobal
);
838 ptr
= GlobalLock(hglobal
);
840 xmldoc
= doparse(doc
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
841 GlobalUnlock(hglobal
);
842 IStream_Release(hstream
);
846 ERR("Failed to parse xml\n");
850 xmldoc
->_private
= create_priv();
852 return attach_xmldoc(doc
, xmldoc
);
855 static HRESULT WINAPI
PersistStreamInit_Load(IPersistStreamInit
*iface
, IStream
*stream
)
857 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
859 TRACE("(%p)->(%p)\n", This
, stream
);
864 return This
->error
= domdoc_load_from_stream(This
, (ISequentialStream
*)stream
);
867 static HRESULT WINAPI
PersistStreamInit_Save(
868 IPersistStreamInit
*iface
, IStream
*stream
, BOOL clr_dirty
)
870 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
874 TRACE("(%p)->(%p %d)\n", This
, stream
, clr_dirty
);
876 hr
= IXMLDOMDocument3_get_xml(&This
->IXMLDOMDocument3_iface
, &xmlString
);
879 DWORD len
= SysStringLen(xmlString
) * sizeof(WCHAR
);
881 hr
= IStream_Write( stream
, xmlString
, len
, NULL
);
882 SysFreeString(xmlString
);
885 TRACE("hr %#lx.\n", hr
);
890 static HRESULT WINAPI
PersistStreamInit_GetSizeMax(
891 IPersistStreamInit
*iface
, ULARGE_INTEGER
*pcbSize
)
893 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
894 TRACE("(%p)->(%p)\n", This
, pcbSize
);
898 static HRESULT WINAPI
PersistStreamInit_InitNew(
899 IPersistStreamInit
*iface
)
901 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
902 TRACE("(%p)\n", This
);
906 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable
=
908 PersistStreamInit_QueryInterface
,
909 PersistStreamInit_AddRef
,
910 PersistStreamInit_Release
,
911 PersistStreamInit_GetClassID
,
912 PersistStreamInit_IsDirty
,
913 PersistStreamInit_Load
,
914 PersistStreamInit_Save
,
915 PersistStreamInit_GetSizeMax
,
916 PersistStreamInit_InitNew
919 /* IXMLDOMDocument3 interface */
921 static const tid_t domdoc_se_tids
[] = {
924 IXMLDOMDocument2_tid
,
925 IXMLDOMDocument3_tid
,
929 static HRESULT WINAPI
domdoc_QueryInterface( IXMLDOMDocument3
*iface
, REFIID riid
, void** ppvObject
)
931 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
933 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( riid
), ppvObject
);
937 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
938 IsEqualGUID( riid
, &IID_IDispatch
) ||
939 IsEqualGUID( riid
, &IID_IXMLDOMNode
) ||
940 IsEqualGUID( riid
, &IID_IXMLDOMDocument
) ||
941 IsEqualGUID( riid
, &IID_IXMLDOMDocument2
)||
942 IsEqualGUID( riid
, &IID_IXMLDOMDocument3
))
946 else if (IsEqualGUID(&IID_IPersistStream
, riid
) ||
947 IsEqualGUID(&IID_IPersistStreamInit
, riid
))
949 *ppvObject
= &This
->IPersistStreamInit_iface
;
951 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
953 *ppvObject
= &This
->IObjectWithSite_iface
;
955 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
957 *ppvObject
= &This
->IObjectSafety_iface
;
959 else if( IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
961 return node_create_supporterrorinfo(domdoc_se_tids
, ppvObject
);
963 else if(node_query_interface(&This
->node
, riid
, ppvObject
))
965 return *ppvObject
? S_OK
: E_NOINTERFACE
;
967 else if (IsEqualGUID( riid
, &IID_IConnectionPointContainer
))
969 *ppvObject
= &This
->IConnectionPointContainer_iface
;
973 TRACE("interface %s not implemented\n", debugstr_guid(riid
));
974 return E_NOINTERFACE
;
977 IUnknown_AddRef((IUnknown
*)*ppvObject
);
982 static ULONG WINAPI
domdoc_AddRef( IXMLDOMDocument3
*iface
)
984 domdoc
*doc
= impl_from_IXMLDOMDocument3(iface
);
985 ULONG ref
= InterlockedIncrement(&doc
->ref
);
986 TRACE("%p, refcount %ld.\n", iface
, ref
);
990 static ULONG WINAPI
domdoc_Release( IXMLDOMDocument3
*iface
)
992 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
993 LONG ref
= InterlockedDecrement( &This
->ref
);
995 TRACE("%p, refcount %ld.\n", iface
, ref
);
1002 IUnknown_Release( This
->site
);
1004 IUri_Release( This
->base_uri
);
1005 destroy_xmlnode(&This
->node
);
1007 for (eid
= 0; eid
< EVENTID_LAST
; eid
++)
1008 if (This
->events
[eid
]) IDispatch_Release(This
->events
[eid
]);
1010 properties_release(This
->properties
);
1011 release_namespaces(This
);
1018 static HRESULT WINAPI
domdoc_GetTypeInfoCount( IXMLDOMDocument3
*iface
, UINT
* pctinfo
)
1020 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1021 return IDispatchEx_GetTypeInfoCount(&This
->node
.dispex
.IDispatchEx_iface
, pctinfo
);
1024 static HRESULT WINAPI
domdoc_GetTypeInfo(
1025 IXMLDOMDocument3
*iface
,
1026 UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
1028 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1029 return IDispatchEx_GetTypeInfo(&This
->node
.dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
1032 static HRESULT WINAPI
domdoc_GetIDsOfNames(
1033 IXMLDOMDocument3
*iface
,
1035 LPOLESTR
* rgszNames
,
1040 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1041 return IDispatchEx_GetIDsOfNames(&This
->node
.dispex
.IDispatchEx_iface
,
1042 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
1045 static HRESULT WINAPI
domdoc_Invoke(
1046 IXMLDOMDocument3
*iface
,
1047 DISPID dispIdMember
,
1051 DISPPARAMS
* pDispParams
,
1052 VARIANT
* pVarResult
,
1053 EXCEPINFO
* pExcepInfo
,
1056 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1057 return IDispatchEx_Invoke(&This
->node
.dispex
.IDispatchEx_iface
,
1058 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1061 static HRESULT WINAPI
domdoc_get_nodeName(
1062 IXMLDOMDocument3
*iface
,
1065 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1067 static const WCHAR documentW
[] = {'#','d','o','c','u','m','e','n','t',0};
1069 TRACE("(%p)->(%p)\n", This
, name
);
1071 return return_bstr(documentW
, name
);
1075 static HRESULT WINAPI
domdoc_get_nodeValue(
1076 IXMLDOMDocument3
*iface
,
1079 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1081 TRACE("(%p)->(%p)\n", This
, value
);
1084 return E_INVALIDARG
;
1086 V_VT(value
) = VT_NULL
;
1087 V_BSTR(value
) = NULL
; /* tests show that we should do this */
1092 static HRESULT WINAPI
domdoc_put_nodeValue(
1093 IXMLDOMDocument3
*iface
,
1096 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1097 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&value
));
1102 static HRESULT WINAPI
domdoc_get_nodeType(
1103 IXMLDOMDocument3
*iface
,
1106 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1108 TRACE("(%p)->(%p)\n", This
, type
);
1110 *type
= NODE_DOCUMENT
;
1115 static HRESULT WINAPI
domdoc_get_parentNode(
1116 IXMLDOMDocument3
*iface
,
1117 IXMLDOMNode
** parent
)
1119 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1121 TRACE("(%p)->(%p)\n", This
, parent
);
1123 return node_get_parent(&This
->node
, parent
);
1127 static HRESULT WINAPI
domdoc_get_childNodes(
1128 IXMLDOMDocument3
*iface
,
1129 IXMLDOMNodeList
** childList
)
1131 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1133 TRACE("(%p)->(%p)\n", This
, childList
);
1135 return node_get_child_nodes(&This
->node
, childList
);
1139 static HRESULT WINAPI
domdoc_get_firstChild(
1140 IXMLDOMDocument3
*iface
,
1141 IXMLDOMNode
** firstChild
)
1143 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1145 TRACE("(%p)->(%p)\n", This
, firstChild
);
1147 return node_get_first_child(&This
->node
, firstChild
);
1151 static HRESULT WINAPI
domdoc_get_lastChild(
1152 IXMLDOMDocument3
*iface
,
1153 IXMLDOMNode
** lastChild
)
1155 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1157 TRACE("(%p)->(%p)\n", This
, lastChild
);
1159 return node_get_last_child(&This
->node
, lastChild
);
1163 static HRESULT WINAPI
domdoc_get_previousSibling(
1164 IXMLDOMDocument3
*iface
,
1165 IXMLDOMNode
** previousSibling
)
1167 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1169 TRACE("(%p)->(%p)\n", This
, previousSibling
);
1171 return return_null_node(previousSibling
);
1175 static HRESULT WINAPI
domdoc_get_nextSibling(
1176 IXMLDOMDocument3
*iface
,
1177 IXMLDOMNode
** nextSibling
)
1179 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1181 TRACE("(%p)->(%p)\n", This
, nextSibling
);
1183 return return_null_node(nextSibling
);
1187 static HRESULT WINAPI
domdoc_get_attributes(
1188 IXMLDOMDocument3
*iface
,
1189 IXMLDOMNamedNodeMap
** attributeMap
)
1191 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1193 TRACE("(%p)->(%p)\n", This
, attributeMap
);
1195 return return_null_ptr((void**)attributeMap
);
1199 static HRESULT WINAPI
domdoc_insertBefore(
1200 IXMLDOMDocument3
*iface
,
1201 IXMLDOMNode
* newChild
,
1203 IXMLDOMNode
** outNewChild
)
1205 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1209 TRACE("(%p)->(%p %s %p)\n", This
, newChild
, debugstr_variant(&refChild
), outNewChild
);
1211 if (!newChild
) return E_INVALIDARG
;
1213 hr
= IXMLDOMNode_get_nodeType(newChild
, &type
);
1214 if (hr
!= S_OK
) return hr
;
1216 TRACE("new node type %d\n", type
);
1219 case NODE_ATTRIBUTE
:
1221 case NODE_CDATA_SECTION
:
1222 if (outNewChild
) *outNewChild
= NULL
;
1225 return node_insert_before(&This
->node
, newChild
, &refChild
, outNewChild
);
1229 static HRESULT WINAPI
domdoc_replaceChild(
1230 IXMLDOMDocument3
*iface
,
1231 IXMLDOMNode
* newChild
,
1232 IXMLDOMNode
* oldChild
,
1233 IXMLDOMNode
** outOldChild
)
1235 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1237 TRACE("(%p)->(%p %p %p)\n", This
, newChild
, oldChild
, outOldChild
);
1239 return node_replace_child(&This
->node
, newChild
, oldChild
, outOldChild
);
1243 static HRESULT WINAPI
domdoc_removeChild(
1244 IXMLDOMDocument3
*iface
,
1246 IXMLDOMNode
**oldChild
)
1248 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1249 TRACE("(%p)->(%p %p)\n", This
, child
, oldChild
);
1250 return node_remove_child(&This
->node
, child
, oldChild
);
1254 static HRESULT WINAPI
domdoc_appendChild(
1255 IXMLDOMDocument3
*iface
,
1257 IXMLDOMNode
**outChild
)
1259 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1260 TRACE("(%p)->(%p %p)\n", This
, child
, outChild
);
1261 return node_append_child(&This
->node
, child
, outChild
);
1265 static HRESULT WINAPI
domdoc_hasChildNodes(
1266 IXMLDOMDocument3
*iface
,
1269 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1270 TRACE("(%p)->(%p)\n", This
, ret
);
1271 return node_has_childnodes(&This
->node
, ret
);
1275 static HRESULT WINAPI
domdoc_get_ownerDocument(
1276 IXMLDOMDocument3
*iface
,
1277 IXMLDOMDocument
**doc
)
1279 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1280 TRACE("(%p)->(%p)\n", This
, doc
);
1281 return node_get_owner_doc(&This
->node
, doc
);
1285 static HRESULT WINAPI
domdoc_cloneNode(
1286 IXMLDOMDocument3
*iface
,
1288 IXMLDOMNode
** outNode
)
1290 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1293 TRACE("(%p)->(%d %p)\n", This
, deep
, outNode
);
1296 return E_INVALIDARG
;
1300 clone
= xmlCopyNode((xmlNodePtr
)get_doc(This
), deep
? 1 : 2);
1304 clone
->doc
->_private
= create_priv();
1305 xmldoc_add_orphan(clone
->doc
, clone
);
1306 xmldoc_add_ref(clone
->doc
);
1308 priv_from_xmlDocPtr(clone
->doc
)->properties
= copy_properties(This
->properties
);
1309 if (!(*outNode
= (IXMLDOMNode
*)create_domdoc(clone
)))
1311 xmldoc_release(clone
->doc
);
1319 static HRESULT WINAPI
domdoc_get_nodeTypeString(
1320 IXMLDOMDocument3
*iface
,
1323 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1324 static const WCHAR documentW
[] = {'d','o','c','u','m','e','n','t',0};
1326 TRACE("(%p)->(%p)\n", This
, p
);
1328 return return_bstr(documentW
, p
);
1332 static HRESULT WINAPI
domdoc_get_text(
1333 IXMLDOMDocument3
*iface
,
1336 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1337 TRACE("(%p)->(%p)\n", This
, p
);
1338 return node_get_text(&This
->node
, p
);
1342 static HRESULT WINAPI
domdoc_put_text(
1343 IXMLDOMDocument3
*iface
,
1346 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1347 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
1352 static HRESULT WINAPI
domdoc_get_specified(
1353 IXMLDOMDocument3
*iface
,
1354 VARIANT_BOOL
* isSpecified
)
1356 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1357 FIXME("(%p)->(%p) stub!\n", This
, isSpecified
);
1358 *isSpecified
= VARIANT_TRUE
;
1363 static HRESULT WINAPI
domdoc_get_definition(
1364 IXMLDOMDocument3
*iface
,
1365 IXMLDOMNode
** definitionNode
)
1367 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1368 FIXME("(%p)->(%p)\n", This
, definitionNode
);
1373 static HRESULT WINAPI
domdoc_get_nodeTypedValue(
1374 IXMLDOMDocument3
*iface
,
1377 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1378 TRACE("(%p)->(%p)\n", This
, v
);
1379 return return_null_var(v
);
1382 static HRESULT WINAPI
domdoc_put_nodeTypedValue(
1383 IXMLDOMDocument3
*iface
,
1384 VARIANT typedValue
)
1386 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1387 FIXME("(%p)->(%s)\n", This
, debugstr_variant(&typedValue
));
1392 static HRESULT WINAPI
domdoc_get_dataType(
1393 IXMLDOMDocument3
*iface
,
1396 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1397 TRACE("(%p)->(%p)\n", This
, typename
);
1398 return return_null_var( typename
);
1402 static HRESULT WINAPI
domdoc_put_dataType(
1403 IXMLDOMDocument3
*iface
,
1406 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1408 FIXME("(%p)->(%s)\n", This
, debugstr_w(dataTypeName
));
1411 return E_INVALIDARG
;
1416 static int XMLCALL
domdoc_get_xml_writecallback(void *ctx
, const char *data
, int len
)
1418 return xmlBufferAdd((xmlBufferPtr
)ctx
, (xmlChar
*)data
, len
) == 0 ? len
: 0;
1421 static HRESULT WINAPI
domdoc_get_xml(
1422 IXMLDOMDocument3
*iface
,
1425 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1426 xmlSaveCtxtPtr ctxt
;
1431 TRACE("(%p)->(%p)\n", This
, p
);
1434 return E_INVALIDARG
;
1438 buf
= xmlBufferCreate();
1440 return E_OUTOFMEMORY
;
1442 options
= XML_SAVE_FORMAT
| XML_SAVE_NO_DECL
;
1443 ctxt
= xmlSaveToIO(domdoc_get_xml_writecallback
, NULL
, buf
, "UTF-8", options
);
1448 return E_OUTOFMEMORY
;
1451 ret
= xmlSaveDoc(ctxt
, get_doc(This
));
1452 /* flushes on close */
1455 TRACE("%ld, len=%d\n", ret
, xmlBufferLength(buf
));
1456 if(ret
!= -1 && xmlBufferLength(buf
) > 0)
1460 content
= bstr_from_xmlChar(xmlBufferContent(buf
));
1461 content
= EnsureCorrectEOL(content
);
1467 *p
= SysAllocStringLen(NULL
, 0);
1472 return *p
? S_OK
: E_OUTOFMEMORY
;
1476 static HRESULT WINAPI
domdoc_transformNode(
1477 IXMLDOMDocument3
*iface
,
1481 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1482 TRACE("(%p)->(%p %p)\n", This
, node
, p
);
1483 return node_transform_node(&This
->node
, node
, p
);
1487 static HRESULT WINAPI
domdoc_selectNodes(
1488 IXMLDOMDocument3
*iface
,
1490 IXMLDOMNodeList
**outList
)
1492 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1493 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outList
);
1494 return node_select_nodes(&This
->node
, p
, outList
);
1498 static HRESULT WINAPI
domdoc_selectSingleNode(
1499 IXMLDOMDocument3
*iface
,
1501 IXMLDOMNode
**outNode
)
1503 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1504 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outNode
);
1505 return node_select_singlenode(&This
->node
, p
, outNode
);
1509 static HRESULT WINAPI
domdoc_get_parsed(
1510 IXMLDOMDocument3
*iface
,
1511 VARIANT_BOOL
* isParsed
)
1513 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1514 FIXME("(%p)->(%p) stub!\n", This
, isParsed
);
1515 *isParsed
= VARIANT_TRUE
;
1519 static HRESULT WINAPI
domdoc_get_namespaceURI(
1520 IXMLDOMDocument3
*iface
,
1521 BSTR
* namespaceURI
)
1523 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1524 TRACE("(%p)->(%p)\n", This
, namespaceURI
);
1525 return return_null_bstr( namespaceURI
);
1528 static HRESULT WINAPI
domdoc_get_prefix(
1529 IXMLDOMDocument3
*iface
,
1532 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1533 TRACE("(%p)->(%p)\n", This
, prefix
);
1534 return return_null_bstr( prefix
);
1538 static HRESULT WINAPI
domdoc_get_baseName(
1539 IXMLDOMDocument3
*iface
,
1542 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1543 TRACE("(%p)->(%p)\n", This
, name
);
1544 return return_null_bstr( name
);
1548 static HRESULT WINAPI
domdoc_transformNodeToObject(
1549 IXMLDOMDocument3
*iface
,
1550 IXMLDOMNode
* stylesheet
,
1553 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1555 TRACE("(%p)->(%p %s)\n", This
, stylesheet
, debugstr_variant(&output
));
1557 switch (V_VT(&output
))
1562 ISequentialStream
*stream
;
1563 IXMLDOMDocument
*doc
;
1567 if (!V_UNKNOWN(&output
))
1568 return E_INVALIDARG
;
1570 /* FIXME: we're not supposed to query for document interface, should use IStream
1571 which we don't support currently. */
1572 if (IUnknown_QueryInterface(V_UNKNOWN(&output
), &IID_IXMLDOMDocument
, (void **)&doc
) == S_OK
)
1576 if (FAILED(hr
= node_transform_node(&This
->node
, stylesheet
, &str
)))
1579 hr
= IXMLDOMDocument_loadXML(doc
, str
, &b
);
1583 else if (IUnknown_QueryInterface(V_UNKNOWN(&output
), &IID_ISequentialStream
, (void**)&stream
) == S_OK
)
1585 hr
= node_transform_node_params(&This
->node
, stylesheet
, NULL
, stream
, NULL
);
1586 ISequentialStream_Release(stream
);
1591 FIXME("Unsupported destination type.\n");
1592 return E_INVALIDARG
;
1596 FIXME("Output type %d not handled.\n", V_VT(&output
));
1604 static HRESULT WINAPI
domdoc_get_doctype(
1605 IXMLDOMDocument3
*iface
,
1606 IXMLDOMDocumentType
** doctype
)
1608 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1613 TRACE("(%p)->(%p)\n", This
, doctype
);
1615 if (!doctype
) return E_INVALIDARG
;
1619 dtd
= xmlGetIntSubset(get_doc(This
));
1620 if (!dtd
) return S_FALSE
;
1622 node
= create_node((xmlNodePtr
)dtd
);
1623 if (!node
) return S_FALSE
;
1625 hr
= IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentType
, (void**)doctype
);
1626 IXMLDOMNode_Release(node
);
1632 static HRESULT WINAPI
domdoc_get_implementation(
1633 IXMLDOMDocument3
*iface
,
1634 IXMLDOMImplementation
** impl
)
1636 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1638 TRACE("(%p)->(%p)\n", This
, impl
);
1641 return E_INVALIDARG
;
1643 return create_dom_implementation(impl
);
1646 static HRESULT WINAPI
domdoc_get_documentElement(
1647 IXMLDOMDocument3
*iface
,
1648 IXMLDOMElement
** DOMElement
)
1650 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1651 IXMLDOMNode
*element_node
;
1655 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1658 return E_INVALIDARG
;
1662 root
= xmlDocGetRootElement( get_doc(This
) );
1666 element_node
= create_node( root
);
1667 if(!element_node
) return S_FALSE
;
1669 hr
= IXMLDOMNode_QueryInterface(element_node
, &IID_IXMLDOMElement
, (void**)DOMElement
);
1670 IXMLDOMNode_Release(element_node
);
1676 static HRESULT WINAPI
domdoc_put_documentElement(
1677 IXMLDOMDocument3
*iface
,
1678 IXMLDOMElement
* DOMElement
)
1680 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1681 IXMLDOMNode
*elementNode
;
1688 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1690 hr
= IXMLDOMElement_QueryInterface( DOMElement
, &IID_IXMLDOMNode
, (void**)&elementNode
);
1694 xmlNode
= get_node_obj( elementNode
);
1695 if(!xmlNode
) return E_FAIL
;
1697 if(!xmlNode
->node
->parent
)
1698 if(xmldoc_remove_orphan(xmlNode
->node
->doc
, xmlNode
->node
) != S_OK
)
1699 WARN("%p is not an orphan of %p\n", xmlNode
->node
->doc
, xmlNode
->node
);
1701 old_doc
= xmlNode
->node
->doc
;
1702 if (old_doc
!= get_doc(This
))
1703 refcount
= xmlnode_get_inst_cnt(xmlNode
);
1705 /* old root is still orphaned by its document, update refcount from new root */
1706 if (refcount
) xmldoc_add_refs(get_doc(This
), refcount
);
1707 oldRoot
= xmlDocSetRootElement( get_doc(This
), xmlNode
->node
);
1708 if (refcount
) xmldoc_release_refs(old_doc
, refcount
);
1709 IXMLDOMNode_Release( elementNode
);
1712 xmldoc_add_orphan(oldRoot
->doc
, oldRoot
);
1718 static HRESULT WINAPI
domdoc_createElement(
1719 IXMLDOMDocument3
*iface
,
1721 IXMLDOMElement
** element
)
1723 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1728 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(tagname
), element
);
1730 if (!element
|| !tagname
) return E_INVALIDARG
;
1732 V_VT(&type
) = VT_I1
;
1733 V_I1(&type
) = NODE_ELEMENT
;
1735 hr
= IXMLDOMDocument3_createNode(iface
, type
, tagname
, NULL
, &node
);
1738 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMElement
, (void**)element
);
1739 IXMLDOMNode_Release(node
);
1746 static HRESULT WINAPI
domdoc_createDocumentFragment(
1747 IXMLDOMDocument3
*iface
,
1748 IXMLDOMDocumentFragment
** frag
)
1750 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1755 TRACE("(%p)->(%p)\n", This
, frag
);
1757 if (!frag
) return E_INVALIDARG
;
1761 V_VT(&type
) = VT_I1
;
1762 V_I1(&type
) = NODE_DOCUMENT_FRAGMENT
;
1764 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1767 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentFragment
, (void**)frag
);
1768 IXMLDOMNode_Release(node
);
1775 static HRESULT WINAPI
domdoc_createTextNode(
1776 IXMLDOMDocument3
*iface
,
1778 IXMLDOMText
** text
)
1780 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1785 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), text
);
1787 if (!text
) return E_INVALIDARG
;
1791 V_VT(&type
) = VT_I1
;
1792 V_I1(&type
) = NODE_TEXT
;
1794 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1797 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMText
, (void**)text
);
1798 IXMLDOMNode_Release(node
);
1799 hr
= IXMLDOMText_put_data(*text
, data
);
1806 static HRESULT WINAPI
domdoc_createComment(
1807 IXMLDOMDocument3
*iface
,
1809 IXMLDOMComment
** comment
)
1811 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1816 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), comment
);
1818 if (!comment
) return E_INVALIDARG
;
1822 V_VT(&type
) = VT_I1
;
1823 V_I1(&type
) = NODE_COMMENT
;
1825 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1828 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMComment
, (void**)comment
);
1829 IXMLDOMNode_Release(node
);
1830 hr
= IXMLDOMComment_put_data(*comment
, data
);
1837 static HRESULT WINAPI
domdoc_createCDATASection(
1838 IXMLDOMDocument3
*iface
,
1840 IXMLDOMCDATASection
** cdata
)
1842 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1847 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), cdata
);
1849 if (!cdata
) return E_INVALIDARG
;
1853 V_VT(&type
) = VT_I1
;
1854 V_I1(&type
) = NODE_CDATA_SECTION
;
1856 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1859 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMCDATASection
, (void**)cdata
);
1860 IXMLDOMNode_Release(node
);
1861 hr
= IXMLDOMCDATASection_put_data(*cdata
, data
);
1868 static HRESULT WINAPI
domdoc_createProcessingInstruction(
1869 IXMLDOMDocument3
*iface
,
1872 IXMLDOMProcessingInstruction
** pi
)
1874 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1879 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_w(target
), debugstr_w(data
), pi
);
1881 if (!pi
) return E_INVALIDARG
;
1885 V_VT(&type
) = VT_I1
;
1886 V_I1(&type
) = NODE_PROCESSING_INSTRUCTION
;
1888 hr
= IXMLDOMDocument3_createNode(iface
, type
, target
, NULL
, &node
);
1891 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1892 hr
= dom_pi_put_xml_decl(node
, data
);
1894 hr
= IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMProcessingInstruction
, (void**)pi
);
1895 IXMLDOMNode_Release(node
);
1902 static HRESULT WINAPI
domdoc_createAttribute(
1903 IXMLDOMDocument3
*iface
,
1905 IXMLDOMAttribute
** attribute
)
1907 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1912 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), attribute
);
1914 if (!attribute
|| !name
) return E_INVALIDARG
;
1916 V_VT(&type
) = VT_I1
;
1917 V_I1(&type
) = NODE_ATTRIBUTE
;
1919 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1922 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMAttribute
, (void**)attribute
);
1923 IXMLDOMNode_Release(node
);
1930 static HRESULT WINAPI
domdoc_createEntityReference(
1931 IXMLDOMDocument3
*iface
,
1933 IXMLDOMEntityReference
** entityref
)
1935 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1940 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), entityref
);
1942 if (!entityref
) return E_INVALIDARG
;
1946 V_VT(&type
) = VT_I1
;
1947 V_I1(&type
) = NODE_ENTITY_REFERENCE
;
1949 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1952 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMEntityReference
, (void**)entityref
);
1953 IXMLDOMNode_Release(node
);
1959 xmlChar
* tagName_to_XPath(const BSTR tagName
)
1961 xmlChar
*query
, *tmp
;
1962 static const xmlChar everything
[] = "/descendant::node()";
1963 static const xmlChar mod_pre
[] = "*[local-name()='";
1964 static const xmlChar mod_post
[] = "']";
1965 static const xmlChar prefix
[] = "descendant::";
1966 const WCHAR
*tokBegin
, *tokEnd
;
1969 /* Special case - empty tagname - means select all nodes,
1970 except document itself. */
1972 return xmlStrdup(everything
);
1974 query
= xmlStrdup(prefix
);
1977 while (tokBegin
&& *tokBegin
)
1982 query
= xmlStrcat(query
, BAD_CAST
"/");
1986 query
= xmlStrcat(query
, BAD_CAST
"*");
1990 query
= xmlStrcat(query
, mod_pre
);
1992 while (*tokEnd
&& *tokEnd
!= '/')
1994 len
= WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, NULL
, 0, NULL
, NULL
);
1995 tmp
= xmlMalloc(len
);
1996 WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, (char*)tmp
, len
, NULL
, NULL
);
1997 query
= xmlStrncat(query
, tmp
, len
);
2000 query
= xmlStrcat(query
, mod_post
);
2007 static HRESULT WINAPI
domdoc_getElementsByTagName(
2008 IXMLDOMDocument3
*iface
,
2010 IXMLDOMNodeList
** resultList
)
2012 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2017 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(tagName
), resultList
);
2019 if (!tagName
|| !resultList
) return E_INVALIDARG
;
2021 XPath
= This
->properties
->XPath
;
2022 This
->properties
->XPath
= TRUE
;
2023 query
= tagName_to_XPath(tagName
);
2024 hr
= create_selection((xmlNodePtr
)get_doc(This
), query
, resultList
);
2026 This
->properties
->XPath
= XPath
;
2031 static HRESULT
get_node_type(VARIANT Type
, DOMNodeType
* type
)
2037 hr
= VariantChangeType(&tmp
, &Type
, 0, VT_I4
);
2039 return E_INVALIDARG
;
2046 static HRESULT WINAPI
domdoc_createNode(
2047 IXMLDOMDocument3
*iface
,
2051 IXMLDOMNode
** node
)
2053 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2054 DOMNodeType node_type
;
2056 xmlChar
*xml_name
, *href
;
2059 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_variant(&Type
), debugstr_w(name
), debugstr_w(namespaceURI
), node
);
2061 if(!node
) return E_INVALIDARG
;
2063 hr
= get_node_type(Type
, &node_type
);
2064 if(FAILED(hr
)) return hr
;
2066 TRACE("node_type %d\n", node_type
);
2068 /* exit earlier for types that need name */
2072 case NODE_ATTRIBUTE
:
2073 case NODE_ENTITY_REFERENCE
:
2074 case NODE_PROCESSING_INSTRUCTION
:
2075 if (!name
|| *name
== 0) return E_FAIL
;
2081 xml_name
= xmlchar_from_wchar(name
);
2082 /* prevent empty href from being allocated */
2083 href
= namespaceURI
? xmlchar_from_wchar(namespaceURI
) : NULL
;
2089 xmlChar
*local
, *prefix
;
2091 local
= xmlSplitQName2(xml_name
, &prefix
);
2093 xmlnode
= xmlNewDocNode(get_doc(This
), NULL
, local
? local
: xml_name
, NULL
);
2095 /* allow creating the default namespace xmlns= */
2096 if (local
|| (href
&& *href
))
2098 xmlNsPtr ns
= xmlNewNs(xmlnode
, href
, prefix
);
2099 xmlSetNs(xmlnode
, ns
);
2107 case NODE_ATTRIBUTE
:
2109 xmlChar
*local
, *prefix
;
2111 local
= xmlSplitQName2(xml_name
, &prefix
);
2113 xmlnode
= (xmlNodePtr
)xmlNewDocProp(get_doc(This
), local
? local
: xml_name
, NULL
);
2115 if (local
|| (href
&& *href
))
2117 /* we need a floating namespace here, it can't be created linked to attribute from
2119 xmlNsPtr ns
= xmlNewNs(NULL
, href
, prefix
);
2120 xmlSetNs(xmlnode
, ns
);
2129 xmlnode
= (xmlNodePtr
)xmlNewDocText(get_doc(This
), NULL
);
2131 case NODE_CDATA_SECTION
:
2132 xmlnode
= xmlNewCDataBlock(get_doc(This
), NULL
, 0);
2134 case NODE_ENTITY_REFERENCE
:
2135 xmlnode
= xmlNewReference(get_doc(This
), xml_name
);
2137 case NODE_PROCESSING_INSTRUCTION
:
2138 xmlnode
= xmlNewDocPI(get_doc(This
), xml_name
, NULL
);
2141 xmlnode
= xmlNewDocComment(get_doc(This
), NULL
);
2143 case NODE_DOCUMENT_FRAGMENT
:
2144 xmlnode
= xmlNewDocFragment(get_doc(This
));
2146 /* unsupported types */
2148 case NODE_DOCUMENT_TYPE
:
2151 heap_free(xml_name
);
2152 return E_INVALIDARG
;
2154 FIXME("unhandled node type %d\n", node_type
);
2159 *node
= create_node(xmlnode
);
2160 heap_free(xml_name
);
2165 TRACE("created node (%d, %p, %p)\n", node_type
, *node
, xmlnode
);
2166 xmldoc_add_orphan(xmlnode
->doc
, xmlnode
);
2173 static HRESULT WINAPI
domdoc_nodeFromID(
2174 IXMLDOMDocument3
*iface
,
2176 IXMLDOMNode
** node
)
2178 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2179 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(idString
), node
);
2183 static HRESULT
domdoc_onDataAvailable(void *obj
, char *ptr
, DWORD len
)
2188 xmldoc
= doparse(This
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
2190 xmldoc
->_private
= create_priv();
2191 return attach_xmldoc(This
, xmldoc
);
2197 static HRESULT
domdoc_load_moniker(domdoc
*This
, IMoniker
*mon
)
2202 hr
= bind_url(mon
, domdoc_onDataAvailable
, This
, &bsc
);
2206 return detach_bsc(bsc
);
2209 static HRESULT WINAPI
domdoc_load(
2210 IXMLDOMDocument3
*iface
,
2212 VARIANT_BOOL
* isSuccessful
)
2214 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2215 LPWSTR filename
= NULL
;
2216 HRESULT hr
= S_FALSE
;
2219 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&source
));
2223 *isSuccessful
= VARIANT_FALSE
;
2225 assert( &This
->node
);
2227 switch( V_VT(&source
) )
2230 filename
= V_BSTR(&source
);
2232 case VT_BSTR
|VT_BYREF
:
2233 if (!V_BSTRREF(&source
)) return E_INVALIDARG
;
2234 filename
= *V_BSTRREF(&source
);
2236 case VT_ARRAY
|VT_UI1
:
2238 SAFEARRAY
*psa
= V_ARRAY(&source
);
2241 UINT dim
= SafeArrayGetDim(psa
);
2246 ERR("SAFEARRAY == NULL\n");
2247 hr
= This
->error
= E_INVALIDARG
;
2250 /* Only takes UTF-8 strings.
2251 * NOT NULL-terminated. */
2252 hr
= SafeArrayAccessData(psa
, (void**)&str
);
2256 WARN("failed to access array data, hr %#lx.\n", hr
);
2259 SafeArrayGetUBound(psa
, 1, &len
);
2261 if ((xmldoc
= doparse(This
, str
, ++len
, XML_CHAR_ENCODING_UTF8
)))
2263 hr
= This
->error
= S_OK
;
2264 *isSuccessful
= VARIANT_TRUE
;
2265 TRACE("parsed document %p\n", xmldoc
);
2269 This
->error
= E_FAIL
;
2270 TRACE("failed to parse document\n");
2273 SafeArrayUnaccessData(psa
);
2277 xmldoc
->_private
= create_priv();
2278 return attach_xmldoc(This
, xmldoc
);
2282 FIXME("unhandled SAFEARRAY dim: %d\n", dim
);
2283 hr
= This
->error
= E_NOTIMPL
;
2289 ISequentialStream
*stream
= NULL
;
2290 IXMLDOMDocument3
*newdoc
= NULL
;
2292 if (!V_UNKNOWN(&source
)) return E_INVALIDARG
;
2294 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IXMLDOMDocument3
, (void**)&newdoc
);
2299 domdoc
*newDoc
= impl_from_IXMLDOMDocument3( newdoc
);
2301 xmldoc
= xmlCopyDoc(get_doc(newDoc
), 1);
2302 xmldoc
->_private
= create_priv();
2303 hr
= attach_xmldoc(This
, xmldoc
);
2306 *isSuccessful
= VARIANT_TRUE
;
2312 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IStream
, (void**)&stream
);
2314 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_ISequentialStream
, (void**)&stream
);
2318 hr
= This
->error
= domdoc_load_from_stream(This
, stream
);
2320 *isSuccessful
= VARIANT_TRUE
;
2321 ISequentialStream_Release(stream
);
2325 FIXME("unsupported IUnknown type (%#lx) (%p)\n", hr
, V_UNKNOWN(&source
)->lpVtbl
);
2329 FIXME("VT type not supported (%d)\n", V_VT(&source
));
2337 if (This
->properties
->uri
)
2339 IUri_Release(This
->properties
->uri
);
2340 This
->properties
->uri
= NULL
;
2343 hr
= create_uri(This
->base_uri
, filename
, &uri
);
2345 hr
= CreateURLMonikerEx2(NULL
, uri
, &mon
, 0);
2346 if ( SUCCEEDED(hr
) )
2348 hr
= domdoc_load_moniker( This
, mon
);
2349 IMoniker_Release(mon
);
2354 get_doc(This
)->name
= (char *)xmlchar_from_wcharn(filename
, -1, TRUE
);
2355 This
->properties
->uri
= uri
;
2356 hr
= This
->error
= S_OK
;
2357 *isSuccessful
= VARIANT_TRUE
;
2363 This
->error
= E_FAIL
;
2367 if(!filename
|| FAILED(hr
)) {
2368 xmldoc
= xmlNewDoc(NULL
);
2369 xmldoc
->_private
= create_priv();
2370 hr
= attach_xmldoc(This
, xmldoc
);
2375 TRACE("hr %#lx.\n", hr
);
2381 static HRESULT WINAPI
domdoc_get_readyState(
2382 IXMLDOMDocument3
*iface
,
2385 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2386 FIXME("stub! (%p)->(%p)\n", This
, value
);
2389 return E_INVALIDARG
;
2391 *value
= READYSTATE_COMPLETE
;
2396 static HRESULT WINAPI
domdoc_get_parseError(
2397 IXMLDOMDocument3
*iface
,
2398 IXMLDOMParseError
** errorObj
)
2400 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2401 static const WCHAR err
[] = {'e','r','r','o','r',0};
2402 BSTR error_string
= NULL
;
2404 FIXME("(%p)->(%p): creating a dummy parseError\n", iface
, errorObj
);
2407 error_string
= SysAllocString(err
);
2409 *errorObj
= create_parseError(This
->error
, NULL
, error_string
, NULL
, 0, 0, 0);
2410 if(!*errorObj
) return E_OUTOFMEMORY
;
2415 static HRESULT WINAPI
domdoc_get_url(
2416 IXMLDOMDocument3
*iface
,
2419 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2421 TRACE("(%p)->(%p)\n", This
, url
);
2424 return E_INVALIDARG
;
2426 if (!This
->properties
->uri
)
2427 return return_null_bstr(url
);
2429 return IUri_GetPropertyBSTR(This
->properties
->uri
, Uri_PROPERTY_DISPLAY_URI
, url
, 0);
2433 static HRESULT WINAPI
domdoc_get_async(
2434 IXMLDOMDocument3
*iface
,
2435 VARIANT_BOOL
* isAsync
)
2437 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2439 TRACE("(%p)->(%p: %d)\n", This
, isAsync
, This
->async
);
2440 *isAsync
= This
->async
;
2445 static HRESULT WINAPI
domdoc_put_async(
2446 IXMLDOMDocument3
*iface
,
2447 VARIANT_BOOL isAsync
)
2449 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2451 TRACE("(%p)->(%d)\n", This
, isAsync
);
2452 This
->async
= isAsync
;
2457 static HRESULT WINAPI
domdoc_abort(
2458 IXMLDOMDocument3
*iface
)
2460 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2461 FIXME("%p\n", This
);
2465 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2466 static HRESULT WINAPI
domdoc_loadXML(
2467 IXMLDOMDocument3
*iface
,
2469 VARIANT_BOOL
* isSuccessful
)
2471 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2472 xmlDocPtr xmldoc
= NULL
;
2473 HRESULT hr
= S_FALSE
, hr2
;
2475 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), isSuccessful
);
2477 assert ( &This
->node
);
2481 *isSuccessful
= VARIANT_FALSE
;
2487 /* skip leading spaces if needed */
2488 if (This
->properties
->version
== MSXML_DEFAULT
|| This
->properties
->version
== MSXML26
)
2489 while (*ptr
&& iswspace(*ptr
)) ptr
++;
2491 xmldoc
= doparse(This
, (char*)ptr
, lstrlenW(ptr
)*sizeof(WCHAR
), XML_CHAR_ENCODING_UTF16LE
);
2494 This
->error
= E_FAIL
;
2495 TRACE("failed to parse document\n");
2499 hr
= This
->error
= S_OK
;
2500 *isSuccessful
= VARIANT_TRUE
;
2501 TRACE("parsed document %p\n", xmldoc
);
2507 xmldoc
= xmlNewDoc(NULL
);
2508 xmldoc
->_private
= create_priv();
2509 hr2
= attach_xmldoc(This
, xmldoc
);
2516 static int XMLCALL
domdoc_save_writecallback(void *ctx
, const char *buffer
, int len
)
2520 if(!WriteFile(ctx
, buffer
, len
, &written
, NULL
))
2522 WARN("write error\n");
2529 static int XMLCALL
domdoc_save_closecallback(void *ctx
)
2531 return CloseHandle(ctx
) ? 0 : -1;
2534 static int XMLCALL
domdoc_stream_save_writecallback(void *ctx
, const char *buffer
, int len
)
2539 hr
= IStream_Write((IStream
*)ctx
, buffer
, len
, &written
);
2540 TRACE("hr %#lx, %p, %d, %lu.\n", hr
, buffer
, len
, written
);
2543 WARN("stream write error, hr %#lx.\n", hr
);
2550 static int XMLCALL
domdoc_stream_save_closecallback(void *ctx
)
2552 IStream_Release((IStream
*)ctx
);
2556 static char *xmldoc_encoding(IXMLDOMDocument3
*doc
)
2560 char *encoding
= NULL
;
2562 hr
= IXMLDOMDocument3_get_firstChild(doc
, &node
);
2567 hr
= IXMLDOMNode_get_nodeType(node
, &type
);
2568 if (hr
== S_OK
&& type
== NODE_PROCESSING_INSTRUCTION
)
2570 IXMLDOMProcessingInstruction
*pi
;
2572 IXMLDOMNamedNodeMap
*node_map
;
2574 hr
= IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMProcessingInstruction
, (void **)&pi
);
2577 hr
= IXMLDOMNode_get_attributes(node
, &node_map
);
2580 static const WCHAR encodingW
[] = {'e','n','c','o','d','i','n','g',0};
2583 bstr
= SysAllocString(encodingW
);
2584 hr
= IXMLDOMNamedNodeMap_getNamedItem(node_map
, bstr
, &item
);
2585 SysFreeString(bstr
);
2590 hr
= IXMLDOMNode_get_nodeValue(item
, &var
);
2593 if (V_VT(&var
) == VT_BSTR
)
2594 encoding
= (char *)xmlchar_from_wchar(V_BSTR(&var
));
2600 IXMLDOMNamedNodeMap_Release(node_map
);
2603 IXMLDOMProcessingInstruction_Release(pi
);
2607 IXMLDOMNode_Release(node
);
2610 if (!encoding
&& (encoding
= heap_alloc(sizeof("UTF-8"))))
2611 strcpy(encoding
, "UTF-8");
2616 static HRESULT WINAPI
domdoc_save(
2617 IXMLDOMDocument3
*iface
,
2618 VARIANT destination
)
2620 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2621 xmlSaveCtxtPtr ctx
= NULL
;
2624 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&destination
));
2626 switch (V_VT(&destination
))
2630 IUnknown
*pUnk
= V_UNKNOWN(&destination
);
2631 IXMLDOMDocument3
*document
;
2634 ret
= IUnknown_QueryInterface(pUnk
, &IID_IXMLDOMDocument3
, (void**)&document
);
2637 VARIANT_BOOL success
;
2640 ret
= IXMLDOMDocument3_get_xml(iface
, &xml
);
2643 ret
= IXMLDOMDocument3_loadXML(document
, xml
, &success
);
2647 IXMLDOMDocument3_Release(document
);
2651 ret
= IUnknown_QueryInterface(pUnk
, &IID_IStream
, (void**)&stream
);
2654 char *encoding
= xmldoc_encoding(iface
);
2656 TRACE("using encoding %s\n", encoding
? debugstr_a(encoding
) : "default");
2657 ctx
= xmlSaveToIO(domdoc_stream_save_writecallback
,
2658 domdoc_stream_save_closecallback
, stream
, encoding
, XML_SAVE_NO_DECL
);
2659 heap_free(encoding
);
2663 IStream_Release(stream
);
2671 case VT_BSTR
| VT_BYREF
:
2674 /* save with file path */
2675 HANDLE handle
= CreateFileW( (V_VT(&destination
) & VT_BYREF
)? *V_BSTRREF(&destination
) : V_BSTR(&destination
),
2676 GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2677 if( handle
== INVALID_HANDLE_VALUE
)
2679 WARN("failed to create file\n");
2683 encoding
= xmldoc_encoding(iface
);
2684 TRACE("using encoding %s\n", encoding
? debugstr_a(encoding
) : "default");
2685 ctx
= xmlSaveToIO(domdoc_save_writecallback
, domdoc_save_closecallback
,
2686 handle
, encoding
, XML_SAVE_NO_DECL
);
2687 heap_free(encoding
);
2691 CloseHandle(handle
);
2698 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination
));
2702 if (xmlSaveDoc(ctx
, get_doc(This
)) == -1) ret
= S_FALSE
;
2704 /* will release resources through close callback */
2710 static HRESULT WINAPI
domdoc_get_validateOnParse(
2711 IXMLDOMDocument3
*iface
,
2712 VARIANT_BOOL
* isValidating
)
2714 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2715 TRACE("(%p)->(%p: %d)\n", This
, isValidating
, This
->properties
->validating
);
2716 *isValidating
= This
->properties
->validating
;
2721 static HRESULT WINAPI
domdoc_put_validateOnParse(
2722 IXMLDOMDocument3
*iface
,
2723 VARIANT_BOOL isValidating
)
2725 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2726 TRACE("(%p)->(%d)\n", This
, isValidating
);
2727 This
->properties
->validating
= isValidating
;
2732 static HRESULT WINAPI
domdoc_get_resolveExternals(
2733 IXMLDOMDocument3
*iface
,
2734 VARIANT_BOOL
* isResolving
)
2736 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2737 TRACE("(%p)->(%p: %d)\n", This
, isResolving
, This
->resolving
);
2738 *isResolving
= This
->resolving
;
2743 static HRESULT WINAPI
domdoc_put_resolveExternals(
2744 IXMLDOMDocument3
*iface
,
2745 VARIANT_BOOL isResolving
)
2747 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2748 TRACE("(%p)->(%d)\n", This
, isResolving
);
2749 This
->resolving
= isResolving
;
2754 static HRESULT WINAPI
domdoc_get_preserveWhiteSpace(
2755 IXMLDOMDocument3
*iface
,
2756 VARIANT_BOOL
* isPreserving
)
2758 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2759 TRACE("(%p)->(%p: %d)\n", This
, isPreserving
, This
->properties
->preserving
);
2760 *isPreserving
= This
->properties
->preserving
;
2765 static HRESULT WINAPI
domdoc_put_preserveWhiteSpace(
2766 IXMLDOMDocument3
*iface
,
2767 VARIANT_BOOL isPreserving
)
2769 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2770 TRACE("(%p)->(%d)\n", This
, isPreserving
);
2771 This
->properties
->preserving
= isPreserving
;
2776 static HRESULT WINAPI
domdoc_put_onreadystatechange(
2777 IXMLDOMDocument3
*iface
,
2780 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2782 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&event
));
2783 return set_doc_event(This
, EVENTID_READYSTATECHANGE
, &event
);
2787 static HRESULT WINAPI
domdoc_put_onDataAvailable(IXMLDOMDocument3
*iface
, VARIANT sink
)
2789 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2790 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2794 static HRESULT WINAPI
domdoc_put_onTransformNode(IXMLDOMDocument3
*iface
, VARIANT sink
)
2796 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2797 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2801 static HRESULT WINAPI
domdoc_get_namespaces(
2802 IXMLDOMDocument3
* iface
,
2803 IXMLDOMSchemaCollection
** collection
)
2805 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2808 FIXME("(%p)->(%p): semi-stub\n", This
, collection
);
2810 if (!collection
) return E_POINTER
;
2812 if (!This
->namespaces
)
2814 hr
= SchemaCache_create(This
->properties
->version
, (void**)&This
->namespaces
);
2815 if (hr
!= S_OK
) return hr
;
2817 hr
= cache_from_doc_ns(This
->namespaces
, &This
->node
);
2819 release_namespaces(This
);
2822 if (This
->namespaces
)
2823 return IXMLDOMSchemaCollection2_QueryInterface(This
->namespaces
,
2824 &IID_IXMLDOMSchemaCollection
, (void**)collection
);
2829 static HRESULT WINAPI
domdoc_get_schemas(
2830 IXMLDOMDocument3
* iface
,
2833 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2834 IXMLDOMSchemaCollection2
* cur_schema
= This
->properties
->schemaCache
;
2835 HRESULT hr
= S_FALSE
;
2837 TRACE("(%p)->(%p)\n", This
, schema
);
2839 V_VT(schema
) = VT_NULL
;
2840 /* just to reset pointer part, cause that's what application is expected to use */
2841 V_DISPATCH(schema
) = NULL
;
2845 hr
= IXMLDOMSchemaCollection2_QueryInterface(cur_schema
, &IID_IDispatch
, (void**)&V_DISPATCH(schema
));
2847 V_VT(schema
) = VT_DISPATCH
;
2852 static HRESULT WINAPI
domdoc_putref_schemas(
2853 IXMLDOMDocument3
* iface
,
2856 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2857 HRESULT hr
= E_FAIL
;
2858 IXMLDOMSchemaCollection2
* new_schema
= NULL
;
2860 FIXME("(%p)->(%s): semi-stub\n", This
, debugstr_variant(&schema
));
2861 switch(V_VT(&schema
))
2864 if (V_UNKNOWN(&schema
))
2866 hr
= IUnknown_QueryInterface(V_UNKNOWN(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2871 if (V_DISPATCH(&schema
))
2873 hr
= IDispatch_QueryInterface(V_DISPATCH(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2883 WARN("Can't get schema from vt %x\n", V_VT(&schema
));
2888 IXMLDOMSchemaCollection2
* old_schema
= InterlockedExchangePointer((void**)&This
->properties
->schemaCache
, new_schema
);
2889 if(old_schema
) IXMLDOMSchemaCollection2_Release(old_schema
);
2895 static inline BOOL
is_wellformed(xmlDocPtr doc
)
2897 return doc
->properties
& XML_DOC_WELLFORMED
;
2900 static void LIBXML2_LOG_CALLBACK
validate_error(void* ctx
, char const* msg
, ...)
2904 LIBXML2_CALLBACK_ERR(domdoc_validateNode
, msg
, ap
);
2908 static void LIBXML2_LOG_CALLBACK
validate_warning(void* ctx
, char const* msg
, ...)
2912 LIBXML2_CALLBACK_WARN(domdoc_validateNode
, msg
, ap
);
2916 static HRESULT WINAPI
domdoc_validateNode(
2917 IXMLDOMDocument3
* iface
,
2919 IXMLDOMParseError
** err
)
2921 domdoc
* This
= impl_from_IXMLDOMDocument3(iface
);
2922 LONG state
, err_code
= 0;
2926 TRACE("(%p)->(%p, %p)\n", This
, node
, err
);
2927 IXMLDOMDocument3_get_readyState(iface
, &state
);
2928 if (state
!= READYSTATE_COMPLETE
)
2931 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2938 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2942 if (!get_node_obj(node
)->node
|| get_node_obj(node
)->node
->doc
!= get_doc(This
))
2945 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2949 if (!is_wellformed(get_doc(This
)))
2951 ERR("doc not well-formed\n");
2953 *err
= create_parseError(E_XML_NOTWF
, NULL
, NULL
, NULL
, 0, 0, 0);
2957 /* DTD validation */
2958 if (get_doc(This
)->intSubset
|| get_doc(This
)->extSubset
)
2960 xmlValidCtxtPtr vctx
= xmlNewValidCtxt();
2961 vctx
->error
= validate_error
;
2962 vctx
->warning
= validate_warning
;
2965 if (!((node
== (IXMLDOMNode
*)iface
)?
2966 xmlValidateDocument(vctx
, get_doc(This
)) :
2967 xmlValidateElement(vctx
, get_doc(This
), get_node_obj(node
)->node
)))
2969 /* TODO: get a real error code here */
2970 TRACE("DTD validation failed\n");
2971 err_code
= E_XML_INVALID
;
2974 xmlFreeValidCtxt(vctx
);
2977 /* Schema validation */
2978 if (hr
== S_OK
&& This
->properties
->schemaCache
!= NULL
)
2981 hr
= SchemaCache_validate_tree(This
->properties
->schemaCache
, get_node_obj(node
)->node
);
2985 /* TODO: get a real error code here */
2988 TRACE("schema validation succeeded\n");
2992 ERR("schema validation failed\n");
2993 err_code
= E_XML_INVALID
;
2998 /* not really OK, just didn't find a schema for the ns */
3005 ERR("no DTD or schema found\n");
3006 err_code
= E_XML_NODTD
;
3011 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
3016 static HRESULT WINAPI
domdoc_validate(
3017 IXMLDOMDocument3
* iface
,
3018 IXMLDOMParseError
** err
)
3020 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3021 TRACE("(%p)->(%p)\n", This
, err
);
3022 return IXMLDOMDocument3_validateNode(iface
, (IXMLDOMNode
*)iface
, err
);
3025 static HRESULT WINAPI
domdoc_setProperty(
3026 IXMLDOMDocument3
* iface
,
3030 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3032 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(p
), debugstr_variant(&value
));
3034 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
3040 V_VT(&varStr
) = VT_EMPTY
;
3041 if (V_VT(&value
) != VT_BSTR
)
3043 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
3045 bstr
= V_BSTR(&varStr
);
3048 bstr
= V_BSTR(&value
);
3051 if (lstrcmpiW(bstr
, PropValueXPathW
) == 0)
3052 This
->properties
->XPath
= TRUE
;
3053 else if (lstrcmpiW(bstr
, PropValueXSLPatternW
) == 0)
3054 This
->properties
->XPath
= FALSE
;
3058 VariantClear(&varStr
);
3061 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3063 xmlChar
*nsStr
= (xmlChar
*)This
->properties
->selectNsStr
;
3064 struct list
*pNsList
;
3069 V_VT(&varStr
) = VT_EMPTY
;
3070 if (V_VT(&value
) != VT_BSTR
)
3072 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
3074 bstr
= V_BSTR(&varStr
);
3077 bstr
= V_BSTR(&value
);
3081 pNsList
= &(This
->properties
->selectNsList
);
3082 clear_selectNsList(pNsList
);
3084 nsStr
= xmlchar_from_wchar(bstr
);
3086 TRACE("property value: \"%s\"\n", debugstr_w(bstr
));
3088 This
->properties
->selectNsStr
= nsStr
;
3089 This
->properties
->selectNsStr_len
= xmlStrlen(nsStr
);
3092 xmlChar
*pTokBegin
, *pTokEnd
, *pTokInner
;
3093 select_ns_entry
* ns_entry
= NULL
;
3094 xmlXPathContextPtr ctx
;
3096 ctx
= xmlXPathNewContext(This
->node
.node
->doc
);
3099 /* skip leading spaces */
3100 while (*pTokBegin
== ' ' || *pTokBegin
== '\n' ||
3101 *pTokBegin
== '\t' || *pTokBegin
== '\r')
3104 for (; *pTokBegin
; pTokBegin
= pTokEnd
)
3107 memset(ns_entry
, 0, sizeof(select_ns_entry
));
3109 ns_entry
= heap_alloc_zero(sizeof(select_ns_entry
));
3111 while (*pTokBegin
== ' ')
3113 pTokEnd
= pTokBegin
;
3114 while (*pTokEnd
!= ' ' && *pTokEnd
!= 0)
3117 /* so it failed to advance which means we've got some trailing spaces */
3118 if (pTokEnd
== pTokBegin
) break;
3120 if (xmlStrncmp(pTokBegin
, (xmlChar
const*)"xmlns", 5) != 0)
3123 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3124 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
3129 if (*pTokBegin
== '=')
3131 /*valid for XSLPattern?*/
3132 FIXME("Setting default xmlns not supported - skipping.\n");
3135 else if (*pTokBegin
== ':')
3137 ns_entry
->prefix
= ++pTokBegin
;
3138 for (pTokInner
= pTokBegin
; pTokInner
!= pTokEnd
&& *pTokInner
!= '='; ++pTokInner
)
3141 if (pTokInner
== pTokEnd
)
3144 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3145 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
3149 ns_entry
->prefix_end
= *pTokInner
;
3153 if (pTokEnd
-pTokInner
> 1 &&
3154 ((*pTokInner
== '\'' && *(pTokEnd
-1) == '\'') ||
3155 (*pTokInner
== '"' && *(pTokEnd
-1) == '"')))
3157 ns_entry
->href
= ++pTokInner
;
3158 ns_entry
->href_end
= *(pTokEnd
-1);
3160 list_add_tail(pNsList
, &ns_entry
->entry
);
3161 /*let libxml figure out if they're valid from here ;)*/
3162 if (xmlXPathRegisterNs(ctx
, ns_entry
->prefix
, ns_entry
->href
) != 0)
3171 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3172 debugstr_w(bstr
), debugstr_an((const char*)pTokInner
, pTokEnd
-pTokInner
));
3173 list_add_tail(pNsList
, &ns_entry
->entry
);
3186 heap_free(ns_entry
);
3187 xmlXPathFreeContext(ctx
);
3190 VariantClear(&varStr
);
3193 else if (lstrcmpiW(p
, PropertyValidateOnParse
) == 0)
3195 if (This
->properties
->version
< MSXML4
)
3199 This
->properties
->validating
= V_BOOL(&value
);
3203 else if (lstrcmpiW(p
, PropertyProhibitDTDW
) == 0 ||
3204 lstrcmpiW(p
, PropertyNewParserW
) == 0 ||
3205 lstrcmpiW(p
, PropertyResolveExternalsW
) == 0 ||
3206 lstrcmpiW(p
, PropertyAllowXsltScriptW
) == 0 ||
3207 lstrcmpiW(p
, PropertyNormalizeAttributeValuesW
) == 0 ||
3208 lstrcmpiW(p
, PropertyAllowDocumentFunctionW
) == 0)
3211 FIXME("Ignoring property %s, value %s\n", debugstr_w(p
), debugstr_variant(&value
));
3215 FIXME("Unknown property %s\n", debugstr_w(p
));
3219 static HRESULT WINAPI
domdoc_getProperty(
3220 IXMLDOMDocument3
* iface
,
3224 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3226 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
3229 return E_INVALIDARG
;
3231 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
3233 V_VT(var
) = VT_BSTR
;
3234 V_BSTR(var
) = This
->properties
->XPath
?
3235 SysAllocString(PropValueXPathW
) :
3236 SysAllocString(PropValueXSLPatternW
);
3237 return V_BSTR(var
) ? S_OK
: E_OUTOFMEMORY
;
3239 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3242 BSTR rebuiltStr
, cur
;
3243 const xmlChar
*nsStr
;
3244 struct list
*pNsList
;
3245 select_ns_entry
* pNsEntry
;
3247 V_VT(var
) = VT_BSTR
;
3248 nsStr
= This
->properties
->selectNsStr
;
3249 pNsList
= &This
->properties
->selectNsList
;
3250 lenA
= This
->properties
->selectNsStr_len
;
3251 lenW
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, NULL
, 0);
3252 rebuiltStr
= heap_alloc(lenW
*sizeof(WCHAR
));
3253 MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, rebuiltStr
, lenW
);
3255 /* this is fine because all of the chars that end tokens are ASCII*/
3256 LIST_FOR_EACH_ENTRY(pNsEntry
, pNsList
, select_ns_entry
, entry
)
3258 while (*cur
!= 0) ++cur
;
3259 if (pNsEntry
->prefix_end
)
3261 *cur
= pNsEntry
->prefix_end
;
3262 while (*cur
!= 0) ++cur
;
3265 if (pNsEntry
->href_end
)
3267 *cur
= pNsEntry
->href_end
;
3270 V_BSTR(var
) = SysAllocString(rebuiltStr
);
3271 heap_free(rebuiltStr
);
3274 else if (lstrcmpiW(p
, PropertyValidateOnParse
) == 0)
3276 if (This
->properties
->version
< MSXML4
)
3280 V_VT(var
) = VT_BOOL
;
3281 V_BOOL(var
) = This
->properties
->validating
;
3286 FIXME("Unknown property %s\n", debugstr_w(p
));
3290 static HRESULT WINAPI
domdoc_importNode(
3291 IXMLDOMDocument3
* iface
,
3294 IXMLDOMNode
** clone
)
3296 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3297 FIXME("(%p)->(%p %d %p): stub\n", This
, node
, deep
, clone
);
3301 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl
=
3303 domdoc_QueryInterface
,
3306 domdoc_GetTypeInfoCount
,
3308 domdoc_GetIDsOfNames
,
3310 domdoc_get_nodeName
,
3311 domdoc_get_nodeValue
,
3312 domdoc_put_nodeValue
,
3313 domdoc_get_nodeType
,
3314 domdoc_get_parentNode
,
3315 domdoc_get_childNodes
,
3316 domdoc_get_firstChild
,
3317 domdoc_get_lastChild
,
3318 domdoc_get_previousSibling
,
3319 domdoc_get_nextSibling
,
3320 domdoc_get_attributes
,
3321 domdoc_insertBefore
,
3322 domdoc_replaceChild
,
3325 domdoc_hasChildNodes
,
3326 domdoc_get_ownerDocument
,
3328 domdoc_get_nodeTypeString
,
3331 domdoc_get_specified
,
3332 domdoc_get_definition
,
3333 domdoc_get_nodeTypedValue
,
3334 domdoc_put_nodeTypedValue
,
3335 domdoc_get_dataType
,
3336 domdoc_put_dataType
,
3338 domdoc_transformNode
,
3340 domdoc_selectSingleNode
,
3342 domdoc_get_namespaceURI
,
3344 domdoc_get_baseName
,
3345 domdoc_transformNodeToObject
,
3347 domdoc_get_implementation
,
3348 domdoc_get_documentElement
,
3349 domdoc_put_documentElement
,
3350 domdoc_createElement
,
3351 domdoc_createDocumentFragment
,
3352 domdoc_createTextNode
,
3353 domdoc_createComment
,
3354 domdoc_createCDATASection
,
3355 domdoc_createProcessingInstruction
,
3356 domdoc_createAttribute
,
3357 domdoc_createEntityReference
,
3358 domdoc_getElementsByTagName
,
3362 domdoc_get_readyState
,
3363 domdoc_get_parseError
,
3370 domdoc_get_validateOnParse
,
3371 domdoc_put_validateOnParse
,
3372 domdoc_get_resolveExternals
,
3373 domdoc_put_resolveExternals
,
3374 domdoc_get_preserveWhiteSpace
,
3375 domdoc_put_preserveWhiteSpace
,
3376 domdoc_put_onreadystatechange
,
3377 domdoc_put_onDataAvailable
,
3378 domdoc_put_onTransformNode
,
3379 domdoc_get_namespaces
,
3381 domdoc_putref_schemas
,
3385 domdoc_validateNode
,
3389 /* IConnectionPointContainer */
3390 static HRESULT WINAPI
ConnectionPointContainer_QueryInterface(IConnectionPointContainer
*iface
,
3391 REFIID riid
, void **ppv
)
3393 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3394 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3397 static ULONG WINAPI
ConnectionPointContainer_AddRef(IConnectionPointContainer
*iface
)
3399 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3400 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3403 static ULONG WINAPI
ConnectionPointContainer_Release(IConnectionPointContainer
*iface
)
3405 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3406 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3409 static HRESULT WINAPI
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer
*iface
,
3410 IEnumConnectionPoints
**ppEnum
)
3412 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3413 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3417 static HRESULT WINAPI
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer
*iface
,
3418 REFIID riid
, IConnectionPoint
**cp
)
3420 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3421 ConnectionPoint
*iter
;
3423 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), cp
);
3427 for(iter
= This
->cp_list
; iter
; iter
= iter
->next
)
3429 if (IsEqualGUID(iter
->iid
, riid
))
3430 *cp
= &iter
->IConnectionPoint_iface
;
3435 IConnectionPoint_AddRef(*cp
);
3439 FIXME("unsupported riid %s\n", debugstr_guid(riid
));
3440 return CONNECT_E_NOCONNECTION
;
3444 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl
=
3446 ConnectionPointContainer_QueryInterface
,
3447 ConnectionPointContainer_AddRef
,
3448 ConnectionPointContainer_Release
,
3449 ConnectionPointContainer_EnumConnectionPoints
,
3450 ConnectionPointContainer_FindConnectionPoint
3453 /* IConnectionPoint */
3454 static HRESULT WINAPI
ConnectionPoint_QueryInterface(IConnectionPoint
*iface
,
3455 REFIID riid
, void **ppv
)
3457 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3459 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
3463 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
3464 IsEqualGUID(&IID_IConnectionPoint
, riid
))
3471 IConnectionPoint_AddRef(iface
);
3475 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
3476 return E_NOINTERFACE
;
3479 static ULONG WINAPI
ConnectionPoint_AddRef(IConnectionPoint
*iface
)
3481 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3482 return IConnectionPointContainer_AddRef(This
->container
);
3485 static ULONG WINAPI
ConnectionPoint_Release(IConnectionPoint
*iface
)
3487 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3488 return IConnectionPointContainer_Release(This
->container
);
3491 static HRESULT WINAPI
ConnectionPoint_GetConnectionInterface(IConnectionPoint
*iface
, IID
*iid
)
3493 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3495 TRACE("(%p)->(%p)\n", This
, iid
);
3497 if (!iid
) return E_POINTER
;
3503 static HRESULT WINAPI
ConnectionPoint_GetConnectionPointContainer(IConnectionPoint
*iface
,
3504 IConnectionPointContainer
**container
)
3506 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3508 TRACE("(%p)->(%p)\n", This
, container
);
3510 if (!container
) return E_POINTER
;
3512 *container
= This
->container
;
3513 IConnectionPointContainer_AddRef(*container
);
3517 static HRESULT WINAPI
ConnectionPoint_Advise(IConnectionPoint
*iface
, IUnknown
*unk_sink
,
3520 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3525 TRACE("(%p)->(%p %p)\n", This
, unk_sink
, cookie
);
3527 hr
= IUnknown_QueryInterface(unk_sink
, This
->iid
, (void**)&sink
);
3528 if(FAILED(hr
) && !IsEqualGUID(&IID_IPropertyNotifySink
, This
->iid
))
3529 hr
= IUnknown_QueryInterface(unk_sink
, &IID_IDispatch
, (void**)&sink
);
3531 return CONNECT_E_CANNOTCONNECT
;
3535 for (i
= 0; i
< This
->sinks_size
; i
++)
3536 if (!This
->sinks
[i
].unk
)
3539 if (i
== This
->sinks_size
)
3540 This
->sinks
= heap_realloc(This
->sinks
,(++This
->sinks_size
)*sizeof(*This
->sinks
));
3544 This
->sinks
= heap_alloc(sizeof(*This
->sinks
));
3545 This
->sinks_size
= 1;
3549 This
->sinks
[i
].unk
= sink
;
3556 static HRESULT WINAPI
ConnectionPoint_Unadvise(IConnectionPoint
*iface
, DWORD cookie
)
3558 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3560 TRACE("%p, %ld.\n", iface
, cookie
);
3562 if (cookie
== 0 || cookie
> This
->sinks_size
|| !This
->sinks
[cookie
-1].unk
)
3563 return CONNECT_E_NOCONNECTION
;
3565 IUnknown_Release(This
->sinks
[cookie
-1].unk
);
3566 This
->sinks
[cookie
-1].unk
= NULL
;
3571 static HRESULT WINAPI
ConnectionPoint_EnumConnections(IConnectionPoint
*iface
,
3572 IEnumConnections
**ppEnum
)
3574 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3575 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3579 static const IConnectionPointVtbl ConnectionPointVtbl
=
3581 ConnectionPoint_QueryInterface
,
3582 ConnectionPoint_AddRef
,
3583 ConnectionPoint_Release
,
3584 ConnectionPoint_GetConnectionInterface
,
3585 ConnectionPoint_GetConnectionPointContainer
,
3586 ConnectionPoint_Advise
,
3587 ConnectionPoint_Unadvise
,
3588 ConnectionPoint_EnumConnections
3591 static void ConnectionPoint_Init(ConnectionPoint
*cp
, struct domdoc
*doc
, REFIID riid
)
3593 cp
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointVtbl
;
3599 cp
->next
= doc
->cp_list
;
3602 cp
->container
= &doc
->IConnectionPointContainer_iface
;
3605 /* domdoc implementation of IObjectWithSite */
3606 static HRESULT WINAPI
3607 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
3609 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3610 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObject
);
3613 static ULONG WINAPI
domdoc_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
3615 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3616 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3619 static ULONG WINAPI
domdoc_ObjectWithSite_Release( IObjectWithSite
* iface
)
3621 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3622 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3625 static HRESULT WINAPI
domdoc_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
3627 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3629 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
3634 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
3637 static HRESULT WINAPI
domdoc_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
3639 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3641 TRACE("(%p)->(%p)\n", iface
, punk
);
3647 IUnknown_Release( This
->site
);
3653 IUri_Release(This
->base_uri
);
3654 This
->base_uri
= NULL
;
3660 IUnknown_AddRef( punk
);
3663 IUnknown_Release( This
->site
);
3666 This
->base_uri
= get_base_uri(This
->site
);
3671 static const IObjectWithSiteVtbl domdocObjectSite
=
3673 domdoc_ObjectWithSite_QueryInterface
,
3674 domdoc_ObjectWithSite_AddRef
,
3675 domdoc_ObjectWithSite_Release
,
3676 domdoc_ObjectWithSite_SetSite
,
3677 domdoc_ObjectWithSite_GetSite
3680 static HRESULT WINAPI
domdoc_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
3682 domdoc
*This
= impl_from_IObjectSafety(iface
);
3683 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3686 static ULONG WINAPI
domdoc_Safety_AddRef(IObjectSafety
*iface
)
3688 domdoc
*This
= impl_from_IObjectSafety(iface
);
3689 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3692 static ULONG WINAPI
domdoc_Safety_Release(IObjectSafety
*iface
)
3694 domdoc
*This
= impl_from_IObjectSafety(iface
);
3695 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3698 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3700 static HRESULT WINAPI
domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3701 DWORD
*supported
, DWORD
*enabled
)
3703 domdoc
*This
= impl_from_IObjectSafety(iface
);
3705 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
3707 if(!supported
|| !enabled
) return E_POINTER
;
3709 *supported
= SAFETY_SUPPORTED_OPTIONS
;
3710 *enabled
= This
->safeopt
;
3715 static HRESULT WINAPI
domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3716 DWORD mask
, DWORD enabled
)
3718 domdoc
*doc
= impl_from_IObjectSafety(iface
);
3720 TRACE("%p, %s, %lx, %lx.\n", iface
, debugstr_guid(riid
), mask
, enabled
);
3722 if ((mask
& ~SAFETY_SUPPORTED_OPTIONS
) != 0)
3725 doc
->safeopt
= (doc
->safeopt
& ~mask
) | (mask
& enabled
);
3730 #undef SAFETY_SUPPORTED_OPTIONS
3732 static const IObjectSafetyVtbl domdocObjectSafetyVtbl
= {
3733 domdoc_Safety_QueryInterface
,
3734 domdoc_Safety_AddRef
,
3735 domdoc_Safety_Release
,
3736 domdoc_Safety_GetInterfaceSafetyOptions
,
3737 domdoc_Safety_SetInterfaceSafetyOptions
3740 static const tid_t domdoc_iface_tids
[] = {
3741 IXMLDOMDocument3_tid
,
3745 static dispex_static_data_t domdoc_dispex
= {
3747 IXMLDOMDocument3_tid
,
3752 HRESULT
get_domdoc_from_xmldoc(xmlDocPtr xmldoc
, IXMLDOMDocument3
**document
)
3756 doc
= heap_alloc( sizeof (*doc
) );
3758 return E_OUTOFMEMORY
;
3760 doc
->IXMLDOMDocument3_iface
.lpVtbl
= &XMLDOMDocument3Vtbl
;
3761 doc
->IPersistStreamInit_iface
.lpVtbl
= &xmldoc_IPersistStreamInit_VTable
;
3762 doc
->IObjectWithSite_iface
.lpVtbl
= &domdocObjectSite
;
3763 doc
->IObjectSafety_iface
.lpVtbl
= &domdocObjectSafetyVtbl
;
3764 doc
->IConnectionPointContainer_iface
.lpVtbl
= &ConnectionPointContainerVtbl
;
3766 doc
->async
= VARIANT_TRUE
;
3768 doc
->properties
= properties_add_ref(properties_from_xmlDocPtr(xmldoc
));
3771 doc
->base_uri
= NULL
;
3773 doc
->cp_list
= NULL
;
3774 doc
->namespaces
= NULL
;
3775 memset(doc
->events
, 0, sizeof(doc
->events
));
3777 /* events connection points */
3778 ConnectionPoint_Init(&doc
->cp_dispatch
, doc
, &IID_IDispatch
);
3779 ConnectionPoint_Init(&doc
->cp_propnotif
, doc
, &IID_IPropertyNotifySink
);
3780 ConnectionPoint_Init(&doc
->cp_domdocevents
, doc
, &DIID_XMLDOMDocumentEvents
);
3782 init_xmlnode(&doc
->node
, (xmlNodePtr
)xmldoc
, (IXMLDOMNode
*)&doc
->IXMLDOMDocument3_iface
,
3785 *document
= &doc
->IXMLDOMDocument3_iface
;
3787 TRACE("returning iface %p\n", *document
);
3791 HRESULT
dom_document_create(MSXML_VERSION version
, void **ppObj
)
3796 TRACE("(%d, %p)\n", version
, ppObj
);
3798 xmldoc
= xmlNewDoc(NULL
);
3800 return E_OUTOFMEMORY
;
3802 xmldoc_init(xmldoc
, version
);
3804 hr
= get_domdoc_from_xmldoc(xmldoc
, (IXMLDOMDocument3
**)ppObj
);
3807 properties_release(properties_from_xmlDocPtr(xmldoc
));
3808 heap_free(xmldoc
->_private
);
3816 IUnknown
* create_domdoc( xmlNodePtr document
)
3818 IUnknown
*obj
= NULL
;
3821 TRACE("(%p)\n", document
);
3823 hr
= get_domdoc_from_xmldoc((xmlDocPtr
)document
, (IXMLDOMDocument3
**)&obj
);