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};
72 /* Anything that passes the test_get_ownerDocument()
73 * tests can go here (data shared between all instances).
74 * We need to preserve this when reloading a document,
75 * and also need access to it from the libxml backend. */
78 MSXML_VERSION version
;
79 VARIANT_BOOL preserving
;
80 IXMLDOMSchemaCollection2
* schemaCache
;
81 struct list selectNsList
;
82 xmlChar
const* selectNsStr
;
88 typedef struct ConnectionPoint ConnectionPoint
;
89 typedef struct domdoc domdoc
;
91 struct ConnectionPoint
93 IConnectionPoint IConnectionPoint_iface
;
96 ConnectionPoint
*next
;
97 IConnectionPointContainer
*container
;
104 IPropertyNotifySink
*propnotif
;
110 EVENTID_READYSTATECHANGE
= 0,
111 EVENTID_DATAAVAILABLE
,
112 EVENTID_TRANSFORMNODE
,
119 IXMLDOMDocument3 IXMLDOMDocument3_iface
;
120 IPersistStreamInit IPersistStreamInit_iface
;
121 IObjectWithSite IObjectWithSite_iface
;
122 IObjectSafety IObjectSafety_iface
;
123 IConnectionPointContainer IConnectionPointContainer_iface
;
126 VARIANT_BOOL validating
;
127 VARIANT_BOOL resolving
;
128 domdoc_properties
* properties
;
131 /* IObjectWithSite */
138 /* connection list */
139 ConnectionPoint
*cp_list
;
140 ConnectionPoint cp_domdocevents
;
141 ConnectionPoint cp_propnotif
;
142 ConnectionPoint cp_dispatch
;
145 IDispatch
*events
[EVENTID_LAST
];
147 IXMLDOMSchemaCollection2
*namespaces
;
150 static HRESULT
set_doc_event(domdoc
*doc
, eventid_t eid
, const VARIANT
*v
)
158 IUnknown_QueryInterface(V_UNKNOWN(v
), &IID_IDispatch
, (void**)&disp
);
163 disp
= V_DISPATCH(v
);
164 if (disp
) IDispatch_AddRef(disp
);
167 return DISP_E_TYPEMISMATCH
;
170 if (doc
->events
[eid
]) IDispatch_Release(doc
->events
[eid
]);
171 doc
->events
[eid
] = disp
;
176 static inline ConnectionPoint
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
178 return CONTAINING_RECORD(iface
, ConnectionPoint
, IConnectionPoint_iface
);
182 In native windows, the whole lifetime management of XMLDOMNodes is
183 managed automatically using reference counts. Wine emulates that by
184 maintaining a reference count to the document that is increased for
185 each IXMLDOMNode pointer passed out for this document. If all these
186 pointers are gone, the document is unreachable and gets freed, that
187 is, all nodes in the tree of the document get freed.
189 You are able to create nodes that are associated to a document (in
190 fact, in msxml's XMLDOM model, all nodes are associated to a document),
191 but not in the tree of that document, for example using the createFoo
192 functions from IXMLDOMDocument. These nodes do not get cleaned up
193 by libxml, so we have to do it ourselves.
195 To catch these nodes, a list of "orphan nodes" is introduced.
196 It contains pointers to all roots of node trees that are
197 associated with the document without being part of the document
198 tree. All nodes with parent==NULL (except for the document root nodes)
199 should be in the orphan node list of their document. All orphan nodes
200 get freed together with the document itself.
203 typedef struct _xmldoc_priv
{
206 domdoc_properties
* properties
;
209 typedef struct _orphan_entry
{
214 typedef struct _select_ns_entry
{
216 xmlChar
const* prefix
;
222 static inline xmldoc_priv
* priv_from_xmlDocPtr(const xmlDocPtr doc
)
224 return doc
->_private
;
227 static inline domdoc_properties
* properties_from_xmlDocPtr(xmlDocPtr doc
)
229 return priv_from_xmlDocPtr(doc
)->properties
;
232 BOOL
is_xpathmode(const xmlDocPtr doc
)
234 return properties_from_xmlDocPtr(doc
)->XPath
;
237 void set_xpathmode(xmlDocPtr doc
, BOOL xpath
)
239 properties_from_xmlDocPtr(doc
)->XPath
= xpath
;
242 int registerNamespaces(xmlXPathContextPtr ctxt
)
245 const select_ns_entry
* ns
= NULL
;
246 const struct list
* pNsList
= &properties_from_xmlDocPtr(ctxt
->doc
)->selectNsList
;
248 TRACE("(%p)\n", ctxt
);
250 LIST_FOR_EACH_ENTRY( ns
, pNsList
, select_ns_entry
, entry
)
252 xmlXPathRegisterNs(ctxt
, ns
->prefix
, ns
->href
);
259 static inline void clear_selectNsList(struct list
* pNsList
)
261 select_ns_entry
*ns
, *ns2
;
262 LIST_FOR_EACH_ENTRY_SAFE( ns
, ns2
, pNsList
, select_ns_entry
, entry
)
269 static xmldoc_priv
* create_priv(void)
272 priv
= heap_alloc( sizeof (*priv
) );
277 list_init( &priv
->orphans
);
278 priv
->properties
= NULL
;
284 static domdoc_properties
*create_properties(MSXML_VERSION version
)
286 domdoc_properties
*properties
= heap_alloc(sizeof(domdoc_properties
));
288 properties
->refs
= 1;
289 list_init(&properties
->selectNsList
);
290 properties
->preserving
= VARIANT_FALSE
;
291 properties
->schemaCache
= NULL
;
292 properties
->selectNsStr
= heap_alloc_zero(sizeof(xmlChar
));
293 properties
->selectNsStr_len
= 0;
295 /* properties that are dependent on object versions */
296 properties
->version
= version
;
297 properties
->XPath
= (version
== MSXML4
|| version
== MSXML6
);
300 properties
->uri
= NULL
;
305 static domdoc_properties
* copy_properties(domdoc_properties
const* properties
)
307 domdoc_properties
* pcopy
= heap_alloc(sizeof(domdoc_properties
));
308 select_ns_entry
const* ns
= NULL
;
309 select_ns_entry
* new_ns
= NULL
;
310 int len
= (properties
->selectNsStr_len
+1)*sizeof(xmlChar
);
316 pcopy
->version
= properties
->version
;
317 pcopy
->preserving
= properties
->preserving
;
318 pcopy
->schemaCache
= properties
->schemaCache
;
319 if (pcopy
->schemaCache
)
320 IXMLDOMSchemaCollection2_AddRef(pcopy
->schemaCache
);
321 pcopy
->XPath
= properties
->XPath
;
322 pcopy
->selectNsStr_len
= properties
->selectNsStr_len
;
323 list_init( &pcopy
->selectNsList
);
324 pcopy
->selectNsStr
= heap_alloc(len
);
325 memcpy((xmlChar
*)pcopy
->selectNsStr
, properties
->selectNsStr
, len
);
326 offset
= pcopy
->selectNsStr
- properties
->selectNsStr
;
328 LIST_FOR_EACH_ENTRY( ns
, (&properties
->selectNsList
), select_ns_entry
, entry
)
330 new_ns
= heap_alloc(sizeof(select_ns_entry
));
331 memcpy(new_ns
, ns
, sizeof(select_ns_entry
));
332 new_ns
->href
+= offset
;
333 new_ns
->prefix
+= offset
;
334 list_add_tail(&pcopy
->selectNsList
, &new_ns
->entry
);
337 pcopy
->uri
= properties
->uri
;
339 IUri_AddRef(pcopy
->uri
);
345 static domdoc_properties
* properties_add_ref(domdoc_properties
*properties
)
349 if (!properties
) return NULL
;
351 ref
= InterlockedIncrement(&properties
->refs
);
352 TRACE("%p, %d.\n", properties
, ref
);
356 static void properties_release(domdoc_properties
*properties
)
360 if (!properties
) return;
362 ref
= InterlockedDecrement(&properties
->refs
);
364 TRACE("%p, %d.\n", properties
, ref
);
367 WARN("negative refcount, expect troubles\n");
371 if (properties
->schemaCache
)
372 IXMLDOMSchemaCollection2_Release(properties
->schemaCache
);
373 clear_selectNsList(&properties
->selectNsList
);
374 heap_free((xmlChar
*)properties
->selectNsStr
);
376 IUri_Release(properties
->uri
);
377 heap_free(properties
);
381 static void release_namespaces(domdoc
*This
)
383 if (This
->namespaces
)
385 IXMLDOMSchemaCollection2_Release(This
->namespaces
);
386 This
->namespaces
= NULL
;
390 /* links a "<?xml" node as a first child */
391 void xmldoc_link_xmldecl(xmlDocPtr doc
, xmlNodePtr node
)
394 if (doc
->standalone
!= -1) xmlAddPrevSibling( doc
->children
, node
);
397 /* unlinks a first "<?xml" child if it was created */
398 xmlNodePtr
xmldoc_unlink_xmldecl(xmlDocPtr doc
)
400 static const xmlChar xmlA
[] = "xml";
401 xmlNodePtr node
, first_child
;
405 /* xml declaration node could be created automatically after parsing or added
407 first_child
= doc
->children
;
408 if (first_child
&& first_child
->type
== XML_PI_NODE
&& xmlStrEqual(first_child
->name
, xmlA
))
411 xmlUnlinkNode( node
);
419 MSXML_VERSION
xmldoc_version(xmlDocPtr doc
)
421 return properties_from_xmlDocPtr(doc
)->version
;
424 BOOL
is_preserving_whitespace(xmlNodePtr node
)
426 domdoc_properties
* properties
= NULL
;
427 /* during parsing the xmlDoc._private stuff is not there */
428 if (priv_from_xmlDocPtr(node
->doc
))
429 properties
= properties_from_xmlDocPtr(node
->doc
);
430 return ((properties
&& properties
->preserving
== VARIANT_TRUE
) ||
431 xmlNodeGetSpacePreserve(node
) == 1);
434 static inline BOOL
strn_isspace(xmlChar
const* str
, int len
)
436 for (; str
&& len
> 0 && *str
; ++str
, --len
)
443 static void sax_characters(void *ctx
, const xmlChar
*ch
, int len
)
445 xmlParserCtxtPtr ctxt
;
448 ctxt
= (xmlParserCtxtPtr
) ctx
;
449 This
= (const domdoc
*) ctxt
->_private
;
453 xmlChar cur
= *(ctxt
->input
->cur
);
455 /* Characters are reported with multiple calls, for example each charref is reported with a separate
456 call and then parser appends it to a single text node or creates a new node if not created.
457 It's not possible to tell if it's ignorable data or not just looking at data itself cause it could be
458 space chars that separate charrefs or similar case. We only need to skip leading and trailing spaces,
459 or whole node if it has nothing but space chars, so to detect leading space node->last is checked that
460 contains text node pointer if already created, trailing spaces are detected directly looking at parser input
461 for next '<' opening bracket - similar logic is used by libxml2 itself. Basically 'cur' == '<' means the last
462 chunk of char data, in case it's not the last chunk we check for previously added node type and if it's not
463 a text node it's safe to ignore.
465 Note that during domdoc_loadXML() the xmlDocPtr->_private data is not available. */
467 if (!This
->properties
->preserving
&&
468 !is_preserving_whitespace(ctxt
->node
) &&
469 strn_isspace(ch
, len
) &&
470 (!ctxt
->node
->last
||
471 ((ctxt
->node
->last
&& (cur
== '<' || ctxt
->node
->last
->type
!= XML_TEXT_NODE
))
474 /* Keep information about ignorable whitespace text node in previous or parent node */
475 if (ctxt
->node
->last
)
476 *(DWORD
*)&ctxt
->node
->last
->_private
|= NODE_PRIV_TRAILING_IGNORABLE_WS
;
477 else if (ctxt
->node
->type
!= XML_DOCUMENT_NODE
)
478 *(DWORD
*)&ctxt
->node
->_private
|= NODE_PRIV_CHILD_IGNORABLE_WS
;
483 xmlSAX2Characters(ctxt
, ch
, len
);
486 static void LIBXML2_LOG_CALLBACK
sax_error(void* ctx
, char const* msg
, ...)
490 LIBXML2_CALLBACK_ERR(doparse
, msg
, ap
);
494 static void LIBXML2_LOG_CALLBACK
sax_warning(void* ctx
, char const* msg
, ...)
498 LIBXML2_CALLBACK_WARN(doparse
, msg
, ap
);
502 static void sax_serror(void* ctx
, xmlErrorPtr err
)
504 LIBXML2_CALLBACK_SERROR(doparse
, err
);
507 static xmlDocPtr
doparse(domdoc
* This
, char const* ptr
, int len
, xmlCharEncoding encoding
)
509 xmlDocPtr doc
= NULL
;
510 xmlParserCtxtPtr pctx
;
511 static xmlSAXHandler sax_handler
= {
512 xmlSAX2InternalSubset
, /* internalSubset */
513 xmlSAX2IsStandalone
, /* isStandalone */
514 xmlSAX2HasInternalSubset
, /* hasInternalSubset */
515 xmlSAX2HasExternalSubset
, /* hasExternalSubset */
516 xmlSAX2ResolveEntity
, /* resolveEntity */
517 xmlSAX2GetEntity
, /* getEntity */
518 xmlSAX2EntityDecl
, /* entityDecl */
519 xmlSAX2NotationDecl
, /* notationDecl */
520 xmlSAX2AttributeDecl
, /* attributeDecl */
521 xmlSAX2ElementDecl
, /* elementDecl */
522 xmlSAX2UnparsedEntityDecl
, /* unparsedEntityDecl */
523 xmlSAX2SetDocumentLocator
, /* setDocumentLocator */
524 xmlSAX2StartDocument
, /* startDocument */
525 xmlSAX2EndDocument
, /* endDocument */
526 xmlSAX2StartElement
, /* startElement */
527 xmlSAX2EndElement
, /* endElement */
528 xmlSAX2Reference
, /* reference */
529 sax_characters
, /* characters */
530 sax_characters
, /* ignorableWhitespace */
531 xmlSAX2ProcessingInstruction
, /* processingInstruction */
532 xmlSAX2Comment
, /* comment */
533 sax_warning
, /* warning */
534 sax_error
, /* error */
535 sax_error
, /* fatalError */
536 xmlSAX2GetParameterEntity
, /* getParameterEntity */
537 xmlSAX2CDataBlock
, /* cdataBlock */
538 xmlSAX2ExternalSubset
, /* externalSubset */
541 xmlSAX2StartElementNs
, /* startElementNs */
542 xmlSAX2EndElementNs
, /* endElementNs */
543 sax_serror
/* serror */
546 pctx
= xmlCreateMemoryParserCtxt(ptr
, len
);
549 ERR("Failed to create parser context\n");
553 if (pctx
->sax
) xmlFree(pctx
->sax
);
554 pctx
->sax
= &sax_handler
;
555 pctx
->_private
= This
;
558 if (encoding
!= XML_CHAR_ENCODING_NONE
)
559 xmlSwitchEncoding(pctx
, encoding
);
561 xmlParseDocument(pctx
);
563 if (pctx
->wellFormed
)
569 xmlFreeDoc(pctx
->myDoc
);
573 xmlFreeParserCtxt(pctx
);
575 /* TODO: put this in one of the SAX callbacks */
576 /* create first child as a <?xml...?> */
577 if (doc
&& doc
->standalone
!= -1)
581 xmlChar
*xmlbuff
= (xmlChar
*)buff
;
583 node
= xmlNewDocPI( doc
, (xmlChar
*)"xml", NULL
);
585 /* version attribute can't be omitted */
586 sprintf(buff
, "version=\"%s\"", doc
->version
? (char*)doc
->version
: "1.0");
587 xmlNodeAddContent( node
, xmlbuff
);
591 sprintf(buff
, " encoding=\"%s\"", doc
->encoding
);
592 xmlNodeAddContent( node
, xmlbuff
);
595 if (doc
->standalone
!= -2)
597 sprintf(buff
, " standalone=\"%s\"", doc
->standalone
== 0 ? "no" : "yes");
598 xmlNodeAddContent( node
, xmlbuff
);
601 xmldoc_link_xmldecl( doc
, node
);
607 void xmldoc_init(xmlDocPtr doc
, MSXML_VERSION version
)
609 doc
->_private
= create_priv();
610 priv_from_xmlDocPtr(doc
)->properties
= create_properties(version
);
613 LONG
xmldoc_add_refs(xmlDocPtr doc
, LONG refs
)
615 LONG ref
= InterlockedExchangeAdd(&priv_from_xmlDocPtr(doc
)->refs
, refs
) + refs
;
616 TRACE("(%p)->(%d)\n", doc
, ref
);
620 LONG
xmldoc_add_ref(xmlDocPtr doc
)
622 return xmldoc_add_refs(doc
, 1);
625 LONG
xmldoc_release_refs(xmlDocPtr doc
, LONG refs
)
627 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
628 LONG ref
= InterlockedExchangeAdd(&priv
->refs
, -refs
) - refs
;
629 TRACE("(%p)->(%d)\n", doc
, ref
);
632 WARN("negative refcount, expect troubles\n");
636 orphan_entry
*orphan
, *orphan2
;
637 TRACE("freeing docptr %p\n", doc
);
639 LIST_FOR_EACH_ENTRY_SAFE( orphan
, orphan2
, &priv
->orphans
, orphan_entry
, entry
)
641 xmlFreeNode( orphan
->node
);
644 properties_release(priv
->properties
);
645 heap_free(doc
->_private
);
653 LONG
xmldoc_release(xmlDocPtr doc
)
655 return xmldoc_release_refs(doc
, 1);
658 HRESULT
xmldoc_add_orphan(xmlDocPtr doc
, xmlNodePtr node
)
660 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
663 entry
= heap_alloc( sizeof (*entry
) );
665 return E_OUTOFMEMORY
;
668 list_add_head( &priv
->orphans
, &entry
->entry
);
672 HRESULT
xmldoc_remove_orphan(xmlDocPtr doc
, xmlNodePtr node
)
674 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
675 orphan_entry
*entry
, *entry2
;
677 LIST_FOR_EACH_ENTRY_SAFE( entry
, entry2
, &priv
->orphans
, orphan_entry
, entry
)
679 if( entry
->node
== node
)
681 list_remove( &entry
->entry
);
690 static inline xmlDocPtr
get_doc( domdoc
*This
)
692 return This
->node
.node
->doc
;
695 static HRESULT
attach_xmldoc(domdoc
*This
, xmlDocPtr xml
)
697 release_namespaces(This
);
701 properties_release(properties_from_xmlDocPtr(get_doc(This
)));
702 priv_from_xmlDocPtr(get_doc(This
))->properties
= NULL
;
703 if (xmldoc_release(get_doc(This
)) != 0)
705 /* The xmlDocPtr object can no longer use the properties of this
706 * domdoc object. So give it its own copy.
708 priv_from_xmlDocPtr(get_doc(This
))->properties
=
709 copy_properties(This
->properties
);
713 This
->node
.node
= (xmlNodePtr
) xml
;
717 xmldoc_add_ref(get_doc(This
));
718 /* Only attach new xmlDocPtr objects, i.e. ones for which properties
721 priv_from_xmlDocPtr(get_doc(This
))->properties
= properties_add_ref(This
->properties
);
727 static inline domdoc
*impl_from_IXMLDOMDocument3( IXMLDOMDocument3
*iface
)
729 return CONTAINING_RECORD(iface
, domdoc
, IXMLDOMDocument3_iface
);
732 static inline domdoc
*impl_from_IPersistStreamInit(IPersistStreamInit
*iface
)
734 return CONTAINING_RECORD(iface
, domdoc
, IPersistStreamInit_iface
);
737 static inline domdoc
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
739 return CONTAINING_RECORD(iface
, domdoc
, IObjectWithSite_iface
);
742 static inline domdoc
*impl_from_IObjectSafety(IObjectSafety
*iface
)
744 return CONTAINING_RECORD(iface
, domdoc
, IObjectSafety_iface
);
747 static inline domdoc
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
749 return CONTAINING_RECORD(iface
, domdoc
, IConnectionPointContainer_iface
);
752 /************************************************************************
753 * domdoc implementation of IPersistStream.
755 static HRESULT WINAPI
PersistStreamInit_QueryInterface(
756 IPersistStreamInit
*iface
, REFIID riid
, void **ppvObj
)
758 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
759 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObj
);
762 static ULONG WINAPI
PersistStreamInit_AddRef(
763 IPersistStreamInit
*iface
)
765 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
766 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
769 static ULONG WINAPI
PersistStreamInit_Release(
770 IPersistStreamInit
*iface
)
772 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
773 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
776 static HRESULT WINAPI
PersistStreamInit_GetClassID(
777 IPersistStreamInit
*iface
, CLSID
*classid
)
779 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
780 TRACE("(%p)->(%p)\n", This
, classid
);
785 *classid
= *DOMDocument_version(This
->properties
->version
);
790 static HRESULT WINAPI
PersistStreamInit_IsDirty(
791 IPersistStreamInit
*iface
)
793 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
794 FIXME("(%p): stub!\n", This
);
798 static HRESULT
domdoc_load_from_stream(domdoc
*doc
, ISequentialStream
*stream
)
800 DWORD read
, written
, len
;
801 xmlDocPtr xmldoc
= NULL
;
809 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &hstream
);
815 ISequentialStream_Read(stream
, buf
, sizeof(buf
), &read
);
816 hr
= IStream_Write(hstream
, buf
, read
, &written
);
817 } while(SUCCEEDED(hr
) && written
!= 0 && read
!= 0);
821 ERR("failed to copy stream 0x%08x\n", hr
);
822 IStream_Release(hstream
);
826 hr
= GetHGlobalFromStream(hstream
, &hglobal
);
829 IStream_Release(hstream
);
833 len
= GlobalSize(hglobal
);
834 ptr
= GlobalLock(hglobal
);
836 xmldoc
= doparse(doc
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
837 GlobalUnlock(hglobal
);
838 IStream_Release(hstream
);
842 ERR("Failed to parse xml\n");
846 xmldoc
->_private
= create_priv();
848 return attach_xmldoc(doc
, xmldoc
);
851 static HRESULT WINAPI
PersistStreamInit_Load(IPersistStreamInit
*iface
, IStream
*stream
)
853 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
855 TRACE("(%p)->(%p)\n", This
, stream
);
860 return This
->error
= domdoc_load_from_stream(This
, (ISequentialStream
*)stream
);
863 static HRESULT WINAPI
PersistStreamInit_Save(
864 IPersistStreamInit
*iface
, IStream
*stream
, BOOL clr_dirty
)
866 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
870 TRACE("(%p)->(%p %d)\n", This
, stream
, clr_dirty
);
872 hr
= IXMLDOMDocument3_get_xml(&This
->IXMLDOMDocument3_iface
, &xmlString
);
875 DWORD len
= SysStringLen(xmlString
) * sizeof(WCHAR
);
877 hr
= IStream_Write( stream
, xmlString
, len
, NULL
);
878 SysFreeString(xmlString
);
881 TRACE("ret 0x%08x\n", hr
);
886 static HRESULT WINAPI
PersistStreamInit_GetSizeMax(
887 IPersistStreamInit
*iface
, ULARGE_INTEGER
*pcbSize
)
889 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
890 TRACE("(%p)->(%p)\n", This
, pcbSize
);
894 static HRESULT WINAPI
PersistStreamInit_InitNew(
895 IPersistStreamInit
*iface
)
897 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
898 TRACE("(%p)\n", This
);
902 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable
=
904 PersistStreamInit_QueryInterface
,
905 PersistStreamInit_AddRef
,
906 PersistStreamInit_Release
,
907 PersistStreamInit_GetClassID
,
908 PersistStreamInit_IsDirty
,
909 PersistStreamInit_Load
,
910 PersistStreamInit_Save
,
911 PersistStreamInit_GetSizeMax
,
912 PersistStreamInit_InitNew
915 /* IXMLDOMDocument3 interface */
917 static const tid_t domdoc_se_tids
[] = {
920 IXMLDOMDocument2_tid
,
921 IXMLDOMDocument3_tid
,
925 static HRESULT WINAPI
domdoc_QueryInterface( IXMLDOMDocument3
*iface
, REFIID riid
, void** ppvObject
)
927 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
929 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( riid
), ppvObject
);
933 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
934 IsEqualGUID( riid
, &IID_IDispatch
) ||
935 IsEqualGUID( riid
, &IID_IXMLDOMNode
) ||
936 IsEqualGUID( riid
, &IID_IXMLDOMDocument
) ||
937 IsEqualGUID( riid
, &IID_IXMLDOMDocument2
)||
938 IsEqualGUID( riid
, &IID_IXMLDOMDocument3
))
942 else if (IsEqualGUID(&IID_IPersistStream
, riid
) ||
943 IsEqualGUID(&IID_IPersistStreamInit
, riid
))
945 *ppvObject
= &This
->IPersistStreamInit_iface
;
947 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
949 *ppvObject
= &This
->IObjectWithSite_iface
;
951 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
953 *ppvObject
= &This
->IObjectSafety_iface
;
955 else if( IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
957 return node_create_supporterrorinfo(domdoc_se_tids
, ppvObject
);
959 else if(node_query_interface(&This
->node
, riid
, ppvObject
))
961 return *ppvObject
? S_OK
: E_NOINTERFACE
;
963 else if (IsEqualGUID( riid
, &IID_IConnectionPointContainer
))
965 *ppvObject
= &This
->IConnectionPointContainer_iface
;
969 TRACE("interface %s not implemented\n", debugstr_guid(riid
));
970 return E_NOINTERFACE
;
973 IUnknown_AddRef((IUnknown
*)*ppvObject
);
978 static ULONG WINAPI
domdoc_AddRef( IXMLDOMDocument3
*iface
)
980 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
981 ULONG ref
= InterlockedIncrement( &This
->ref
);
982 TRACE("(%p)->(%d)\n", This
, ref
);
986 static ULONG WINAPI
domdoc_Release( IXMLDOMDocument3
*iface
)
988 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
989 LONG ref
= InterlockedDecrement( &This
->ref
);
991 TRACE("(%p)->(%d)\n", This
, ref
);
998 IUnknown_Release( This
->site
);
1000 IUri_Release( This
->base_uri
);
1001 destroy_xmlnode(&This
->node
);
1003 for (eid
= 0; eid
< EVENTID_LAST
; eid
++)
1004 if (This
->events
[eid
]) IDispatch_Release(This
->events
[eid
]);
1006 properties_release(This
->properties
);
1007 release_namespaces(This
);
1014 static HRESULT WINAPI
domdoc_GetTypeInfoCount( IXMLDOMDocument3
*iface
, UINT
* pctinfo
)
1016 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1017 return IDispatchEx_GetTypeInfoCount(&This
->node
.dispex
.IDispatchEx_iface
, pctinfo
);
1020 static HRESULT WINAPI
domdoc_GetTypeInfo(
1021 IXMLDOMDocument3
*iface
,
1022 UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
1024 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1025 return IDispatchEx_GetTypeInfo(&This
->node
.dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
1028 static HRESULT WINAPI
domdoc_GetIDsOfNames(
1029 IXMLDOMDocument3
*iface
,
1031 LPOLESTR
* rgszNames
,
1036 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1037 return IDispatchEx_GetIDsOfNames(&This
->node
.dispex
.IDispatchEx_iface
,
1038 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
1041 static HRESULT WINAPI
domdoc_Invoke(
1042 IXMLDOMDocument3
*iface
,
1043 DISPID dispIdMember
,
1047 DISPPARAMS
* pDispParams
,
1048 VARIANT
* pVarResult
,
1049 EXCEPINFO
* pExcepInfo
,
1052 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1053 return IDispatchEx_Invoke(&This
->node
.dispex
.IDispatchEx_iface
,
1054 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1057 static HRESULT WINAPI
domdoc_get_nodeName(
1058 IXMLDOMDocument3
*iface
,
1061 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1063 static const WCHAR documentW
[] = {'#','d','o','c','u','m','e','n','t',0};
1065 TRACE("(%p)->(%p)\n", This
, name
);
1067 return return_bstr(documentW
, name
);
1071 static HRESULT WINAPI
domdoc_get_nodeValue(
1072 IXMLDOMDocument3
*iface
,
1075 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1077 TRACE("(%p)->(%p)\n", This
, value
);
1080 return E_INVALIDARG
;
1082 V_VT(value
) = VT_NULL
;
1083 V_BSTR(value
) = NULL
; /* tests show that we should do this */
1088 static HRESULT WINAPI
domdoc_put_nodeValue(
1089 IXMLDOMDocument3
*iface
,
1092 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1093 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&value
));
1098 static HRESULT WINAPI
domdoc_get_nodeType(
1099 IXMLDOMDocument3
*iface
,
1102 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1104 TRACE("(%p)->(%p)\n", This
, type
);
1106 *type
= NODE_DOCUMENT
;
1111 static HRESULT WINAPI
domdoc_get_parentNode(
1112 IXMLDOMDocument3
*iface
,
1113 IXMLDOMNode
** parent
)
1115 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1117 TRACE("(%p)->(%p)\n", This
, parent
);
1119 return node_get_parent(&This
->node
, parent
);
1123 static HRESULT WINAPI
domdoc_get_childNodes(
1124 IXMLDOMDocument3
*iface
,
1125 IXMLDOMNodeList
** childList
)
1127 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1129 TRACE("(%p)->(%p)\n", This
, childList
);
1131 return node_get_child_nodes(&This
->node
, childList
);
1135 static HRESULT WINAPI
domdoc_get_firstChild(
1136 IXMLDOMDocument3
*iface
,
1137 IXMLDOMNode
** firstChild
)
1139 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1141 TRACE("(%p)->(%p)\n", This
, firstChild
);
1143 return node_get_first_child(&This
->node
, firstChild
);
1147 static HRESULT WINAPI
domdoc_get_lastChild(
1148 IXMLDOMDocument3
*iface
,
1149 IXMLDOMNode
** lastChild
)
1151 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1153 TRACE("(%p)->(%p)\n", This
, lastChild
);
1155 return node_get_last_child(&This
->node
, lastChild
);
1159 static HRESULT WINAPI
domdoc_get_previousSibling(
1160 IXMLDOMDocument3
*iface
,
1161 IXMLDOMNode
** previousSibling
)
1163 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1165 TRACE("(%p)->(%p)\n", This
, previousSibling
);
1167 return return_null_node(previousSibling
);
1171 static HRESULT WINAPI
domdoc_get_nextSibling(
1172 IXMLDOMDocument3
*iface
,
1173 IXMLDOMNode
** nextSibling
)
1175 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1177 TRACE("(%p)->(%p)\n", This
, nextSibling
);
1179 return return_null_node(nextSibling
);
1183 static HRESULT WINAPI
domdoc_get_attributes(
1184 IXMLDOMDocument3
*iface
,
1185 IXMLDOMNamedNodeMap
** attributeMap
)
1187 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1189 TRACE("(%p)->(%p)\n", This
, attributeMap
);
1191 return return_null_ptr((void**)attributeMap
);
1195 static HRESULT WINAPI
domdoc_insertBefore(
1196 IXMLDOMDocument3
*iface
,
1197 IXMLDOMNode
* newChild
,
1199 IXMLDOMNode
** outNewChild
)
1201 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1205 TRACE("(%p)->(%p %s %p)\n", This
, newChild
, debugstr_variant(&refChild
), outNewChild
);
1207 if (!newChild
) return E_INVALIDARG
;
1209 hr
= IXMLDOMNode_get_nodeType(newChild
, &type
);
1210 if (hr
!= S_OK
) return hr
;
1212 TRACE("new node type %d\n", type
);
1215 case NODE_ATTRIBUTE
:
1217 case NODE_CDATA_SECTION
:
1218 if (outNewChild
) *outNewChild
= NULL
;
1221 return node_insert_before(&This
->node
, newChild
, &refChild
, outNewChild
);
1225 static HRESULT WINAPI
domdoc_replaceChild(
1226 IXMLDOMDocument3
*iface
,
1227 IXMLDOMNode
* newChild
,
1228 IXMLDOMNode
* oldChild
,
1229 IXMLDOMNode
** outOldChild
)
1231 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1233 TRACE("(%p)->(%p %p %p)\n", This
, newChild
, oldChild
, outOldChild
);
1235 return node_replace_child(&This
->node
, newChild
, oldChild
, outOldChild
);
1239 static HRESULT WINAPI
domdoc_removeChild(
1240 IXMLDOMDocument3
*iface
,
1242 IXMLDOMNode
**oldChild
)
1244 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1245 TRACE("(%p)->(%p %p)\n", This
, child
, oldChild
);
1246 return node_remove_child(&This
->node
, child
, oldChild
);
1250 static HRESULT WINAPI
domdoc_appendChild(
1251 IXMLDOMDocument3
*iface
,
1253 IXMLDOMNode
**outChild
)
1255 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1256 TRACE("(%p)->(%p %p)\n", This
, child
, outChild
);
1257 return node_append_child(&This
->node
, child
, outChild
);
1261 static HRESULT WINAPI
domdoc_hasChildNodes(
1262 IXMLDOMDocument3
*iface
,
1265 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1266 TRACE("(%p)->(%p)\n", This
, ret
);
1267 return node_has_childnodes(&This
->node
, ret
);
1271 static HRESULT WINAPI
domdoc_get_ownerDocument(
1272 IXMLDOMDocument3
*iface
,
1273 IXMLDOMDocument
**doc
)
1275 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1276 TRACE("(%p)->(%p)\n", This
, doc
);
1277 return node_get_owner_doc(&This
->node
, doc
);
1281 static HRESULT WINAPI
domdoc_cloneNode(
1282 IXMLDOMDocument3
*iface
,
1284 IXMLDOMNode
** outNode
)
1286 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1289 TRACE("(%p)->(%d %p)\n", This
, deep
, outNode
);
1292 return E_INVALIDARG
;
1296 clone
= xmlCopyNode((xmlNodePtr
)get_doc(This
), deep
? 1 : 2);
1300 clone
->doc
->_private
= create_priv();
1301 xmldoc_add_orphan(clone
->doc
, clone
);
1302 xmldoc_add_ref(clone
->doc
);
1304 priv_from_xmlDocPtr(clone
->doc
)->properties
= copy_properties(This
->properties
);
1305 if (!(*outNode
= (IXMLDOMNode
*)create_domdoc(clone
)))
1307 xmldoc_release(clone
->doc
);
1315 static HRESULT WINAPI
domdoc_get_nodeTypeString(
1316 IXMLDOMDocument3
*iface
,
1319 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1320 static const WCHAR documentW
[] = {'d','o','c','u','m','e','n','t',0};
1322 TRACE("(%p)->(%p)\n", This
, p
);
1324 return return_bstr(documentW
, p
);
1328 static HRESULT WINAPI
domdoc_get_text(
1329 IXMLDOMDocument3
*iface
,
1332 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1333 TRACE("(%p)->(%p)\n", This
, p
);
1334 return node_get_text(&This
->node
, p
);
1338 static HRESULT WINAPI
domdoc_put_text(
1339 IXMLDOMDocument3
*iface
,
1342 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1343 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
1348 static HRESULT WINAPI
domdoc_get_specified(
1349 IXMLDOMDocument3
*iface
,
1350 VARIANT_BOOL
* isSpecified
)
1352 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1353 FIXME("(%p)->(%p) stub!\n", This
, isSpecified
);
1354 *isSpecified
= VARIANT_TRUE
;
1359 static HRESULT WINAPI
domdoc_get_definition(
1360 IXMLDOMDocument3
*iface
,
1361 IXMLDOMNode
** definitionNode
)
1363 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1364 FIXME("(%p)->(%p)\n", This
, definitionNode
);
1369 static HRESULT WINAPI
domdoc_get_nodeTypedValue(
1370 IXMLDOMDocument3
*iface
,
1373 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1374 TRACE("(%p)->(%p)\n", This
, v
);
1375 return return_null_var(v
);
1378 static HRESULT WINAPI
domdoc_put_nodeTypedValue(
1379 IXMLDOMDocument3
*iface
,
1380 VARIANT typedValue
)
1382 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1383 FIXME("(%p)->(%s)\n", This
, debugstr_variant(&typedValue
));
1388 static HRESULT WINAPI
domdoc_get_dataType(
1389 IXMLDOMDocument3
*iface
,
1392 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1393 TRACE("(%p)->(%p)\n", This
, typename
);
1394 return return_null_var( typename
);
1398 static HRESULT WINAPI
domdoc_put_dataType(
1399 IXMLDOMDocument3
*iface
,
1402 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1404 FIXME("(%p)->(%s)\n", This
, debugstr_w(dataTypeName
));
1407 return E_INVALIDARG
;
1412 static int XMLCALL
domdoc_get_xml_writecallback(void *ctx
, const char *data
, int len
)
1414 return xmlBufferAdd((xmlBufferPtr
)ctx
, (xmlChar
*)data
, len
) == 0 ? len
: 0;
1417 static HRESULT WINAPI
domdoc_get_xml(
1418 IXMLDOMDocument3
*iface
,
1421 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1422 xmlSaveCtxtPtr ctxt
;
1427 TRACE("(%p)->(%p)\n", This
, p
);
1430 return E_INVALIDARG
;
1434 buf
= xmlBufferCreate();
1436 return E_OUTOFMEMORY
;
1438 options
= XML_SAVE_FORMAT
| XML_SAVE_NO_DECL
;
1439 ctxt
= xmlSaveToIO(domdoc_get_xml_writecallback
, NULL
, buf
, "UTF-8", options
);
1444 return E_OUTOFMEMORY
;
1447 ret
= xmlSaveDoc(ctxt
, get_doc(This
));
1448 /* flushes on close */
1451 TRACE("%ld, len=%d\n", ret
, xmlBufferLength(buf
));
1452 if(ret
!= -1 && xmlBufferLength(buf
) > 0)
1456 content
= bstr_from_xmlChar(xmlBufferContent(buf
));
1457 content
= EnsureCorrectEOL(content
);
1463 *p
= SysAllocStringLen(NULL
, 0);
1468 return *p
? S_OK
: E_OUTOFMEMORY
;
1472 static HRESULT WINAPI
domdoc_transformNode(
1473 IXMLDOMDocument3
*iface
,
1477 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1478 TRACE("(%p)->(%p %p)\n", This
, node
, p
);
1479 return node_transform_node(&This
->node
, node
, p
);
1483 static HRESULT WINAPI
domdoc_selectNodes(
1484 IXMLDOMDocument3
*iface
,
1486 IXMLDOMNodeList
**outList
)
1488 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1489 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outList
);
1490 return node_select_nodes(&This
->node
, p
, outList
);
1494 static HRESULT WINAPI
domdoc_selectSingleNode(
1495 IXMLDOMDocument3
*iface
,
1497 IXMLDOMNode
**outNode
)
1499 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1500 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outNode
);
1501 return node_select_singlenode(&This
->node
, p
, outNode
);
1505 static HRESULT WINAPI
domdoc_get_parsed(
1506 IXMLDOMDocument3
*iface
,
1507 VARIANT_BOOL
* isParsed
)
1509 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1510 FIXME("(%p)->(%p) stub!\n", This
, isParsed
);
1511 *isParsed
= VARIANT_TRUE
;
1515 static HRESULT WINAPI
domdoc_get_namespaceURI(
1516 IXMLDOMDocument3
*iface
,
1517 BSTR
* namespaceURI
)
1519 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1520 TRACE("(%p)->(%p)\n", This
, namespaceURI
);
1521 return return_null_bstr( namespaceURI
);
1524 static HRESULT WINAPI
domdoc_get_prefix(
1525 IXMLDOMDocument3
*iface
,
1528 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1529 TRACE("(%p)->(%p)\n", This
, prefix
);
1530 return return_null_bstr( prefix
);
1534 static HRESULT WINAPI
domdoc_get_baseName(
1535 IXMLDOMDocument3
*iface
,
1538 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1539 TRACE("(%p)->(%p)\n", This
, name
);
1540 return return_null_bstr( name
);
1544 static HRESULT WINAPI
domdoc_transformNodeToObject(
1545 IXMLDOMDocument3
*iface
,
1546 IXMLDOMNode
* stylesheet
,
1549 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1551 TRACE("(%p)->(%p %s)\n", This
, stylesheet
, debugstr_variant(&output
));
1553 switch (V_VT(&output
))
1558 ISequentialStream
*stream
;
1559 IXMLDOMDocument
*doc
;
1563 if (!V_UNKNOWN(&output
))
1564 return E_INVALIDARG
;
1566 /* FIXME: we're not supposed to query for document interface, should use IStream
1567 which we don't support currently. */
1568 if (IUnknown_QueryInterface(V_UNKNOWN(&output
), &IID_IXMLDOMDocument
, (void **)&doc
) == S_OK
)
1572 if (FAILED(hr
= node_transform_node(&This
->node
, stylesheet
, &str
)))
1575 hr
= IXMLDOMDocument_loadXML(doc
, str
, &b
);
1579 else if (IUnknown_QueryInterface(V_UNKNOWN(&output
), &IID_ISequentialStream
, (void**)&stream
) == S_OK
)
1581 hr
= node_transform_node_params(&This
->node
, stylesheet
, NULL
, stream
, NULL
);
1582 ISequentialStream_Release(stream
);
1587 FIXME("Unsupported destination type.\n");
1588 return E_INVALIDARG
;
1592 FIXME("Output type %d not handled.\n", V_VT(&output
));
1600 static HRESULT WINAPI
domdoc_get_doctype(
1601 IXMLDOMDocument3
*iface
,
1602 IXMLDOMDocumentType
** doctype
)
1604 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1609 TRACE("(%p)->(%p)\n", This
, doctype
);
1611 if (!doctype
) return E_INVALIDARG
;
1615 dtd
= xmlGetIntSubset(get_doc(This
));
1616 if (!dtd
) return S_FALSE
;
1618 node
= create_node((xmlNodePtr
)dtd
);
1619 if (!node
) return S_FALSE
;
1621 hr
= IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentType
, (void**)doctype
);
1622 IXMLDOMNode_Release(node
);
1628 static HRESULT WINAPI
domdoc_get_implementation(
1629 IXMLDOMDocument3
*iface
,
1630 IXMLDOMImplementation
** impl
)
1632 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1634 TRACE("(%p)->(%p)\n", This
, impl
);
1637 return E_INVALIDARG
;
1639 return create_dom_implementation(impl
);
1642 static HRESULT WINAPI
domdoc_get_documentElement(
1643 IXMLDOMDocument3
*iface
,
1644 IXMLDOMElement
** DOMElement
)
1646 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1647 IXMLDOMNode
*element_node
;
1651 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1654 return E_INVALIDARG
;
1658 root
= xmlDocGetRootElement( get_doc(This
) );
1662 element_node
= create_node( root
);
1663 if(!element_node
) return S_FALSE
;
1665 hr
= IXMLDOMNode_QueryInterface(element_node
, &IID_IXMLDOMElement
, (void**)DOMElement
);
1666 IXMLDOMNode_Release(element_node
);
1672 static HRESULT WINAPI
domdoc_put_documentElement(
1673 IXMLDOMDocument3
*iface
,
1674 IXMLDOMElement
* DOMElement
)
1676 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1677 IXMLDOMNode
*elementNode
;
1684 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1686 hr
= IXMLDOMElement_QueryInterface( DOMElement
, &IID_IXMLDOMNode
, (void**)&elementNode
);
1690 xmlNode
= get_node_obj( elementNode
);
1691 if(!xmlNode
) return E_FAIL
;
1693 if(!xmlNode
->node
->parent
)
1694 if(xmldoc_remove_orphan(xmlNode
->node
->doc
, xmlNode
->node
) != S_OK
)
1695 WARN("%p is not an orphan of %p\n", xmlNode
->node
->doc
, xmlNode
->node
);
1697 old_doc
= xmlNode
->node
->doc
;
1698 if (old_doc
!= get_doc(This
))
1699 refcount
= xmlnode_get_inst_cnt(xmlNode
);
1701 /* old root is still orphaned by its document, update refcount from new root */
1702 if (refcount
) xmldoc_add_refs(get_doc(This
), refcount
);
1703 oldRoot
= xmlDocSetRootElement( get_doc(This
), xmlNode
->node
);
1704 if (refcount
) xmldoc_release_refs(old_doc
, refcount
);
1705 IXMLDOMNode_Release( elementNode
);
1708 xmldoc_add_orphan(oldRoot
->doc
, oldRoot
);
1714 static HRESULT WINAPI
domdoc_createElement(
1715 IXMLDOMDocument3
*iface
,
1717 IXMLDOMElement
** element
)
1719 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1724 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(tagname
), element
);
1726 if (!element
|| !tagname
) return E_INVALIDARG
;
1728 V_VT(&type
) = VT_I1
;
1729 V_I1(&type
) = NODE_ELEMENT
;
1731 hr
= IXMLDOMDocument3_createNode(iface
, type
, tagname
, NULL
, &node
);
1734 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMElement
, (void**)element
);
1735 IXMLDOMNode_Release(node
);
1742 static HRESULT WINAPI
domdoc_createDocumentFragment(
1743 IXMLDOMDocument3
*iface
,
1744 IXMLDOMDocumentFragment
** frag
)
1746 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1751 TRACE("(%p)->(%p)\n", This
, frag
);
1753 if (!frag
) return E_INVALIDARG
;
1757 V_VT(&type
) = VT_I1
;
1758 V_I1(&type
) = NODE_DOCUMENT_FRAGMENT
;
1760 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1763 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentFragment
, (void**)frag
);
1764 IXMLDOMNode_Release(node
);
1771 static HRESULT WINAPI
domdoc_createTextNode(
1772 IXMLDOMDocument3
*iface
,
1774 IXMLDOMText
** text
)
1776 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1781 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), text
);
1783 if (!text
) return E_INVALIDARG
;
1787 V_VT(&type
) = VT_I1
;
1788 V_I1(&type
) = NODE_TEXT
;
1790 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1793 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMText
, (void**)text
);
1794 IXMLDOMNode_Release(node
);
1795 hr
= IXMLDOMText_put_data(*text
, data
);
1802 static HRESULT WINAPI
domdoc_createComment(
1803 IXMLDOMDocument3
*iface
,
1805 IXMLDOMComment
** comment
)
1807 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1812 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), comment
);
1814 if (!comment
) return E_INVALIDARG
;
1818 V_VT(&type
) = VT_I1
;
1819 V_I1(&type
) = NODE_COMMENT
;
1821 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1824 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMComment
, (void**)comment
);
1825 IXMLDOMNode_Release(node
);
1826 hr
= IXMLDOMComment_put_data(*comment
, data
);
1833 static HRESULT WINAPI
domdoc_createCDATASection(
1834 IXMLDOMDocument3
*iface
,
1836 IXMLDOMCDATASection
** cdata
)
1838 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1843 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), cdata
);
1845 if (!cdata
) return E_INVALIDARG
;
1849 V_VT(&type
) = VT_I1
;
1850 V_I1(&type
) = NODE_CDATA_SECTION
;
1852 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1855 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMCDATASection
, (void**)cdata
);
1856 IXMLDOMNode_Release(node
);
1857 hr
= IXMLDOMCDATASection_put_data(*cdata
, data
);
1864 static HRESULT WINAPI
domdoc_createProcessingInstruction(
1865 IXMLDOMDocument3
*iface
,
1868 IXMLDOMProcessingInstruction
** pi
)
1870 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1875 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_w(target
), debugstr_w(data
), pi
);
1877 if (!pi
) return E_INVALIDARG
;
1881 V_VT(&type
) = VT_I1
;
1882 V_I1(&type
) = NODE_PROCESSING_INSTRUCTION
;
1884 hr
= IXMLDOMDocument3_createNode(iface
, type
, target
, NULL
, &node
);
1887 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1888 hr
= dom_pi_put_xml_decl(node
, data
);
1890 hr
= IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMProcessingInstruction
, (void**)pi
);
1891 IXMLDOMNode_Release(node
);
1898 static HRESULT WINAPI
domdoc_createAttribute(
1899 IXMLDOMDocument3
*iface
,
1901 IXMLDOMAttribute
** attribute
)
1903 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1908 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), attribute
);
1910 if (!attribute
|| !name
) return E_INVALIDARG
;
1912 V_VT(&type
) = VT_I1
;
1913 V_I1(&type
) = NODE_ATTRIBUTE
;
1915 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1918 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMAttribute
, (void**)attribute
);
1919 IXMLDOMNode_Release(node
);
1926 static HRESULT WINAPI
domdoc_createEntityReference(
1927 IXMLDOMDocument3
*iface
,
1929 IXMLDOMEntityReference
** entityref
)
1931 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1936 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), entityref
);
1938 if (!entityref
) return E_INVALIDARG
;
1942 V_VT(&type
) = VT_I1
;
1943 V_I1(&type
) = NODE_ENTITY_REFERENCE
;
1945 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1948 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMEntityReference
, (void**)entityref
);
1949 IXMLDOMNode_Release(node
);
1955 xmlChar
* tagName_to_XPath(const BSTR tagName
)
1957 xmlChar
*query
, *tmp
;
1958 static const xmlChar everything
[] = "/descendant::node()";
1959 static const xmlChar mod_pre
[] = "*[local-name()='";
1960 static const xmlChar mod_post
[] = "']";
1961 static const xmlChar prefix
[] = "descendant::";
1962 const WCHAR
*tokBegin
, *tokEnd
;
1965 /* Special case - empty tagname - means select all nodes,
1966 except document itself. */
1968 return xmlStrdup(everything
);
1970 query
= xmlStrdup(prefix
);
1973 while (tokBegin
&& *tokBegin
)
1978 query
= xmlStrcat(query
, BAD_CAST
"/");
1982 query
= xmlStrcat(query
, BAD_CAST
"*");
1986 query
= xmlStrcat(query
, mod_pre
);
1988 while (*tokEnd
&& *tokEnd
!= '/')
1990 len
= WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, NULL
, 0, NULL
, NULL
);
1991 tmp
= xmlMalloc(len
);
1992 WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, (char*)tmp
, len
, NULL
, NULL
);
1993 query
= xmlStrncat(query
, tmp
, len
);
1996 query
= xmlStrcat(query
, mod_post
);
2003 static HRESULT WINAPI
domdoc_getElementsByTagName(
2004 IXMLDOMDocument3
*iface
,
2006 IXMLDOMNodeList
** resultList
)
2008 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2013 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(tagName
), resultList
);
2015 if (!tagName
|| !resultList
) return E_INVALIDARG
;
2017 XPath
= This
->properties
->XPath
;
2018 This
->properties
->XPath
= TRUE
;
2019 query
= tagName_to_XPath(tagName
);
2020 hr
= create_selection((xmlNodePtr
)get_doc(This
), query
, resultList
);
2022 This
->properties
->XPath
= XPath
;
2027 static HRESULT
get_node_type(VARIANT Type
, DOMNodeType
* type
)
2033 hr
= VariantChangeType(&tmp
, &Type
, 0, VT_I4
);
2035 return E_INVALIDARG
;
2042 static HRESULT WINAPI
domdoc_createNode(
2043 IXMLDOMDocument3
*iface
,
2047 IXMLDOMNode
** node
)
2049 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2050 DOMNodeType node_type
;
2052 xmlChar
*xml_name
, *href
;
2055 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_variant(&Type
), debugstr_w(name
), debugstr_w(namespaceURI
), node
);
2057 if(!node
) return E_INVALIDARG
;
2059 hr
= get_node_type(Type
, &node_type
);
2060 if(FAILED(hr
)) return hr
;
2062 TRACE("node_type %d\n", node_type
);
2064 /* exit earlier for types that need name */
2068 case NODE_ATTRIBUTE
:
2069 case NODE_ENTITY_REFERENCE
:
2070 case NODE_PROCESSING_INSTRUCTION
:
2071 if (!name
|| *name
== 0) return E_FAIL
;
2077 xml_name
= xmlchar_from_wchar(name
);
2078 /* prevent empty href from being allocated */
2079 href
= namespaceURI
? xmlchar_from_wchar(namespaceURI
) : NULL
;
2085 xmlChar
*local
, *prefix
;
2087 local
= xmlSplitQName2(xml_name
, &prefix
);
2089 xmlnode
= xmlNewDocNode(get_doc(This
), NULL
, local
? local
: xml_name
, NULL
);
2091 /* allow creating the default namespace xmlns= */
2092 if (local
|| (href
&& *href
))
2094 xmlNsPtr ns
= xmlNewNs(xmlnode
, href
, prefix
);
2095 xmlSetNs(xmlnode
, ns
);
2103 case NODE_ATTRIBUTE
:
2105 xmlChar
*local
, *prefix
;
2107 local
= xmlSplitQName2(xml_name
, &prefix
);
2109 xmlnode
= (xmlNodePtr
)xmlNewDocProp(get_doc(This
), local
? local
: xml_name
, NULL
);
2111 if (local
|| (href
&& *href
))
2113 /* we need a floating namespace here, it can't be created linked to attribute from
2115 xmlNsPtr ns
= xmlNewNs(NULL
, href
, prefix
);
2116 xmlSetNs(xmlnode
, ns
);
2125 xmlnode
= (xmlNodePtr
)xmlNewDocText(get_doc(This
), NULL
);
2127 case NODE_CDATA_SECTION
:
2128 xmlnode
= xmlNewCDataBlock(get_doc(This
), NULL
, 0);
2130 case NODE_ENTITY_REFERENCE
:
2131 xmlnode
= xmlNewReference(get_doc(This
), xml_name
);
2133 case NODE_PROCESSING_INSTRUCTION
:
2134 xmlnode
= xmlNewDocPI(get_doc(This
), xml_name
, NULL
);
2137 xmlnode
= xmlNewDocComment(get_doc(This
), NULL
);
2139 case NODE_DOCUMENT_FRAGMENT
:
2140 xmlnode
= xmlNewDocFragment(get_doc(This
));
2142 /* unsupported types */
2144 case NODE_DOCUMENT_TYPE
:
2147 heap_free(xml_name
);
2148 return E_INVALIDARG
;
2150 FIXME("unhandled node type %d\n", node_type
);
2155 *node
= create_node(xmlnode
);
2156 heap_free(xml_name
);
2161 TRACE("created node (%d, %p, %p)\n", node_type
, *node
, xmlnode
);
2162 xmldoc_add_orphan(xmlnode
->doc
, xmlnode
);
2169 static HRESULT WINAPI
domdoc_nodeFromID(
2170 IXMLDOMDocument3
*iface
,
2172 IXMLDOMNode
** node
)
2174 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2175 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(idString
), node
);
2179 static HRESULT
domdoc_onDataAvailable(void *obj
, char *ptr
, DWORD len
)
2184 xmldoc
= doparse(This
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
2186 xmldoc
->_private
= create_priv();
2187 return attach_xmldoc(This
, xmldoc
);
2193 static HRESULT
domdoc_load_moniker(domdoc
*This
, IMoniker
*mon
)
2198 hr
= bind_url(mon
, domdoc_onDataAvailable
, This
, &bsc
);
2202 return detach_bsc(bsc
);
2205 static HRESULT WINAPI
domdoc_load(
2206 IXMLDOMDocument3
*iface
,
2208 VARIANT_BOOL
* isSuccessful
)
2210 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2211 LPWSTR filename
= NULL
;
2212 HRESULT hr
= S_FALSE
;
2215 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&source
));
2219 *isSuccessful
= VARIANT_FALSE
;
2221 assert( &This
->node
);
2223 switch( V_VT(&source
) )
2226 filename
= V_BSTR(&source
);
2228 case VT_BSTR
|VT_BYREF
:
2229 if (!V_BSTRREF(&source
)) return E_INVALIDARG
;
2230 filename
= *V_BSTRREF(&source
);
2232 case VT_ARRAY
|VT_UI1
:
2234 SAFEARRAY
*psa
= V_ARRAY(&source
);
2237 UINT dim
= SafeArrayGetDim(psa
);
2242 ERR("SAFEARRAY == NULL\n");
2243 hr
= This
->error
= E_INVALIDARG
;
2246 /* Only takes UTF-8 strings.
2247 * NOT NULL-terminated. */
2248 hr
= SafeArrayAccessData(psa
, (void**)&str
);
2252 WARN("failed to access array data, 0x%08x\n", hr
);
2255 SafeArrayGetUBound(psa
, 1, &len
);
2257 if ((xmldoc
= doparse(This
, str
, ++len
, XML_CHAR_ENCODING_UTF8
)))
2259 hr
= This
->error
= S_OK
;
2260 *isSuccessful
= VARIANT_TRUE
;
2261 TRACE("parsed document %p\n", xmldoc
);
2265 This
->error
= E_FAIL
;
2266 TRACE("failed to parse document\n");
2269 SafeArrayUnaccessData(psa
);
2273 xmldoc
->_private
= create_priv();
2274 return attach_xmldoc(This
, xmldoc
);
2278 FIXME("unhandled SAFEARRAY dim: %d\n", dim
);
2279 hr
= This
->error
= E_NOTIMPL
;
2285 ISequentialStream
*stream
= NULL
;
2286 IXMLDOMDocument3
*newdoc
= NULL
;
2288 if (!V_UNKNOWN(&source
)) return E_INVALIDARG
;
2290 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IXMLDOMDocument3
, (void**)&newdoc
);
2295 domdoc
*newDoc
= impl_from_IXMLDOMDocument3( newdoc
);
2297 xmldoc
= xmlCopyDoc(get_doc(newDoc
), 1);
2298 xmldoc
->_private
= create_priv();
2299 hr
= attach_xmldoc(This
, xmldoc
);
2302 *isSuccessful
= VARIANT_TRUE
;
2308 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IStream
, (void**)&stream
);
2310 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_ISequentialStream
, (void**)&stream
);
2314 hr
= This
->error
= domdoc_load_from_stream(This
, stream
);
2316 *isSuccessful
= VARIANT_TRUE
;
2317 ISequentialStream_Release(stream
);
2321 FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr
, V_UNKNOWN(&source
)->lpVtbl
);
2325 FIXME("VT type not supported (%d)\n", V_VT(&source
));
2333 if (This
->properties
->uri
)
2335 IUri_Release(This
->properties
->uri
);
2336 This
->properties
->uri
= NULL
;
2339 hr
= create_uri(This
->base_uri
, filename
, &uri
);
2341 hr
= CreateURLMonikerEx2(NULL
, uri
, &mon
, 0);
2342 if ( SUCCEEDED(hr
) )
2344 hr
= domdoc_load_moniker( This
, mon
);
2345 IMoniker_Release(mon
);
2350 get_doc(This
)->name
= (char *)xmlchar_from_wcharn(filename
, -1, TRUE
);
2351 This
->properties
->uri
= uri
;
2352 hr
= This
->error
= S_OK
;
2353 *isSuccessful
= VARIANT_TRUE
;
2359 This
->error
= E_FAIL
;
2363 if(!filename
|| FAILED(hr
)) {
2364 xmldoc
= xmlNewDoc(NULL
);
2365 xmldoc
->_private
= create_priv();
2366 hr
= attach_xmldoc(This
, xmldoc
);
2371 TRACE("ret (%d)\n", hr
);
2377 static HRESULT WINAPI
domdoc_get_readyState(
2378 IXMLDOMDocument3
*iface
,
2381 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2382 FIXME("stub! (%p)->(%p)\n", This
, value
);
2385 return E_INVALIDARG
;
2387 *value
= READYSTATE_COMPLETE
;
2392 static HRESULT WINAPI
domdoc_get_parseError(
2393 IXMLDOMDocument3
*iface
,
2394 IXMLDOMParseError
** errorObj
)
2396 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2397 static const WCHAR err
[] = {'e','r','r','o','r',0};
2398 BSTR error_string
= NULL
;
2400 FIXME("(%p)->(%p): creating a dummy parseError\n", iface
, errorObj
);
2403 error_string
= SysAllocString(err
);
2405 *errorObj
= create_parseError(This
->error
, NULL
, error_string
, NULL
, 0, 0, 0);
2406 if(!*errorObj
) return E_OUTOFMEMORY
;
2411 static HRESULT WINAPI
domdoc_get_url(
2412 IXMLDOMDocument3
*iface
,
2415 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2417 TRACE("(%p)->(%p)\n", This
, url
);
2420 return E_INVALIDARG
;
2422 if (!This
->properties
->uri
)
2423 return return_null_bstr(url
);
2425 return IUri_GetPropertyBSTR(This
->properties
->uri
, Uri_PROPERTY_DISPLAY_URI
, url
, 0);
2429 static HRESULT WINAPI
domdoc_get_async(
2430 IXMLDOMDocument3
*iface
,
2431 VARIANT_BOOL
* isAsync
)
2433 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2435 TRACE("(%p)->(%p: %d)\n", This
, isAsync
, This
->async
);
2436 *isAsync
= This
->async
;
2441 static HRESULT WINAPI
domdoc_put_async(
2442 IXMLDOMDocument3
*iface
,
2443 VARIANT_BOOL isAsync
)
2445 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2447 TRACE("(%p)->(%d)\n", This
, isAsync
);
2448 This
->async
= isAsync
;
2453 static HRESULT WINAPI
domdoc_abort(
2454 IXMLDOMDocument3
*iface
)
2456 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2457 FIXME("%p\n", This
);
2461 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2462 static HRESULT WINAPI
domdoc_loadXML(
2463 IXMLDOMDocument3
*iface
,
2465 VARIANT_BOOL
* isSuccessful
)
2467 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2468 xmlDocPtr xmldoc
= NULL
;
2469 HRESULT hr
= S_FALSE
, hr2
;
2471 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), isSuccessful
);
2473 assert ( &This
->node
);
2477 *isSuccessful
= VARIANT_FALSE
;
2483 /* skip leading spaces if needed */
2484 if (This
->properties
->version
== MSXML_DEFAULT
|| This
->properties
->version
== MSXML26
)
2485 while (*ptr
&& iswspace(*ptr
)) ptr
++;
2487 xmldoc
= doparse(This
, (char*)ptr
, lstrlenW(ptr
)*sizeof(WCHAR
), XML_CHAR_ENCODING_UTF16LE
);
2490 This
->error
= E_FAIL
;
2491 TRACE("failed to parse document\n");
2495 hr
= This
->error
= S_OK
;
2496 *isSuccessful
= VARIANT_TRUE
;
2497 TRACE("parsed document %p\n", xmldoc
);
2503 xmldoc
= xmlNewDoc(NULL
);
2504 xmldoc
->_private
= create_priv();
2505 hr2
= attach_xmldoc(This
, xmldoc
);
2512 static int XMLCALL
domdoc_save_writecallback(void *ctx
, const char *buffer
, int len
)
2516 if(!WriteFile(ctx
, buffer
, len
, &written
, NULL
))
2518 WARN("write error\n");
2525 static int XMLCALL
domdoc_save_closecallback(void *ctx
)
2527 return CloseHandle(ctx
) ? 0 : -1;
2530 static int XMLCALL
domdoc_stream_save_writecallback(void *ctx
, const char *buffer
, int len
)
2535 hr
= IStream_Write((IStream
*)ctx
, buffer
, len
, &written
);
2536 TRACE("0x%08x %p %d %u\n", hr
, buffer
, len
, written
);
2539 WARN("stream write error: 0x%08x\n", hr
);
2546 static int XMLCALL
domdoc_stream_save_closecallback(void *ctx
)
2548 IStream_Release((IStream
*)ctx
);
2552 static char *xmldoc_encoding(IXMLDOMDocument3
*doc
)
2556 char *encoding
= NULL
;
2558 hr
= IXMLDOMDocument3_get_firstChild(doc
, &node
);
2563 hr
= IXMLDOMNode_get_nodeType(node
, &type
);
2564 if (hr
== S_OK
&& type
== NODE_PROCESSING_INSTRUCTION
)
2566 IXMLDOMProcessingInstruction
*pi
;
2568 IXMLDOMNamedNodeMap
*node_map
;
2570 hr
= IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMProcessingInstruction
, (void **)&pi
);
2573 hr
= IXMLDOMNode_get_attributes(node
, &node_map
);
2576 static const WCHAR encodingW
[] = {'e','n','c','o','d','i','n','g',0};
2579 bstr
= SysAllocString(encodingW
);
2580 hr
= IXMLDOMNamedNodeMap_getNamedItem(node_map
, bstr
, &item
);
2581 SysFreeString(bstr
);
2586 hr
= IXMLDOMNode_get_nodeValue(item
, &var
);
2589 if (V_VT(&var
) == VT_BSTR
)
2590 encoding
= (char *)xmlchar_from_wchar(V_BSTR(&var
));
2596 IXMLDOMNamedNodeMap_Release(node_map
);
2599 IXMLDOMProcessingInstruction_Release(pi
);
2603 IXMLDOMNode_Release(node
);
2609 static HRESULT WINAPI
domdoc_save(
2610 IXMLDOMDocument3
*iface
,
2611 VARIANT destination
)
2613 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2614 xmlSaveCtxtPtr ctx
= NULL
;
2617 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&destination
));
2619 switch (V_VT(&destination
))
2623 IUnknown
*pUnk
= V_UNKNOWN(&destination
);
2624 IXMLDOMDocument3
*document
;
2627 ret
= IUnknown_QueryInterface(pUnk
, &IID_IXMLDOMDocument3
, (void**)&document
);
2630 VARIANT_BOOL success
;
2633 ret
= IXMLDOMDocument3_get_xml(iface
, &xml
);
2636 ret
= IXMLDOMDocument3_loadXML(document
, xml
, &success
);
2640 IXMLDOMDocument3_Release(document
);
2644 ret
= IUnknown_QueryInterface(pUnk
, &IID_IStream
, (void**)&stream
);
2647 char *encoding
= xmldoc_encoding(iface
);
2649 TRACE("using encoding %s\n", encoding
? debugstr_a(encoding
) : "default");
2650 ctx
= xmlSaveToIO(domdoc_stream_save_writecallback
,
2651 domdoc_stream_save_closecallback
, stream
, encoding
, XML_SAVE_NO_DECL
);
2652 heap_free(encoding
);
2656 IStream_Release(stream
);
2664 case VT_BSTR
| VT_BYREF
:
2667 /* save with file path */
2668 HANDLE handle
= CreateFileW( (V_VT(&destination
) & VT_BYREF
)? *V_BSTRREF(&destination
) : V_BSTR(&destination
),
2669 GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2670 if( handle
== INVALID_HANDLE_VALUE
)
2672 WARN("failed to create file\n");
2676 encoding
= xmldoc_encoding(iface
);
2677 TRACE("using encoding %s\n", encoding
? debugstr_a(encoding
) : "default");
2678 ctx
= xmlSaveToIO(domdoc_save_writecallback
, domdoc_save_closecallback
,
2679 handle
, encoding
, XML_SAVE_NO_DECL
);
2680 heap_free(encoding
);
2684 CloseHandle(handle
);
2691 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination
));
2695 if (xmlSaveDoc(ctx
, get_doc(This
)) == -1) ret
= S_FALSE
;
2697 /* will release resources through close callback */
2703 static HRESULT WINAPI
domdoc_get_validateOnParse(
2704 IXMLDOMDocument3
*iface
,
2705 VARIANT_BOOL
* isValidating
)
2707 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2708 TRACE("(%p)->(%p: %d)\n", This
, isValidating
, This
->validating
);
2709 *isValidating
= This
->validating
;
2714 static HRESULT WINAPI
domdoc_put_validateOnParse(
2715 IXMLDOMDocument3
*iface
,
2716 VARIANT_BOOL isValidating
)
2718 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2719 TRACE("(%p)->(%d)\n", This
, isValidating
);
2720 This
->validating
= isValidating
;
2725 static HRESULT WINAPI
domdoc_get_resolveExternals(
2726 IXMLDOMDocument3
*iface
,
2727 VARIANT_BOOL
* isResolving
)
2729 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2730 TRACE("(%p)->(%p: %d)\n", This
, isResolving
, This
->resolving
);
2731 *isResolving
= This
->resolving
;
2736 static HRESULT WINAPI
domdoc_put_resolveExternals(
2737 IXMLDOMDocument3
*iface
,
2738 VARIANT_BOOL isResolving
)
2740 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2741 TRACE("(%p)->(%d)\n", This
, isResolving
);
2742 This
->resolving
= isResolving
;
2747 static HRESULT WINAPI
domdoc_get_preserveWhiteSpace(
2748 IXMLDOMDocument3
*iface
,
2749 VARIANT_BOOL
* isPreserving
)
2751 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2752 TRACE("(%p)->(%p: %d)\n", This
, isPreserving
, This
->properties
->preserving
);
2753 *isPreserving
= This
->properties
->preserving
;
2758 static HRESULT WINAPI
domdoc_put_preserveWhiteSpace(
2759 IXMLDOMDocument3
*iface
,
2760 VARIANT_BOOL isPreserving
)
2762 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2763 TRACE("(%p)->(%d)\n", This
, isPreserving
);
2764 This
->properties
->preserving
= isPreserving
;
2769 static HRESULT WINAPI
domdoc_put_onreadystatechange(
2770 IXMLDOMDocument3
*iface
,
2773 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2775 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&event
));
2776 return set_doc_event(This
, EVENTID_READYSTATECHANGE
, &event
);
2780 static HRESULT WINAPI
domdoc_put_onDataAvailable(IXMLDOMDocument3
*iface
, VARIANT sink
)
2782 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2783 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2787 static HRESULT WINAPI
domdoc_put_onTransformNode(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_get_namespaces(
2795 IXMLDOMDocument3
* iface
,
2796 IXMLDOMSchemaCollection
** collection
)
2798 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2801 FIXME("(%p)->(%p): semi-stub\n", This
, collection
);
2803 if (!collection
) return E_POINTER
;
2805 if (!This
->namespaces
)
2807 hr
= SchemaCache_create(This
->properties
->version
, (void**)&This
->namespaces
);
2808 if (hr
!= S_OK
) return hr
;
2810 hr
= cache_from_doc_ns(This
->namespaces
, &This
->node
);
2812 release_namespaces(This
);
2815 if (This
->namespaces
)
2816 return IXMLDOMSchemaCollection2_QueryInterface(This
->namespaces
,
2817 &IID_IXMLDOMSchemaCollection
, (void**)collection
);
2822 static HRESULT WINAPI
domdoc_get_schemas(
2823 IXMLDOMDocument3
* iface
,
2826 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2827 IXMLDOMSchemaCollection2
* cur_schema
= This
->properties
->schemaCache
;
2828 HRESULT hr
= S_FALSE
;
2830 TRACE("(%p)->(%p)\n", This
, schema
);
2832 V_VT(schema
) = VT_NULL
;
2833 /* just to reset pointer part, cause that's what application is expected to use */
2834 V_DISPATCH(schema
) = NULL
;
2838 hr
= IXMLDOMSchemaCollection2_QueryInterface(cur_schema
, &IID_IDispatch
, (void**)&V_DISPATCH(schema
));
2840 V_VT(schema
) = VT_DISPATCH
;
2845 static HRESULT WINAPI
domdoc_putref_schemas(
2846 IXMLDOMDocument3
* iface
,
2849 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2850 HRESULT hr
= E_FAIL
;
2851 IXMLDOMSchemaCollection2
* new_schema
= NULL
;
2853 FIXME("(%p)->(%s): semi-stub\n", This
, debugstr_variant(&schema
));
2854 switch(V_VT(&schema
))
2857 if (V_UNKNOWN(&schema
))
2859 hr
= IUnknown_QueryInterface(V_UNKNOWN(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2864 if (V_DISPATCH(&schema
))
2866 hr
= IDispatch_QueryInterface(V_DISPATCH(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2876 WARN("Can't get schema from vt %x\n", V_VT(&schema
));
2881 IXMLDOMSchemaCollection2
* old_schema
= InterlockedExchangePointer((void**)&This
->properties
->schemaCache
, new_schema
);
2882 if(old_schema
) IXMLDOMSchemaCollection2_Release(old_schema
);
2888 static inline BOOL
is_wellformed(xmlDocPtr doc
)
2890 return doc
->properties
& XML_DOC_WELLFORMED
;
2893 static void LIBXML2_LOG_CALLBACK
validate_error(void* ctx
, char const* msg
, ...)
2897 LIBXML2_CALLBACK_ERR(domdoc_validateNode
, msg
, ap
);
2901 static void LIBXML2_LOG_CALLBACK
validate_warning(void* ctx
, char const* msg
, ...)
2905 LIBXML2_CALLBACK_WARN(domdoc_validateNode
, msg
, ap
);
2909 static HRESULT WINAPI
domdoc_validateNode(
2910 IXMLDOMDocument3
* iface
,
2912 IXMLDOMParseError
** err
)
2914 domdoc
* This
= impl_from_IXMLDOMDocument3(iface
);
2915 LONG state
, err_code
= 0;
2919 TRACE("(%p)->(%p, %p)\n", This
, node
, err
);
2920 IXMLDOMDocument3_get_readyState(iface
, &state
);
2921 if (state
!= READYSTATE_COMPLETE
)
2924 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2931 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2935 if (!get_node_obj(node
)->node
|| get_node_obj(node
)->node
->doc
!= get_doc(This
))
2938 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2942 if (!is_wellformed(get_doc(This
)))
2944 ERR("doc not well-formed\n");
2946 *err
= create_parseError(E_XML_NOTWF
, NULL
, NULL
, NULL
, 0, 0, 0);
2950 /* DTD validation */
2951 if (get_doc(This
)->intSubset
|| get_doc(This
)->extSubset
)
2953 xmlValidCtxtPtr vctx
= xmlNewValidCtxt();
2954 vctx
->error
= validate_error
;
2955 vctx
->warning
= validate_warning
;
2958 if (!((node
== (IXMLDOMNode
*)iface
)?
2959 xmlValidateDocument(vctx
, get_doc(This
)) :
2960 xmlValidateElement(vctx
, get_doc(This
), get_node_obj(node
)->node
)))
2962 /* TODO: get a real error code here */
2963 TRACE("DTD validation failed\n");
2964 err_code
= E_XML_INVALID
;
2967 xmlFreeValidCtxt(vctx
);
2970 /* Schema validation */
2971 if (hr
== S_OK
&& This
->properties
->schemaCache
!= NULL
)
2974 hr
= SchemaCache_validate_tree(This
->properties
->schemaCache
, get_node_obj(node
)->node
);
2978 /* TODO: get a real error code here */
2981 TRACE("schema validation succeeded\n");
2985 ERR("schema validation failed\n");
2986 err_code
= E_XML_INVALID
;
2991 /* not really OK, just didn't find a schema for the ns */
2998 ERR("no DTD or schema found\n");
2999 err_code
= E_XML_NODTD
;
3004 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
3009 static HRESULT WINAPI
domdoc_validate(
3010 IXMLDOMDocument3
* iface
,
3011 IXMLDOMParseError
** err
)
3013 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3014 TRACE("(%p)->(%p)\n", This
, err
);
3015 return IXMLDOMDocument3_validateNode(iface
, (IXMLDOMNode
*)iface
, err
);
3018 static HRESULT WINAPI
domdoc_setProperty(
3019 IXMLDOMDocument3
* iface
,
3023 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3025 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(p
), debugstr_variant(&value
));
3027 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
3033 V_VT(&varStr
) = VT_EMPTY
;
3034 if (V_VT(&value
) != VT_BSTR
)
3036 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
3038 bstr
= V_BSTR(&varStr
);
3041 bstr
= V_BSTR(&value
);
3044 if (lstrcmpiW(bstr
, PropValueXPathW
) == 0)
3045 This
->properties
->XPath
= TRUE
;
3046 else if (lstrcmpiW(bstr
, PropValueXSLPatternW
) == 0)
3047 This
->properties
->XPath
= FALSE
;
3051 VariantClear(&varStr
);
3054 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3056 xmlChar
*nsStr
= (xmlChar
*)This
->properties
->selectNsStr
;
3057 struct list
*pNsList
;
3062 V_VT(&varStr
) = VT_EMPTY
;
3063 if (V_VT(&value
) != VT_BSTR
)
3065 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
3067 bstr
= V_BSTR(&varStr
);
3070 bstr
= V_BSTR(&value
);
3074 pNsList
= &(This
->properties
->selectNsList
);
3075 clear_selectNsList(pNsList
);
3077 nsStr
= xmlchar_from_wchar(bstr
);
3079 TRACE("property value: \"%s\"\n", debugstr_w(bstr
));
3081 This
->properties
->selectNsStr
= nsStr
;
3082 This
->properties
->selectNsStr_len
= xmlStrlen(nsStr
);
3085 xmlChar
*pTokBegin
, *pTokEnd
, *pTokInner
;
3086 select_ns_entry
* ns_entry
= NULL
;
3087 xmlXPathContextPtr ctx
;
3089 ctx
= xmlXPathNewContext(This
->node
.node
->doc
);
3092 /* skip leading spaces */
3093 while (*pTokBegin
== ' ' || *pTokBegin
== '\n' ||
3094 *pTokBegin
== '\t' || *pTokBegin
== '\r')
3097 for (; *pTokBegin
; pTokBegin
= pTokEnd
)
3100 memset(ns_entry
, 0, sizeof(select_ns_entry
));
3102 ns_entry
= heap_alloc_zero(sizeof(select_ns_entry
));
3104 while (*pTokBegin
== ' ')
3106 pTokEnd
= pTokBegin
;
3107 while (*pTokEnd
!= ' ' && *pTokEnd
!= 0)
3110 /* so it failed to advance which means we've got some trailing spaces */
3111 if (pTokEnd
== pTokBegin
) break;
3113 if (xmlStrncmp(pTokBegin
, (xmlChar
const*)"xmlns", 5) != 0)
3116 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3117 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
3122 if (*pTokBegin
== '=')
3124 /*valid for XSLPattern?*/
3125 FIXME("Setting default xmlns not supported - skipping.\n");
3128 else if (*pTokBegin
== ':')
3130 ns_entry
->prefix
= ++pTokBegin
;
3131 for (pTokInner
= pTokBegin
; pTokInner
!= pTokEnd
&& *pTokInner
!= '='; ++pTokInner
)
3134 if (pTokInner
== pTokEnd
)
3137 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3138 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
3142 ns_entry
->prefix_end
= *pTokInner
;
3146 if (pTokEnd
-pTokInner
> 1 &&
3147 ((*pTokInner
== '\'' && *(pTokEnd
-1) == '\'') ||
3148 (*pTokInner
== '"' && *(pTokEnd
-1) == '"')))
3150 ns_entry
->href
= ++pTokInner
;
3151 ns_entry
->href_end
= *(pTokEnd
-1);
3153 list_add_tail(pNsList
, &ns_entry
->entry
);
3154 /*let libxml figure out if they're valid from here ;)*/
3155 if (xmlXPathRegisterNs(ctx
, ns_entry
->prefix
, ns_entry
->href
) != 0)
3164 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3165 debugstr_w(bstr
), debugstr_an((const char*)pTokInner
, pTokEnd
-pTokInner
));
3166 list_add_tail(pNsList
, &ns_entry
->entry
);
3179 heap_free(ns_entry
);
3180 xmlXPathFreeContext(ctx
);
3183 VariantClear(&varStr
);
3186 else if (lstrcmpiW(p
, PropertyProhibitDTDW
) == 0 ||
3187 lstrcmpiW(p
, PropertyNewParserW
) == 0 ||
3188 lstrcmpiW(p
, PropertyResolveExternalsW
) == 0 ||
3189 lstrcmpiW(p
, PropertyAllowXsltScriptW
) == 0 ||
3190 lstrcmpiW(p
, PropertyNormalizeAttributeValuesW
) == 0 ||
3191 lstrcmpiW(p
, PropertyAllowDocumentFunctionW
) == 0)
3194 FIXME("Ignoring property %s, value %s\n", debugstr_w(p
), debugstr_variant(&value
));
3198 FIXME("Unknown property %s\n", debugstr_w(p
));
3202 static HRESULT WINAPI
domdoc_getProperty(
3203 IXMLDOMDocument3
* iface
,
3207 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3209 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
3212 return E_INVALIDARG
;
3214 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
3216 V_VT(var
) = VT_BSTR
;
3217 V_BSTR(var
) = This
->properties
->XPath
?
3218 SysAllocString(PropValueXPathW
) :
3219 SysAllocString(PropValueXSLPatternW
);
3220 return V_BSTR(var
) ? S_OK
: E_OUTOFMEMORY
;
3222 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3225 BSTR rebuiltStr
, cur
;
3226 const xmlChar
*nsStr
;
3227 struct list
*pNsList
;
3228 select_ns_entry
* pNsEntry
;
3230 V_VT(var
) = VT_BSTR
;
3231 nsStr
= This
->properties
->selectNsStr
;
3232 pNsList
= &This
->properties
->selectNsList
;
3233 lenA
= This
->properties
->selectNsStr_len
;
3234 lenW
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, NULL
, 0);
3235 rebuiltStr
= heap_alloc(lenW
*sizeof(WCHAR
));
3236 MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, rebuiltStr
, lenW
);
3238 /* this is fine because all of the chars that end tokens are ASCII*/
3239 LIST_FOR_EACH_ENTRY(pNsEntry
, pNsList
, select_ns_entry
, entry
)
3241 while (*cur
!= 0) ++cur
;
3242 if (pNsEntry
->prefix_end
)
3244 *cur
= pNsEntry
->prefix_end
;
3245 while (*cur
!= 0) ++cur
;
3248 if (pNsEntry
->href_end
)
3250 *cur
= pNsEntry
->href_end
;
3253 V_BSTR(var
) = SysAllocString(rebuiltStr
);
3254 heap_free(rebuiltStr
);
3258 FIXME("Unknown property %s\n", debugstr_w(p
));
3262 static HRESULT WINAPI
domdoc_importNode(
3263 IXMLDOMDocument3
* iface
,
3266 IXMLDOMNode
** clone
)
3268 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3269 FIXME("(%p)->(%p %d %p): stub\n", This
, node
, deep
, clone
);
3273 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl
=
3275 domdoc_QueryInterface
,
3278 domdoc_GetTypeInfoCount
,
3280 domdoc_GetIDsOfNames
,
3282 domdoc_get_nodeName
,
3283 domdoc_get_nodeValue
,
3284 domdoc_put_nodeValue
,
3285 domdoc_get_nodeType
,
3286 domdoc_get_parentNode
,
3287 domdoc_get_childNodes
,
3288 domdoc_get_firstChild
,
3289 domdoc_get_lastChild
,
3290 domdoc_get_previousSibling
,
3291 domdoc_get_nextSibling
,
3292 domdoc_get_attributes
,
3293 domdoc_insertBefore
,
3294 domdoc_replaceChild
,
3297 domdoc_hasChildNodes
,
3298 domdoc_get_ownerDocument
,
3300 domdoc_get_nodeTypeString
,
3303 domdoc_get_specified
,
3304 domdoc_get_definition
,
3305 domdoc_get_nodeTypedValue
,
3306 domdoc_put_nodeTypedValue
,
3307 domdoc_get_dataType
,
3308 domdoc_put_dataType
,
3310 domdoc_transformNode
,
3312 domdoc_selectSingleNode
,
3314 domdoc_get_namespaceURI
,
3316 domdoc_get_baseName
,
3317 domdoc_transformNodeToObject
,
3319 domdoc_get_implementation
,
3320 domdoc_get_documentElement
,
3321 domdoc_put_documentElement
,
3322 domdoc_createElement
,
3323 domdoc_createDocumentFragment
,
3324 domdoc_createTextNode
,
3325 domdoc_createComment
,
3326 domdoc_createCDATASection
,
3327 domdoc_createProcessingInstruction
,
3328 domdoc_createAttribute
,
3329 domdoc_createEntityReference
,
3330 domdoc_getElementsByTagName
,
3334 domdoc_get_readyState
,
3335 domdoc_get_parseError
,
3342 domdoc_get_validateOnParse
,
3343 domdoc_put_validateOnParse
,
3344 domdoc_get_resolveExternals
,
3345 domdoc_put_resolveExternals
,
3346 domdoc_get_preserveWhiteSpace
,
3347 domdoc_put_preserveWhiteSpace
,
3348 domdoc_put_onreadystatechange
,
3349 domdoc_put_onDataAvailable
,
3350 domdoc_put_onTransformNode
,
3351 domdoc_get_namespaces
,
3353 domdoc_putref_schemas
,
3357 domdoc_validateNode
,
3361 /* IConnectionPointContainer */
3362 static HRESULT WINAPI
ConnectionPointContainer_QueryInterface(IConnectionPointContainer
*iface
,
3363 REFIID riid
, void **ppv
)
3365 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3366 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3369 static ULONG WINAPI
ConnectionPointContainer_AddRef(IConnectionPointContainer
*iface
)
3371 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3372 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3375 static ULONG WINAPI
ConnectionPointContainer_Release(IConnectionPointContainer
*iface
)
3377 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3378 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3381 static HRESULT WINAPI
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer
*iface
,
3382 IEnumConnectionPoints
**ppEnum
)
3384 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3385 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3389 static HRESULT WINAPI
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer
*iface
,
3390 REFIID riid
, IConnectionPoint
**cp
)
3392 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3393 ConnectionPoint
*iter
;
3395 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), cp
);
3399 for(iter
= This
->cp_list
; iter
; iter
= iter
->next
)
3401 if (IsEqualGUID(iter
->iid
, riid
))
3402 *cp
= &iter
->IConnectionPoint_iface
;
3407 IConnectionPoint_AddRef(*cp
);
3411 FIXME("unsupported riid %s\n", debugstr_guid(riid
));
3412 return CONNECT_E_NOCONNECTION
;
3416 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl
=
3418 ConnectionPointContainer_QueryInterface
,
3419 ConnectionPointContainer_AddRef
,
3420 ConnectionPointContainer_Release
,
3421 ConnectionPointContainer_EnumConnectionPoints
,
3422 ConnectionPointContainer_FindConnectionPoint
3425 /* IConnectionPoint */
3426 static HRESULT WINAPI
ConnectionPoint_QueryInterface(IConnectionPoint
*iface
,
3427 REFIID riid
, void **ppv
)
3429 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3431 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
3435 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
3436 IsEqualGUID(&IID_IConnectionPoint
, riid
))
3443 IConnectionPoint_AddRef(iface
);
3447 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
3448 return E_NOINTERFACE
;
3451 static ULONG WINAPI
ConnectionPoint_AddRef(IConnectionPoint
*iface
)
3453 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3454 return IConnectionPointContainer_AddRef(This
->container
);
3457 static ULONG WINAPI
ConnectionPoint_Release(IConnectionPoint
*iface
)
3459 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3460 return IConnectionPointContainer_Release(This
->container
);
3463 static HRESULT WINAPI
ConnectionPoint_GetConnectionInterface(IConnectionPoint
*iface
, IID
*iid
)
3465 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3467 TRACE("(%p)->(%p)\n", This
, iid
);
3469 if (!iid
) return E_POINTER
;
3475 static HRESULT WINAPI
ConnectionPoint_GetConnectionPointContainer(IConnectionPoint
*iface
,
3476 IConnectionPointContainer
**container
)
3478 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3480 TRACE("(%p)->(%p)\n", This
, container
);
3482 if (!container
) return E_POINTER
;
3484 *container
= This
->container
;
3485 IConnectionPointContainer_AddRef(*container
);
3489 static HRESULT WINAPI
ConnectionPoint_Advise(IConnectionPoint
*iface
, IUnknown
*unk_sink
,
3492 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3497 TRACE("(%p)->(%p %p)\n", This
, unk_sink
, cookie
);
3499 hr
= IUnknown_QueryInterface(unk_sink
, This
->iid
, (void**)&sink
);
3500 if(FAILED(hr
) && !IsEqualGUID(&IID_IPropertyNotifySink
, This
->iid
))
3501 hr
= IUnknown_QueryInterface(unk_sink
, &IID_IDispatch
, (void**)&sink
);
3503 return CONNECT_E_CANNOTCONNECT
;
3507 for (i
= 0; i
< This
->sinks_size
; i
++)
3508 if (!This
->sinks
[i
].unk
)
3511 if (i
== This
->sinks_size
)
3512 This
->sinks
= heap_realloc(This
->sinks
,(++This
->sinks_size
)*sizeof(*This
->sinks
));
3516 This
->sinks
= heap_alloc(sizeof(*This
->sinks
));
3517 This
->sinks_size
= 1;
3521 This
->sinks
[i
].unk
= sink
;
3528 static HRESULT WINAPI
ConnectionPoint_Unadvise(IConnectionPoint
*iface
, DWORD cookie
)
3530 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3532 TRACE("(%p)->(%d)\n", This
, cookie
);
3534 if (cookie
== 0 || cookie
> This
->sinks_size
|| !This
->sinks
[cookie
-1].unk
)
3535 return CONNECT_E_NOCONNECTION
;
3537 IUnknown_Release(This
->sinks
[cookie
-1].unk
);
3538 This
->sinks
[cookie
-1].unk
= NULL
;
3543 static HRESULT WINAPI
ConnectionPoint_EnumConnections(IConnectionPoint
*iface
,
3544 IEnumConnections
**ppEnum
)
3546 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3547 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3551 static const IConnectionPointVtbl ConnectionPointVtbl
=
3553 ConnectionPoint_QueryInterface
,
3554 ConnectionPoint_AddRef
,
3555 ConnectionPoint_Release
,
3556 ConnectionPoint_GetConnectionInterface
,
3557 ConnectionPoint_GetConnectionPointContainer
,
3558 ConnectionPoint_Advise
,
3559 ConnectionPoint_Unadvise
,
3560 ConnectionPoint_EnumConnections
3563 static void ConnectionPoint_Init(ConnectionPoint
*cp
, struct domdoc
*doc
, REFIID riid
)
3565 cp
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointVtbl
;
3571 cp
->next
= doc
->cp_list
;
3574 cp
->container
= &doc
->IConnectionPointContainer_iface
;
3577 /* domdoc implementation of IObjectWithSite */
3578 static HRESULT WINAPI
3579 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
3581 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3582 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObject
);
3585 static ULONG WINAPI
domdoc_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
3587 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3588 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3591 static ULONG WINAPI
domdoc_ObjectWithSite_Release( IObjectWithSite
* iface
)
3593 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3594 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3597 static HRESULT WINAPI
domdoc_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
3599 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3601 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
3606 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
3609 static HRESULT WINAPI
domdoc_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
3611 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3613 TRACE("(%p)->(%p)\n", iface
, punk
);
3619 IUnknown_Release( This
->site
);
3625 IUri_Release(This
->base_uri
);
3626 This
->base_uri
= NULL
;
3632 IUnknown_AddRef( punk
);
3635 IUnknown_Release( This
->site
);
3638 This
->base_uri
= get_base_uri(This
->site
);
3643 static const IObjectWithSiteVtbl domdocObjectSite
=
3645 domdoc_ObjectWithSite_QueryInterface
,
3646 domdoc_ObjectWithSite_AddRef
,
3647 domdoc_ObjectWithSite_Release
,
3648 domdoc_ObjectWithSite_SetSite
,
3649 domdoc_ObjectWithSite_GetSite
3652 static HRESULT WINAPI
domdoc_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
3654 domdoc
*This
= impl_from_IObjectSafety(iface
);
3655 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3658 static ULONG WINAPI
domdoc_Safety_AddRef(IObjectSafety
*iface
)
3660 domdoc
*This
= impl_from_IObjectSafety(iface
);
3661 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3664 static ULONG WINAPI
domdoc_Safety_Release(IObjectSafety
*iface
)
3666 domdoc
*This
= impl_from_IObjectSafety(iface
);
3667 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3670 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3672 static HRESULT WINAPI
domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3673 DWORD
*supported
, DWORD
*enabled
)
3675 domdoc
*This
= impl_from_IObjectSafety(iface
);
3677 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
3679 if(!supported
|| !enabled
) return E_POINTER
;
3681 *supported
= SAFETY_SUPPORTED_OPTIONS
;
3682 *enabled
= This
->safeopt
;
3687 static HRESULT WINAPI
domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3688 DWORD mask
, DWORD enabled
)
3690 domdoc
*This
= impl_from_IObjectSafety(iface
);
3691 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
3693 if ((mask
& ~SAFETY_SUPPORTED_OPTIONS
) != 0)
3696 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
3701 #undef SAFETY_SUPPORTED_OPTIONS
3703 static const IObjectSafetyVtbl domdocObjectSafetyVtbl
= {
3704 domdoc_Safety_QueryInterface
,
3705 domdoc_Safety_AddRef
,
3706 domdoc_Safety_Release
,
3707 domdoc_Safety_GetInterfaceSafetyOptions
,
3708 domdoc_Safety_SetInterfaceSafetyOptions
3711 static const tid_t domdoc_iface_tids
[] = {
3712 IXMLDOMDocument3_tid
,
3716 static dispex_static_data_t domdoc_dispex
= {
3718 IXMLDOMDocument3_tid
,
3723 HRESULT
get_domdoc_from_xmldoc(xmlDocPtr xmldoc
, IXMLDOMDocument3
**document
)
3727 doc
= heap_alloc( sizeof (*doc
) );
3729 return E_OUTOFMEMORY
;
3731 doc
->IXMLDOMDocument3_iface
.lpVtbl
= &XMLDOMDocument3Vtbl
;
3732 doc
->IPersistStreamInit_iface
.lpVtbl
= &xmldoc_IPersistStreamInit_VTable
;
3733 doc
->IObjectWithSite_iface
.lpVtbl
= &domdocObjectSite
;
3734 doc
->IObjectSafety_iface
.lpVtbl
= &domdocObjectSafetyVtbl
;
3735 doc
->IConnectionPointContainer_iface
.lpVtbl
= &ConnectionPointContainerVtbl
;
3737 doc
->async
= VARIANT_TRUE
;
3738 doc
->validating
= 0;
3740 doc
->properties
= properties_add_ref(properties_from_xmlDocPtr(xmldoc
));
3743 doc
->base_uri
= NULL
;
3745 doc
->cp_list
= NULL
;
3746 doc
->namespaces
= NULL
;
3747 memset(doc
->events
, 0, sizeof(doc
->events
));
3749 /* events connection points */
3750 ConnectionPoint_Init(&doc
->cp_dispatch
, doc
, &IID_IDispatch
);
3751 ConnectionPoint_Init(&doc
->cp_propnotif
, doc
, &IID_IPropertyNotifySink
);
3752 ConnectionPoint_Init(&doc
->cp_domdocevents
, doc
, &DIID_XMLDOMDocumentEvents
);
3754 init_xmlnode(&doc
->node
, (xmlNodePtr
)xmldoc
, (IXMLDOMNode
*)&doc
->IXMLDOMDocument3_iface
,
3757 *document
= &doc
->IXMLDOMDocument3_iface
;
3759 TRACE("returning iface %p\n", *document
);
3763 HRESULT
dom_document_create(MSXML_VERSION version
, void **ppObj
)
3768 TRACE("(%d, %p)\n", version
, ppObj
);
3770 xmldoc
= xmlNewDoc(NULL
);
3772 return E_OUTOFMEMORY
;
3774 xmldoc_init(xmldoc
, version
);
3776 hr
= get_domdoc_from_xmldoc(xmldoc
, (IXMLDOMDocument3
**)ppObj
);
3779 properties_release(properties_from_xmlDocPtr(xmldoc
));
3780 heap_free(xmldoc
->_private
);
3788 IUnknown
* create_domdoc( xmlNodePtr document
)
3790 IUnknown
*obj
= NULL
;
3793 TRACE("(%p)\n", document
);
3795 hr
= get_domdoc_from_xmldoc((xmlDocPtr
)document
, (IXMLDOMDocument3
**)&obj
);