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
29 # include <libxml/parser.h>
30 # include <libxml/xmlerror.h>
31 # include <libxml/xpathInternals.h>
32 # include <libxml/xmlsave.h>
33 # include <libxml/SAX2.h>
34 # include <libxml/parserInternals.h>
50 #include "wine/debug.h"
52 #include "msxml_private.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
58 /* not defined in older versions */
59 #define XML_SAVE_FORMAT 1
60 #define XML_SAVE_NO_DECL 2
61 #define XML_SAVE_NO_EMPTY 4
62 #define XML_SAVE_NO_XHTML 8
63 #define XML_SAVE_XHTML 16
64 #define XML_SAVE_AS_XML 32
65 #define XML_SAVE_AS_HTML 64
67 static const WCHAR PropertySelectionLanguageW
[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
68 static const WCHAR PropertySelectionNamespacesW
[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
69 static const WCHAR PropertyProhibitDTDW
[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
70 static const WCHAR PropertyNewParserW
[] = {'N','e','w','P','a','r','s','e','r',0};
71 static const WCHAR PropValueXPathW
[] = {'X','P','a','t','h',0};
72 static const WCHAR PropValueXSLPatternW
[] = {'X','S','L','P','a','t','t','e','r','n',0};
73 static const WCHAR PropertyResolveExternalsW
[] = {'R','e','s','o','l','v','e','E','x','t','e','r','n','a','l','s',0};
74 static const WCHAR PropertyAllowXsltScriptW
[] = {'A','l','l','o','w','X','s','l','t','S','c','r','i','p','t',0};
75 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};
76 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};
78 /* Anything that passes the test_get_ownerDocument()
79 * tests can go here (data shared between all instances).
80 * We need to preserve this when reloading a document,
81 * and also need access to it from the libxml backend. */
83 MSXML_VERSION version
;
84 VARIANT_BOOL preserving
;
85 IXMLDOMSchemaCollection2
* schemaCache
;
86 struct list selectNsList
;
87 xmlChar
const* selectNsStr
;
93 typedef struct ConnectionPoint ConnectionPoint
;
94 typedef struct domdoc domdoc
;
96 struct ConnectionPoint
98 IConnectionPoint IConnectionPoint_iface
;
101 ConnectionPoint
*next
;
102 IConnectionPointContainer
*container
;
109 IPropertyNotifySink
*propnotif
;
115 EVENTID_READYSTATECHANGE
= 0,
116 EVENTID_DATAAVAILABLE
,
117 EVENTID_TRANSFORMNODE
,
124 IXMLDOMDocument3 IXMLDOMDocument3_iface
;
125 IPersistStreamInit IPersistStreamInit_iface
;
126 IObjectWithSite IObjectWithSite_iface
;
127 IObjectSafety IObjectSafety_iface
;
128 IConnectionPointContainer IConnectionPointContainer_iface
;
131 VARIANT_BOOL validating
;
132 VARIANT_BOOL resolving
;
133 domdoc_properties
* properties
;
136 /* IObjectWithSite */
143 /* connection list */
144 ConnectionPoint
*cp_list
;
145 ConnectionPoint cp_domdocevents
;
146 ConnectionPoint cp_propnotif
;
147 ConnectionPoint cp_dispatch
;
150 IDispatch
*events
[EVENTID_LAST
];
152 IXMLDOMSchemaCollection2
*namespaces
;
155 static HRESULT
set_doc_event(domdoc
*doc
, eventid_t eid
, const VARIANT
*v
)
163 IUnknown_QueryInterface(V_UNKNOWN(v
), &IID_IDispatch
, (void**)&disp
);
168 disp
= V_DISPATCH(v
);
169 if (disp
) IDispatch_AddRef(disp
);
172 return DISP_E_TYPEMISMATCH
;
175 if (doc
->events
[eid
]) IDispatch_Release(doc
->events
[eid
]);
176 doc
->events
[eid
] = disp
;
181 static inline ConnectionPoint
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
183 return CONTAINING_RECORD(iface
, ConnectionPoint
, IConnectionPoint_iface
);
187 In native windows, the whole lifetime management of XMLDOMNodes is
188 managed automatically using reference counts. Wine emulates that by
189 maintaining a reference count to the document that is increased for
190 each IXMLDOMNode pointer passed out for this document. If all these
191 pointers are gone, the document is unreachable and gets freed, that
192 is, all nodes in the tree of the document get freed.
194 You are able to create nodes that are associated to a document (in
195 fact, in msxml's XMLDOM model, all nodes are associated to a document),
196 but not in the tree of that document, for example using the createFoo
197 functions from IXMLDOMDocument. These nodes do not get cleaned up
198 by libxml, so we have to do it ourselves.
200 To catch these nodes, a list of "orphan nodes" is introduced.
201 It contains pointers to all roots of node trees that are
202 associated with the document without being part of the document
203 tree. All nodes with parent==NULL (except for the document root nodes)
204 should be in the orphan node list of their document. All orphan nodes
205 get freed together with the document itself.
208 typedef struct _xmldoc_priv
{
211 domdoc_properties
* properties
;
214 typedef struct _orphan_entry
{
219 typedef struct _select_ns_entry
{
221 xmlChar
const* prefix
;
227 static inline xmldoc_priv
* priv_from_xmlDocPtr(const xmlDocPtr doc
)
229 return doc
->_private
;
232 static inline domdoc_properties
* properties_from_xmlDocPtr(xmlDocPtr doc
)
234 return priv_from_xmlDocPtr(doc
)->properties
;
237 BOOL
is_xpathmode(const xmlDocPtr doc
)
239 return properties_from_xmlDocPtr(doc
)->XPath
;
242 void set_xpathmode(xmlDocPtr doc
, BOOL xpath
)
244 properties_from_xmlDocPtr(doc
)->XPath
= xpath
;
247 int registerNamespaces(xmlXPathContextPtr ctxt
)
250 const select_ns_entry
* ns
= NULL
;
251 const struct list
* pNsList
= &properties_from_xmlDocPtr(ctxt
->doc
)->selectNsList
;
253 TRACE("(%p)\n", ctxt
);
255 LIST_FOR_EACH_ENTRY( ns
, pNsList
, select_ns_entry
, entry
)
257 xmlXPathRegisterNs(ctxt
, ns
->prefix
, ns
->href
);
264 static inline void clear_selectNsList(struct list
* pNsList
)
266 select_ns_entry
*ns
, *ns2
;
267 LIST_FOR_EACH_ENTRY_SAFE( ns
, ns2
, pNsList
, select_ns_entry
, entry
)
274 static xmldoc_priv
* create_priv(void)
277 priv
= heap_alloc( sizeof (*priv
) );
282 list_init( &priv
->orphans
);
283 priv
->properties
= NULL
;
289 static domdoc_properties
*create_properties(MSXML_VERSION version
)
291 domdoc_properties
*properties
= heap_alloc(sizeof(domdoc_properties
));
293 list_init(&properties
->selectNsList
);
294 properties
->preserving
= VARIANT_FALSE
;
295 properties
->schemaCache
= NULL
;
296 properties
->selectNsStr
= heap_alloc_zero(sizeof(xmlChar
));
297 properties
->selectNsStr_len
= 0;
299 /* properties that are dependent on object versions */
300 properties
->version
= version
;
301 properties
->XPath
= (version
== MSXML4
|| version
== MSXML6
);
304 properties
->uri
= NULL
;
309 static domdoc_properties
* copy_properties(domdoc_properties
const* properties
)
311 domdoc_properties
* pcopy
= heap_alloc(sizeof(domdoc_properties
));
312 select_ns_entry
const* ns
= NULL
;
313 select_ns_entry
* new_ns
= NULL
;
314 int len
= (properties
->selectNsStr_len
+1)*sizeof(xmlChar
);
319 pcopy
->version
= properties
->version
;
320 pcopy
->preserving
= properties
->preserving
;
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 void free_properties(domdoc_properties
* properties
)
352 if (properties
->schemaCache
)
353 IXMLDOMSchemaCollection2_Release(properties
->schemaCache
);
354 clear_selectNsList(&properties
->selectNsList
);
355 heap_free((xmlChar
*)properties
->selectNsStr
);
357 IUri_Release(properties
->uri
);
358 heap_free(properties
);
362 static void release_namespaces(domdoc
*This
)
364 if (This
->namespaces
)
366 IXMLDOMSchemaCollection2_Release(This
->namespaces
);
367 This
->namespaces
= NULL
;
371 /* links a "<?xml" node as a first child */
372 void xmldoc_link_xmldecl(xmlDocPtr doc
, xmlNodePtr node
)
375 if (doc
->standalone
!= -1) xmlAddPrevSibling( doc
->children
, node
);
378 /* unlinks a first "<?xml" child if it was created */
379 xmlNodePtr
xmldoc_unlink_xmldecl(xmlDocPtr doc
)
381 static const xmlChar xmlA
[] = "xml";
382 xmlNodePtr node
, first_child
;
386 /* xml declaration node could be created automatically after parsing or added
388 first_child
= doc
->children
;
389 if (first_child
&& first_child
->type
== XML_PI_NODE
&& xmlStrEqual(first_child
->name
, xmlA
))
392 xmlUnlinkNode( node
);
400 MSXML_VERSION
xmldoc_version(xmlDocPtr doc
)
402 return properties_from_xmlDocPtr(doc
)->version
;
405 BOOL
is_preserving_whitespace(xmlNodePtr node
)
407 domdoc_properties
* properties
= NULL
;
408 /* during parsing the xmlDoc._private stuff is not there */
409 if (priv_from_xmlDocPtr(node
->doc
))
410 properties
= properties_from_xmlDocPtr(node
->doc
);
411 return ((properties
&& properties
->preserving
== VARIANT_TRUE
) ||
412 xmlNodeGetSpacePreserve(node
) == 1);
415 static inline BOOL
strn_isspace(xmlChar
const* str
, int len
)
417 for (; str
&& len
> 0 && *str
; ++str
, --len
)
424 static void sax_characters(void *ctx
, const xmlChar
*ch
, int len
)
426 xmlParserCtxtPtr ctxt
;
429 ctxt
= (xmlParserCtxtPtr
) ctx
;
430 This
= (const domdoc
*) ctxt
->_private
;
434 xmlChar cur
= *(ctxt
->input
->cur
);
436 /* Characters are reported with multiple calls, for example each charref is reported with a separate
437 call and then parser appends it to a single text node or creates a new node if not created.
438 It's not possible to tell if it's ignorable data or not just looking at data itself cause it could be
439 space chars that separate charrefs or similar case. We only need to skip leading and trailing spaces,
440 or whole node if it has nothing but space chars, so to detect leading space node->last is checked that
441 contains text node pointer if already created, trailing spaces are detected directly looking at parser input
442 for next '<' opening bracket - similar logic is used by libxml2 itself. Basically 'cur' == '<' means the last
443 chunk of char data, in case it's not the last chunk we check for previously added node type and if it's not
444 a text node it's safe to ignore.
446 Note that during domdoc_loadXML() the xmlDocPtr->_private data is not available. */
448 if (!This
->properties
->preserving
&&
449 !is_preserving_whitespace(ctxt
->node
) &&
450 strn_isspace(ch
, len
) &&
451 (!ctxt
->node
->last
||
452 ((ctxt
->node
->last
&& (cur
== '<' || ctxt
->node
->last
->type
!= XML_TEXT_NODE
))
455 /* Keep information about ignorable whitespace text node in previous or parent node */
456 if (ctxt
->node
->last
)
457 *(DWORD
*)&ctxt
->node
->last
->_private
|= NODE_PRIV_TRAILING_IGNORABLE_WS
;
458 else if (ctxt
->node
->type
!= XML_DOCUMENT_NODE
)
459 *(DWORD
*)&ctxt
->node
->_private
|= NODE_PRIV_CHILD_IGNORABLE_WS
;
464 xmlSAX2Characters(ctxt
, ch
, len
);
467 static void LIBXML2_LOG_CALLBACK
sax_error(void* ctx
, char const* msg
, ...)
471 LIBXML2_CALLBACK_ERR(doparse
, msg
, ap
);
475 static void LIBXML2_LOG_CALLBACK
sax_warning(void* ctx
, char const* msg
, ...)
479 LIBXML2_CALLBACK_WARN(doparse
, msg
, ap
);
483 static void sax_serror(void* ctx
, xmlErrorPtr err
)
485 LIBXML2_CALLBACK_SERROR(doparse
, err
);
488 static xmlDocPtr
doparse(domdoc
* This
, char const* ptr
, int len
, xmlCharEncoding encoding
)
490 xmlDocPtr doc
= NULL
;
491 xmlParserCtxtPtr pctx
;
492 static xmlSAXHandler sax_handler
= {
493 xmlSAX2InternalSubset
, /* internalSubset */
494 xmlSAX2IsStandalone
, /* isStandalone */
495 xmlSAX2HasInternalSubset
, /* hasInternalSubset */
496 xmlSAX2HasExternalSubset
, /* hasExternalSubset */
497 xmlSAX2ResolveEntity
, /* resolveEntity */
498 xmlSAX2GetEntity
, /* getEntity */
499 xmlSAX2EntityDecl
, /* entityDecl */
500 xmlSAX2NotationDecl
, /* notationDecl */
501 xmlSAX2AttributeDecl
, /* attributeDecl */
502 xmlSAX2ElementDecl
, /* elementDecl */
503 xmlSAX2UnparsedEntityDecl
, /* unparsedEntityDecl */
504 xmlSAX2SetDocumentLocator
, /* setDocumentLocator */
505 xmlSAX2StartDocument
, /* startDocument */
506 xmlSAX2EndDocument
, /* endDocument */
507 xmlSAX2StartElement
, /* startElement */
508 xmlSAX2EndElement
, /* endElement */
509 xmlSAX2Reference
, /* reference */
510 sax_characters
, /* characters */
511 sax_characters
, /* ignorableWhitespace */
512 xmlSAX2ProcessingInstruction
, /* processingInstruction */
513 xmlSAX2Comment
, /* comment */
514 sax_warning
, /* warning */
515 sax_error
, /* error */
516 sax_error
, /* fatalError */
517 xmlSAX2GetParameterEntity
, /* getParameterEntity */
518 xmlSAX2CDataBlock
, /* cdataBlock */
519 xmlSAX2ExternalSubset
, /* externalSubset */
522 xmlSAX2StartElementNs
, /* startElementNs */
523 xmlSAX2EndElementNs
, /* endElementNs */
524 sax_serror
/* serror */
527 pctx
= xmlCreateMemoryParserCtxt(ptr
, len
);
530 ERR("Failed to create parser context\n");
534 if (pctx
->sax
) xmlFree(pctx
->sax
);
535 pctx
->sax
= &sax_handler
;
536 pctx
->_private
= This
;
539 if (encoding
!= XML_CHAR_ENCODING_NONE
)
540 xmlSwitchEncoding(pctx
, encoding
);
542 xmlParseDocument(pctx
);
544 if (pctx
->wellFormed
)
550 xmlFreeDoc(pctx
->myDoc
);
554 xmlFreeParserCtxt(pctx
);
556 /* TODO: put this in one of the SAX callbacks */
557 /* create first child as a <?xml...?> */
558 if (doc
&& doc
->standalone
!= -1)
562 xmlChar
*xmlbuff
= (xmlChar
*)buff
;
564 node
= xmlNewDocPI( doc
, (xmlChar
*)"xml", NULL
);
566 /* version attribute can't be omitted */
567 sprintf(buff
, "version=\"%s\"", doc
->version
? (char*)doc
->version
: "1.0");
568 xmlNodeAddContent( node
, xmlbuff
);
572 sprintf(buff
, " encoding=\"%s\"", doc
->encoding
);
573 xmlNodeAddContent( node
, xmlbuff
);
576 if (doc
->standalone
!= -2)
578 sprintf(buff
, " standalone=\"%s\"", doc
->standalone
== 0 ? "no" : "yes");
579 xmlNodeAddContent( node
, xmlbuff
);
582 xmldoc_link_xmldecl( doc
, node
);
588 void xmldoc_init(xmlDocPtr doc
, MSXML_VERSION version
)
590 doc
->_private
= create_priv();
591 priv_from_xmlDocPtr(doc
)->properties
= create_properties(version
);
594 LONG
xmldoc_add_refs(xmlDocPtr doc
, LONG refs
)
596 LONG ref
= InterlockedExchangeAdd(&priv_from_xmlDocPtr(doc
)->refs
, refs
) + refs
;
597 TRACE("(%p)->(%d)\n", doc
, ref
);
601 LONG
xmldoc_add_ref(xmlDocPtr doc
)
603 return xmldoc_add_refs(doc
, 1);
606 LONG
xmldoc_release_refs(xmlDocPtr doc
, LONG refs
)
608 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
609 LONG ref
= InterlockedExchangeAdd(&priv
->refs
, -refs
) - refs
;
610 TRACE("(%p)->(%d)\n", doc
, ref
);
613 WARN("negative refcount, expect troubles\n");
617 orphan_entry
*orphan
, *orphan2
;
618 TRACE("freeing docptr %p\n", doc
);
620 LIST_FOR_EACH_ENTRY_SAFE( orphan
, orphan2
, &priv
->orphans
, orphan_entry
, entry
)
622 xmlFreeNode( orphan
->node
);
625 free_properties(priv
->properties
);
626 heap_free(doc
->_private
);
634 LONG
xmldoc_release(xmlDocPtr doc
)
636 return xmldoc_release_refs(doc
, 1);
639 HRESULT
xmldoc_add_orphan(xmlDocPtr doc
, xmlNodePtr node
)
641 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
644 entry
= heap_alloc( sizeof (*entry
) );
646 return E_OUTOFMEMORY
;
649 list_add_head( &priv
->orphans
, &entry
->entry
);
653 HRESULT
xmldoc_remove_orphan(xmlDocPtr doc
, xmlNodePtr node
)
655 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
656 orphan_entry
*entry
, *entry2
;
658 LIST_FOR_EACH_ENTRY_SAFE( entry
, entry2
, &priv
->orphans
, orphan_entry
, entry
)
660 if( entry
->node
== node
)
662 list_remove( &entry
->entry
);
671 static inline xmlDocPtr
get_doc( domdoc
*This
)
673 return This
->node
.node
->doc
;
676 static HRESULT
attach_xmldoc(domdoc
*This
, xmlDocPtr xml
)
678 release_namespaces(This
);
682 priv_from_xmlDocPtr(get_doc(This
))->properties
= NULL
;
683 if (xmldoc_release(get_doc(This
)) != 0)
684 priv_from_xmlDocPtr(get_doc(This
))->properties
=
685 copy_properties(This
->properties
);
688 This
->node
.node
= (xmlNodePtr
) xml
;
692 xmldoc_add_ref(get_doc(This
));
693 priv_from_xmlDocPtr(get_doc(This
))->properties
= This
->properties
;
699 static inline domdoc
*impl_from_IXMLDOMDocument3( IXMLDOMDocument3
*iface
)
701 return CONTAINING_RECORD(iface
, domdoc
, IXMLDOMDocument3_iface
);
704 static inline domdoc
*impl_from_IPersistStreamInit(IPersistStreamInit
*iface
)
706 return CONTAINING_RECORD(iface
, domdoc
, IPersistStreamInit_iface
);
709 static inline domdoc
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
711 return CONTAINING_RECORD(iface
, domdoc
, IObjectWithSite_iface
);
714 static inline domdoc
*impl_from_IObjectSafety(IObjectSafety
*iface
)
716 return CONTAINING_RECORD(iface
, domdoc
, IObjectSafety_iface
);
719 static inline domdoc
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
721 return CONTAINING_RECORD(iface
, domdoc
, IConnectionPointContainer_iface
);
724 /************************************************************************
725 * domdoc implementation of IPersistStream.
727 static HRESULT WINAPI
PersistStreamInit_QueryInterface(
728 IPersistStreamInit
*iface
, REFIID riid
, void **ppvObj
)
730 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
731 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObj
);
734 static ULONG WINAPI
PersistStreamInit_AddRef(
735 IPersistStreamInit
*iface
)
737 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
738 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
741 static ULONG WINAPI
PersistStreamInit_Release(
742 IPersistStreamInit
*iface
)
744 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
745 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
748 static HRESULT WINAPI
PersistStreamInit_GetClassID(
749 IPersistStreamInit
*iface
, CLSID
*classid
)
751 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
752 TRACE("(%p)->(%p)\n", This
, classid
);
757 *classid
= *DOMDocument_version(This
->properties
->version
);
762 static HRESULT WINAPI
PersistStreamInit_IsDirty(
763 IPersistStreamInit
*iface
)
765 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
766 FIXME("(%p): stub!\n", This
);
770 static HRESULT
domdoc_load_from_stream(domdoc
*doc
, ISequentialStream
*stream
)
772 DWORD read
, written
, len
;
773 xmlDocPtr xmldoc
= NULL
;
781 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &hstream
);
787 ISequentialStream_Read(stream
, buf
, sizeof(buf
), &read
);
788 hr
= IStream_Write(hstream
, buf
, read
, &written
);
789 } while(SUCCEEDED(hr
) && written
!= 0 && read
!= 0);
793 ERR("failed to copy stream 0x%08x\n", hr
);
794 IStream_Release(hstream
);
798 hr
= GetHGlobalFromStream(hstream
, &hglobal
);
801 IStream_Release(hstream
);
805 len
= GlobalSize(hglobal
);
806 ptr
= GlobalLock(hglobal
);
808 xmldoc
= doparse(doc
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
809 GlobalUnlock(hglobal
);
810 IStream_Release(hstream
);
814 ERR("Failed to parse xml\n");
818 xmldoc
->_private
= create_priv();
820 return attach_xmldoc(doc
, xmldoc
);
823 static HRESULT WINAPI
PersistStreamInit_Load(IPersistStreamInit
*iface
, IStream
*stream
)
825 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
827 TRACE("(%p)->(%p)\n", This
, stream
);
832 return This
->error
= domdoc_load_from_stream(This
, (ISequentialStream
*)stream
);
835 static HRESULT WINAPI
PersistStreamInit_Save(
836 IPersistStreamInit
*iface
, IStream
*stream
, BOOL clr_dirty
)
838 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
842 TRACE("(%p)->(%p %d)\n", This
, stream
, clr_dirty
);
844 hr
= IXMLDOMDocument3_get_xml(&This
->IXMLDOMDocument3_iface
, &xmlString
);
847 DWORD len
= SysStringLen(xmlString
) * sizeof(WCHAR
);
849 hr
= IStream_Write( stream
, xmlString
, len
, NULL
);
850 SysFreeString(xmlString
);
853 TRACE("ret 0x%08x\n", hr
);
858 static HRESULT WINAPI
PersistStreamInit_GetSizeMax(
859 IPersistStreamInit
*iface
, ULARGE_INTEGER
*pcbSize
)
861 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
862 TRACE("(%p)->(%p)\n", This
, pcbSize
);
866 static HRESULT WINAPI
PersistStreamInit_InitNew(
867 IPersistStreamInit
*iface
)
869 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
870 TRACE("(%p)\n", This
);
874 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable
=
876 PersistStreamInit_QueryInterface
,
877 PersistStreamInit_AddRef
,
878 PersistStreamInit_Release
,
879 PersistStreamInit_GetClassID
,
880 PersistStreamInit_IsDirty
,
881 PersistStreamInit_Load
,
882 PersistStreamInit_Save
,
883 PersistStreamInit_GetSizeMax
,
884 PersistStreamInit_InitNew
887 /* IXMLDOMDocument3 interface */
889 static const tid_t domdoc_se_tids
[] = {
892 IXMLDOMDocument2_tid
,
893 IXMLDOMDocument3_tid
,
897 static HRESULT WINAPI
domdoc_QueryInterface( IXMLDOMDocument3
*iface
, REFIID riid
, void** ppvObject
)
899 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
901 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( riid
), ppvObject
);
905 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
906 IsEqualGUID( riid
, &IID_IDispatch
) ||
907 IsEqualGUID( riid
, &IID_IXMLDOMNode
) ||
908 IsEqualGUID( riid
, &IID_IXMLDOMDocument
) ||
909 IsEqualGUID( riid
, &IID_IXMLDOMDocument2
)||
910 IsEqualGUID( riid
, &IID_IXMLDOMDocument3
))
914 else if (IsEqualGUID(&IID_IPersistStream
, riid
) ||
915 IsEqualGUID(&IID_IPersistStreamInit
, riid
))
917 *ppvObject
= &This
->IPersistStreamInit_iface
;
919 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
921 *ppvObject
= &This
->IObjectWithSite_iface
;
923 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
925 *ppvObject
= &This
->IObjectSafety_iface
;
927 else if( IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
929 return node_create_supporterrorinfo(domdoc_se_tids
, ppvObject
);
931 else if(node_query_interface(&This
->node
, riid
, ppvObject
))
933 return *ppvObject
? S_OK
: E_NOINTERFACE
;
935 else if (IsEqualGUID( riid
, &IID_IConnectionPointContainer
))
937 *ppvObject
= &This
->IConnectionPointContainer_iface
;
941 TRACE("interface %s not implemented\n", debugstr_guid(riid
));
942 return E_NOINTERFACE
;
945 IUnknown_AddRef((IUnknown
*)*ppvObject
);
950 static ULONG WINAPI
domdoc_AddRef( IXMLDOMDocument3
*iface
)
952 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
953 ULONG ref
= InterlockedIncrement( &This
->ref
);
954 TRACE("(%p)->(%d)\n", This
, ref
);
958 static ULONG WINAPI
domdoc_Release( IXMLDOMDocument3
*iface
)
960 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
961 LONG ref
= InterlockedDecrement( &This
->ref
);
963 TRACE("(%p)->(%d)\n", This
, ref
);
970 IUnknown_Release( This
->site
);
972 IUri_Release( This
->base_uri
);
973 destroy_xmlnode(&This
->node
);
975 for (eid
= 0; eid
< EVENTID_LAST
; eid
++)
976 if (This
->events
[eid
]) IDispatch_Release(This
->events
[eid
]);
978 release_namespaces(This
);
985 static HRESULT WINAPI
domdoc_GetTypeInfoCount( IXMLDOMDocument3
*iface
, UINT
* pctinfo
)
987 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
988 return IDispatchEx_GetTypeInfoCount(&This
->node
.dispex
.IDispatchEx_iface
, pctinfo
);
991 static HRESULT WINAPI
domdoc_GetTypeInfo(
992 IXMLDOMDocument3
*iface
,
993 UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
995 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
996 return IDispatchEx_GetTypeInfo(&This
->node
.dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
999 static HRESULT WINAPI
domdoc_GetIDsOfNames(
1000 IXMLDOMDocument3
*iface
,
1002 LPOLESTR
* rgszNames
,
1007 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1008 return IDispatchEx_GetIDsOfNames(&This
->node
.dispex
.IDispatchEx_iface
,
1009 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
1012 static HRESULT WINAPI
domdoc_Invoke(
1013 IXMLDOMDocument3
*iface
,
1014 DISPID dispIdMember
,
1018 DISPPARAMS
* pDispParams
,
1019 VARIANT
* pVarResult
,
1020 EXCEPINFO
* pExcepInfo
,
1023 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1024 return IDispatchEx_Invoke(&This
->node
.dispex
.IDispatchEx_iface
,
1025 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1028 static HRESULT WINAPI
domdoc_get_nodeName(
1029 IXMLDOMDocument3
*iface
,
1032 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1034 static const WCHAR documentW
[] = {'#','d','o','c','u','m','e','n','t',0};
1036 TRACE("(%p)->(%p)\n", This
, name
);
1038 return return_bstr(documentW
, name
);
1042 static HRESULT WINAPI
domdoc_get_nodeValue(
1043 IXMLDOMDocument3
*iface
,
1046 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1048 TRACE("(%p)->(%p)\n", This
, value
);
1051 return E_INVALIDARG
;
1053 V_VT(value
) = VT_NULL
;
1054 V_BSTR(value
) = NULL
; /* tests show that we should do this */
1059 static HRESULT WINAPI
domdoc_put_nodeValue(
1060 IXMLDOMDocument3
*iface
,
1063 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1064 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&value
));
1069 static HRESULT WINAPI
domdoc_get_nodeType(
1070 IXMLDOMDocument3
*iface
,
1073 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1075 TRACE("(%p)->(%p)\n", This
, type
);
1077 *type
= NODE_DOCUMENT
;
1082 static HRESULT WINAPI
domdoc_get_parentNode(
1083 IXMLDOMDocument3
*iface
,
1084 IXMLDOMNode
** parent
)
1086 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1088 TRACE("(%p)->(%p)\n", This
, parent
);
1090 return node_get_parent(&This
->node
, parent
);
1094 static HRESULT WINAPI
domdoc_get_childNodes(
1095 IXMLDOMDocument3
*iface
,
1096 IXMLDOMNodeList
** childList
)
1098 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1100 TRACE("(%p)->(%p)\n", This
, childList
);
1102 return node_get_child_nodes(&This
->node
, childList
);
1106 static HRESULT WINAPI
domdoc_get_firstChild(
1107 IXMLDOMDocument3
*iface
,
1108 IXMLDOMNode
** firstChild
)
1110 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1112 TRACE("(%p)->(%p)\n", This
, firstChild
);
1114 return node_get_first_child(&This
->node
, firstChild
);
1118 static HRESULT WINAPI
domdoc_get_lastChild(
1119 IXMLDOMDocument3
*iface
,
1120 IXMLDOMNode
** lastChild
)
1122 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1124 TRACE("(%p)->(%p)\n", This
, lastChild
);
1126 return node_get_last_child(&This
->node
, lastChild
);
1130 static HRESULT WINAPI
domdoc_get_previousSibling(
1131 IXMLDOMDocument3
*iface
,
1132 IXMLDOMNode
** previousSibling
)
1134 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1136 TRACE("(%p)->(%p)\n", This
, previousSibling
);
1138 return return_null_node(previousSibling
);
1142 static HRESULT WINAPI
domdoc_get_nextSibling(
1143 IXMLDOMDocument3
*iface
,
1144 IXMLDOMNode
** nextSibling
)
1146 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1148 TRACE("(%p)->(%p)\n", This
, nextSibling
);
1150 return return_null_node(nextSibling
);
1154 static HRESULT WINAPI
domdoc_get_attributes(
1155 IXMLDOMDocument3
*iface
,
1156 IXMLDOMNamedNodeMap
** attributeMap
)
1158 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1160 TRACE("(%p)->(%p)\n", This
, attributeMap
);
1162 return return_null_ptr((void**)attributeMap
);
1166 static HRESULT WINAPI
domdoc_insertBefore(
1167 IXMLDOMDocument3
*iface
,
1168 IXMLDOMNode
* newChild
,
1170 IXMLDOMNode
** outNewChild
)
1172 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1176 TRACE("(%p)->(%p %s %p)\n", This
, newChild
, debugstr_variant(&refChild
), outNewChild
);
1178 hr
= IXMLDOMNode_get_nodeType(newChild
, &type
);
1179 if (hr
!= S_OK
) return hr
;
1181 TRACE("new node type %d\n", type
);
1184 case NODE_ATTRIBUTE
:
1186 case NODE_CDATA_SECTION
:
1187 if (outNewChild
) *outNewChild
= NULL
;
1190 return node_insert_before(&This
->node
, newChild
, &refChild
, outNewChild
);
1194 static HRESULT WINAPI
domdoc_replaceChild(
1195 IXMLDOMDocument3
*iface
,
1196 IXMLDOMNode
* newChild
,
1197 IXMLDOMNode
* oldChild
,
1198 IXMLDOMNode
** outOldChild
)
1200 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1202 TRACE("(%p)->(%p %p %p)\n", This
, newChild
, oldChild
, outOldChild
);
1204 return node_replace_child(&This
->node
, newChild
, oldChild
, outOldChild
);
1208 static HRESULT WINAPI
domdoc_removeChild(
1209 IXMLDOMDocument3
*iface
,
1211 IXMLDOMNode
**oldChild
)
1213 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1214 TRACE("(%p)->(%p %p)\n", This
, child
, oldChild
);
1215 return node_remove_child(&This
->node
, child
, oldChild
);
1219 static HRESULT WINAPI
domdoc_appendChild(
1220 IXMLDOMDocument3
*iface
,
1222 IXMLDOMNode
**outChild
)
1224 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1225 TRACE("(%p)->(%p %p)\n", This
, child
, outChild
);
1226 return node_append_child(&This
->node
, child
, outChild
);
1230 static HRESULT WINAPI
domdoc_hasChildNodes(
1231 IXMLDOMDocument3
*iface
,
1234 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1235 TRACE("(%p)->(%p)\n", This
, ret
);
1236 return node_has_childnodes(&This
->node
, ret
);
1240 static HRESULT WINAPI
domdoc_get_ownerDocument(
1241 IXMLDOMDocument3
*iface
,
1242 IXMLDOMDocument
**doc
)
1244 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1245 TRACE("(%p)->(%p)\n", This
, doc
);
1246 return node_get_owner_doc(&This
->node
, doc
);
1250 static HRESULT WINAPI
domdoc_cloneNode(
1251 IXMLDOMDocument3
*iface
,
1253 IXMLDOMNode
** outNode
)
1255 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1258 TRACE("(%p)->(%d %p)\n", This
, deep
, outNode
);
1261 return E_INVALIDARG
;
1265 clone
= xmlCopyNode((xmlNodePtr
)get_doc(This
), deep
? 1 : 2);
1269 clone
->doc
->_private
= create_priv();
1270 xmldoc_add_orphan(clone
->doc
, clone
);
1271 xmldoc_add_ref(clone
->doc
);
1273 priv_from_xmlDocPtr(clone
->doc
)->properties
= copy_properties(This
->properties
);
1274 if (!(*outNode
= (IXMLDOMNode
*)create_domdoc(clone
)))
1276 xmldoc_release(clone
->doc
);
1284 static HRESULT WINAPI
domdoc_get_nodeTypeString(
1285 IXMLDOMDocument3
*iface
,
1288 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1289 static const WCHAR documentW
[] = {'d','o','c','u','m','e','n','t',0};
1291 TRACE("(%p)->(%p)\n", This
, p
);
1293 return return_bstr(documentW
, p
);
1297 static HRESULT WINAPI
domdoc_get_text(
1298 IXMLDOMDocument3
*iface
,
1301 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1302 TRACE("(%p)->(%p)\n", This
, p
);
1303 return node_get_text(&This
->node
, p
);
1307 static HRESULT WINAPI
domdoc_put_text(
1308 IXMLDOMDocument3
*iface
,
1311 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1312 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
1317 static HRESULT WINAPI
domdoc_get_specified(
1318 IXMLDOMDocument3
*iface
,
1319 VARIANT_BOOL
* isSpecified
)
1321 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1322 FIXME("(%p)->(%p) stub!\n", This
, isSpecified
);
1323 *isSpecified
= VARIANT_TRUE
;
1328 static HRESULT WINAPI
domdoc_get_definition(
1329 IXMLDOMDocument3
*iface
,
1330 IXMLDOMNode
** definitionNode
)
1332 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1333 FIXME("(%p)->(%p)\n", This
, definitionNode
);
1338 static HRESULT WINAPI
domdoc_get_nodeTypedValue(
1339 IXMLDOMDocument3
*iface
,
1342 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1343 TRACE("(%p)->(%p)\n", This
, v
);
1344 return return_null_var(v
);
1347 static HRESULT WINAPI
domdoc_put_nodeTypedValue(
1348 IXMLDOMDocument3
*iface
,
1349 VARIANT typedValue
)
1351 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1352 FIXME("(%p)->(%s)\n", This
, debugstr_variant(&typedValue
));
1357 static HRESULT WINAPI
domdoc_get_dataType(
1358 IXMLDOMDocument3
*iface
,
1361 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1362 TRACE("(%p)->(%p)\n", This
, typename
);
1363 return return_null_var( typename
);
1367 static HRESULT WINAPI
domdoc_put_dataType(
1368 IXMLDOMDocument3
*iface
,
1371 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1373 FIXME("(%p)->(%s)\n", This
, debugstr_w(dataTypeName
));
1376 return E_INVALIDARG
;
1381 static int XMLCALL
domdoc_get_xml_writecallback(void *ctx
, const char *data
, int len
)
1383 return xmlBufferAdd((xmlBufferPtr
)ctx
, (xmlChar
*)data
, len
) == 0 ? len
: 0;
1386 static HRESULT WINAPI
domdoc_get_xml(
1387 IXMLDOMDocument3
*iface
,
1390 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1391 xmlSaveCtxtPtr ctxt
;
1396 TRACE("(%p)->(%p)\n", This
, p
);
1399 return E_INVALIDARG
;
1403 buf
= xmlBufferCreate();
1405 return E_OUTOFMEMORY
;
1407 options
= XML_SAVE_FORMAT
| XML_SAVE_NO_DECL
;
1408 ctxt
= xmlSaveToIO(domdoc_get_xml_writecallback
, NULL
, buf
, "UTF-8", options
);
1413 return E_OUTOFMEMORY
;
1416 ret
= xmlSaveDoc(ctxt
, get_doc(This
));
1417 /* flushes on close */
1420 TRACE("%ld, len=%d\n", ret
, xmlBufferLength(buf
));
1421 if(ret
!= -1 && xmlBufferLength(buf
) > 0)
1425 content
= bstr_from_xmlChar(xmlBufferContent(buf
));
1426 content
= EnsureCorrectEOL(content
);
1432 *p
= SysAllocStringLen(NULL
, 0);
1437 return *p
? S_OK
: E_OUTOFMEMORY
;
1441 static HRESULT WINAPI
domdoc_transformNode(
1442 IXMLDOMDocument3
*iface
,
1446 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1447 TRACE("(%p)->(%p %p)\n", This
, node
, p
);
1448 return node_transform_node(&This
->node
, node
, p
);
1452 static HRESULT WINAPI
domdoc_selectNodes(
1453 IXMLDOMDocument3
*iface
,
1455 IXMLDOMNodeList
**outList
)
1457 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1458 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outList
);
1459 return node_select_nodes(&This
->node
, p
, outList
);
1463 static HRESULT WINAPI
domdoc_selectSingleNode(
1464 IXMLDOMDocument3
*iface
,
1466 IXMLDOMNode
**outNode
)
1468 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1469 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outNode
);
1470 return node_select_singlenode(&This
->node
, p
, outNode
);
1474 static HRESULT WINAPI
domdoc_get_parsed(
1475 IXMLDOMDocument3
*iface
,
1476 VARIANT_BOOL
* isParsed
)
1478 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1479 FIXME("(%p)->(%p) stub!\n", This
, isParsed
);
1480 *isParsed
= VARIANT_TRUE
;
1484 static HRESULT WINAPI
domdoc_get_namespaceURI(
1485 IXMLDOMDocument3
*iface
,
1486 BSTR
* namespaceURI
)
1488 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1489 TRACE("(%p)->(%p)\n", This
, namespaceURI
);
1490 return return_null_bstr( namespaceURI
);
1493 static HRESULT WINAPI
domdoc_get_prefix(
1494 IXMLDOMDocument3
*iface
,
1497 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1498 TRACE("(%p)->(%p)\n", This
, prefix
);
1499 return return_null_bstr( prefix
);
1503 static HRESULT WINAPI
domdoc_get_baseName(
1504 IXMLDOMDocument3
*iface
,
1507 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1508 TRACE("(%p)->(%p)\n", This
, name
);
1509 return return_null_bstr( name
);
1513 static HRESULT WINAPI
domdoc_transformNodeToObject(
1514 IXMLDOMDocument3
*iface
,
1515 IXMLDOMNode
* stylesheet
,
1518 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1520 TRACE("(%p)->(%p %s)\n", This
, stylesheet
, debugstr_variant(&output
));
1522 switch (V_VT(&output
))
1527 ISequentialStream
*stream
;
1528 IXMLDOMDocument
*doc
;
1532 if (!V_UNKNOWN(&output
))
1533 return E_INVALIDARG
;
1535 /* FIXME: we're not supposed to query for document interface, should use IStream
1536 which we don't support currently. */
1537 if (IUnknown_QueryInterface(V_UNKNOWN(&output
), &IID_IXMLDOMDocument
, (void **)&doc
) == S_OK
)
1541 if (FAILED(hr
= node_transform_node(&This
->node
, stylesheet
, &str
)))
1544 hr
= IXMLDOMDocument_loadXML(doc
, str
, &b
);
1548 else if (IUnknown_QueryInterface(V_UNKNOWN(&output
), &IID_ISequentialStream
, (void**)&stream
) == S_OK
)
1550 hr
= node_transform_node_params(&This
->node
, stylesheet
, NULL
, stream
, NULL
);
1551 ISequentialStream_Release(stream
);
1556 FIXME("Unsupported destination type.\n");
1557 return E_INVALIDARG
;
1561 FIXME("Output type %d not handled.\n", V_VT(&output
));
1569 static HRESULT WINAPI
domdoc_get_doctype(
1570 IXMLDOMDocument3
*iface
,
1571 IXMLDOMDocumentType
** doctype
)
1573 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1578 TRACE("(%p)->(%p)\n", This
, doctype
);
1580 if (!doctype
) return E_INVALIDARG
;
1584 dtd
= xmlGetIntSubset(get_doc(This
));
1585 if (!dtd
) return S_FALSE
;
1587 node
= create_node((xmlNodePtr
)dtd
);
1588 if (!node
) return S_FALSE
;
1590 hr
= IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentType
, (void**)doctype
);
1591 IXMLDOMNode_Release(node
);
1597 static HRESULT WINAPI
domdoc_get_implementation(
1598 IXMLDOMDocument3
*iface
,
1599 IXMLDOMImplementation
** impl
)
1601 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1603 TRACE("(%p)->(%p)\n", This
, impl
);
1606 return E_INVALIDARG
;
1608 *impl
= (IXMLDOMImplementation
*)create_doc_Implementation();
1613 static HRESULT WINAPI
domdoc_get_documentElement(
1614 IXMLDOMDocument3
*iface
,
1615 IXMLDOMElement
** DOMElement
)
1617 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1618 IXMLDOMNode
*element_node
;
1622 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1625 return E_INVALIDARG
;
1629 root
= xmlDocGetRootElement( get_doc(This
) );
1633 element_node
= create_node( root
);
1634 if(!element_node
) return S_FALSE
;
1636 hr
= IXMLDOMNode_QueryInterface(element_node
, &IID_IXMLDOMElement
, (void**)DOMElement
);
1637 IXMLDOMNode_Release(element_node
);
1643 static HRESULT WINAPI
domdoc_put_documentElement(
1644 IXMLDOMDocument3
*iface
,
1645 IXMLDOMElement
* DOMElement
)
1647 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1648 IXMLDOMNode
*elementNode
;
1655 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1657 hr
= IXMLDOMElement_QueryInterface( DOMElement
, &IID_IXMLDOMNode
, (void**)&elementNode
);
1661 xmlNode
= get_node_obj( elementNode
);
1662 if(!xmlNode
) return E_FAIL
;
1664 if(!xmlNode
->node
->parent
)
1665 if(xmldoc_remove_orphan(xmlNode
->node
->doc
, xmlNode
->node
) != S_OK
)
1666 WARN("%p is not an orphan of %p\n", xmlNode
->node
->doc
, xmlNode
->node
);
1668 old_doc
= xmlNode
->node
->doc
;
1669 if (old_doc
!= get_doc(This
))
1670 refcount
= xmlnode_get_inst_cnt(xmlNode
);
1672 /* old root is still orphaned by its document, update refcount from new root */
1673 if (refcount
) xmldoc_add_refs(get_doc(This
), refcount
);
1674 oldRoot
= xmlDocSetRootElement( get_doc(This
), xmlNode
->node
);
1675 if (refcount
) xmldoc_release_refs(old_doc
, refcount
);
1676 IXMLDOMNode_Release( elementNode
);
1679 xmldoc_add_orphan(oldRoot
->doc
, oldRoot
);
1685 static HRESULT WINAPI
domdoc_createElement(
1686 IXMLDOMDocument3
*iface
,
1688 IXMLDOMElement
** element
)
1690 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1695 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(tagname
), element
);
1697 if (!element
|| !tagname
) return E_INVALIDARG
;
1699 V_VT(&type
) = VT_I1
;
1700 V_I1(&type
) = NODE_ELEMENT
;
1702 hr
= IXMLDOMDocument3_createNode(iface
, type
, tagname
, NULL
, &node
);
1705 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMElement
, (void**)element
);
1706 IXMLDOMNode_Release(node
);
1713 static HRESULT WINAPI
domdoc_createDocumentFragment(
1714 IXMLDOMDocument3
*iface
,
1715 IXMLDOMDocumentFragment
** frag
)
1717 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1722 TRACE("(%p)->(%p)\n", This
, frag
);
1724 if (!frag
) return E_INVALIDARG
;
1728 V_VT(&type
) = VT_I1
;
1729 V_I1(&type
) = NODE_DOCUMENT_FRAGMENT
;
1731 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1734 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentFragment
, (void**)frag
);
1735 IXMLDOMNode_Release(node
);
1742 static HRESULT WINAPI
domdoc_createTextNode(
1743 IXMLDOMDocument3
*iface
,
1745 IXMLDOMText
** text
)
1747 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1752 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), text
);
1754 if (!text
) return E_INVALIDARG
;
1758 V_VT(&type
) = VT_I1
;
1759 V_I1(&type
) = NODE_TEXT
;
1761 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1764 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMText
, (void**)text
);
1765 IXMLDOMNode_Release(node
);
1766 hr
= IXMLDOMText_put_data(*text
, data
);
1773 static HRESULT WINAPI
domdoc_createComment(
1774 IXMLDOMDocument3
*iface
,
1776 IXMLDOMComment
** comment
)
1778 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1783 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), comment
);
1785 if (!comment
) return E_INVALIDARG
;
1789 V_VT(&type
) = VT_I1
;
1790 V_I1(&type
) = NODE_COMMENT
;
1792 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1795 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMComment
, (void**)comment
);
1796 IXMLDOMNode_Release(node
);
1797 hr
= IXMLDOMComment_put_data(*comment
, data
);
1804 static HRESULT WINAPI
domdoc_createCDATASection(
1805 IXMLDOMDocument3
*iface
,
1807 IXMLDOMCDATASection
** cdata
)
1809 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1814 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), cdata
);
1816 if (!cdata
) return E_INVALIDARG
;
1820 V_VT(&type
) = VT_I1
;
1821 V_I1(&type
) = NODE_CDATA_SECTION
;
1823 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1826 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMCDATASection
, (void**)cdata
);
1827 IXMLDOMNode_Release(node
);
1828 hr
= IXMLDOMCDATASection_put_data(*cdata
, data
);
1835 static HRESULT WINAPI
domdoc_createProcessingInstruction(
1836 IXMLDOMDocument3
*iface
,
1839 IXMLDOMProcessingInstruction
** pi
)
1841 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1846 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_w(target
), debugstr_w(data
), pi
);
1848 if (!pi
) return E_INVALIDARG
;
1852 V_VT(&type
) = VT_I1
;
1853 V_I1(&type
) = NODE_PROCESSING_INSTRUCTION
;
1855 hr
= IXMLDOMDocument3_createNode(iface
, type
, target
, NULL
, &node
);
1860 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1861 node_obj
= get_node_obj(node
);
1862 hr
= node_set_content(node_obj
, data
);
1864 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMProcessingInstruction
, (void**)pi
);
1865 IXMLDOMNode_Release(node
);
1872 static HRESULT WINAPI
domdoc_createAttribute(
1873 IXMLDOMDocument3
*iface
,
1875 IXMLDOMAttribute
** attribute
)
1877 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1882 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), attribute
);
1884 if (!attribute
|| !name
) return E_INVALIDARG
;
1886 V_VT(&type
) = VT_I1
;
1887 V_I1(&type
) = NODE_ATTRIBUTE
;
1889 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1892 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMAttribute
, (void**)attribute
);
1893 IXMLDOMNode_Release(node
);
1900 static HRESULT WINAPI
domdoc_createEntityReference(
1901 IXMLDOMDocument3
*iface
,
1903 IXMLDOMEntityReference
** entityref
)
1905 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1910 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), entityref
);
1912 if (!entityref
) return E_INVALIDARG
;
1916 V_VT(&type
) = VT_I1
;
1917 V_I1(&type
) = NODE_ENTITY_REFERENCE
;
1919 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1922 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMEntityReference
, (void**)entityref
);
1923 IXMLDOMNode_Release(node
);
1929 xmlChar
* tagName_to_XPath(const BSTR tagName
)
1931 xmlChar
*query
, *tmp
;
1932 static const xmlChar everything
[] = "/descendant::node()";
1933 static const xmlChar mod_pre
[] = "*[local-name()='";
1934 static const xmlChar mod_post
[] = "']";
1935 static const xmlChar prefix
[] = "descendant::";
1936 const WCHAR
*tokBegin
, *tokEnd
;
1939 /* Special case - empty tagname - means select all nodes,
1940 except document itself. */
1942 return xmlStrdup(everything
);
1944 query
= xmlStrdup(prefix
);
1947 while (tokBegin
&& *tokBegin
)
1952 query
= xmlStrcat(query
, BAD_CAST
"/");
1956 query
= xmlStrcat(query
, BAD_CAST
"*");
1960 query
= xmlStrcat(query
, mod_pre
);
1962 while (*tokEnd
&& *tokEnd
!= '/')
1964 len
= WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, NULL
, 0, NULL
, NULL
);
1965 tmp
= xmlMalloc(len
);
1966 WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, (char*)tmp
, len
, NULL
, NULL
);
1967 query
= xmlStrncat(query
, tmp
, len
);
1970 query
= xmlStrcat(query
, mod_post
);
1977 static HRESULT WINAPI
domdoc_getElementsByTagName(
1978 IXMLDOMDocument3
*iface
,
1980 IXMLDOMNodeList
** resultList
)
1982 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1987 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(tagName
), resultList
);
1989 if (!tagName
|| !resultList
) return E_INVALIDARG
;
1991 XPath
= This
->properties
->XPath
;
1992 This
->properties
->XPath
= TRUE
;
1993 query
= tagName_to_XPath(tagName
);
1994 hr
= create_selection((xmlNodePtr
)get_doc(This
), query
, resultList
);
1996 This
->properties
->XPath
= XPath
;
2001 static HRESULT
get_node_type(VARIANT Type
, DOMNodeType
* type
)
2007 hr
= VariantChangeType(&tmp
, &Type
, 0, VT_I4
);
2009 return E_INVALIDARG
;
2016 static HRESULT WINAPI
domdoc_createNode(
2017 IXMLDOMDocument3
*iface
,
2021 IXMLDOMNode
** node
)
2023 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2024 DOMNodeType node_type
;
2026 xmlChar
*xml_name
, *href
;
2029 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_variant(&Type
), debugstr_w(name
), debugstr_w(namespaceURI
), node
);
2031 if(!node
) return E_INVALIDARG
;
2033 hr
= get_node_type(Type
, &node_type
);
2034 if(FAILED(hr
)) return hr
;
2036 TRACE("node_type %d\n", node_type
);
2038 /* exit earlier for types that need name */
2042 case NODE_ATTRIBUTE
:
2043 case NODE_ENTITY_REFERENCE
:
2044 case NODE_PROCESSING_INSTRUCTION
:
2045 if (!name
|| *name
== 0) return E_FAIL
;
2051 xml_name
= xmlchar_from_wchar(name
);
2052 /* prevent empty href from being allocated */
2053 href
= namespaceURI
? xmlchar_from_wchar(namespaceURI
) : NULL
;
2059 xmlChar
*local
, *prefix
;
2061 local
= xmlSplitQName2(xml_name
, &prefix
);
2063 xmlnode
= xmlNewDocNode(get_doc(This
), NULL
, local
? local
: xml_name
, NULL
);
2065 /* allow creating the default namespace xmlns= */
2066 if (local
|| (href
&& *href
))
2068 xmlNsPtr ns
= xmlNewNs(xmlnode
, href
, prefix
);
2069 xmlSetNs(xmlnode
, ns
);
2077 case NODE_ATTRIBUTE
:
2079 xmlChar
*local
, *prefix
;
2081 local
= xmlSplitQName2(xml_name
, &prefix
);
2083 xmlnode
= (xmlNodePtr
)xmlNewDocProp(get_doc(This
), local
? local
: xml_name
, NULL
);
2085 if (local
|| (href
&& *href
))
2087 /* we need a floating namespace here, it can't be created linked to attribute from
2089 xmlNsPtr ns
= xmlNewNs(NULL
, href
, prefix
);
2090 xmlSetNs(xmlnode
, ns
);
2099 xmlnode
= (xmlNodePtr
)xmlNewDocText(get_doc(This
), NULL
);
2101 case NODE_CDATA_SECTION
:
2102 xmlnode
= xmlNewCDataBlock(get_doc(This
), NULL
, 0);
2104 case NODE_ENTITY_REFERENCE
:
2105 xmlnode
= xmlNewReference(get_doc(This
), xml_name
);
2107 case NODE_PROCESSING_INSTRUCTION
:
2108 #ifdef HAVE_XMLNEWDOCPI
2109 xmlnode
= xmlNewDocPI(get_doc(This
), xml_name
, NULL
);
2111 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2116 xmlnode
= xmlNewDocComment(get_doc(This
), NULL
);
2118 case NODE_DOCUMENT_FRAGMENT
:
2119 xmlnode
= xmlNewDocFragment(get_doc(This
));
2121 /* unsupported types */
2123 case NODE_DOCUMENT_TYPE
:
2126 heap_free(xml_name
);
2127 return E_INVALIDARG
;
2129 FIXME("unhandled node type %d\n", node_type
);
2134 *node
= create_node(xmlnode
);
2135 heap_free(xml_name
);
2140 TRACE("created node (%d, %p, %p)\n", node_type
, *node
, xmlnode
);
2141 xmldoc_add_orphan(xmlnode
->doc
, xmlnode
);
2148 static HRESULT WINAPI
domdoc_nodeFromID(
2149 IXMLDOMDocument3
*iface
,
2151 IXMLDOMNode
** node
)
2153 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2154 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(idString
), node
);
2158 static HRESULT
domdoc_onDataAvailable(void *obj
, char *ptr
, DWORD len
)
2163 xmldoc
= doparse(This
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
2165 xmldoc
->_private
= create_priv();
2166 return attach_xmldoc(This
, xmldoc
);
2172 static HRESULT
domdoc_load_moniker(domdoc
*This
, IMoniker
*mon
)
2177 hr
= bind_url(mon
, domdoc_onDataAvailable
, This
, &bsc
);
2181 return detach_bsc(bsc
);
2184 static HRESULT WINAPI
domdoc_load(
2185 IXMLDOMDocument3
*iface
,
2187 VARIANT_BOOL
* isSuccessful
)
2189 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2190 LPWSTR filename
= NULL
;
2191 HRESULT hr
= S_FALSE
;
2194 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&source
));
2198 *isSuccessful
= VARIANT_FALSE
;
2200 assert( &This
->node
);
2202 switch( V_VT(&source
) )
2205 filename
= V_BSTR(&source
);
2207 case VT_BSTR
|VT_BYREF
:
2208 if (!V_BSTRREF(&source
)) return E_INVALIDARG
;
2209 filename
= *V_BSTRREF(&source
);
2211 case VT_ARRAY
|VT_UI1
:
2213 SAFEARRAY
*psa
= V_ARRAY(&source
);
2216 UINT dim
= SafeArrayGetDim(psa
);
2221 ERR("SAFEARRAY == NULL\n");
2222 hr
= This
->error
= E_INVALIDARG
;
2225 /* Only takes UTF-8 strings.
2226 * NOT NULL-terminated. */
2227 hr
= SafeArrayAccessData(psa
, (void**)&str
);
2231 WARN("failed to access array data, 0x%08x\n", hr
);
2234 SafeArrayGetUBound(psa
, 1, &len
);
2236 if ((xmldoc
= doparse(This
, str
, ++len
, XML_CHAR_ENCODING_UTF8
)))
2238 hr
= This
->error
= S_OK
;
2239 *isSuccessful
= VARIANT_TRUE
;
2240 TRACE("parsed document %p\n", xmldoc
);
2244 This
->error
= E_FAIL
;
2245 TRACE("failed to parse document\n");
2248 SafeArrayUnaccessData(psa
);
2252 xmldoc
->_private
= create_priv();
2253 return attach_xmldoc(This
, xmldoc
);
2257 FIXME("unhandled SAFEARRAY dim: %d\n", dim
);
2258 hr
= This
->error
= E_NOTIMPL
;
2264 ISequentialStream
*stream
= NULL
;
2265 IXMLDOMDocument3
*newdoc
= NULL
;
2267 if (!V_UNKNOWN(&source
)) return E_INVALIDARG
;
2269 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IXMLDOMDocument3
, (void**)&newdoc
);
2274 domdoc
*newDoc
= impl_from_IXMLDOMDocument3( newdoc
);
2276 xmldoc
= xmlCopyDoc(get_doc(newDoc
), 1);
2277 xmldoc
->_private
= create_priv();
2278 hr
= attach_xmldoc(This
, xmldoc
);
2281 *isSuccessful
= VARIANT_TRUE
;
2287 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IStream
, (void**)&stream
);
2289 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_ISequentialStream
, (void**)&stream
);
2293 hr
= This
->error
= domdoc_load_from_stream(This
, stream
);
2295 *isSuccessful
= VARIANT_TRUE
;
2296 ISequentialStream_Release(stream
);
2300 FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr
, V_UNKNOWN(&source
)->lpVtbl
);
2304 FIXME("VT type not supported (%d)\n", V_VT(&source
));
2312 if (This
->properties
->uri
)
2314 IUri_Release(This
->properties
->uri
);
2315 This
->properties
->uri
= NULL
;
2318 hr
= create_uri(This
->base_uri
, filename
, &uri
);
2320 hr
= CreateURLMonikerEx2(NULL
, uri
, &mon
, 0);
2321 if ( SUCCEEDED(hr
) )
2323 hr
= domdoc_load_moniker( This
, mon
);
2324 IMoniker_Release(mon
);
2329 get_doc(This
)->name
= (char *)xmlchar_from_wcharn(filename
, -1, TRUE
);
2330 This
->properties
->uri
= uri
;
2331 hr
= This
->error
= S_OK
;
2332 *isSuccessful
= VARIANT_TRUE
;
2338 This
->error
= E_FAIL
;
2342 if(!filename
|| FAILED(hr
)) {
2343 xmldoc
= xmlNewDoc(NULL
);
2344 xmldoc
->_private
= create_priv();
2345 hr
= attach_xmldoc(This
, xmldoc
);
2350 TRACE("ret (%d)\n", hr
);
2356 static HRESULT WINAPI
domdoc_get_readyState(
2357 IXMLDOMDocument3
*iface
,
2360 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2361 FIXME("stub! (%p)->(%p)\n", This
, value
);
2364 return E_INVALIDARG
;
2366 *value
= READYSTATE_COMPLETE
;
2371 static HRESULT WINAPI
domdoc_get_parseError(
2372 IXMLDOMDocument3
*iface
,
2373 IXMLDOMParseError
** errorObj
)
2375 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2376 static const WCHAR err
[] = {'e','r','r','o','r',0};
2377 BSTR error_string
= NULL
;
2379 FIXME("(%p)->(%p): creating a dummy parseError\n", iface
, errorObj
);
2382 error_string
= SysAllocString(err
);
2384 *errorObj
= create_parseError(This
->error
, NULL
, error_string
, NULL
, 0, 0, 0);
2385 if(!*errorObj
) return E_OUTOFMEMORY
;
2390 static HRESULT WINAPI
domdoc_get_url(
2391 IXMLDOMDocument3
*iface
,
2394 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2396 TRACE("(%p)->(%p)\n", This
, url
);
2399 return E_INVALIDARG
;
2401 if (!This
->properties
->uri
)
2402 return return_null_bstr(url
);
2404 return IUri_GetPropertyBSTR(This
->properties
->uri
, Uri_PROPERTY_DISPLAY_URI
, url
, 0);
2408 static HRESULT WINAPI
domdoc_get_async(
2409 IXMLDOMDocument3
*iface
,
2410 VARIANT_BOOL
* isAsync
)
2412 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2414 TRACE("(%p)->(%p: %d)\n", This
, isAsync
, This
->async
);
2415 *isAsync
= This
->async
;
2420 static HRESULT WINAPI
domdoc_put_async(
2421 IXMLDOMDocument3
*iface
,
2422 VARIANT_BOOL isAsync
)
2424 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2426 TRACE("(%p)->(%d)\n", This
, isAsync
);
2427 This
->async
= isAsync
;
2432 static HRESULT WINAPI
domdoc_abort(
2433 IXMLDOMDocument3
*iface
)
2435 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2436 FIXME("%p\n", This
);
2440 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2441 static HRESULT WINAPI
domdoc_loadXML(
2442 IXMLDOMDocument3
*iface
,
2444 VARIANT_BOOL
* isSuccessful
)
2446 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2447 xmlDocPtr xmldoc
= NULL
;
2448 HRESULT hr
= S_FALSE
, hr2
;
2450 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), isSuccessful
);
2452 assert ( &This
->node
);
2456 *isSuccessful
= VARIANT_FALSE
;
2462 /* skip leading spaces if needed */
2463 if (This
->properties
->version
== MSXML_DEFAULT
|| This
->properties
->version
== MSXML26
)
2464 while (*ptr
&& isspaceW(*ptr
)) ptr
++;
2466 xmldoc
= doparse(This
, (char*)ptr
, strlenW(ptr
)*sizeof(WCHAR
), XML_CHAR_ENCODING_UTF16LE
);
2469 This
->error
= E_FAIL
;
2470 TRACE("failed to parse document\n");
2474 hr
= This
->error
= S_OK
;
2475 *isSuccessful
= VARIANT_TRUE
;
2476 TRACE("parsed document %p\n", xmldoc
);
2482 xmldoc
= xmlNewDoc(NULL
);
2483 xmldoc
->_private
= create_priv();
2484 hr2
= attach_xmldoc(This
, xmldoc
);
2491 static int XMLCALL
domdoc_save_writecallback(void *ctx
, const char *buffer
, int len
)
2495 if(!WriteFile(ctx
, buffer
, len
, &written
, NULL
))
2497 WARN("write error\n");
2504 static int XMLCALL
domdoc_save_closecallback(void *ctx
)
2506 return CloseHandle(ctx
) ? 0 : -1;
2509 static int XMLCALL
domdoc_stream_save_writecallback(void *ctx
, const char *buffer
, int len
)
2514 hr
= IStream_Write((IStream
*)ctx
, buffer
, len
, &written
);
2515 TRACE("0x%08x %p %d %u\n", hr
, buffer
, len
, written
);
2518 WARN("stream write error: 0x%08x\n", hr
);
2525 static int XMLCALL
domdoc_stream_save_closecallback(void *ctx
)
2527 IStream_Release((IStream
*)ctx
);
2531 static HRESULT WINAPI
domdoc_save(
2532 IXMLDOMDocument3
*iface
,
2533 VARIANT destination
)
2535 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2536 xmlSaveCtxtPtr ctx
= NULL
;
2540 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&destination
));
2542 switch (V_VT(&destination
))
2546 IUnknown
*pUnk
= V_UNKNOWN(&destination
);
2547 IXMLDOMDocument3
*document
;
2550 ret
= IUnknown_QueryInterface(pUnk
, &IID_IXMLDOMDocument3
, (void**)&document
);
2553 VARIANT_BOOL success
;
2556 ret
= IXMLDOMDocument3_get_xml(iface
, &xml
);
2559 ret
= IXMLDOMDocument3_loadXML(document
, xml
, &success
);
2563 IXMLDOMDocument3_Release(document
);
2567 ret
= IUnknown_QueryInterface(pUnk
, &IID_IStream
, (void**)&stream
);
2570 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2571 ctx
= xmlSaveToIO(domdoc_stream_save_writecallback
,
2572 domdoc_stream_save_closecallback
, stream
, NULL
, options
);
2576 IStream_Release(stream
);
2584 case VT_BSTR
| VT_BYREF
:
2586 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2588 /* save with file path */
2589 HANDLE handle
= CreateFileW( (V_VT(&destination
) & VT_BYREF
)? *V_BSTRREF(&destination
) : V_BSTR(&destination
),
2590 GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2591 if( handle
== INVALID_HANDLE_VALUE
)
2593 WARN("failed to create file\n");
2597 /* disable top XML declaration */
2598 ctx
= xmlSaveToIO(domdoc_save_writecallback
, domdoc_save_closecallback
,
2599 handle
, NULL
, options
);
2602 CloseHandle(handle
);
2609 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination
));
2613 xmldecl
= xmldoc_unlink_xmldecl(get_doc(This
));
2614 if (xmlSaveDoc(ctx
, get_doc(This
)) == -1) ret
= S_FALSE
;
2615 xmldoc_link_xmldecl(get_doc(This
), xmldecl
);
2617 /* will release resources through close callback */
2623 static HRESULT WINAPI
domdoc_get_validateOnParse(
2624 IXMLDOMDocument3
*iface
,
2625 VARIANT_BOOL
* isValidating
)
2627 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2628 TRACE("(%p)->(%p: %d)\n", This
, isValidating
, This
->validating
);
2629 *isValidating
= This
->validating
;
2634 static HRESULT WINAPI
domdoc_put_validateOnParse(
2635 IXMLDOMDocument3
*iface
,
2636 VARIANT_BOOL isValidating
)
2638 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2639 TRACE("(%p)->(%d)\n", This
, isValidating
);
2640 This
->validating
= isValidating
;
2645 static HRESULT WINAPI
domdoc_get_resolveExternals(
2646 IXMLDOMDocument3
*iface
,
2647 VARIANT_BOOL
* isResolving
)
2649 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2650 TRACE("(%p)->(%p: %d)\n", This
, isResolving
, This
->resolving
);
2651 *isResolving
= This
->resolving
;
2656 static HRESULT WINAPI
domdoc_put_resolveExternals(
2657 IXMLDOMDocument3
*iface
,
2658 VARIANT_BOOL isResolving
)
2660 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2661 TRACE("(%p)->(%d)\n", This
, isResolving
);
2662 This
->resolving
= isResolving
;
2667 static HRESULT WINAPI
domdoc_get_preserveWhiteSpace(
2668 IXMLDOMDocument3
*iface
,
2669 VARIANT_BOOL
* isPreserving
)
2671 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2672 TRACE("(%p)->(%p: %d)\n", This
, isPreserving
, This
->properties
->preserving
);
2673 *isPreserving
= This
->properties
->preserving
;
2678 static HRESULT WINAPI
domdoc_put_preserveWhiteSpace(
2679 IXMLDOMDocument3
*iface
,
2680 VARIANT_BOOL isPreserving
)
2682 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2683 TRACE("(%p)->(%d)\n", This
, isPreserving
);
2684 This
->properties
->preserving
= isPreserving
;
2689 static HRESULT WINAPI
domdoc_put_onreadystatechange(
2690 IXMLDOMDocument3
*iface
,
2693 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2695 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&event
));
2696 return set_doc_event(This
, EVENTID_READYSTATECHANGE
, &event
);
2700 static HRESULT WINAPI
domdoc_put_onDataAvailable(IXMLDOMDocument3
*iface
, VARIANT sink
)
2702 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2703 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2707 static HRESULT WINAPI
domdoc_put_onTransformNode(IXMLDOMDocument3
*iface
, VARIANT sink
)
2709 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2710 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2714 static HRESULT WINAPI
domdoc_get_namespaces(
2715 IXMLDOMDocument3
* iface
,
2716 IXMLDOMSchemaCollection
** collection
)
2718 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2721 FIXME("(%p)->(%p): semi-stub\n", This
, collection
);
2723 if (!collection
) return E_POINTER
;
2725 if (!This
->namespaces
)
2727 hr
= SchemaCache_create(This
->properties
->version
, (void**)&This
->namespaces
);
2728 if (hr
!= S_OK
) return hr
;
2730 hr
= cache_from_doc_ns(This
->namespaces
, &This
->node
);
2732 release_namespaces(This
);
2735 if (This
->namespaces
)
2736 return IXMLDOMSchemaCollection2_QueryInterface(This
->namespaces
,
2737 &IID_IXMLDOMSchemaCollection
, (void**)collection
);
2742 static HRESULT WINAPI
domdoc_get_schemas(
2743 IXMLDOMDocument3
* iface
,
2746 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2747 IXMLDOMSchemaCollection2
* cur_schema
= This
->properties
->schemaCache
;
2748 HRESULT hr
= S_FALSE
;
2750 TRACE("(%p)->(%p)\n", This
, schema
);
2752 V_VT(schema
) = VT_NULL
;
2753 /* just to reset pointer part, cause that's what application is expected to use */
2754 V_DISPATCH(schema
) = NULL
;
2758 hr
= IXMLDOMSchemaCollection2_QueryInterface(cur_schema
, &IID_IDispatch
, (void**)&V_DISPATCH(schema
));
2760 V_VT(schema
) = VT_DISPATCH
;
2765 static HRESULT WINAPI
domdoc_putref_schemas(
2766 IXMLDOMDocument3
* iface
,
2769 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2770 HRESULT hr
= E_FAIL
;
2771 IXMLDOMSchemaCollection2
* new_schema
= NULL
;
2773 FIXME("(%p)->(%s): semi-stub\n", This
, debugstr_variant(&schema
));
2774 switch(V_VT(&schema
))
2777 if (V_UNKNOWN(&schema
))
2779 hr
= IUnknown_QueryInterface(V_UNKNOWN(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2784 if (V_DISPATCH(&schema
))
2786 hr
= IDispatch_QueryInterface(V_DISPATCH(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2796 WARN("Can't get schema from vt %x\n", V_VT(&schema
));
2801 IXMLDOMSchemaCollection2
* old_schema
= InterlockedExchangePointer((void**)&This
->properties
->schemaCache
, new_schema
);
2802 if(old_schema
) IXMLDOMSchemaCollection2_Release(old_schema
);
2808 static inline BOOL
is_wellformed(xmlDocPtr doc
)
2810 #ifdef HAVE_XMLDOC_PROPERTIES
2811 return doc
->properties
& XML_DOC_WELLFORMED
;
2813 /* Not a full check, but catches the worst violations */
2817 for (child
= doc
->children
; child
!= NULL
; child
= child
->next
)
2819 switch (child
->type
)
2821 case XML_ELEMENT_NODE
:
2826 case XML_CDATA_SECTION_NODE
:
2838 static void LIBXML2_LOG_CALLBACK
validate_error(void* ctx
, char const* msg
, ...)
2842 LIBXML2_CALLBACK_ERR(domdoc_validateNode
, msg
, ap
);
2846 static void LIBXML2_LOG_CALLBACK
validate_warning(void* ctx
, char const* msg
, ...)
2850 LIBXML2_CALLBACK_WARN(domdoc_validateNode
, msg
, ap
);
2854 static HRESULT WINAPI
domdoc_validateNode(
2855 IXMLDOMDocument3
* iface
,
2857 IXMLDOMParseError
** err
)
2859 domdoc
* This
= impl_from_IXMLDOMDocument3(iface
);
2860 LONG state
, err_code
= 0;
2864 TRACE("(%p)->(%p, %p)\n", This
, node
, err
);
2865 IXMLDOMDocument3_get_readyState(iface
, &state
);
2866 if (state
!= READYSTATE_COMPLETE
)
2869 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2876 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2880 if (!get_node_obj(node
)->node
|| get_node_obj(node
)->node
->doc
!= get_doc(This
))
2883 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2887 if (!is_wellformed(get_doc(This
)))
2889 ERR("doc not well-formed\n");
2891 *err
= create_parseError(E_XML_NOTWF
, NULL
, NULL
, NULL
, 0, 0, 0);
2895 /* DTD validation */
2896 if (get_doc(This
)->intSubset
|| get_doc(This
)->extSubset
)
2898 xmlValidCtxtPtr vctx
= xmlNewValidCtxt();
2899 vctx
->error
= validate_error
;
2900 vctx
->warning
= validate_warning
;
2903 if (!((node
== (IXMLDOMNode
*)iface
)?
2904 xmlValidateDocument(vctx
, get_doc(This
)) :
2905 xmlValidateElement(vctx
, get_doc(This
), get_node_obj(node
)->node
)))
2907 /* TODO: get a real error code here */
2908 TRACE("DTD validation failed\n");
2909 err_code
= E_XML_INVALID
;
2912 xmlFreeValidCtxt(vctx
);
2915 /* Schema validation */
2916 if (hr
== S_OK
&& This
->properties
->schemaCache
!= NULL
)
2919 hr
= SchemaCache_validate_tree(This
->properties
->schemaCache
, get_node_obj(node
)->node
);
2923 /* TODO: get a real error code here */
2926 TRACE("schema validation succeeded\n");
2930 ERR("schema validation failed\n");
2931 err_code
= E_XML_INVALID
;
2936 /* not really OK, just didn't find a schema for the ns */
2943 ERR("no DTD or schema found\n");
2944 err_code
= E_XML_NODTD
;
2949 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2954 static HRESULT WINAPI
domdoc_validate(
2955 IXMLDOMDocument3
* iface
,
2956 IXMLDOMParseError
** err
)
2958 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2959 TRACE("(%p)->(%p)\n", This
, err
);
2960 return IXMLDOMDocument3_validateNode(iface
, (IXMLDOMNode
*)iface
, err
);
2963 static HRESULT WINAPI
domdoc_setProperty(
2964 IXMLDOMDocument3
* iface
,
2968 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2970 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(p
), debugstr_variant(&value
));
2972 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
2978 V_VT(&varStr
) = VT_EMPTY
;
2979 if (V_VT(&value
) != VT_BSTR
)
2981 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2983 bstr
= V_BSTR(&varStr
);
2986 bstr
= V_BSTR(&value
);
2989 if (lstrcmpiW(bstr
, PropValueXPathW
) == 0)
2990 This
->properties
->XPath
= TRUE
;
2991 else if (lstrcmpiW(bstr
, PropValueXSLPatternW
) == 0)
2992 This
->properties
->XPath
= FALSE
;
2996 VariantClear(&varStr
);
2999 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3001 xmlChar
*nsStr
= (xmlChar
*)This
->properties
->selectNsStr
;
3002 struct list
*pNsList
;
3007 V_VT(&varStr
) = VT_EMPTY
;
3008 if (V_VT(&value
) != VT_BSTR
)
3010 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
3012 bstr
= V_BSTR(&varStr
);
3015 bstr
= V_BSTR(&value
);
3019 pNsList
= &(This
->properties
->selectNsList
);
3020 clear_selectNsList(pNsList
);
3022 nsStr
= xmlchar_from_wchar(bstr
);
3024 TRACE("property value: \"%s\"\n", debugstr_w(bstr
));
3026 This
->properties
->selectNsStr
= nsStr
;
3027 This
->properties
->selectNsStr_len
= xmlStrlen(nsStr
);
3030 xmlChar
*pTokBegin
, *pTokEnd
, *pTokInner
;
3031 select_ns_entry
* ns_entry
= NULL
;
3032 xmlXPathContextPtr ctx
;
3034 ctx
= xmlXPathNewContext(This
->node
.node
->doc
);
3037 /* skip leading spaces */
3038 while (*pTokBegin
== ' ' || *pTokBegin
== '\n' ||
3039 *pTokBegin
== '\t' || *pTokBegin
== '\r')
3042 for (; *pTokBegin
; pTokBegin
= pTokEnd
)
3045 memset(ns_entry
, 0, sizeof(select_ns_entry
));
3047 ns_entry
= heap_alloc_zero(sizeof(select_ns_entry
));
3049 while (*pTokBegin
== ' ')
3051 pTokEnd
= pTokBegin
;
3052 while (*pTokEnd
!= ' ' && *pTokEnd
!= 0)
3055 /* so it failed to advance which means we've got some trailing spaces */
3056 if (pTokEnd
== pTokBegin
) break;
3058 if (xmlStrncmp(pTokBegin
, (xmlChar
const*)"xmlns", 5) != 0)
3061 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3062 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
3067 if (*pTokBegin
== '=')
3069 /*valid for XSLPattern?*/
3070 FIXME("Setting default xmlns not supported - skipping.\n");
3073 else if (*pTokBegin
== ':')
3075 ns_entry
->prefix
= ++pTokBegin
;
3076 for (pTokInner
= pTokBegin
; pTokInner
!= pTokEnd
&& *pTokInner
!= '='; ++pTokInner
)
3079 if (pTokInner
== pTokEnd
)
3082 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3083 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
3087 ns_entry
->prefix_end
= *pTokInner
;
3091 if (pTokEnd
-pTokInner
> 1 &&
3092 ((*pTokInner
== '\'' && *(pTokEnd
-1) == '\'') ||
3093 (*pTokInner
== '"' && *(pTokEnd
-1) == '"')))
3095 ns_entry
->href
= ++pTokInner
;
3096 ns_entry
->href_end
= *(pTokEnd
-1);
3098 list_add_tail(pNsList
, &ns_entry
->entry
);
3099 /*let libxml figure out if they're valid from here ;)*/
3100 if (xmlXPathRegisterNs(ctx
, ns_entry
->prefix
, ns_entry
->href
) != 0)
3109 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3110 debugstr_w(bstr
), debugstr_an((const char*)pTokInner
, pTokEnd
-pTokInner
));
3111 list_add_tail(pNsList
, &ns_entry
->entry
);
3124 heap_free(ns_entry
);
3125 xmlXPathFreeContext(ctx
);
3128 VariantClear(&varStr
);
3131 else if (lstrcmpiW(p
, PropertyProhibitDTDW
) == 0 ||
3132 lstrcmpiW(p
, PropertyNewParserW
) == 0 ||
3133 lstrcmpiW(p
, PropertyResolveExternalsW
) == 0 ||
3134 lstrcmpiW(p
, PropertyAllowXsltScriptW
) == 0 ||
3135 lstrcmpiW(p
, PropertyNormalizeAttributeValuesW
) == 0 ||
3136 lstrcmpiW(p
, PropertyAllowDocumentFunctionW
) == 0)
3139 FIXME("Ignoring property %s, value %s\n", debugstr_w(p
), debugstr_variant(&value
));
3143 FIXME("Unknown property %s\n", debugstr_w(p
));
3147 static HRESULT WINAPI
domdoc_getProperty(
3148 IXMLDOMDocument3
* iface
,
3152 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3154 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
3157 return E_INVALIDARG
;
3159 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
3161 V_VT(var
) = VT_BSTR
;
3162 V_BSTR(var
) = This
->properties
->XPath
?
3163 SysAllocString(PropValueXPathW
) :
3164 SysAllocString(PropValueXSLPatternW
);
3165 return V_BSTR(var
) ? S_OK
: E_OUTOFMEMORY
;
3167 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3170 BSTR rebuiltStr
, cur
;
3171 const xmlChar
*nsStr
;
3172 struct list
*pNsList
;
3173 select_ns_entry
* pNsEntry
;
3175 V_VT(var
) = VT_BSTR
;
3176 nsStr
= This
->properties
->selectNsStr
;
3177 pNsList
= &This
->properties
->selectNsList
;
3178 lenA
= This
->properties
->selectNsStr_len
;
3179 lenW
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, NULL
, 0);
3180 rebuiltStr
= heap_alloc(lenW
*sizeof(WCHAR
));
3181 MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, rebuiltStr
, lenW
);
3183 /* this is fine because all of the chars that end tokens are ASCII*/
3184 LIST_FOR_EACH_ENTRY(pNsEntry
, pNsList
, select_ns_entry
, entry
)
3186 while (*cur
!= 0) ++cur
;
3187 if (pNsEntry
->prefix_end
)
3189 *cur
= pNsEntry
->prefix_end
;
3190 while (*cur
!= 0) ++cur
;
3193 if (pNsEntry
->href_end
)
3195 *cur
= pNsEntry
->href_end
;
3198 V_BSTR(var
) = SysAllocString(rebuiltStr
);
3199 heap_free(rebuiltStr
);
3203 FIXME("Unknown property %s\n", debugstr_w(p
));
3207 static HRESULT WINAPI
domdoc_importNode(
3208 IXMLDOMDocument3
* iface
,
3211 IXMLDOMNode
** clone
)
3213 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3214 FIXME("(%p)->(%p %d %p): stub\n", This
, node
, deep
, clone
);
3218 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl
=
3220 domdoc_QueryInterface
,
3223 domdoc_GetTypeInfoCount
,
3225 domdoc_GetIDsOfNames
,
3227 domdoc_get_nodeName
,
3228 domdoc_get_nodeValue
,
3229 domdoc_put_nodeValue
,
3230 domdoc_get_nodeType
,
3231 domdoc_get_parentNode
,
3232 domdoc_get_childNodes
,
3233 domdoc_get_firstChild
,
3234 domdoc_get_lastChild
,
3235 domdoc_get_previousSibling
,
3236 domdoc_get_nextSibling
,
3237 domdoc_get_attributes
,
3238 domdoc_insertBefore
,
3239 domdoc_replaceChild
,
3242 domdoc_hasChildNodes
,
3243 domdoc_get_ownerDocument
,
3245 domdoc_get_nodeTypeString
,
3248 domdoc_get_specified
,
3249 domdoc_get_definition
,
3250 domdoc_get_nodeTypedValue
,
3251 domdoc_put_nodeTypedValue
,
3252 domdoc_get_dataType
,
3253 domdoc_put_dataType
,
3255 domdoc_transformNode
,
3257 domdoc_selectSingleNode
,
3259 domdoc_get_namespaceURI
,
3261 domdoc_get_baseName
,
3262 domdoc_transformNodeToObject
,
3264 domdoc_get_implementation
,
3265 domdoc_get_documentElement
,
3266 domdoc_put_documentElement
,
3267 domdoc_createElement
,
3268 domdoc_createDocumentFragment
,
3269 domdoc_createTextNode
,
3270 domdoc_createComment
,
3271 domdoc_createCDATASection
,
3272 domdoc_createProcessingInstruction
,
3273 domdoc_createAttribute
,
3274 domdoc_createEntityReference
,
3275 domdoc_getElementsByTagName
,
3279 domdoc_get_readyState
,
3280 domdoc_get_parseError
,
3287 domdoc_get_validateOnParse
,
3288 domdoc_put_validateOnParse
,
3289 domdoc_get_resolveExternals
,
3290 domdoc_put_resolveExternals
,
3291 domdoc_get_preserveWhiteSpace
,
3292 domdoc_put_preserveWhiteSpace
,
3293 domdoc_put_onreadystatechange
,
3294 domdoc_put_onDataAvailable
,
3295 domdoc_put_onTransformNode
,
3296 domdoc_get_namespaces
,
3298 domdoc_putref_schemas
,
3302 domdoc_validateNode
,
3306 /* IConnectionPointContainer */
3307 static HRESULT WINAPI
ConnectionPointContainer_QueryInterface(IConnectionPointContainer
*iface
,
3308 REFIID riid
, void **ppv
)
3310 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3311 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3314 static ULONG WINAPI
ConnectionPointContainer_AddRef(IConnectionPointContainer
*iface
)
3316 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3317 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3320 static ULONG WINAPI
ConnectionPointContainer_Release(IConnectionPointContainer
*iface
)
3322 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3323 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3326 static HRESULT WINAPI
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer
*iface
,
3327 IEnumConnectionPoints
**ppEnum
)
3329 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3330 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3334 static HRESULT WINAPI
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer
*iface
,
3335 REFIID riid
, IConnectionPoint
**cp
)
3337 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3338 ConnectionPoint
*iter
;
3340 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), cp
);
3344 for(iter
= This
->cp_list
; iter
; iter
= iter
->next
)
3346 if (IsEqualGUID(iter
->iid
, riid
))
3347 *cp
= &iter
->IConnectionPoint_iface
;
3352 IConnectionPoint_AddRef(*cp
);
3356 FIXME("unsupported riid %s\n", debugstr_guid(riid
));
3357 return CONNECT_E_NOCONNECTION
;
3361 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl
=
3363 ConnectionPointContainer_QueryInterface
,
3364 ConnectionPointContainer_AddRef
,
3365 ConnectionPointContainer_Release
,
3366 ConnectionPointContainer_EnumConnectionPoints
,
3367 ConnectionPointContainer_FindConnectionPoint
3370 /* IConnectionPoint */
3371 static HRESULT WINAPI
ConnectionPoint_QueryInterface(IConnectionPoint
*iface
,
3372 REFIID riid
, void **ppv
)
3374 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3376 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
3380 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
3381 IsEqualGUID(&IID_IConnectionPoint
, riid
))
3388 IConnectionPoint_AddRef(iface
);
3392 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
3393 return E_NOINTERFACE
;
3396 static ULONG WINAPI
ConnectionPoint_AddRef(IConnectionPoint
*iface
)
3398 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3399 return IConnectionPointContainer_AddRef(This
->container
);
3402 static ULONG WINAPI
ConnectionPoint_Release(IConnectionPoint
*iface
)
3404 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3405 return IConnectionPointContainer_Release(This
->container
);
3408 static HRESULT WINAPI
ConnectionPoint_GetConnectionInterface(IConnectionPoint
*iface
, IID
*iid
)
3410 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3412 TRACE("(%p)->(%p)\n", This
, iid
);
3414 if (!iid
) return E_POINTER
;
3420 static HRESULT WINAPI
ConnectionPoint_GetConnectionPointContainer(IConnectionPoint
*iface
,
3421 IConnectionPointContainer
**container
)
3423 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3425 TRACE("(%p)->(%p)\n", This
, container
);
3427 if (!container
) return E_POINTER
;
3429 *container
= This
->container
;
3430 IConnectionPointContainer_AddRef(*container
);
3434 static HRESULT WINAPI
ConnectionPoint_Advise(IConnectionPoint
*iface
, IUnknown
*unk_sink
,
3437 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3442 TRACE("(%p)->(%p %p)\n", This
, unk_sink
, cookie
);
3444 hr
= IUnknown_QueryInterface(unk_sink
, This
->iid
, (void**)&sink
);
3445 if(FAILED(hr
) && !IsEqualGUID(&IID_IPropertyNotifySink
, This
->iid
))
3446 hr
= IUnknown_QueryInterface(unk_sink
, &IID_IDispatch
, (void**)&sink
);
3448 return CONNECT_E_CANNOTCONNECT
;
3452 for (i
= 0; i
< This
->sinks_size
; i
++)
3453 if (!This
->sinks
[i
].unk
)
3456 if (i
== This
->sinks_size
)
3457 This
->sinks
= heap_realloc(This
->sinks
,(++This
->sinks_size
)*sizeof(*This
->sinks
));
3461 This
->sinks
= heap_alloc(sizeof(*This
->sinks
));
3462 This
->sinks_size
= 1;
3466 This
->sinks
[i
].unk
= sink
;
3473 static HRESULT WINAPI
ConnectionPoint_Unadvise(IConnectionPoint
*iface
, DWORD cookie
)
3475 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3477 TRACE("(%p)->(%d)\n", This
, cookie
);
3479 if (cookie
== 0 || cookie
> This
->sinks_size
|| !This
->sinks
[cookie
-1].unk
)
3480 return CONNECT_E_NOCONNECTION
;
3482 IUnknown_Release(This
->sinks
[cookie
-1].unk
);
3483 This
->sinks
[cookie
-1].unk
= NULL
;
3488 static HRESULT WINAPI
ConnectionPoint_EnumConnections(IConnectionPoint
*iface
,
3489 IEnumConnections
**ppEnum
)
3491 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3492 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3496 static const IConnectionPointVtbl ConnectionPointVtbl
=
3498 ConnectionPoint_QueryInterface
,
3499 ConnectionPoint_AddRef
,
3500 ConnectionPoint_Release
,
3501 ConnectionPoint_GetConnectionInterface
,
3502 ConnectionPoint_GetConnectionPointContainer
,
3503 ConnectionPoint_Advise
,
3504 ConnectionPoint_Unadvise
,
3505 ConnectionPoint_EnumConnections
3508 static void ConnectionPoint_Init(ConnectionPoint
*cp
, struct domdoc
*doc
, REFIID riid
)
3510 cp
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointVtbl
;
3516 cp
->next
= doc
->cp_list
;
3519 cp
->container
= &doc
->IConnectionPointContainer_iface
;
3522 /* domdoc implementation of IObjectWithSite */
3523 static HRESULT WINAPI
3524 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
3526 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3527 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObject
);
3530 static ULONG WINAPI
domdoc_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
3532 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3533 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3536 static ULONG WINAPI
domdoc_ObjectWithSite_Release( IObjectWithSite
* iface
)
3538 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3539 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3542 static HRESULT WINAPI
domdoc_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
3544 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3546 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
3551 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
3554 static HRESULT WINAPI
domdoc_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
3556 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3558 TRACE("(%p)->(%p)\n", iface
, punk
);
3564 IUnknown_Release( This
->site
);
3570 IUri_Release(This
->base_uri
);
3571 This
->base_uri
= NULL
;
3577 IUnknown_AddRef( punk
);
3580 IUnknown_Release( This
->site
);
3583 This
->base_uri
= get_base_uri(This
->site
);
3588 static const IObjectWithSiteVtbl domdocObjectSite
=
3590 domdoc_ObjectWithSite_QueryInterface
,
3591 domdoc_ObjectWithSite_AddRef
,
3592 domdoc_ObjectWithSite_Release
,
3593 domdoc_ObjectWithSite_SetSite
,
3594 domdoc_ObjectWithSite_GetSite
3597 static HRESULT WINAPI
domdoc_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
3599 domdoc
*This
= impl_from_IObjectSafety(iface
);
3600 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3603 static ULONG WINAPI
domdoc_Safety_AddRef(IObjectSafety
*iface
)
3605 domdoc
*This
= impl_from_IObjectSafety(iface
);
3606 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3609 static ULONG WINAPI
domdoc_Safety_Release(IObjectSafety
*iface
)
3611 domdoc
*This
= impl_from_IObjectSafety(iface
);
3612 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3615 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3617 static HRESULT WINAPI
domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3618 DWORD
*supported
, DWORD
*enabled
)
3620 domdoc
*This
= impl_from_IObjectSafety(iface
);
3622 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
3624 if(!supported
|| !enabled
) return E_POINTER
;
3626 *supported
= SAFETY_SUPPORTED_OPTIONS
;
3627 *enabled
= This
->safeopt
;
3632 static HRESULT WINAPI
domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3633 DWORD mask
, DWORD enabled
)
3635 domdoc
*This
= impl_from_IObjectSafety(iface
);
3636 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
3638 if ((mask
& ~SAFETY_SUPPORTED_OPTIONS
) != 0)
3641 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
3646 #undef SAFETY_SUPPORTED_OPTIONS
3648 static const IObjectSafetyVtbl domdocObjectSafetyVtbl
= {
3649 domdoc_Safety_QueryInterface
,
3650 domdoc_Safety_AddRef
,
3651 domdoc_Safety_Release
,
3652 domdoc_Safety_GetInterfaceSafetyOptions
,
3653 domdoc_Safety_SetInterfaceSafetyOptions
3656 static const tid_t domdoc_iface_tids
[] = {
3657 IXMLDOMDocument3_tid
,
3661 static dispex_static_data_t domdoc_dispex
= {
3663 IXMLDOMDocument3_tid
,
3668 HRESULT
get_domdoc_from_xmldoc(xmlDocPtr xmldoc
, IXMLDOMDocument3
**document
)
3672 doc
= heap_alloc( sizeof (*doc
) );
3674 return E_OUTOFMEMORY
;
3676 doc
->IXMLDOMDocument3_iface
.lpVtbl
= &XMLDOMDocument3Vtbl
;
3677 doc
->IPersistStreamInit_iface
.lpVtbl
= &xmldoc_IPersistStreamInit_VTable
;
3678 doc
->IObjectWithSite_iface
.lpVtbl
= &domdocObjectSite
;
3679 doc
->IObjectSafety_iface
.lpVtbl
= &domdocObjectSafetyVtbl
;
3680 doc
->IConnectionPointContainer_iface
.lpVtbl
= &ConnectionPointContainerVtbl
;
3682 doc
->async
= VARIANT_TRUE
;
3683 doc
->validating
= 0;
3685 doc
->properties
= properties_from_xmlDocPtr(xmldoc
);
3688 doc
->base_uri
= NULL
;
3690 doc
->cp_list
= NULL
;
3691 doc
->namespaces
= NULL
;
3692 memset(doc
->events
, 0, sizeof(doc
->events
));
3694 /* events connection points */
3695 ConnectionPoint_Init(&doc
->cp_dispatch
, doc
, &IID_IDispatch
);
3696 ConnectionPoint_Init(&doc
->cp_propnotif
, doc
, &IID_IPropertyNotifySink
);
3697 ConnectionPoint_Init(&doc
->cp_domdocevents
, doc
, &DIID_XMLDOMDocumentEvents
);
3699 init_xmlnode(&doc
->node
, (xmlNodePtr
)xmldoc
, (IXMLDOMNode
*)&doc
->IXMLDOMDocument3_iface
,
3702 *document
= &doc
->IXMLDOMDocument3_iface
;
3704 TRACE("returning iface %p\n", *document
);
3708 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3713 TRACE("(%d, %p)\n", version
, ppObj
);
3715 xmldoc
= xmlNewDoc(NULL
);
3717 return E_OUTOFMEMORY
;
3719 xmldoc_init(xmldoc
, version
);
3721 hr
= get_domdoc_from_xmldoc(xmldoc
, (IXMLDOMDocument3
**)ppObj
);
3724 free_properties(properties_from_xmlDocPtr(xmldoc
));
3725 heap_free(xmldoc
->_private
);
3733 IUnknown
* create_domdoc( xmlNodePtr document
)
3735 IUnknown
*obj
= NULL
;
3738 TRACE("(%p)\n", document
);
3740 hr
= get_domdoc_from_xmldoc((xmlDocPtr
)document
, (IXMLDOMDocument3
**)&obj
);
3749 HRESULT
DOMDocument_create(MSXML_VERSION version
, void **ppObj
)
3751 MESSAGE("This program tried to use a DOMDocument object, but\n"
3752 "libxml2 support was not present at compile time.\n");