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
22 #define WIN32_NO_STATUS
26 #define NONAMELESSUNION
33 # include <libxml/parser.h>
34 //# include <libxml/xmlerror.h>
35 # include <libxml/xpathInternals.h>
36 # include <libxml/xmlsave.h>
37 # include <libxml/SAX2.h>
38 # include <libxml/parserInternals.h>
43 //#include "winuser.h"
48 //#include "wininet.h"
50 //#include "shlwapi.h"
54 #include <wine/debug.h>
55 #include <wine/list.h>
57 #include "msxml_private.h"
59 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
63 /* not defined in older versions */
64 #define XML_SAVE_FORMAT 1
65 #define XML_SAVE_NO_DECL 2
66 #define XML_SAVE_NO_EMPTY 4
67 #define XML_SAVE_NO_XHTML 8
68 #define XML_SAVE_XHTML 16
69 #define XML_SAVE_AS_XML 32
70 #define XML_SAVE_AS_HTML 64
72 static const WCHAR PropertySelectionLanguageW
[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
73 static const WCHAR PropertySelectionNamespacesW
[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
74 static const WCHAR PropertyProhibitDTDW
[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
75 static const WCHAR PropertyNewParserW
[] = {'N','e','w','P','a','r','s','e','r',0};
76 static const WCHAR PropValueXPathW
[] = {'X','P','a','t','h',0};
77 static const WCHAR PropValueXSLPatternW
[] = {'X','S','L','P','a','t','t','e','r','n',0};
78 static const WCHAR PropertyResolveExternalsW
[] = {'R','e','s','o','l','v','e','E','x','t','e','r','n','a','l','s',0};
80 /* Anything that passes the test_get_ownerDocument()
81 * tests can go here (data shared between all instances).
82 * We need to preserve this when reloading a document,
83 * and also need access to it from the libxml backend. */
85 MSXML_VERSION version
;
86 VARIANT_BOOL preserving
;
87 IXMLDOMSchemaCollection2
* schemaCache
;
88 struct list selectNsList
;
89 xmlChar
const* selectNsStr
;
94 typedef struct ConnectionPoint ConnectionPoint
;
95 typedef struct domdoc domdoc
;
97 struct ConnectionPoint
99 IConnectionPoint IConnectionPoint_iface
;
102 ConnectionPoint
*next
;
103 IConnectionPointContainer
*container
;
110 IPropertyNotifySink
*propnotif
;
116 EVENTID_READYSTATECHANGE
= 0,
117 EVENTID_DATAAVAILABLE
,
118 EVENTID_TRANSFORMNODE
,
125 IXMLDOMDocument3 IXMLDOMDocument3_iface
;
126 IPersistStreamInit IPersistStreamInit_iface
;
127 IObjectWithSite IObjectWithSite_iface
;
128 IObjectSafety IObjectSafety_iface
;
129 IConnectionPointContainer IConnectionPointContainer_iface
;
132 VARIANT_BOOL validating
;
133 VARIANT_BOOL resolving
;
134 domdoc_properties
* properties
;
144 /* connection list */
145 ConnectionPoint
*cp_list
;
146 ConnectionPoint cp_domdocevents
;
147 ConnectionPoint cp_propnotif
;
148 ConnectionPoint cp_dispatch
;
151 IDispatch
*events
[EVENTID_LAST
];
153 IXMLDOMSchemaCollection2
*namespaces
;
156 static HRESULT
set_doc_event(domdoc
*doc
, eventid_t eid
, const VARIANT
*v
)
164 IUnknown_QueryInterface(V_UNKNOWN(v
), &IID_IDispatch
, (void**)&disp
);
169 disp
= V_DISPATCH(v
);
170 if (disp
) IDispatch_AddRef(disp
);
173 return DISP_E_TYPEMISMATCH
;
176 if (doc
->events
[eid
]) IDispatch_Release(doc
->events
[eid
]);
177 doc
->events
[eid
] = disp
;
182 static inline ConnectionPoint
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
184 return CONTAINING_RECORD(iface
, ConnectionPoint
, IConnectionPoint_iface
);
188 In native windows, the whole lifetime management of XMLDOMNodes is
189 managed automatically using reference counts. Wine emulates that by
190 maintaining a reference count to the document that is increased for
191 each IXMLDOMNode pointer passed out for this document. If all these
192 pointers are gone, the document is unreachable and gets freed, that
193 is, all nodes in the tree of the document get freed.
195 You are able to create nodes that are associated to a document (in
196 fact, in msxml's XMLDOM model, all nodes are associated to a document),
197 but not in the tree of that document, for example using the createFoo
198 functions from IXMLDOMDocument. These nodes do not get cleaned up
199 by libxml, so we have to do it ourselves.
201 To catch these nodes, a list of "orphan nodes" is introduced.
202 It contains pointers to all roots of node trees that are
203 associated with the document without being part of the document
204 tree. All nodes with parent==NULL (except for the document root nodes)
205 should be in the orphan node list of their document. All orphan nodes
206 get freed together with the document itself.
209 typedef struct _xmldoc_priv
{
212 domdoc_properties
* properties
;
215 typedef struct _orphan_entry
{
220 typedef struct _select_ns_entry
{
222 xmlChar
const* prefix
;
228 static inline xmldoc_priv
* priv_from_xmlDocPtr(const xmlDocPtr doc
)
230 return doc
->_private
;
233 static inline domdoc_properties
* properties_from_xmlDocPtr(xmlDocPtr doc
)
235 return priv_from_xmlDocPtr(doc
)->properties
;
238 BOOL
is_xpathmode(const xmlDocPtr doc
)
240 return properties_from_xmlDocPtr(doc
)->XPath
;
243 void set_xpathmode(xmlDocPtr doc
, BOOL xpath
)
245 properties_from_xmlDocPtr(doc
)->XPath
= xpath
;
248 int registerNamespaces(xmlXPathContextPtr ctxt
)
251 const select_ns_entry
* ns
= NULL
;
252 const struct list
* pNsList
= &properties_from_xmlDocPtr(ctxt
->doc
)->selectNsList
;
254 TRACE("(%p)\n", ctxt
);
256 LIST_FOR_EACH_ENTRY( ns
, pNsList
, select_ns_entry
, entry
)
258 xmlXPathRegisterNs(ctxt
, ns
->prefix
, ns
->href
);
265 static inline void clear_selectNsList(struct list
* pNsList
)
267 select_ns_entry
*ns
, *ns2
;
268 LIST_FOR_EACH_ENTRY_SAFE( ns
, ns2
, pNsList
, select_ns_entry
, entry
)
275 static xmldoc_priv
* create_priv(void)
278 priv
= heap_alloc( sizeof (*priv
) );
283 list_init( &priv
->orphans
);
284 priv
->properties
= NULL
;
290 static domdoc_properties
*create_properties(MSXML_VERSION version
)
292 domdoc_properties
*properties
= heap_alloc(sizeof(domdoc_properties
));
294 list_init(&properties
->selectNsList
);
295 properties
->preserving
= VARIANT_FALSE
;
296 properties
->schemaCache
= NULL
;
297 properties
->selectNsStr
= heap_alloc_zero(sizeof(xmlChar
));
298 properties
->selectNsStr_len
= 0;
300 /* properties that are dependent on object versions */
301 properties
->version
= version
;
302 properties
->XPath
= (version
== MSXML4
|| version
== MSXML6
);
307 static domdoc_properties
* copy_properties(domdoc_properties
const* properties
)
309 domdoc_properties
* pcopy
= heap_alloc(sizeof(domdoc_properties
));
310 select_ns_entry
const* ns
= NULL
;
311 select_ns_entry
* new_ns
= NULL
;
312 int len
= (properties
->selectNsStr_len
+1)*sizeof(xmlChar
);
317 pcopy
->version
= properties
->version
;
318 pcopy
->preserving
= properties
->preserving
;
319 pcopy
->schemaCache
= properties
->schemaCache
;
320 if (pcopy
->schemaCache
)
321 IXMLDOMSchemaCollection2_AddRef(pcopy
->schemaCache
);
322 pcopy
->XPath
= properties
->XPath
;
323 pcopy
->selectNsStr_len
= properties
->selectNsStr_len
;
324 list_init( &pcopy
->selectNsList
);
325 pcopy
->selectNsStr
= heap_alloc(len
);
326 memcpy((xmlChar
*)pcopy
->selectNsStr
, properties
->selectNsStr
, len
);
327 offset
= pcopy
->selectNsStr
- properties
->selectNsStr
;
329 LIST_FOR_EACH_ENTRY( ns
, (&properties
->selectNsList
), select_ns_entry
, entry
)
331 new_ns
= heap_alloc(sizeof(select_ns_entry
));
332 memcpy(new_ns
, ns
, sizeof(select_ns_entry
));
333 new_ns
->href
+= offset
;
334 new_ns
->prefix
+= offset
;
335 list_add_tail(&pcopy
->selectNsList
, &new_ns
->entry
);
343 static void free_properties(domdoc_properties
* properties
)
347 if (properties
->schemaCache
)
348 IXMLDOMSchemaCollection2_Release(properties
->schemaCache
);
349 clear_selectNsList(&properties
->selectNsList
);
350 heap_free((xmlChar
*)properties
->selectNsStr
);
351 heap_free(properties
);
355 static void release_namespaces(domdoc
*This
)
357 if (This
->namespaces
)
359 IXMLDOMSchemaCollection2_Release(This
->namespaces
);
360 This
->namespaces
= NULL
;
364 /* links a "<?xml" node as a first child */
365 void xmldoc_link_xmldecl(xmlDocPtr doc
, xmlNodePtr node
)
368 if (doc
->standalone
!= -1) xmlAddPrevSibling( doc
->children
, node
);
371 /* unlinks a first "<?xml" child if it was created */
372 xmlNodePtr
xmldoc_unlink_xmldecl(xmlDocPtr doc
)
374 static const xmlChar xmlA
[] = "xml";
375 xmlNodePtr node
, first_child
;
379 /* xml declaration node could be created automatically after parsing or added
381 first_child
= doc
->children
;
382 if (first_child
&& first_child
->type
== XML_PI_NODE
&& xmlStrEqual(first_child
->name
, xmlA
))
385 xmlUnlinkNode( node
);
393 BOOL
is_preserving_whitespace(xmlNodePtr node
)
395 domdoc_properties
* properties
= NULL
;
396 /* during parsing the xmlDoc._private stuff is not there */
397 if (priv_from_xmlDocPtr(node
->doc
))
398 properties
= properties_from_xmlDocPtr(node
->doc
);
399 return ((properties
&& properties
->preserving
== VARIANT_TRUE
) ||
400 xmlNodeGetSpacePreserve(node
) == 1);
403 static inline BOOL
strn_isspace(xmlChar
const* str
, int len
)
405 for (; str
&& len
> 0 && *str
; ++str
, --len
)
412 static void sax_characters(void *ctx
, const xmlChar
*ch
, int len
)
414 xmlParserCtxtPtr ctxt
;
417 ctxt
= (xmlParserCtxtPtr
) ctx
;
418 This
= (const domdoc
*) ctxt
->_private
;
422 /* during domdoc_loadXML() the xmlDocPtr->_private data is not available */
423 if (!This
->properties
->preserving
&&
424 !is_preserving_whitespace(ctxt
->node
) &&
425 strn_isspace(ch
, len
))
429 xmlSAX2Characters(ctxt
, ch
, len
);
432 static void LIBXML2_LOG_CALLBACK
sax_error(void* ctx
, char const* msg
, ...)
436 LIBXML2_CALLBACK_ERR(doparse
, msg
, ap
);
440 static void LIBXML2_LOG_CALLBACK
sax_warning(void* ctx
, char const* msg
, ...)
444 LIBXML2_CALLBACK_WARN(doparse
, msg
, ap
);
448 static void sax_serror(void* ctx
, xmlErrorPtr err
)
450 LIBXML2_CALLBACK_SERROR(doparse
, err
);
453 static xmlDocPtr
doparse(domdoc
* This
, char const* ptr
, int len
, xmlCharEncoding encoding
)
455 xmlDocPtr doc
= NULL
;
456 xmlParserCtxtPtr pctx
;
457 static xmlSAXHandler sax_handler
= {
458 xmlSAX2InternalSubset
, /* internalSubset */
459 xmlSAX2IsStandalone
, /* isStandalone */
460 xmlSAX2HasInternalSubset
, /* hasInternalSubset */
461 xmlSAX2HasExternalSubset
, /* hasExternalSubset */
462 xmlSAX2ResolveEntity
, /* resolveEntity */
463 xmlSAX2GetEntity
, /* getEntity */
464 xmlSAX2EntityDecl
, /* entityDecl */
465 xmlSAX2NotationDecl
, /* notationDecl */
466 xmlSAX2AttributeDecl
, /* attributeDecl */
467 xmlSAX2ElementDecl
, /* elementDecl */
468 xmlSAX2UnparsedEntityDecl
, /* unparsedEntityDecl */
469 xmlSAX2SetDocumentLocator
, /* setDocumentLocator */
470 xmlSAX2StartDocument
, /* startDocument */
471 xmlSAX2EndDocument
, /* endDocument */
472 xmlSAX2StartElement
, /* startElement */
473 xmlSAX2EndElement
, /* endElement */
474 xmlSAX2Reference
, /* reference */
475 sax_characters
, /* characters */
476 sax_characters
, /* ignorableWhitespace */
477 xmlSAX2ProcessingInstruction
, /* processingInstruction */
478 xmlSAX2Comment
, /* comment */
479 sax_warning
, /* warning */
480 sax_error
, /* error */
481 sax_error
, /* fatalError */
482 xmlSAX2GetParameterEntity
, /* getParameterEntity */
483 xmlSAX2CDataBlock
, /* cdataBlock */
484 xmlSAX2ExternalSubset
, /* externalSubset */
487 xmlSAX2StartElementNs
, /* startElementNs */
488 xmlSAX2EndElementNs
, /* endElementNs */
489 sax_serror
/* serror */
492 pctx
= xmlCreateMemoryParserCtxt(ptr
, len
);
495 ERR("Failed to create parser context\n");
499 if (pctx
->sax
) xmlFree(pctx
->sax
);
500 pctx
->sax
= &sax_handler
;
501 pctx
->_private
= This
;
504 if (encoding
!= XML_CHAR_ENCODING_NONE
)
505 xmlSwitchEncoding(pctx
, encoding
);
507 xmlParseDocument(pctx
);
509 if (pctx
->wellFormed
)
515 xmlFreeDoc(pctx
->myDoc
);
519 xmlFreeParserCtxt(pctx
);
521 /* TODO: put this in one of the SAX callbacks */
522 /* create first child as a <?xml...?> */
523 if (doc
&& doc
->standalone
!= -1)
527 xmlChar
*xmlbuff
= (xmlChar
*)buff
;
529 node
= xmlNewDocPI( doc
, (xmlChar
*)"xml", NULL
);
531 /* version attribute can't be omitted */
532 sprintf(buff
, "version=\"%s\"", doc
->version
? (char*)doc
->version
: "1.0");
533 xmlNodeAddContent( node
, xmlbuff
);
537 sprintf(buff
, " encoding=\"%s\"", doc
->encoding
);
538 xmlNodeAddContent( node
, xmlbuff
);
541 if (doc
->standalone
!= -2)
543 sprintf(buff
, " standalone=\"%s\"", doc
->standalone
== 0 ? "no" : "yes");
544 xmlNodeAddContent( node
, xmlbuff
);
547 xmldoc_link_xmldecl( doc
, node
);
553 void xmldoc_init(xmlDocPtr doc
, MSXML_VERSION version
)
555 doc
->_private
= create_priv();
556 priv_from_xmlDocPtr(doc
)->properties
= create_properties(version
);
559 LONG
xmldoc_add_refs(xmlDocPtr doc
, LONG refs
)
561 LONG ref
= InterlockedExchangeAdd(&priv_from_xmlDocPtr(doc
)->refs
, refs
) + refs
;
562 TRACE("(%p)->(%d)\n", doc
, ref
);
566 LONG
xmldoc_add_ref(xmlDocPtr doc
)
568 return xmldoc_add_refs(doc
, 1);
571 LONG
xmldoc_release_refs(xmlDocPtr doc
, LONG refs
)
573 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
574 LONG ref
= InterlockedExchangeAdd(&priv
->refs
, -refs
) - refs
;
575 TRACE("(%p)->(%d)\n", doc
, ref
);
578 WARN("negative refcount, expect troubles\n");
582 orphan_entry
*orphan
, *orphan2
;
583 TRACE("freeing docptr %p\n", doc
);
585 LIST_FOR_EACH_ENTRY_SAFE( orphan
, orphan2
, &priv
->orphans
, orphan_entry
, entry
)
587 xmlFreeNode( orphan
->node
);
590 free_properties(priv
->properties
);
591 heap_free(doc
->_private
);
599 LONG
xmldoc_release(xmlDocPtr doc
)
601 return xmldoc_release_refs(doc
, 1);
604 HRESULT
xmldoc_add_orphan(xmlDocPtr doc
, xmlNodePtr node
)
606 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
609 entry
= heap_alloc( sizeof (*entry
) );
611 return E_OUTOFMEMORY
;
614 list_add_head( &priv
->orphans
, &entry
->entry
);
618 HRESULT
xmldoc_remove_orphan(xmlDocPtr doc
, xmlNodePtr node
)
620 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
621 orphan_entry
*entry
, *entry2
;
623 LIST_FOR_EACH_ENTRY_SAFE( entry
, entry2
, &priv
->orphans
, orphan_entry
, entry
)
625 if( entry
->node
== node
)
627 list_remove( &entry
->entry
);
636 static inline xmlDocPtr
get_doc( domdoc
*This
)
638 return This
->node
.node
->doc
;
641 static HRESULT
attach_xmldoc(domdoc
*This
, xmlDocPtr xml
)
643 release_namespaces(This
);
647 priv_from_xmlDocPtr(get_doc(This
))->properties
= NULL
;
648 if (xmldoc_release(get_doc(This
)) != 0)
649 priv_from_xmlDocPtr(get_doc(This
))->properties
=
650 copy_properties(This
->properties
);
653 This
->node
.node
= (xmlNodePtr
) xml
;
657 xmldoc_add_ref(get_doc(This
));
658 priv_from_xmlDocPtr(get_doc(This
))->properties
= This
->properties
;
664 static inline domdoc
*impl_from_IXMLDOMDocument3( IXMLDOMDocument3
*iface
)
666 return CONTAINING_RECORD(iface
, domdoc
, IXMLDOMDocument3_iface
);
669 static inline domdoc
*impl_from_IPersistStreamInit(IPersistStreamInit
*iface
)
671 return CONTAINING_RECORD(iface
, domdoc
, IPersistStreamInit_iface
);
674 static inline domdoc
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
676 return CONTAINING_RECORD(iface
, domdoc
, IObjectWithSite_iface
);
679 static inline domdoc
*impl_from_IObjectSafety(IObjectSafety
*iface
)
681 return CONTAINING_RECORD(iface
, domdoc
, IObjectSafety_iface
);
684 static inline domdoc
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
686 return CONTAINING_RECORD(iface
, domdoc
, IConnectionPointContainer_iface
);
689 /************************************************************************
690 * domdoc implementation of IPersistStream.
692 static HRESULT WINAPI
PersistStreamInit_QueryInterface(
693 IPersistStreamInit
*iface
, REFIID riid
, void **ppvObj
)
695 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
696 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObj
);
699 static ULONG WINAPI
PersistStreamInit_AddRef(
700 IPersistStreamInit
*iface
)
702 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
703 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
706 static ULONG WINAPI
PersistStreamInit_Release(
707 IPersistStreamInit
*iface
)
709 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
710 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
713 static HRESULT WINAPI
PersistStreamInit_GetClassID(
714 IPersistStreamInit
*iface
, CLSID
*classid
)
716 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
717 TRACE("(%p)->(%p)\n", This
, classid
);
722 *classid
= *DOMDocument_version(This
->properties
->version
);
727 static HRESULT WINAPI
PersistStreamInit_IsDirty(
728 IPersistStreamInit
*iface
)
730 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
731 FIXME("(%p): stub!\n", This
);
735 static HRESULT
domdoc_load_from_stream(domdoc
*doc
, ISequentialStream
*stream
)
737 DWORD read
, written
, len
;
738 xmlDocPtr xmldoc
= NULL
;
746 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &hstream
);
752 ISequentialStream_Read(stream
, buf
, sizeof(buf
), &read
);
753 hr
= IStream_Write(hstream
, buf
, read
, &written
);
754 } while(SUCCEEDED(hr
) && written
!= 0 && read
!= 0);
758 ERR("failed to copy stream 0x%08x\n", hr
);
759 IStream_Release(hstream
);
763 hr
= GetHGlobalFromStream(hstream
, &hglobal
);
767 len
= GlobalSize(hglobal
);
768 ptr
= GlobalLock(hglobal
);
770 xmldoc
= doparse(doc
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
771 GlobalUnlock(hglobal
);
775 ERR("Failed to parse xml\n");
779 xmldoc
->_private
= create_priv();
781 return attach_xmldoc(doc
, xmldoc
);
784 static HRESULT WINAPI
PersistStreamInit_Load(IPersistStreamInit
*iface
, IStream
*stream
)
786 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
788 TRACE("(%p)->(%p)\n", This
, stream
);
793 return domdoc_load_from_stream(This
, (ISequentialStream
*)stream
);
796 static HRESULT WINAPI
PersistStreamInit_Save(
797 IPersistStreamInit
*iface
, IStream
*stream
, BOOL clr_dirty
)
799 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
803 TRACE("(%p)->(%p %d)\n", This
, stream
, clr_dirty
);
805 hr
= IXMLDOMDocument3_get_xml(&This
->IXMLDOMDocument3_iface
, &xmlString
);
808 DWORD len
= SysStringLen(xmlString
) * sizeof(WCHAR
);
810 hr
= IStream_Write( stream
, xmlString
, len
, NULL
);
811 SysFreeString(xmlString
);
814 TRACE("ret 0x%08x\n", hr
);
819 static HRESULT WINAPI
PersistStreamInit_GetSizeMax(
820 IPersistStreamInit
*iface
, ULARGE_INTEGER
*pcbSize
)
822 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
823 TRACE("(%p)->(%p)\n", This
, pcbSize
);
827 static HRESULT WINAPI
PersistStreamInit_InitNew(
828 IPersistStreamInit
*iface
)
830 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
831 TRACE("(%p)\n", This
);
835 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable
=
837 PersistStreamInit_QueryInterface
,
838 PersistStreamInit_AddRef
,
839 PersistStreamInit_Release
,
840 PersistStreamInit_GetClassID
,
841 PersistStreamInit_IsDirty
,
842 PersistStreamInit_Load
,
843 PersistStreamInit_Save
,
844 PersistStreamInit_GetSizeMax
,
845 PersistStreamInit_InitNew
848 /* IXMLDOMDocument3 interface */
850 static const tid_t domdoc_se_tids
[] = {
853 IXMLDOMDocument2_tid
,
854 IXMLDOMDocument3_tid
,
858 static HRESULT WINAPI
domdoc_QueryInterface( IXMLDOMDocument3
*iface
, REFIID riid
, void** ppvObject
)
860 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
862 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( riid
), ppvObject
);
866 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
867 IsEqualGUID( riid
, &IID_IDispatch
) ||
868 IsEqualGUID( riid
, &IID_IXMLDOMNode
) ||
869 IsEqualGUID( riid
, &IID_IXMLDOMDocument
) ||
870 IsEqualGUID( riid
, &IID_IXMLDOMDocument2
)||
871 IsEqualGUID( riid
, &IID_IXMLDOMDocument3
))
875 else if (IsEqualGUID(&IID_IPersistStream
, riid
) ||
876 IsEqualGUID(&IID_IPersistStreamInit
, riid
))
878 *ppvObject
= &This
->IPersistStreamInit_iface
;
880 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
882 *ppvObject
= &This
->IObjectWithSite_iface
;
884 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
886 *ppvObject
= &This
->IObjectSafety_iface
;
888 else if( IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
890 return node_create_supporterrorinfo(domdoc_se_tids
, ppvObject
);
892 else if(node_query_interface(&This
->node
, riid
, ppvObject
))
894 return *ppvObject
? S_OK
: E_NOINTERFACE
;
896 else if (IsEqualGUID( riid
, &IID_IConnectionPointContainer
))
898 *ppvObject
= &This
->IConnectionPointContainer_iface
;
902 TRACE("interface %s not implemented\n", debugstr_guid(riid
));
903 return E_NOINTERFACE
;
906 IUnknown_AddRef((IUnknown
*)*ppvObject
);
911 static ULONG WINAPI
domdoc_AddRef( IXMLDOMDocument3
*iface
)
913 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
914 ULONG ref
= InterlockedIncrement( &This
->ref
);
915 TRACE("(%p)->(%d)\n", This
, ref
);
919 static ULONG WINAPI
domdoc_Release( IXMLDOMDocument3
*iface
)
921 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
922 LONG ref
= InterlockedDecrement( &This
->ref
);
924 TRACE("(%p)->(%d)\n", This
, ref
);
931 detach_bsc(This
->bsc
);
934 IUnknown_Release( This
->site
);
935 destroy_xmlnode(&This
->node
);
937 for (eid
= 0; eid
< EVENTID_LAST
; eid
++)
938 if (This
->events
[eid
]) IDispatch_Release(This
->events
[eid
]);
940 release_namespaces(This
);
947 static HRESULT WINAPI
domdoc_GetTypeInfoCount( IXMLDOMDocument3
*iface
, UINT
* pctinfo
)
949 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
950 return IDispatchEx_GetTypeInfoCount(&This
->node
.dispex
.IDispatchEx_iface
, pctinfo
);
953 static HRESULT WINAPI
domdoc_GetTypeInfo(
954 IXMLDOMDocument3
*iface
,
955 UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
957 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
958 return IDispatchEx_GetTypeInfo(&This
->node
.dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
961 static HRESULT WINAPI
domdoc_GetIDsOfNames(
962 IXMLDOMDocument3
*iface
,
969 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
970 return IDispatchEx_GetIDsOfNames(&This
->node
.dispex
.IDispatchEx_iface
,
971 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
974 static HRESULT WINAPI
domdoc_Invoke(
975 IXMLDOMDocument3
*iface
,
980 DISPPARAMS
* pDispParams
,
982 EXCEPINFO
* pExcepInfo
,
985 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
986 return IDispatchEx_Invoke(&This
->node
.dispex
.IDispatchEx_iface
,
987 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
990 static HRESULT WINAPI
domdoc_get_nodeName(
991 IXMLDOMDocument3
*iface
,
994 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
996 static const WCHAR documentW
[] = {'#','d','o','c','u','m','e','n','t',0};
998 TRACE("(%p)->(%p)\n", This
, name
);
1000 return return_bstr(documentW
, name
);
1004 static HRESULT WINAPI
domdoc_get_nodeValue(
1005 IXMLDOMDocument3
*iface
,
1008 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1010 TRACE("(%p)->(%p)\n", This
, value
);
1013 return E_INVALIDARG
;
1015 V_VT(value
) = VT_NULL
;
1016 V_BSTR(value
) = NULL
; /* tests show that we should do this */
1021 static HRESULT WINAPI
domdoc_put_nodeValue(
1022 IXMLDOMDocument3
*iface
,
1025 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1026 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&value
));
1031 static HRESULT WINAPI
domdoc_get_nodeType(
1032 IXMLDOMDocument3
*iface
,
1035 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1037 TRACE("(%p)->(%p)\n", This
, type
);
1039 *type
= NODE_DOCUMENT
;
1044 static HRESULT WINAPI
domdoc_get_parentNode(
1045 IXMLDOMDocument3
*iface
,
1046 IXMLDOMNode
** parent
)
1048 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1050 TRACE("(%p)->(%p)\n", This
, parent
);
1052 return node_get_parent(&This
->node
, parent
);
1056 static HRESULT WINAPI
domdoc_get_childNodes(
1057 IXMLDOMDocument3
*iface
,
1058 IXMLDOMNodeList
** childList
)
1060 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1062 TRACE("(%p)->(%p)\n", This
, childList
);
1064 return node_get_child_nodes(&This
->node
, childList
);
1068 static HRESULT WINAPI
domdoc_get_firstChild(
1069 IXMLDOMDocument3
*iface
,
1070 IXMLDOMNode
** firstChild
)
1072 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1074 TRACE("(%p)->(%p)\n", This
, firstChild
);
1076 return node_get_first_child(&This
->node
, firstChild
);
1080 static HRESULT WINAPI
domdoc_get_lastChild(
1081 IXMLDOMDocument3
*iface
,
1082 IXMLDOMNode
** lastChild
)
1084 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1086 TRACE("(%p)->(%p)\n", This
, lastChild
);
1088 return node_get_last_child(&This
->node
, lastChild
);
1092 static HRESULT WINAPI
domdoc_get_previousSibling(
1093 IXMLDOMDocument3
*iface
,
1094 IXMLDOMNode
** previousSibling
)
1096 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1098 TRACE("(%p)->(%p)\n", This
, previousSibling
);
1100 return return_null_node(previousSibling
);
1104 static HRESULT WINAPI
domdoc_get_nextSibling(
1105 IXMLDOMDocument3
*iface
,
1106 IXMLDOMNode
** nextSibling
)
1108 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1110 TRACE("(%p)->(%p)\n", This
, nextSibling
);
1112 return return_null_node(nextSibling
);
1116 static HRESULT WINAPI
domdoc_get_attributes(
1117 IXMLDOMDocument3
*iface
,
1118 IXMLDOMNamedNodeMap
** attributeMap
)
1120 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1122 TRACE("(%p)->(%p)\n", This
, attributeMap
);
1124 return return_null_ptr((void**)attributeMap
);
1128 static HRESULT WINAPI
domdoc_insertBefore(
1129 IXMLDOMDocument3
*iface
,
1130 IXMLDOMNode
* newChild
,
1132 IXMLDOMNode
** outNewChild
)
1134 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1138 TRACE("(%p)->(%p %s %p)\n", This
, newChild
, debugstr_variant(&refChild
), outNewChild
);
1140 hr
= IXMLDOMNode_get_nodeType(newChild
, &type
);
1141 if (hr
!= S_OK
) return hr
;
1143 TRACE("new node type %d\n", type
);
1146 case NODE_ATTRIBUTE
:
1148 case NODE_CDATA_SECTION
:
1149 if (outNewChild
) *outNewChild
= NULL
;
1152 return node_insert_before(&This
->node
, newChild
, &refChild
, outNewChild
);
1156 static HRESULT WINAPI
domdoc_replaceChild(
1157 IXMLDOMDocument3
*iface
,
1158 IXMLDOMNode
* newChild
,
1159 IXMLDOMNode
* oldChild
,
1160 IXMLDOMNode
** outOldChild
)
1162 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1164 TRACE("(%p)->(%p %p %p)\n", This
, newChild
, oldChild
, outOldChild
);
1166 return node_replace_child(&This
->node
, newChild
, oldChild
, outOldChild
);
1170 static HRESULT WINAPI
domdoc_removeChild(
1171 IXMLDOMDocument3
*iface
,
1173 IXMLDOMNode
**oldChild
)
1175 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1176 TRACE("(%p)->(%p %p)\n", This
, child
, oldChild
);
1177 return node_remove_child(&This
->node
, child
, oldChild
);
1181 static HRESULT WINAPI
domdoc_appendChild(
1182 IXMLDOMDocument3
*iface
,
1184 IXMLDOMNode
**outChild
)
1186 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1187 TRACE("(%p)->(%p %p)\n", This
, child
, outChild
);
1188 return node_append_child(&This
->node
, child
, outChild
);
1192 static HRESULT WINAPI
domdoc_hasChildNodes(
1193 IXMLDOMDocument3
*iface
,
1196 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1197 TRACE("(%p)->(%p)\n", This
, ret
);
1198 return node_has_childnodes(&This
->node
, ret
);
1202 static HRESULT WINAPI
domdoc_get_ownerDocument(
1203 IXMLDOMDocument3
*iface
,
1204 IXMLDOMDocument
**doc
)
1206 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1207 TRACE("(%p)->(%p)\n", This
, doc
);
1208 return node_get_owner_doc(&This
->node
, doc
);
1212 static HRESULT WINAPI
domdoc_cloneNode(
1213 IXMLDOMDocument3
*iface
,
1215 IXMLDOMNode
** outNode
)
1217 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1218 TRACE("(%p)->(%d %p)\n", This
, deep
, outNode
);
1219 return node_clone( &This
->node
, deep
, outNode
);
1223 static HRESULT WINAPI
domdoc_get_nodeTypeString(
1224 IXMLDOMDocument3
*iface
,
1227 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1228 static const WCHAR documentW
[] = {'d','o','c','u','m','e','n','t',0};
1230 TRACE("(%p)->(%p)\n", This
, p
);
1232 return return_bstr(documentW
, p
);
1236 static HRESULT WINAPI
domdoc_get_text(
1237 IXMLDOMDocument3
*iface
,
1240 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1241 TRACE("(%p)->(%p)\n", This
, p
);
1242 return node_get_text(&This
->node
, p
);
1246 static HRESULT WINAPI
domdoc_put_text(
1247 IXMLDOMDocument3
*iface
,
1250 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1251 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
1256 static HRESULT WINAPI
domdoc_get_specified(
1257 IXMLDOMDocument3
*iface
,
1258 VARIANT_BOOL
* isSpecified
)
1260 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1261 FIXME("(%p)->(%p) stub!\n", This
, isSpecified
);
1262 *isSpecified
= VARIANT_TRUE
;
1267 static HRESULT WINAPI
domdoc_get_definition(
1268 IXMLDOMDocument3
*iface
,
1269 IXMLDOMNode
** definitionNode
)
1271 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1272 FIXME("(%p)->(%p)\n", This
, definitionNode
);
1277 static HRESULT WINAPI
domdoc_get_nodeTypedValue(
1278 IXMLDOMDocument3
*iface
,
1281 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1282 TRACE("(%p)->(%p)\n", This
, v
);
1283 return return_null_var(v
);
1286 static HRESULT WINAPI
domdoc_put_nodeTypedValue(
1287 IXMLDOMDocument3
*iface
,
1288 VARIANT typedValue
)
1290 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1291 FIXME("(%p)->(%s)\n", This
, debugstr_variant(&typedValue
));
1296 static HRESULT WINAPI
domdoc_get_dataType(
1297 IXMLDOMDocument3
*iface
,
1300 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1301 TRACE("(%p)->(%p)\n", This
, typename
);
1302 return return_null_var( typename
);
1306 static HRESULT WINAPI
domdoc_put_dataType(
1307 IXMLDOMDocument3
*iface
,
1310 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1312 FIXME("(%p)->(%s)\n", This
, debugstr_w(dataTypeName
));
1315 return E_INVALIDARG
;
1320 static int XMLCALL
domdoc_get_xml_writecallback(void *ctx
, const char *data
, int len
)
1322 return xmlBufferAdd((xmlBufferPtr
)ctx
, (xmlChar
*)data
, len
) == 0 ? len
: 0;
1325 static HRESULT WINAPI
domdoc_get_xml(
1326 IXMLDOMDocument3
*iface
,
1329 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1330 xmlSaveCtxtPtr ctxt
;
1335 TRACE("(%p)->(%p)\n", This
, p
);
1338 return E_INVALIDARG
;
1342 buf
= xmlBufferCreate();
1344 return E_OUTOFMEMORY
;
1346 options
= XML_SAVE_FORMAT
| XML_SAVE_NO_DECL
;
1347 ctxt
= xmlSaveToIO(domdoc_get_xml_writecallback
, NULL
, buf
, "UTF-8", options
);
1352 return E_OUTOFMEMORY
;
1355 ret
= xmlSaveDoc(ctxt
, get_doc(This
));
1356 /* flushes on close */
1359 TRACE("%ld, len=%d\n", ret
, xmlBufferLength(buf
));
1360 if(ret
!= -1 && xmlBufferLength(buf
) > 0)
1364 content
= bstr_from_xmlChar(xmlBufferContent(buf
));
1365 content
= EnsureCorrectEOL(content
);
1371 *p
= SysAllocStringLen(NULL
, 0);
1376 return *p
? S_OK
: E_OUTOFMEMORY
;
1380 static HRESULT WINAPI
domdoc_transformNode(
1381 IXMLDOMDocument3
*iface
,
1385 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1386 TRACE("(%p)->(%p %p)\n", This
, node
, p
);
1387 return node_transform_node(&This
->node
, node
, p
);
1391 static HRESULT WINAPI
domdoc_selectNodes(
1392 IXMLDOMDocument3
*iface
,
1394 IXMLDOMNodeList
**outList
)
1396 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1397 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outList
);
1398 return node_select_nodes(&This
->node
, p
, outList
);
1402 static HRESULT WINAPI
domdoc_selectSingleNode(
1403 IXMLDOMDocument3
*iface
,
1405 IXMLDOMNode
**outNode
)
1407 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1408 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outNode
);
1409 return node_select_singlenode(&This
->node
, p
, outNode
);
1413 static HRESULT WINAPI
domdoc_get_parsed(
1414 IXMLDOMDocument3
*iface
,
1415 VARIANT_BOOL
* isParsed
)
1417 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1418 FIXME("(%p)->(%p) stub!\n", This
, isParsed
);
1419 *isParsed
= VARIANT_TRUE
;
1423 static HRESULT WINAPI
domdoc_get_namespaceURI(
1424 IXMLDOMDocument3
*iface
,
1425 BSTR
* namespaceURI
)
1427 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1428 TRACE("(%p)->(%p)\n", This
, namespaceURI
);
1429 return return_null_bstr( namespaceURI
);
1432 static HRESULT WINAPI
domdoc_get_prefix(
1433 IXMLDOMDocument3
*iface
,
1436 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1437 TRACE("(%p)->(%p)\n", This
, prefix
);
1438 return return_null_bstr( prefix
);
1442 static HRESULT WINAPI
domdoc_get_baseName(
1443 IXMLDOMDocument3
*iface
,
1446 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1447 TRACE("(%p)->(%p)\n", This
, name
);
1448 return return_null_bstr( name
);
1452 static HRESULT WINAPI
domdoc_transformNodeToObject(
1453 IXMLDOMDocument3
*iface
,
1454 IXMLDOMNode
* stylesheet
,
1455 VARIANT outputObject
)
1457 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1458 FIXME("(%p)->(%p %s)\n", This
, stylesheet
, debugstr_variant(&outputObject
));
1463 static HRESULT WINAPI
domdoc_get_doctype(
1464 IXMLDOMDocument3
*iface
,
1465 IXMLDOMDocumentType
** doctype
)
1467 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1472 TRACE("(%p)->(%p)\n", This
, doctype
);
1474 if (!doctype
) return E_INVALIDARG
;
1478 dtd
= xmlGetIntSubset(get_doc(This
));
1479 if (!dtd
) return S_FALSE
;
1481 node
= create_node((xmlNodePtr
)dtd
);
1482 if (!node
) return S_FALSE
;
1484 hr
= IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentType
, (void**)doctype
);
1485 IXMLDOMNode_Release(node
);
1491 static HRESULT WINAPI
domdoc_get_implementation(
1492 IXMLDOMDocument3
*iface
,
1493 IXMLDOMImplementation
** impl
)
1495 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1497 TRACE("(%p)->(%p)\n", This
, impl
);
1500 return E_INVALIDARG
;
1502 *impl
= (IXMLDOMImplementation
*)create_doc_Implementation();
1507 static HRESULT WINAPI
domdoc_get_documentElement(
1508 IXMLDOMDocument3
*iface
,
1509 IXMLDOMElement
** DOMElement
)
1511 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1512 IXMLDOMNode
*element_node
;
1516 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1519 return E_INVALIDARG
;
1523 root
= xmlDocGetRootElement( get_doc(This
) );
1527 element_node
= create_node( root
);
1528 if(!element_node
) return S_FALSE
;
1530 hr
= IXMLDOMNode_QueryInterface(element_node
, &IID_IXMLDOMElement
, (void**)DOMElement
);
1531 IXMLDOMNode_Release(element_node
);
1537 static HRESULT WINAPI
domdoc_put_documentElement(
1538 IXMLDOMDocument3
*iface
,
1539 IXMLDOMElement
* DOMElement
)
1541 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1542 IXMLDOMNode
*elementNode
;
1549 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1551 hr
= IXMLDOMElement_QueryInterface( DOMElement
, &IID_IXMLDOMNode
, (void**)&elementNode
);
1555 xmlNode
= get_node_obj( elementNode
);
1556 if(!xmlNode
) return E_FAIL
;
1558 if(!xmlNode
->node
->parent
)
1559 if(xmldoc_remove_orphan(xmlNode
->node
->doc
, xmlNode
->node
) != S_OK
)
1560 WARN("%p is not an orphan of %p\n", xmlNode
->node
->doc
, xmlNode
->node
);
1562 old_doc
= xmlNode
->node
->doc
;
1563 if (old_doc
!= get_doc(This
))
1564 refcount
= xmlnode_get_inst_cnt(xmlNode
);
1566 /* old root is still orphaned by its document, update refcount from new root */
1567 if (refcount
) xmldoc_add_refs(get_doc(This
), refcount
);
1568 oldRoot
= xmlDocSetRootElement( get_doc(This
), xmlNode
->node
);
1569 if (refcount
) xmldoc_release_refs(old_doc
, refcount
);
1570 IXMLDOMNode_Release( elementNode
);
1573 xmldoc_add_orphan(oldRoot
->doc
, oldRoot
);
1579 static HRESULT WINAPI
domdoc_createElement(
1580 IXMLDOMDocument3
*iface
,
1582 IXMLDOMElement
** element
)
1584 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1589 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(tagname
), element
);
1591 if (!element
|| !tagname
) return E_INVALIDARG
;
1593 V_VT(&type
) = VT_I1
;
1594 V_I1(&type
) = NODE_ELEMENT
;
1596 hr
= IXMLDOMDocument3_createNode(iface
, type
, tagname
, NULL
, &node
);
1599 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMElement
, (void**)element
);
1600 IXMLDOMNode_Release(node
);
1607 static HRESULT WINAPI
domdoc_createDocumentFragment(
1608 IXMLDOMDocument3
*iface
,
1609 IXMLDOMDocumentFragment
** frag
)
1611 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1616 TRACE("(%p)->(%p)\n", This
, frag
);
1618 if (!frag
) return E_INVALIDARG
;
1622 V_VT(&type
) = VT_I1
;
1623 V_I1(&type
) = NODE_DOCUMENT_FRAGMENT
;
1625 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1628 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentFragment
, (void**)frag
);
1629 IXMLDOMNode_Release(node
);
1636 static HRESULT WINAPI
domdoc_createTextNode(
1637 IXMLDOMDocument3
*iface
,
1639 IXMLDOMText
** text
)
1641 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1646 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), text
);
1648 if (!text
) return E_INVALIDARG
;
1652 V_VT(&type
) = VT_I1
;
1653 V_I1(&type
) = NODE_TEXT
;
1655 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1658 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMText
, (void**)text
);
1659 IXMLDOMNode_Release(node
);
1660 hr
= IXMLDOMText_put_data(*text
, data
);
1667 static HRESULT WINAPI
domdoc_createComment(
1668 IXMLDOMDocument3
*iface
,
1670 IXMLDOMComment
** comment
)
1672 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1677 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), comment
);
1679 if (!comment
) return E_INVALIDARG
;
1683 V_VT(&type
) = VT_I1
;
1684 V_I1(&type
) = NODE_COMMENT
;
1686 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1689 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMComment
, (void**)comment
);
1690 IXMLDOMNode_Release(node
);
1691 hr
= IXMLDOMComment_put_data(*comment
, data
);
1698 static HRESULT WINAPI
domdoc_createCDATASection(
1699 IXMLDOMDocument3
*iface
,
1701 IXMLDOMCDATASection
** cdata
)
1703 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1708 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), cdata
);
1710 if (!cdata
) return E_INVALIDARG
;
1714 V_VT(&type
) = VT_I1
;
1715 V_I1(&type
) = NODE_CDATA_SECTION
;
1717 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1720 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMCDATASection
, (void**)cdata
);
1721 IXMLDOMNode_Release(node
);
1722 hr
= IXMLDOMCDATASection_put_data(*cdata
, data
);
1729 static HRESULT WINAPI
domdoc_createProcessingInstruction(
1730 IXMLDOMDocument3
*iface
,
1733 IXMLDOMProcessingInstruction
** pi
)
1735 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1740 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_w(target
), debugstr_w(data
), pi
);
1742 if (!pi
) return E_INVALIDARG
;
1746 V_VT(&type
) = VT_I1
;
1747 V_I1(&type
) = NODE_PROCESSING_INSTRUCTION
;
1749 hr
= IXMLDOMDocument3_createNode(iface
, type
, target
, NULL
, &node
);
1754 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1755 node_obj
= get_node_obj(node
);
1756 hr
= node_set_content(node_obj
, data
);
1758 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMProcessingInstruction
, (void**)pi
);
1759 IXMLDOMNode_Release(node
);
1766 static HRESULT WINAPI
domdoc_createAttribute(
1767 IXMLDOMDocument3
*iface
,
1769 IXMLDOMAttribute
** attribute
)
1771 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1776 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), attribute
);
1778 if (!attribute
|| !name
) return E_INVALIDARG
;
1780 V_VT(&type
) = VT_I1
;
1781 V_I1(&type
) = NODE_ATTRIBUTE
;
1783 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1786 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMAttribute
, (void**)attribute
);
1787 IXMLDOMNode_Release(node
);
1794 static HRESULT WINAPI
domdoc_createEntityReference(
1795 IXMLDOMDocument3
*iface
,
1797 IXMLDOMEntityReference
** entityref
)
1799 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1804 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), entityref
);
1806 if (!entityref
) return E_INVALIDARG
;
1810 V_VT(&type
) = VT_I1
;
1811 V_I1(&type
) = NODE_ENTITY_REFERENCE
;
1813 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1816 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMEntityReference
, (void**)entityref
);
1817 IXMLDOMNode_Release(node
);
1823 xmlChar
* tagName_to_XPath(const BSTR tagName
)
1825 xmlChar
*query
, *tmp
;
1826 static const xmlChar mod_pre
[] = "*[local-name()='";
1827 static const xmlChar mod_post
[] = "']";
1828 static const xmlChar prefix
[] = "descendant::";
1829 const WCHAR
*tokBegin
, *tokEnd
;
1832 query
= xmlStrdup(prefix
);
1835 while (tokBegin
&& *tokBegin
)
1840 query
= xmlStrcat(query
, BAD_CAST
"/");
1844 query
= xmlStrcat(query
, BAD_CAST
"*");
1848 query
= xmlStrcat(query
, mod_pre
);
1850 while (*tokEnd
&& *tokEnd
!= '/')
1852 len
= WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, NULL
, 0, NULL
, NULL
);
1853 tmp
= xmlMalloc(len
);
1854 WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, (char*)tmp
, len
, NULL
, NULL
);
1855 query
= xmlStrncat(query
, tmp
, len
);
1858 query
= xmlStrcat(query
, mod_post
);
1865 static HRESULT WINAPI
domdoc_getElementsByTagName(
1866 IXMLDOMDocument3
*iface
,
1868 IXMLDOMNodeList
** resultList
)
1870 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1875 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(tagName
), resultList
);
1877 if (!tagName
|| !resultList
) return E_INVALIDARG
;
1879 XPath
= This
->properties
->XPath
;
1880 This
->properties
->XPath
= TRUE
;
1881 query
= tagName_to_XPath(tagName
);
1882 hr
= create_selection((xmlNodePtr
)get_doc(This
), query
, resultList
);
1884 This
->properties
->XPath
= XPath
;
1889 static HRESULT
get_node_type(VARIANT Type
, DOMNodeType
* type
)
1895 hr
= VariantChangeType(&tmp
, &Type
, 0, VT_I4
);
1897 return E_INVALIDARG
;
1904 static HRESULT WINAPI
domdoc_createNode(
1905 IXMLDOMDocument3
*iface
,
1909 IXMLDOMNode
** node
)
1911 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1912 DOMNodeType node_type
;
1914 xmlChar
*xml_name
, *href
;
1917 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_variant(&Type
), debugstr_w(name
), debugstr_w(namespaceURI
), node
);
1919 if(!node
) return E_INVALIDARG
;
1921 hr
= get_node_type(Type
, &node_type
);
1922 if(FAILED(hr
)) return hr
;
1924 if(namespaceURI
&& namespaceURI
[0] && node_type
!= NODE_ELEMENT
)
1925 FIXME("nodes with namespaces currently not supported.\n");
1927 TRACE("node_type %d\n", node_type
);
1929 /* exit earlier for types that need name */
1933 case NODE_ATTRIBUTE
:
1934 case NODE_ENTITY_REFERENCE
:
1935 case NODE_PROCESSING_INSTRUCTION
:
1936 if (!name
|| *name
== 0) return E_FAIL
;
1942 xml_name
= xmlchar_from_wchar(name
);
1943 /* prevent empty href to be allocated */
1944 href
= namespaceURI
? xmlchar_from_wchar(namespaceURI
) : NULL
;
1950 xmlChar
*local
, *prefix
;
1952 local
= xmlSplitQName2(xml_name
, &prefix
);
1954 xmlnode
= xmlNewDocNode(get_doc(This
), NULL
, local
? local
: xml_name
, NULL
);
1956 /* allow to create default namespace xmlns= */
1957 if (local
|| (href
&& *href
))
1959 xmlNsPtr ns
= xmlNewNs(xmlnode
, href
, prefix
);
1960 xmlSetNs(xmlnode
, ns
);
1968 case NODE_ATTRIBUTE
:
1969 xmlnode
= (xmlNodePtr
)xmlNewDocProp(get_doc(This
), xml_name
, NULL
);
1972 xmlnode
= (xmlNodePtr
)xmlNewDocText(get_doc(This
), NULL
);
1974 case NODE_CDATA_SECTION
:
1975 xmlnode
= xmlNewCDataBlock(get_doc(This
), NULL
, 0);
1977 case NODE_ENTITY_REFERENCE
:
1978 xmlnode
= xmlNewReference(get_doc(This
), xml_name
);
1980 case NODE_PROCESSING_INSTRUCTION
:
1981 #ifdef HAVE_XMLNEWDOCPI
1982 xmlnode
= xmlNewDocPI(get_doc(This
), xml_name
, NULL
);
1984 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1989 xmlnode
= xmlNewDocComment(get_doc(This
), NULL
);
1991 case NODE_DOCUMENT_FRAGMENT
:
1992 xmlnode
= xmlNewDocFragment(get_doc(This
));
1994 /* unsupported types */
1996 case NODE_DOCUMENT_TYPE
:
1999 heap_free(xml_name
);
2000 return E_INVALIDARG
;
2002 FIXME("unhandled node type %d\n", node_type
);
2007 *node
= create_node(xmlnode
);
2008 heap_free(xml_name
);
2013 TRACE("created node (%d, %p, %p)\n", node_type
, *node
, xmlnode
);
2014 xmldoc_add_orphan(xmlnode
->doc
, xmlnode
);
2021 static HRESULT WINAPI
domdoc_nodeFromID(
2022 IXMLDOMDocument3
*iface
,
2024 IXMLDOMNode
** node
)
2026 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2027 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(idString
), node
);
2031 static HRESULT
domdoc_onDataAvailable(void *obj
, char *ptr
, DWORD len
)
2036 xmldoc
= doparse(This
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
2038 xmldoc
->_private
= create_priv();
2039 return attach_xmldoc(This
, xmldoc
);
2045 static HRESULT
domdoc_load_moniker(domdoc
*This
, IMoniker
*mon
)
2050 hr
= bind_url(mon
, domdoc_onDataAvailable
, This
, &bsc
);
2055 hr
= detach_bsc(This
->bsc
);
2064 static HRESULT WINAPI
domdoc_load(
2065 IXMLDOMDocument3
*iface
,
2067 VARIANT_BOOL
* isSuccessful
)
2069 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2070 LPWSTR filename
= NULL
;
2071 HRESULT hr
= S_FALSE
;
2074 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&source
));
2078 *isSuccessful
= VARIANT_FALSE
;
2080 assert( &This
->node
);
2082 switch( V_VT(&source
) )
2085 filename
= V_BSTR(&source
);
2087 case VT_BSTR
|VT_BYREF
:
2088 if (!V_BSTRREF(&source
)) return E_INVALIDARG
;
2089 filename
= *V_BSTRREF(&source
);
2091 case VT_ARRAY
|VT_UI1
:
2093 SAFEARRAY
*psa
= V_ARRAY(&source
);
2096 UINT dim
= SafeArrayGetDim(psa
);
2101 ERR("SAFEARRAY == NULL\n");
2102 hr
= This
->error
= E_INVALIDARG
;
2105 /* Only takes UTF-8 strings.
2106 * NOT NULL-terminated. */
2107 SafeArrayAccessData(psa
, (void**)&str
);
2108 SafeArrayGetUBound(psa
, 1, &len
);
2110 if ((xmldoc
= doparse(This
, str
, ++len
, XML_CHAR_ENCODING_UTF8
)))
2112 hr
= This
->error
= S_OK
;
2113 *isSuccessful
= VARIANT_TRUE
;
2114 TRACE("parsed document %p\n", xmldoc
);
2118 This
->error
= E_FAIL
;
2119 TRACE("failed to parse document\n");
2122 SafeArrayUnaccessData(psa
);
2126 xmldoc
->_private
= create_priv();
2127 return attach_xmldoc(This
, xmldoc
);
2131 FIXME("unhandled SAFEARRAY dim: %d\n", dim
);
2132 hr
= This
->error
= E_NOTIMPL
;
2138 ISequentialStream
*stream
= NULL
;
2139 IXMLDOMDocument3
*newdoc
= NULL
;
2141 if (!V_UNKNOWN(&source
)) return E_INVALIDARG
;
2143 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IXMLDOMDocument3
, (void**)&newdoc
);
2148 domdoc
*newDoc
= impl_from_IXMLDOMDocument3( newdoc
);
2150 xmldoc
= xmlCopyDoc(get_doc(newDoc
), 1);
2151 xmldoc
->_private
= create_priv();
2152 hr
= attach_xmldoc(This
, xmldoc
);
2155 *isSuccessful
= VARIANT_TRUE
;
2161 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IStream
, (void**)&stream
);
2163 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_ISequentialStream
, (void**)&stream
);
2167 hr
= domdoc_load_from_stream(This
, stream
);
2169 *isSuccessful
= VARIANT_TRUE
;
2170 ISequentialStream_Release(stream
);
2174 FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr
, V_UNKNOWN(&source
)->lpVtbl
);
2178 FIXME("VT type not supported (%d)\n", V_VT(&source
));
2185 hr
= create_moniker_from_url( filename
, &mon
);
2186 if ( SUCCEEDED(hr
) )
2188 hr
= domdoc_load_moniker( This
, mon
);
2189 IMoniker_Release(mon
);
2193 This
->error
= E_FAIL
;
2196 hr
= This
->error
= S_OK
;
2197 *isSuccessful
= VARIANT_TRUE
;
2201 if(!filename
|| FAILED(hr
)) {
2202 xmldoc
= xmlNewDoc(NULL
);
2203 xmldoc
->_private
= create_priv();
2204 hr
= attach_xmldoc(This
, xmldoc
);
2209 TRACE("ret (%d)\n", hr
);
2215 static HRESULT WINAPI
domdoc_get_readyState(
2216 IXMLDOMDocument3
*iface
,
2219 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2220 FIXME("stub! (%p)->(%p)\n", This
, value
);
2223 return E_INVALIDARG
;
2225 *value
= READYSTATE_COMPLETE
;
2230 static HRESULT WINAPI
domdoc_get_parseError(
2231 IXMLDOMDocument3
*iface
,
2232 IXMLDOMParseError
** errorObj
)
2234 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2235 static const WCHAR err
[] = {'e','r','r','o','r',0};
2236 BSTR error_string
= NULL
;
2238 FIXME("(%p)->(%p): creating a dummy parseError\n", iface
, errorObj
);
2241 error_string
= SysAllocString(err
);
2243 *errorObj
= create_parseError(This
->error
, NULL
, error_string
, NULL
, 0, 0, 0);
2244 if(!*errorObj
) return E_OUTOFMEMORY
;
2249 static HRESULT WINAPI
domdoc_get_url(
2250 IXMLDOMDocument3
*iface
,
2253 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2254 FIXME("(%p)->(%p)\n", This
, urlString
);
2259 static HRESULT WINAPI
domdoc_get_async(
2260 IXMLDOMDocument3
*iface
,
2261 VARIANT_BOOL
* isAsync
)
2263 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2265 TRACE("(%p)->(%p: %d)\n", This
, isAsync
, This
->async
);
2266 *isAsync
= This
->async
;
2271 static HRESULT WINAPI
domdoc_put_async(
2272 IXMLDOMDocument3
*iface
,
2273 VARIANT_BOOL isAsync
)
2275 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2277 TRACE("(%p)->(%d)\n", This
, isAsync
);
2278 This
->async
= isAsync
;
2283 static HRESULT WINAPI
domdoc_abort(
2284 IXMLDOMDocument3
*iface
)
2286 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2287 FIXME("%p\n", This
);
2291 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2292 static HRESULT WINAPI
domdoc_loadXML(
2293 IXMLDOMDocument3
*iface
,
2295 VARIANT_BOOL
* isSuccessful
)
2297 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2298 xmlDocPtr xmldoc
= NULL
;
2299 HRESULT hr
= S_FALSE
, hr2
;
2301 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), isSuccessful
);
2303 assert ( &This
->node
);
2307 *isSuccessful
= VARIANT_FALSE
;
2313 /* skip leading spaces if needed */
2314 if (This
->properties
->version
== MSXML_DEFAULT
|| This
->properties
->version
== MSXML26
)
2315 while (*ptr
&& isspaceW(*ptr
)) ptr
++;
2317 xmldoc
= doparse(This
, (char*)ptr
, strlenW(ptr
)*sizeof(WCHAR
), XML_CHAR_ENCODING_UTF16LE
);
2320 This
->error
= E_FAIL
;
2321 TRACE("failed to parse document\n");
2325 hr
= This
->error
= S_OK
;
2326 *isSuccessful
= VARIANT_TRUE
;
2327 TRACE("parsed document %p\n", xmldoc
);
2333 xmldoc
= xmlNewDoc(NULL
);
2334 xmldoc
->_private
= create_priv();
2335 hr2
= attach_xmldoc(This
, xmldoc
);
2342 static int XMLCALL
domdoc_save_writecallback(void *ctx
, const char *buffer
, int len
)
2346 if(!WriteFile(ctx
, buffer
, len
, &written
, NULL
))
2348 WARN("write error\n");
2355 static int XMLCALL
domdoc_save_closecallback(void *ctx
)
2357 return CloseHandle(ctx
) ? 0 : -1;
2360 static int XMLCALL
domdoc_stream_save_writecallback(void *ctx
, const char *buffer
, int len
)
2365 hr
= IStream_Write((IStream
*)ctx
, buffer
, len
, &written
);
2366 TRACE("0x%08x %p %d %u\n", hr
, buffer
, len
, written
);
2369 WARN("stream write error: 0x%08x\n", hr
);
2376 static int XMLCALL
domdoc_stream_save_closecallback(void *ctx
)
2378 IStream_Release((IStream
*)ctx
);
2382 static HRESULT WINAPI
domdoc_save(
2383 IXMLDOMDocument3
*iface
,
2384 VARIANT destination
)
2386 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2387 xmlSaveCtxtPtr ctx
= NULL
;
2391 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&destination
));
2393 switch (V_VT(&destination
))
2397 IUnknown
*pUnk
= V_UNKNOWN(&destination
);
2398 IXMLDOMDocument3
*document
;
2401 ret
= IUnknown_QueryInterface(pUnk
, &IID_IXMLDOMDocument3
, (void**)&document
);
2404 VARIANT_BOOL success
;
2407 ret
= IXMLDOMDocument3_get_xml(iface
, &xml
);
2410 ret
= IXMLDOMDocument3_loadXML(document
, xml
, &success
);
2414 IXMLDOMDocument3_Release(document
);
2418 ret
= IUnknown_QueryInterface(pUnk
, &IID_IStream
, (void**)&stream
);
2421 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2422 ctx
= xmlSaveToIO(domdoc_stream_save_writecallback
,
2423 domdoc_stream_save_closecallback
, stream
, NULL
, options
);
2427 IStream_Release(stream
);
2435 case VT_BSTR
| VT_BYREF
:
2437 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2439 /* save with file path */
2440 HANDLE handle
= CreateFileW( (V_VT(&destination
) & VT_BYREF
)? *V_BSTRREF(&destination
) : V_BSTR(&destination
),
2441 GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2442 if( handle
== INVALID_HANDLE_VALUE
)
2444 WARN("failed to create file\n");
2448 /* disable top XML declaration */
2449 ctx
= xmlSaveToIO(domdoc_save_writecallback
, domdoc_save_closecallback
,
2450 handle
, NULL
, options
);
2453 CloseHandle(handle
);
2460 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination
));
2464 xmldecl
= xmldoc_unlink_xmldecl(get_doc(This
));
2465 if (xmlSaveDoc(ctx
, get_doc(This
)) == -1) ret
= S_FALSE
;
2466 xmldoc_link_xmldecl(get_doc(This
), xmldecl
);
2468 /* will release resources through close callback */
2474 static HRESULT WINAPI
domdoc_get_validateOnParse(
2475 IXMLDOMDocument3
*iface
,
2476 VARIANT_BOOL
* isValidating
)
2478 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2479 TRACE("(%p)->(%p: %d)\n", This
, isValidating
, This
->validating
);
2480 *isValidating
= This
->validating
;
2485 static HRESULT WINAPI
domdoc_put_validateOnParse(
2486 IXMLDOMDocument3
*iface
,
2487 VARIANT_BOOL isValidating
)
2489 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2490 TRACE("(%p)->(%d)\n", This
, isValidating
);
2491 This
->validating
= isValidating
;
2496 static HRESULT WINAPI
domdoc_get_resolveExternals(
2497 IXMLDOMDocument3
*iface
,
2498 VARIANT_BOOL
* isResolving
)
2500 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2501 TRACE("(%p)->(%p: %d)\n", This
, isResolving
, This
->resolving
);
2502 *isResolving
= This
->resolving
;
2507 static HRESULT WINAPI
domdoc_put_resolveExternals(
2508 IXMLDOMDocument3
*iface
,
2509 VARIANT_BOOL isResolving
)
2511 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2512 TRACE("(%p)->(%d)\n", This
, isResolving
);
2513 This
->resolving
= isResolving
;
2518 static HRESULT WINAPI
domdoc_get_preserveWhiteSpace(
2519 IXMLDOMDocument3
*iface
,
2520 VARIANT_BOOL
* isPreserving
)
2522 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2523 TRACE("(%p)->(%p: %d)\n", This
, isPreserving
, This
->properties
->preserving
);
2524 *isPreserving
= This
->properties
->preserving
;
2529 static HRESULT WINAPI
domdoc_put_preserveWhiteSpace(
2530 IXMLDOMDocument3
*iface
,
2531 VARIANT_BOOL isPreserving
)
2533 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2534 TRACE("(%p)->(%d)\n", This
, isPreserving
);
2535 This
->properties
->preserving
= isPreserving
;
2540 static HRESULT WINAPI
domdoc_put_onreadystatechange(
2541 IXMLDOMDocument3
*iface
,
2544 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2546 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&event
));
2547 return set_doc_event(This
, EVENTID_READYSTATECHANGE
, &event
);
2551 static HRESULT WINAPI
domdoc_put_onDataAvailable(IXMLDOMDocument3
*iface
, VARIANT sink
)
2553 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2554 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2558 static HRESULT WINAPI
domdoc_put_onTransformNode(IXMLDOMDocument3
*iface
, VARIANT sink
)
2560 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2561 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2565 static HRESULT WINAPI
domdoc_get_namespaces(
2566 IXMLDOMDocument3
* iface
,
2567 IXMLDOMSchemaCollection
** collection
)
2569 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2572 FIXME("(%p)->(%p): semi-stub\n", This
, collection
);
2574 if (!collection
) return E_POINTER
;
2576 if (!This
->namespaces
)
2578 hr
= SchemaCache_create(This
->properties
->version
, NULL
, (void**)&This
->namespaces
);
2579 if (hr
!= S_OK
) return hr
;
2581 hr
= cache_from_doc_ns(This
->namespaces
, &This
->node
);
2583 release_namespaces(This
);
2586 if (This
->namespaces
)
2587 return IXMLDOMSchemaCollection2_QueryInterface(This
->namespaces
,
2588 &IID_IXMLDOMSchemaCollection
, (void**)collection
);
2593 static HRESULT WINAPI
domdoc_get_schemas(
2594 IXMLDOMDocument3
* iface
,
2597 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2598 IXMLDOMSchemaCollection2
* cur_schema
= This
->properties
->schemaCache
;
2599 HRESULT hr
= S_FALSE
;
2601 TRACE("(%p)->(%p)\n", This
, schema
);
2603 V_VT(schema
) = VT_NULL
;
2604 /* just to reset pointer part, cause that's what application is expected to use */
2605 V_DISPATCH(schema
) = NULL
;
2609 hr
= IXMLDOMSchemaCollection2_QueryInterface(cur_schema
, &IID_IDispatch
, (void**)&V_DISPATCH(schema
));
2611 V_VT(schema
) = VT_DISPATCH
;
2616 static HRESULT WINAPI
domdoc_putref_schemas(
2617 IXMLDOMDocument3
* iface
,
2620 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2621 HRESULT hr
= E_FAIL
;
2622 IXMLDOMSchemaCollection2
* new_schema
= NULL
;
2624 FIXME("(%p)->(%s): semi-stub\n", This
, debugstr_variant(&schema
));
2625 switch(V_VT(&schema
))
2628 if (V_UNKNOWN(&schema
))
2630 hr
= IUnknown_QueryInterface(V_UNKNOWN(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2635 if (V_DISPATCH(&schema
))
2637 hr
= IDispatch_QueryInterface(V_DISPATCH(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2647 WARN("Can't get schema from vt %x\n", V_VT(&schema
));
2652 IXMLDOMSchemaCollection2
* old_schema
= InterlockedExchangePointer((void**)&This
->properties
->schemaCache
, new_schema
);
2653 if(old_schema
) IXMLDOMSchemaCollection2_Release(old_schema
);
2659 static inline BOOL
is_wellformed(xmlDocPtr doc
)
2661 #ifdef HAVE_XMLDOC_PROPERTIES
2662 return doc
->properties
& XML_DOC_WELLFORMED
;
2664 /* Not a full check, but catches the worst violations */
2668 for (child
= doc
->children
; child
!= NULL
; child
= child
->next
)
2670 switch (child
->type
)
2672 case XML_ELEMENT_NODE
:
2677 case XML_CDATA_SECTION_NODE
:
2689 static void LIBXML2_LOG_CALLBACK
validate_error(void* ctx
, char const* msg
, ...)
2693 LIBXML2_CALLBACK_ERR(domdoc_validateNode
, msg
, ap
);
2697 static void LIBXML2_LOG_CALLBACK
validate_warning(void* ctx
, char const* msg
, ...)
2701 LIBXML2_CALLBACK_WARN(domdoc_validateNode
, msg
, ap
);
2705 static HRESULT WINAPI
domdoc_validateNode(
2706 IXMLDOMDocument3
* iface
,
2708 IXMLDOMParseError
** err
)
2710 domdoc
* This
= impl_from_IXMLDOMDocument3(iface
);
2711 LONG state
, err_code
= 0;
2715 TRACE("(%p)->(%p, %p)\n", This
, node
, err
);
2716 IXMLDOMDocument3_get_readyState(iface
, &state
);
2717 if (state
!= READYSTATE_COMPLETE
)
2720 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2727 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2731 if (!get_node_obj(node
)->node
|| get_node_obj(node
)->node
->doc
!= get_doc(This
))
2734 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2738 if (!is_wellformed(get_doc(This
)))
2740 ERR("doc not well-formed\n");
2742 *err
= create_parseError(E_XML_NOTWF
, NULL
, NULL
, NULL
, 0, 0, 0);
2746 /* DTD validation */
2747 if (get_doc(This
)->intSubset
|| get_doc(This
)->extSubset
)
2749 xmlValidCtxtPtr vctx
= xmlNewValidCtxt();
2750 vctx
->error
= validate_error
;
2751 vctx
->warning
= validate_warning
;
2754 if (!((node
== (IXMLDOMNode
*)iface
)?
2755 xmlValidateDocument(vctx
, get_doc(This
)) :
2756 xmlValidateElement(vctx
, get_doc(This
), get_node_obj(node
)->node
)))
2758 /* TODO: get a real error code here */
2759 TRACE("DTD validation failed\n");
2760 err_code
= E_XML_INVALID
;
2763 xmlFreeValidCtxt(vctx
);
2766 /* Schema validation */
2767 if (hr
== S_OK
&& This
->properties
->schemaCache
!= NULL
)
2770 hr
= SchemaCache_validate_tree(This
->properties
->schemaCache
, get_node_obj(node
)->node
);
2774 /* TODO: get a real error code here */
2777 TRACE("schema validation succeeded\n");
2781 ERR("schema validation failed\n");
2782 err_code
= E_XML_INVALID
;
2787 /* not really OK, just didn't find a schema for the ns */
2794 ERR("no DTD or schema found\n");
2795 err_code
= E_XML_NODTD
;
2800 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2805 static HRESULT WINAPI
domdoc_validate(
2806 IXMLDOMDocument3
* iface
,
2807 IXMLDOMParseError
** err
)
2809 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2810 TRACE("(%p)->(%p)\n", This
, err
);
2811 return IXMLDOMDocument3_validateNode(iface
, (IXMLDOMNode
*)iface
, err
);
2814 static HRESULT WINAPI
domdoc_setProperty(
2815 IXMLDOMDocument3
* iface
,
2819 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2821 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(p
), debugstr_variant(&value
));
2823 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
2829 V_VT(&varStr
) = VT_EMPTY
;
2830 if (V_VT(&value
) != VT_BSTR
)
2832 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2834 bstr
= V_BSTR(&varStr
);
2837 bstr
= V_BSTR(&value
);
2840 if (lstrcmpiW(bstr
, PropValueXPathW
) == 0)
2841 This
->properties
->XPath
= TRUE
;
2842 else if (lstrcmpiW(bstr
, PropValueXSLPatternW
) == 0)
2843 This
->properties
->XPath
= FALSE
;
2847 VariantClear(&varStr
);
2850 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
2852 xmlChar
*nsStr
= (xmlChar
*)This
->properties
->selectNsStr
;
2853 struct list
*pNsList
;
2858 V_VT(&varStr
) = VT_EMPTY
;
2859 if (V_VT(&value
) != VT_BSTR
)
2861 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2863 bstr
= V_BSTR(&varStr
);
2866 bstr
= V_BSTR(&value
);
2870 pNsList
= &(This
->properties
->selectNsList
);
2871 clear_selectNsList(pNsList
);
2873 nsStr
= xmlchar_from_wchar(bstr
);
2875 TRACE("property value: \"%s\"\n", debugstr_w(bstr
));
2877 This
->properties
->selectNsStr
= nsStr
;
2878 This
->properties
->selectNsStr_len
= xmlStrlen(nsStr
);
2881 xmlChar
*pTokBegin
, *pTokEnd
, *pTokInner
;
2882 select_ns_entry
* ns_entry
= NULL
;
2883 xmlXPathContextPtr ctx
;
2885 ctx
= xmlXPathNewContext(This
->node
.node
->doc
);
2888 /* skip leading spaces */
2889 while (*pTokBegin
== ' ' || *pTokBegin
== '\n' ||
2890 *pTokBegin
== '\t' || *pTokBegin
== '\r')
2893 for (; *pTokBegin
; pTokBegin
= pTokEnd
)
2896 memset(ns_entry
, 0, sizeof(select_ns_entry
));
2898 ns_entry
= heap_alloc_zero(sizeof(select_ns_entry
));
2900 while (*pTokBegin
== ' ')
2902 pTokEnd
= pTokBegin
;
2903 while (*pTokEnd
!= ' ' && *pTokEnd
!= 0)
2906 /* so it failed to advance which means we've got some trailing spaces */
2907 if (pTokEnd
== pTokBegin
) break;
2909 if (xmlStrncmp(pTokBegin
, (xmlChar
const*)"xmlns", 5) != 0)
2912 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2913 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2918 if (*pTokBegin
== '=')
2920 /*valid for XSLPattern?*/
2921 FIXME("Setting default xmlns not supported - skipping.\n");
2924 else if (*pTokBegin
== ':')
2926 ns_entry
->prefix
= ++pTokBegin
;
2927 for (pTokInner
= pTokBegin
; pTokInner
!= pTokEnd
&& *pTokInner
!= '='; ++pTokInner
)
2930 if (pTokInner
== pTokEnd
)
2933 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2934 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2938 ns_entry
->prefix_end
= *pTokInner
;
2942 if (pTokEnd
-pTokInner
> 1 &&
2943 ((*pTokInner
== '\'' && *(pTokEnd
-1) == '\'') ||
2944 (*pTokInner
== '"' && *(pTokEnd
-1) == '"')))
2946 ns_entry
->href
= ++pTokInner
;
2947 ns_entry
->href_end
= *(pTokEnd
-1);
2949 list_add_tail(pNsList
, &ns_entry
->entry
);
2950 /*let libxml figure out if they're valid from here ;)*/
2951 if (xmlXPathRegisterNs(ctx
, ns_entry
->prefix
, ns_entry
->href
) != 0)
2960 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2961 debugstr_w(bstr
), debugstr_an((const char*)pTokInner
, pTokEnd
-pTokInner
));
2962 list_add_tail(pNsList
, &ns_entry
->entry
);
2975 heap_free(ns_entry
);
2976 xmlXPathFreeContext(ctx
);
2979 VariantClear(&varStr
);
2982 else if (lstrcmpiW(p
, PropertyProhibitDTDW
) == 0 ||
2983 lstrcmpiW(p
, PropertyNewParserW
) == 0 ||
2984 lstrcmpiW(p
, PropertyResolveExternalsW
) == 0)
2987 FIXME("Ignoring property %s, value %d\n", debugstr_w(p
), V_BOOL(&value
));
2991 FIXME("Unknown property %s\n", debugstr_w(p
));
2995 static HRESULT WINAPI
domdoc_getProperty(
2996 IXMLDOMDocument3
* iface
,
3000 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3002 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
3005 return E_INVALIDARG
;
3007 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
3009 V_VT(var
) = VT_BSTR
;
3010 V_BSTR(var
) = This
->properties
->XPath
?
3011 SysAllocString(PropValueXPathW
) :
3012 SysAllocString(PropValueXSLPatternW
);
3013 return V_BSTR(var
) ? S_OK
: E_OUTOFMEMORY
;
3015 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3018 BSTR rebuiltStr
, cur
;
3019 const xmlChar
*nsStr
;
3020 struct list
*pNsList
;
3021 select_ns_entry
* pNsEntry
;
3023 V_VT(var
) = VT_BSTR
;
3024 nsStr
= This
->properties
->selectNsStr
;
3025 pNsList
= &This
->properties
->selectNsList
;
3026 lenA
= This
->properties
->selectNsStr_len
;
3027 lenW
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, NULL
, 0);
3028 rebuiltStr
= heap_alloc(lenW
*sizeof(WCHAR
));
3029 MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, rebuiltStr
, lenW
);
3031 /* this is fine because all of the chars that end tokens are ASCII*/
3032 LIST_FOR_EACH_ENTRY(pNsEntry
, pNsList
, select_ns_entry
, entry
)
3034 while (*cur
!= 0) ++cur
;
3035 if (pNsEntry
->prefix_end
)
3037 *cur
= pNsEntry
->prefix_end
;
3038 while (*cur
!= 0) ++cur
;
3041 if (pNsEntry
->href_end
)
3043 *cur
= pNsEntry
->href_end
;
3046 V_BSTR(var
) = SysAllocString(rebuiltStr
);
3047 heap_free(rebuiltStr
);
3051 FIXME("Unknown property %s\n", debugstr_w(p
));
3055 static HRESULT WINAPI
domdoc_importNode(
3056 IXMLDOMDocument3
* iface
,
3059 IXMLDOMNode
** clone
)
3061 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3062 FIXME("(%p)->(%p %d %p): stub\n", This
, node
, deep
, clone
);
3066 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl
=
3068 domdoc_QueryInterface
,
3071 domdoc_GetTypeInfoCount
,
3073 domdoc_GetIDsOfNames
,
3075 domdoc_get_nodeName
,
3076 domdoc_get_nodeValue
,
3077 domdoc_put_nodeValue
,
3078 domdoc_get_nodeType
,
3079 domdoc_get_parentNode
,
3080 domdoc_get_childNodes
,
3081 domdoc_get_firstChild
,
3082 domdoc_get_lastChild
,
3083 domdoc_get_previousSibling
,
3084 domdoc_get_nextSibling
,
3085 domdoc_get_attributes
,
3086 domdoc_insertBefore
,
3087 domdoc_replaceChild
,
3090 domdoc_hasChildNodes
,
3091 domdoc_get_ownerDocument
,
3093 domdoc_get_nodeTypeString
,
3096 domdoc_get_specified
,
3097 domdoc_get_definition
,
3098 domdoc_get_nodeTypedValue
,
3099 domdoc_put_nodeTypedValue
,
3100 domdoc_get_dataType
,
3101 domdoc_put_dataType
,
3103 domdoc_transformNode
,
3105 domdoc_selectSingleNode
,
3107 domdoc_get_namespaceURI
,
3109 domdoc_get_baseName
,
3110 domdoc_transformNodeToObject
,
3112 domdoc_get_implementation
,
3113 domdoc_get_documentElement
,
3114 domdoc_put_documentElement
,
3115 domdoc_createElement
,
3116 domdoc_createDocumentFragment
,
3117 domdoc_createTextNode
,
3118 domdoc_createComment
,
3119 domdoc_createCDATASection
,
3120 domdoc_createProcessingInstruction
,
3121 domdoc_createAttribute
,
3122 domdoc_createEntityReference
,
3123 domdoc_getElementsByTagName
,
3127 domdoc_get_readyState
,
3128 domdoc_get_parseError
,
3135 domdoc_get_validateOnParse
,
3136 domdoc_put_validateOnParse
,
3137 domdoc_get_resolveExternals
,
3138 domdoc_put_resolveExternals
,
3139 domdoc_get_preserveWhiteSpace
,
3140 domdoc_put_preserveWhiteSpace
,
3141 domdoc_put_onreadystatechange
,
3142 domdoc_put_onDataAvailable
,
3143 domdoc_put_onTransformNode
,
3144 domdoc_get_namespaces
,
3146 domdoc_putref_schemas
,
3150 domdoc_validateNode
,
3154 /* IConnectionPointContainer */
3155 static HRESULT WINAPI
ConnectionPointContainer_QueryInterface(IConnectionPointContainer
*iface
,
3156 REFIID riid
, void **ppv
)
3158 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3159 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3162 static ULONG WINAPI
ConnectionPointContainer_AddRef(IConnectionPointContainer
*iface
)
3164 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3165 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3168 static ULONG WINAPI
ConnectionPointContainer_Release(IConnectionPointContainer
*iface
)
3170 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3171 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3174 static HRESULT WINAPI
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer
*iface
,
3175 IEnumConnectionPoints
**ppEnum
)
3177 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3178 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3182 static HRESULT WINAPI
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer
*iface
,
3183 REFIID riid
, IConnectionPoint
**cp
)
3185 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3186 ConnectionPoint
*iter
;
3188 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), cp
);
3192 for(iter
= This
->cp_list
; iter
; iter
= iter
->next
)
3194 if (IsEqualGUID(iter
->iid
, riid
))
3195 *cp
= &iter
->IConnectionPoint_iface
;
3200 IConnectionPoint_AddRef(*cp
);
3204 FIXME("unsupported riid %s\n", debugstr_guid(riid
));
3205 return CONNECT_E_NOCONNECTION
;
3209 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl
=
3211 ConnectionPointContainer_QueryInterface
,
3212 ConnectionPointContainer_AddRef
,
3213 ConnectionPointContainer_Release
,
3214 ConnectionPointContainer_EnumConnectionPoints
,
3215 ConnectionPointContainer_FindConnectionPoint
3218 /* IConnectionPoint */
3219 static HRESULT WINAPI
ConnectionPoint_QueryInterface(IConnectionPoint
*iface
,
3220 REFIID riid
, void **ppv
)
3222 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3224 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
3228 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
3229 IsEqualGUID(&IID_IConnectionPoint
, riid
))
3236 IConnectionPoint_AddRef(iface
);
3240 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
3241 return E_NOINTERFACE
;
3244 static ULONG WINAPI
ConnectionPoint_AddRef(IConnectionPoint
*iface
)
3246 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3247 return IConnectionPointContainer_AddRef(This
->container
);
3250 static ULONG WINAPI
ConnectionPoint_Release(IConnectionPoint
*iface
)
3252 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3253 return IConnectionPointContainer_Release(This
->container
);
3256 static HRESULT WINAPI
ConnectionPoint_GetConnectionInterface(IConnectionPoint
*iface
, IID
*iid
)
3258 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3260 TRACE("(%p)->(%p)\n", This
, iid
);
3262 if (!iid
) return E_POINTER
;
3268 static HRESULT WINAPI
ConnectionPoint_GetConnectionPointContainer(IConnectionPoint
*iface
,
3269 IConnectionPointContainer
**container
)
3271 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3273 TRACE("(%p)->(%p)\n", This
, container
);
3275 if (!container
) return E_POINTER
;
3277 *container
= This
->container
;
3278 IConnectionPointContainer_AddRef(*container
);
3282 static HRESULT WINAPI
ConnectionPoint_Advise(IConnectionPoint
*iface
, IUnknown
*unk_sink
,
3285 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3290 TRACE("(%p)->(%p %p)\n", This
, unk_sink
, cookie
);
3292 hr
= IUnknown_QueryInterface(unk_sink
, This
->iid
, (void**)&sink
);
3293 if(FAILED(hr
) && !IsEqualGUID(&IID_IPropertyNotifySink
, This
->iid
))
3294 hr
= IUnknown_QueryInterface(unk_sink
, &IID_IDispatch
, (void**)&sink
);
3296 return CONNECT_E_CANNOTCONNECT
;
3300 for (i
= 0; i
< This
->sinks_size
; i
++)
3301 if (!This
->sinks
[i
].unk
)
3304 if (i
== This
->sinks_size
)
3305 This
->sinks
= heap_realloc(This
->sinks
,(++This
->sinks_size
)*sizeof(*This
->sinks
));
3309 This
->sinks
= heap_alloc(sizeof(*This
->sinks
));
3310 This
->sinks_size
= 1;
3314 This
->sinks
[i
].unk
= sink
;
3321 static HRESULT WINAPI
ConnectionPoint_Unadvise(IConnectionPoint
*iface
, DWORD cookie
)
3323 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3325 TRACE("(%p)->(%d)\n", This
, cookie
);
3327 if (cookie
== 0 || cookie
> This
->sinks_size
|| !This
->sinks
[cookie
-1].unk
)
3328 return CONNECT_E_NOCONNECTION
;
3330 IUnknown_Release(This
->sinks
[cookie
-1].unk
);
3331 This
->sinks
[cookie
-1].unk
= NULL
;
3336 static HRESULT WINAPI
ConnectionPoint_EnumConnections(IConnectionPoint
*iface
,
3337 IEnumConnections
**ppEnum
)
3339 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3340 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3344 static const IConnectionPointVtbl ConnectionPointVtbl
=
3346 ConnectionPoint_QueryInterface
,
3347 ConnectionPoint_AddRef
,
3348 ConnectionPoint_Release
,
3349 ConnectionPoint_GetConnectionInterface
,
3350 ConnectionPoint_GetConnectionPointContainer
,
3351 ConnectionPoint_Advise
,
3352 ConnectionPoint_Unadvise
,
3353 ConnectionPoint_EnumConnections
3356 static void ConnectionPoint_Init(ConnectionPoint
*cp
, struct domdoc
*doc
, REFIID riid
)
3358 cp
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointVtbl
;
3364 cp
->next
= doc
->cp_list
;
3367 cp
->container
= &doc
->IConnectionPointContainer_iface
;
3370 /* domdoc implementation of IObjectWithSite */
3371 static HRESULT WINAPI
3372 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
3374 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3375 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObject
);
3378 static ULONG WINAPI
domdoc_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
3380 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3381 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3384 static ULONG WINAPI
domdoc_ObjectWithSite_Release( IObjectWithSite
* iface
)
3386 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3387 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3390 static HRESULT WINAPI
domdoc_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
3392 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3394 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
3399 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
3402 static HRESULT WINAPI
domdoc_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
3404 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3406 TRACE("(%p)->(%p)\n", iface
, punk
);
3412 IUnknown_Release( This
->site
);
3419 IUnknown_AddRef( punk
);
3422 IUnknown_Release( This
->site
);
3429 static const IObjectWithSiteVtbl domdocObjectSite
=
3431 domdoc_ObjectWithSite_QueryInterface
,
3432 domdoc_ObjectWithSite_AddRef
,
3433 domdoc_ObjectWithSite_Release
,
3434 domdoc_ObjectWithSite_SetSite
,
3435 domdoc_ObjectWithSite_GetSite
3438 static HRESULT WINAPI
domdoc_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
3440 domdoc
*This
= impl_from_IObjectSafety(iface
);
3441 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3444 static ULONG WINAPI
domdoc_Safety_AddRef(IObjectSafety
*iface
)
3446 domdoc
*This
= impl_from_IObjectSafety(iface
);
3447 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3450 static ULONG WINAPI
domdoc_Safety_Release(IObjectSafety
*iface
)
3452 domdoc
*This
= impl_from_IObjectSafety(iface
);
3453 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3456 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3458 static HRESULT WINAPI
domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3459 DWORD
*supported
, DWORD
*enabled
)
3461 domdoc
*This
= impl_from_IObjectSafety(iface
);
3463 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
3465 if(!supported
|| !enabled
) return E_POINTER
;
3467 *supported
= SAFETY_SUPPORTED_OPTIONS
;
3468 *enabled
= This
->safeopt
;
3473 static HRESULT WINAPI
domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3474 DWORD mask
, DWORD enabled
)
3476 domdoc
*This
= impl_from_IObjectSafety(iface
);
3477 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
3479 if ((mask
& ~SAFETY_SUPPORTED_OPTIONS
) != 0)
3482 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
3487 #undef SAFETY_SUPPORTED_OPTIONS
3489 static const IObjectSafetyVtbl domdocObjectSafetyVtbl
= {
3490 domdoc_Safety_QueryInterface
,
3491 domdoc_Safety_AddRef
,
3492 domdoc_Safety_Release
,
3493 domdoc_Safety_GetInterfaceSafetyOptions
,
3494 domdoc_Safety_SetInterfaceSafetyOptions
3497 static const tid_t domdoc_iface_tids
[] = {
3498 IXMLDOMDocument3_tid
,
3502 static dispex_static_data_t domdoc_dispex
= {
3504 IXMLDOMDocument3_tid
,
3509 HRESULT
get_domdoc_from_xmldoc(xmlDocPtr xmldoc
, IXMLDOMDocument3
**document
)
3513 doc
= heap_alloc( sizeof (*doc
) );
3515 return E_OUTOFMEMORY
;
3517 doc
->IXMLDOMDocument3_iface
.lpVtbl
= &XMLDOMDocument3Vtbl
;
3518 doc
->IPersistStreamInit_iface
.lpVtbl
= &xmldoc_IPersistStreamInit_VTable
;
3519 doc
->IObjectWithSite_iface
.lpVtbl
= &domdocObjectSite
;
3520 doc
->IObjectSafety_iface
.lpVtbl
= &domdocObjectSafetyVtbl
;
3521 doc
->IConnectionPointContainer_iface
.lpVtbl
= &ConnectionPointContainerVtbl
;
3523 doc
->async
= VARIANT_TRUE
;
3524 doc
->validating
= 0;
3526 doc
->properties
= properties_from_xmlDocPtr(xmldoc
);
3531 doc
->cp_list
= NULL
;
3532 doc
->namespaces
= NULL
;
3533 memset(doc
->events
, 0, sizeof(doc
->events
));
3535 /* events connection points */
3536 ConnectionPoint_Init(&doc
->cp_dispatch
, doc
, &IID_IDispatch
);
3537 ConnectionPoint_Init(&doc
->cp_propnotif
, doc
, &IID_IPropertyNotifySink
);
3538 ConnectionPoint_Init(&doc
->cp_domdocevents
, doc
, &DIID_XMLDOMDocumentEvents
);
3540 init_xmlnode(&doc
->node
, (xmlNodePtr
)xmldoc
, (IXMLDOMNode
*)&doc
->IXMLDOMDocument3_iface
,
3543 *document
= &doc
->IXMLDOMDocument3_iface
;
3545 TRACE("returning iface %p\n", *document
);
3549 HRESULT
DOMDocument_create(MSXML_VERSION version
, IUnknown
*pUnkOuter
, void **ppObj
)
3554 TRACE("(%d, %p, %p)\n", version
, pUnkOuter
, ppObj
);
3556 xmldoc
= xmlNewDoc(NULL
);
3558 return E_OUTOFMEMORY
;
3560 xmldoc_init(xmldoc
, version
);
3562 hr
= get_domdoc_from_xmldoc(xmldoc
, (IXMLDOMDocument3
**)ppObj
);
3565 free_properties(properties_from_xmlDocPtr(xmldoc
));
3566 heap_free(xmldoc
->_private
);
3574 IUnknown
* create_domdoc( xmlNodePtr document
)
3579 TRACE("(%p)\n", document
);
3581 hr
= get_domdoc_from_xmldoc((xmlDocPtr
)document
, (IXMLDOMDocument3
**)&pObj
);
3590 HRESULT
DOMDocument_create(MSXML_VERSION version
, IUnknown
*pUnkOuter
, void **ppObj
)
3592 MESSAGE("This program tried to use a DOMDocument object, but\n"
3593 "libxml2 support was not present at compile time.\n");