2 * DOM Document implementation
4 * Copyright 2005 Mike McCormack
5 * Copyright 2010-2011 Adam Martinson for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 # include <libxml/xpathInternals.h>
28 # include <libxml/xmlsave.h>
29 # include <libxml/SAX2.h>
30 # include <libxml/parserInternals.h>
36 #include <wine/list.h>
40 /* not defined in older versions */
41 #define XML_SAVE_FORMAT 1
42 #define XML_SAVE_NO_DECL 2
43 #define XML_SAVE_NO_EMPTY 4
44 #define XML_SAVE_NO_XHTML 8
45 #define XML_SAVE_XHTML 16
46 #define XML_SAVE_AS_XML 32
47 #define XML_SAVE_AS_HTML 64
49 static const WCHAR PropertySelectionLanguageW
[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
50 static const WCHAR PropertySelectionNamespacesW
[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
51 static const WCHAR PropertyProhibitDTDW
[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
52 static const WCHAR PropertyNewParserW
[] = {'N','e','w','P','a','r','s','e','r',0};
53 static const WCHAR PropValueXPathW
[] = {'X','P','a','t','h',0};
54 static const WCHAR PropValueXSLPatternW
[] = {'X','S','L','P','a','t','t','e','r','n',0};
55 static const WCHAR PropertyResolveExternalsW
[] = {'R','e','s','o','l','v','e','E','x','t','e','r','n','a','l','s',0};
57 /* Anything that passes the test_get_ownerDocument()
58 * tests can go here (data shared between all instances).
59 * We need to preserve this when reloading a document,
60 * and also need access to it from the libxml backend. */
62 MSXML_VERSION version
;
63 VARIANT_BOOL preserving
;
64 IXMLDOMSchemaCollection2
* schemaCache
;
65 struct list selectNsList
;
66 xmlChar
const* selectNsStr
;
71 typedef struct ConnectionPoint ConnectionPoint
;
72 typedef struct domdoc domdoc
;
74 struct ConnectionPoint
76 IConnectionPoint IConnectionPoint_iface
;
79 ConnectionPoint
*next
;
80 IConnectionPointContainer
*container
;
87 IPropertyNotifySink
*propnotif
;
93 EVENTID_READYSTATECHANGE
= 0,
94 EVENTID_DATAAVAILABLE
,
95 EVENTID_TRANSFORMNODE
,
102 IXMLDOMDocument3 IXMLDOMDocument3_iface
;
103 IPersistStreamInit IPersistStreamInit_iface
;
104 IObjectWithSite IObjectWithSite_iface
;
105 IObjectSafety IObjectSafety_iface
;
106 IConnectionPointContainer IConnectionPointContainer_iface
;
109 VARIANT_BOOL validating
;
110 VARIANT_BOOL resolving
;
111 domdoc_properties
* properties
;
121 /* connection list */
122 ConnectionPoint
*cp_list
;
123 ConnectionPoint cp_domdocevents
;
124 ConnectionPoint cp_propnotif
;
125 ConnectionPoint cp_dispatch
;
128 IDispatch
*events
[EVENTID_LAST
];
130 IXMLDOMSchemaCollection2
*namespaces
;
133 static HRESULT
set_doc_event(domdoc
*doc
, eventid_t eid
, const VARIANT
*v
)
141 IUnknown_QueryInterface(V_UNKNOWN(v
), &IID_IDispatch
, (void**)&disp
);
146 disp
= V_DISPATCH(v
);
147 if (disp
) IDispatch_AddRef(disp
);
150 return DISP_E_TYPEMISMATCH
;
153 if (doc
->events
[eid
]) IDispatch_Release(doc
->events
[eid
]);
154 doc
->events
[eid
] = disp
;
159 static inline ConnectionPoint
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
161 return CONTAINING_RECORD(iface
, ConnectionPoint
, IConnectionPoint_iface
);
165 In native windows, the whole lifetime management of XMLDOMNodes is
166 managed automatically using reference counts. Wine emulates that by
167 maintaining a reference count to the document that is increased for
168 each IXMLDOMNode pointer passed out for this document. If all these
169 pointers are gone, the document is unreachable and gets freed, that
170 is, all nodes in the tree of the document get freed.
172 You are able to create nodes that are associated to a document (in
173 fact, in msxml's XMLDOM model, all nodes are associated to a document),
174 but not in the tree of that document, for example using the createFoo
175 functions from IXMLDOMDocument. These nodes do not get cleaned up
176 by libxml, so we have to do it ourselves.
178 To catch these nodes, a list of "orphan nodes" is introduced.
179 It contains pointers to all roots of node trees that are
180 associated with the document without being part of the document
181 tree. All nodes with parent==NULL (except for the document root nodes)
182 should be in the orphan node list of their document. All orphan nodes
183 get freed together with the document itself.
186 typedef struct _xmldoc_priv
{
189 domdoc_properties
* properties
;
192 typedef struct _orphan_entry
{
197 typedef struct _select_ns_entry
{
199 xmlChar
const* prefix
;
205 static inline xmldoc_priv
* priv_from_xmlDocPtr(const xmlDocPtr doc
)
207 return doc
->_private
;
210 static inline domdoc_properties
* properties_from_xmlDocPtr(xmlDocPtr doc
)
212 return priv_from_xmlDocPtr(doc
)->properties
;
215 BOOL
is_xpathmode(const xmlDocPtr doc
)
217 return properties_from_xmlDocPtr(doc
)->XPath
;
220 void set_xpathmode(xmlDocPtr doc
, BOOL xpath
)
222 properties_from_xmlDocPtr(doc
)->XPath
= xpath
;
225 int registerNamespaces(xmlXPathContextPtr ctxt
)
228 const select_ns_entry
* ns
= NULL
;
229 const struct list
* pNsList
= &properties_from_xmlDocPtr(ctxt
->doc
)->selectNsList
;
231 TRACE("(%p)\n", ctxt
);
233 LIST_FOR_EACH_ENTRY( ns
, pNsList
, select_ns_entry
, entry
)
235 xmlXPathRegisterNs(ctxt
, ns
->prefix
, ns
->href
);
242 static inline void clear_selectNsList(struct list
* pNsList
)
244 select_ns_entry
*ns
, *ns2
;
245 LIST_FOR_EACH_ENTRY_SAFE( ns
, ns2
, pNsList
, select_ns_entry
, entry
)
252 static xmldoc_priv
* create_priv(void)
255 priv
= heap_alloc( sizeof (*priv
) );
260 list_init( &priv
->orphans
);
261 priv
->properties
= NULL
;
267 static domdoc_properties
*create_properties(MSXML_VERSION version
)
269 domdoc_properties
*properties
= heap_alloc(sizeof(domdoc_properties
));
271 list_init(&properties
->selectNsList
);
272 properties
->preserving
= VARIANT_FALSE
;
273 properties
->schemaCache
= NULL
;
274 properties
->selectNsStr
= heap_alloc_zero(sizeof(xmlChar
));
275 properties
->selectNsStr_len
= 0;
277 /* properties that are dependent on object versions */
278 properties
->version
= version
;
279 properties
->XPath
= (version
== MSXML4
|| version
== MSXML6
);
284 static domdoc_properties
* copy_properties(domdoc_properties
const* properties
)
286 domdoc_properties
* pcopy
= heap_alloc(sizeof(domdoc_properties
));
287 select_ns_entry
const* ns
= NULL
;
288 select_ns_entry
* new_ns
= NULL
;
289 int len
= (properties
->selectNsStr_len
+1)*sizeof(xmlChar
);
294 pcopy
->version
= properties
->version
;
295 pcopy
->preserving
= properties
->preserving
;
296 pcopy
->schemaCache
= properties
->schemaCache
;
297 if (pcopy
->schemaCache
)
298 IXMLDOMSchemaCollection2_AddRef(pcopy
->schemaCache
);
299 pcopy
->XPath
= properties
->XPath
;
300 pcopy
->selectNsStr_len
= properties
->selectNsStr_len
;
301 list_init( &pcopy
->selectNsList
);
302 pcopy
->selectNsStr
= heap_alloc(len
);
303 memcpy((xmlChar
*)pcopy
->selectNsStr
, properties
->selectNsStr
, len
);
304 offset
= pcopy
->selectNsStr
- properties
->selectNsStr
;
306 LIST_FOR_EACH_ENTRY( ns
, (&properties
->selectNsList
), select_ns_entry
, entry
)
308 new_ns
= heap_alloc(sizeof(select_ns_entry
));
309 memcpy(new_ns
, ns
, sizeof(select_ns_entry
));
310 new_ns
->href
+= offset
;
311 new_ns
->prefix
+= offset
;
312 list_add_tail(&pcopy
->selectNsList
, &new_ns
->entry
);
320 static void free_properties(domdoc_properties
* properties
)
324 if (properties
->schemaCache
)
325 IXMLDOMSchemaCollection2_Release(properties
->schemaCache
);
326 clear_selectNsList(&properties
->selectNsList
);
327 heap_free((xmlChar
*)properties
->selectNsStr
);
328 heap_free(properties
);
332 static void release_namespaces(domdoc
*This
)
334 if (This
->namespaces
)
336 IXMLDOMSchemaCollection2_Release(This
->namespaces
);
337 This
->namespaces
= NULL
;
341 /* links a "<?xml" node as a first child */
342 void xmldoc_link_xmldecl(xmlDocPtr doc
, xmlNodePtr node
)
345 if (doc
->standalone
!= -1) xmlAddPrevSibling( doc
->children
, node
);
348 /* unlinks a first "<?xml" child if it was created */
349 xmlNodePtr
xmldoc_unlink_xmldecl(xmlDocPtr doc
)
351 static const xmlChar xmlA
[] = "xml";
352 xmlNodePtr node
, first_child
;
356 /* xml declaration node could be created automatically after parsing or added
358 first_child
= doc
->children
;
359 if (first_child
&& first_child
->type
== XML_PI_NODE
&& xmlStrEqual(first_child
->name
, xmlA
))
362 xmlUnlinkNode( node
);
370 BOOL
is_preserving_whitespace(xmlNodePtr node
)
372 domdoc_properties
* properties
= NULL
;
373 /* during parsing the xmlDoc._private stuff is not there */
374 if (priv_from_xmlDocPtr(node
->doc
))
375 properties
= properties_from_xmlDocPtr(node
->doc
);
376 return ((properties
&& properties
->preserving
== VARIANT_TRUE
) ||
377 xmlNodeGetSpacePreserve(node
) == 1);
380 static inline BOOL
strn_isspace(xmlChar
const* str
, int len
)
382 for (; str
&& len
> 0 && *str
; ++str
, --len
)
389 static void sax_characters(void *ctx
, const xmlChar
*ch
, int len
)
391 xmlParserCtxtPtr ctxt
;
394 ctxt
= (xmlParserCtxtPtr
) ctx
;
395 This
= (const domdoc
*) ctxt
->_private
;
399 xmlChar cur
= *(ctxt
->input
->cur
);
401 /* Characters are reported with multiple calls, for example each charref is reported with a separate
402 call and then parser appends it to a single text node or creates a new node if not created.
403 It's not possible to tell if it's ignorable data or not just looking at data itself cause it could be
404 space chars that separate charrefs or similar case. We only need to skip leading and trailing spaces,
405 or whole node if it has nothing but space chars, so to detect leading space node->last is checked that
406 contains text node pointer if already created, trailing spaces are detected directly looking at parser input
407 for next '<' opening bracket - similar logic is used by libxml2 itself. Basically 'cur' == '<' means the last
408 chunk of char data, in case it's not the last chunk we check for previously added node type and if it's not
409 a text node it's safe to ignore.
411 Note that during domdoc_loadXML() the xmlDocPtr->_private data is not available. */
413 if (!This
->properties
->preserving
&&
414 !is_preserving_whitespace(ctxt
->node
) &&
415 strn_isspace(ch
, len
) &&
416 (!ctxt
->node
->last
||
417 ((ctxt
->node
->last
&& (cur
== '<' || ctxt
->node
->last
->type
!= XML_TEXT_NODE
))
422 xmlSAX2Characters(ctxt
, ch
, len
);
425 static void LIBXML2_LOG_CALLBACK
sax_error(void* ctx
, char const* msg
, ...)
429 LIBXML2_CALLBACK_ERR(doparse
, msg
, ap
);
433 static void LIBXML2_LOG_CALLBACK
sax_warning(void* ctx
, char const* msg
, ...)
437 LIBXML2_CALLBACK_WARN(doparse
, msg
, ap
);
441 static void sax_serror(void* ctx
, xmlErrorPtr err
)
443 LIBXML2_CALLBACK_SERROR(doparse
, err
);
446 static xmlDocPtr
doparse(domdoc
* This
, char const* ptr
, int len
, xmlCharEncoding encoding
)
448 xmlDocPtr doc
= NULL
;
449 xmlParserCtxtPtr pctx
;
450 static xmlSAXHandler sax_handler
= {
451 xmlSAX2InternalSubset
, /* internalSubset */
452 xmlSAX2IsStandalone
, /* isStandalone */
453 xmlSAX2HasInternalSubset
, /* hasInternalSubset */
454 xmlSAX2HasExternalSubset
, /* hasExternalSubset */
455 xmlSAX2ResolveEntity
, /* resolveEntity */
456 xmlSAX2GetEntity
, /* getEntity */
457 xmlSAX2EntityDecl
, /* entityDecl */
458 xmlSAX2NotationDecl
, /* notationDecl */
459 xmlSAX2AttributeDecl
, /* attributeDecl */
460 xmlSAX2ElementDecl
, /* elementDecl */
461 xmlSAX2UnparsedEntityDecl
, /* unparsedEntityDecl */
462 xmlSAX2SetDocumentLocator
, /* setDocumentLocator */
463 xmlSAX2StartDocument
, /* startDocument */
464 xmlSAX2EndDocument
, /* endDocument */
465 xmlSAX2StartElement
, /* startElement */
466 xmlSAX2EndElement
, /* endElement */
467 xmlSAX2Reference
, /* reference */
468 sax_characters
, /* characters */
469 sax_characters
, /* ignorableWhitespace */
470 xmlSAX2ProcessingInstruction
, /* processingInstruction */
471 xmlSAX2Comment
, /* comment */
472 sax_warning
, /* warning */
473 sax_error
, /* error */
474 sax_error
, /* fatalError */
475 xmlSAX2GetParameterEntity
, /* getParameterEntity */
476 xmlSAX2CDataBlock
, /* cdataBlock */
477 xmlSAX2ExternalSubset
, /* externalSubset */
480 xmlSAX2StartElementNs
, /* startElementNs */
481 xmlSAX2EndElementNs
, /* endElementNs */
482 sax_serror
/* serror */
485 pctx
= xmlCreateMemoryParserCtxt(ptr
, len
);
488 ERR("Failed to create parser context\n");
492 if (pctx
->sax
) xmlFree(pctx
->sax
);
493 pctx
->sax
= &sax_handler
;
494 pctx
->_private
= This
;
497 if (encoding
!= XML_CHAR_ENCODING_NONE
)
498 xmlSwitchEncoding(pctx
, encoding
);
500 xmlParseDocument(pctx
);
502 if (pctx
->wellFormed
)
508 xmlFreeDoc(pctx
->myDoc
);
512 xmlFreeParserCtxt(pctx
);
514 /* TODO: put this in one of the SAX callbacks */
515 /* create first child as a <?xml...?> */
516 if (doc
&& doc
->standalone
!= -1)
520 xmlChar
*xmlbuff
= (xmlChar
*)buff
;
522 node
= xmlNewDocPI( doc
, (xmlChar
*)"xml", NULL
);
524 /* version attribute can't be omitted */
525 sprintf(buff
, "version=\"%s\"", doc
->version
? (char*)doc
->version
: "1.0");
526 xmlNodeAddContent( node
, xmlbuff
);
530 sprintf(buff
, " encoding=\"%s\"", doc
->encoding
);
531 xmlNodeAddContent( node
, xmlbuff
);
534 if (doc
->standalone
!= -2)
536 sprintf(buff
, " standalone=\"%s\"", doc
->standalone
== 0 ? "no" : "yes");
537 xmlNodeAddContent( node
, xmlbuff
);
540 xmldoc_link_xmldecl( doc
, node
);
546 void xmldoc_init(xmlDocPtr doc
, MSXML_VERSION version
)
548 doc
->_private
= create_priv();
549 priv_from_xmlDocPtr(doc
)->properties
= create_properties(version
);
552 LONG
xmldoc_add_refs(xmlDocPtr doc
, LONG refs
)
554 LONG ref
= InterlockedExchangeAdd(&priv_from_xmlDocPtr(doc
)->refs
, refs
) + refs
;
555 TRACE("(%p)->(%d)\n", doc
, ref
);
559 LONG
xmldoc_add_ref(xmlDocPtr doc
)
561 return xmldoc_add_refs(doc
, 1);
564 LONG
xmldoc_release_refs(xmlDocPtr doc
, LONG refs
)
566 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
567 LONG ref
= InterlockedExchangeAdd(&priv
->refs
, -refs
) - refs
;
568 TRACE("(%p)->(%d)\n", doc
, ref
);
571 WARN("negative refcount, expect troubles\n");
575 orphan_entry
*orphan
, *orphan2
;
576 TRACE("freeing docptr %p\n", doc
);
578 LIST_FOR_EACH_ENTRY_SAFE( orphan
, orphan2
, &priv
->orphans
, orphan_entry
, entry
)
580 xmlFreeNode( orphan
->node
);
583 free_properties(priv
->properties
);
584 heap_free(doc
->_private
);
592 LONG
xmldoc_release(xmlDocPtr doc
)
594 return xmldoc_release_refs(doc
, 1);
597 HRESULT
xmldoc_add_orphan(xmlDocPtr doc
, xmlNodePtr node
)
599 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
602 entry
= heap_alloc( sizeof (*entry
) );
604 return E_OUTOFMEMORY
;
607 list_add_head( &priv
->orphans
, &entry
->entry
);
611 HRESULT
xmldoc_remove_orphan(xmlDocPtr doc
, xmlNodePtr node
)
613 xmldoc_priv
*priv
= priv_from_xmlDocPtr(doc
);
614 orphan_entry
*entry
, *entry2
;
616 LIST_FOR_EACH_ENTRY_SAFE( entry
, entry2
, &priv
->orphans
, orphan_entry
, entry
)
618 if( entry
->node
== node
)
620 list_remove( &entry
->entry
);
629 static inline xmlDocPtr
get_doc( domdoc
*This
)
631 return This
->node
.node
->doc
;
634 static HRESULT
attach_xmldoc(domdoc
*This
, xmlDocPtr xml
)
636 release_namespaces(This
);
640 priv_from_xmlDocPtr(get_doc(This
))->properties
= NULL
;
641 if (xmldoc_release(get_doc(This
)) != 0)
642 priv_from_xmlDocPtr(get_doc(This
))->properties
=
643 copy_properties(This
->properties
);
646 This
->node
.node
= (xmlNodePtr
) xml
;
650 xmldoc_add_ref(get_doc(This
));
651 priv_from_xmlDocPtr(get_doc(This
))->properties
= This
->properties
;
657 static inline domdoc
*impl_from_IXMLDOMDocument3( IXMLDOMDocument3
*iface
)
659 return CONTAINING_RECORD(iface
, domdoc
, IXMLDOMDocument3_iface
);
662 static inline domdoc
*impl_from_IPersistStreamInit(IPersistStreamInit
*iface
)
664 return CONTAINING_RECORD(iface
, domdoc
, IPersistStreamInit_iface
);
667 static inline domdoc
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
669 return CONTAINING_RECORD(iface
, domdoc
, IObjectWithSite_iface
);
672 static inline domdoc
*impl_from_IObjectSafety(IObjectSafety
*iface
)
674 return CONTAINING_RECORD(iface
, domdoc
, IObjectSafety_iface
);
677 static inline domdoc
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
679 return CONTAINING_RECORD(iface
, domdoc
, IConnectionPointContainer_iface
);
682 /************************************************************************
683 * domdoc implementation of IPersistStream.
685 static HRESULT WINAPI
PersistStreamInit_QueryInterface(
686 IPersistStreamInit
*iface
, REFIID riid
, void **ppvObj
)
688 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
689 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObj
);
692 static ULONG WINAPI
PersistStreamInit_AddRef(
693 IPersistStreamInit
*iface
)
695 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
696 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
699 static ULONG WINAPI
PersistStreamInit_Release(
700 IPersistStreamInit
*iface
)
702 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
703 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
706 static HRESULT WINAPI
PersistStreamInit_GetClassID(
707 IPersistStreamInit
*iface
, CLSID
*classid
)
709 domdoc
* This
= impl_from_IPersistStreamInit(iface
);
710 TRACE("(%p)->(%p)\n", This
, classid
);
715 *classid
= *DOMDocument_version(This
->properties
->version
);
720 static HRESULT WINAPI
PersistStreamInit_IsDirty(
721 IPersistStreamInit
*iface
)
723 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
724 FIXME("(%p): stub!\n", This
);
728 static HRESULT
domdoc_load_from_stream(domdoc
*doc
, ISequentialStream
*stream
)
730 DWORD read
, written
, len
;
731 xmlDocPtr xmldoc
= NULL
;
739 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &hstream
);
745 ISequentialStream_Read(stream
, buf
, sizeof(buf
), &read
);
746 hr
= IStream_Write(hstream
, buf
, read
, &written
);
747 } while(SUCCEEDED(hr
) && written
!= 0 && read
!= 0);
751 ERR("failed to copy stream 0x%08x\n", hr
);
752 IStream_Release(hstream
);
756 hr
= GetHGlobalFromStream(hstream
, &hglobal
);
760 len
= GlobalSize(hglobal
);
761 ptr
= GlobalLock(hglobal
);
763 xmldoc
= doparse(doc
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
764 GlobalUnlock(hglobal
);
768 ERR("Failed to parse xml\n");
772 xmldoc
->_private
= create_priv();
774 return attach_xmldoc(doc
, xmldoc
);
777 static HRESULT WINAPI
PersistStreamInit_Load(IPersistStreamInit
*iface
, IStream
*stream
)
779 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
781 TRACE("(%p)->(%p)\n", This
, stream
);
786 return domdoc_load_from_stream(This
, (ISequentialStream
*)stream
);
789 static HRESULT WINAPI
PersistStreamInit_Save(
790 IPersistStreamInit
*iface
, IStream
*stream
, BOOL clr_dirty
)
792 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
796 TRACE("(%p)->(%p %d)\n", This
, stream
, clr_dirty
);
798 hr
= IXMLDOMDocument3_get_xml(&This
->IXMLDOMDocument3_iface
, &xmlString
);
801 DWORD len
= SysStringLen(xmlString
) * sizeof(WCHAR
);
803 hr
= IStream_Write( stream
, xmlString
, len
, NULL
);
804 SysFreeString(xmlString
);
807 TRACE("ret 0x%08x\n", hr
);
812 static HRESULT WINAPI
PersistStreamInit_GetSizeMax(
813 IPersistStreamInit
*iface
, ULARGE_INTEGER
*pcbSize
)
815 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
816 TRACE("(%p)->(%p)\n", This
, pcbSize
);
820 static HRESULT WINAPI
PersistStreamInit_InitNew(
821 IPersistStreamInit
*iface
)
823 domdoc
*This
= impl_from_IPersistStreamInit(iface
);
824 TRACE("(%p)\n", This
);
828 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable
=
830 PersistStreamInit_QueryInterface
,
831 PersistStreamInit_AddRef
,
832 PersistStreamInit_Release
,
833 PersistStreamInit_GetClassID
,
834 PersistStreamInit_IsDirty
,
835 PersistStreamInit_Load
,
836 PersistStreamInit_Save
,
837 PersistStreamInit_GetSizeMax
,
838 PersistStreamInit_InitNew
841 /* IXMLDOMDocument3 interface */
843 static const tid_t domdoc_se_tids
[] = {
846 IXMLDOMDocument2_tid
,
847 IXMLDOMDocument3_tid
,
851 static HRESULT WINAPI
domdoc_QueryInterface( IXMLDOMDocument3
*iface
, REFIID riid
, void** ppvObject
)
853 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
855 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( riid
), ppvObject
);
859 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
860 IsEqualGUID( riid
, &IID_IDispatch
) ||
861 IsEqualGUID( riid
, &IID_IXMLDOMNode
) ||
862 IsEqualGUID( riid
, &IID_IXMLDOMDocument
) ||
863 IsEqualGUID( riid
, &IID_IXMLDOMDocument2
)||
864 IsEqualGUID( riid
, &IID_IXMLDOMDocument3
))
868 else if (IsEqualGUID(&IID_IPersistStream
, riid
) ||
869 IsEqualGUID(&IID_IPersistStreamInit
, riid
))
871 *ppvObject
= &This
->IPersistStreamInit_iface
;
873 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
875 *ppvObject
= &This
->IObjectWithSite_iface
;
877 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
879 *ppvObject
= &This
->IObjectSafety_iface
;
881 else if( IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
883 return node_create_supporterrorinfo(domdoc_se_tids
, ppvObject
);
885 else if(node_query_interface(&This
->node
, riid
, ppvObject
))
887 return *ppvObject
? S_OK
: E_NOINTERFACE
;
889 else if (IsEqualGUID( riid
, &IID_IConnectionPointContainer
))
891 *ppvObject
= &This
->IConnectionPointContainer_iface
;
895 TRACE("interface %s not implemented\n", debugstr_guid(riid
));
896 return E_NOINTERFACE
;
899 IUnknown_AddRef((IUnknown
*)*ppvObject
);
904 static ULONG WINAPI
domdoc_AddRef( IXMLDOMDocument3
*iface
)
906 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
907 ULONG ref
= InterlockedIncrement( &This
->ref
);
908 TRACE("(%p)->(%d)\n", This
, ref
);
912 static ULONG WINAPI
domdoc_Release( IXMLDOMDocument3
*iface
)
914 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
915 LONG ref
= InterlockedDecrement( &This
->ref
);
917 TRACE("(%p)->(%d)\n", This
, ref
);
924 detach_bsc(This
->bsc
);
927 IUnknown_Release( This
->site
);
928 destroy_xmlnode(&This
->node
);
930 for (eid
= 0; eid
< EVENTID_LAST
; eid
++)
931 if (This
->events
[eid
]) IDispatch_Release(This
->events
[eid
]);
933 release_namespaces(This
);
940 static HRESULT WINAPI
domdoc_GetTypeInfoCount( IXMLDOMDocument3
*iface
, UINT
* pctinfo
)
942 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
943 return IDispatchEx_GetTypeInfoCount(&This
->node
.dispex
.IDispatchEx_iface
, pctinfo
);
946 static HRESULT WINAPI
domdoc_GetTypeInfo(
947 IXMLDOMDocument3
*iface
,
948 UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
950 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
951 return IDispatchEx_GetTypeInfo(&This
->node
.dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
954 static HRESULT WINAPI
domdoc_GetIDsOfNames(
955 IXMLDOMDocument3
*iface
,
962 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
963 return IDispatchEx_GetIDsOfNames(&This
->node
.dispex
.IDispatchEx_iface
,
964 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
967 static HRESULT WINAPI
domdoc_Invoke(
968 IXMLDOMDocument3
*iface
,
973 DISPPARAMS
* pDispParams
,
975 EXCEPINFO
* pExcepInfo
,
978 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
979 return IDispatchEx_Invoke(&This
->node
.dispex
.IDispatchEx_iface
,
980 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
983 static HRESULT WINAPI
domdoc_get_nodeName(
984 IXMLDOMDocument3
*iface
,
987 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
989 static const WCHAR documentW
[] = {'#','d','o','c','u','m','e','n','t',0};
991 TRACE("(%p)->(%p)\n", This
, name
);
993 return return_bstr(documentW
, name
);
997 static HRESULT WINAPI
domdoc_get_nodeValue(
998 IXMLDOMDocument3
*iface
,
1001 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1003 TRACE("(%p)->(%p)\n", This
, value
);
1006 return E_INVALIDARG
;
1008 V_VT(value
) = VT_NULL
;
1009 V_BSTR(value
) = NULL
; /* tests show that we should do this */
1014 static HRESULT WINAPI
domdoc_put_nodeValue(
1015 IXMLDOMDocument3
*iface
,
1018 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1019 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&value
));
1024 static HRESULT WINAPI
domdoc_get_nodeType(
1025 IXMLDOMDocument3
*iface
,
1028 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1030 TRACE("(%p)->(%p)\n", This
, type
);
1032 *type
= NODE_DOCUMENT
;
1037 static HRESULT WINAPI
domdoc_get_parentNode(
1038 IXMLDOMDocument3
*iface
,
1039 IXMLDOMNode
** parent
)
1041 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1043 TRACE("(%p)->(%p)\n", This
, parent
);
1045 return node_get_parent(&This
->node
, parent
);
1049 static HRESULT WINAPI
domdoc_get_childNodes(
1050 IXMLDOMDocument3
*iface
,
1051 IXMLDOMNodeList
** childList
)
1053 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1055 TRACE("(%p)->(%p)\n", This
, childList
);
1057 return node_get_child_nodes(&This
->node
, childList
);
1061 static HRESULT WINAPI
domdoc_get_firstChild(
1062 IXMLDOMDocument3
*iface
,
1063 IXMLDOMNode
** firstChild
)
1065 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1067 TRACE("(%p)->(%p)\n", This
, firstChild
);
1069 return node_get_first_child(&This
->node
, firstChild
);
1073 static HRESULT WINAPI
domdoc_get_lastChild(
1074 IXMLDOMDocument3
*iface
,
1075 IXMLDOMNode
** lastChild
)
1077 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1079 TRACE("(%p)->(%p)\n", This
, lastChild
);
1081 return node_get_last_child(&This
->node
, lastChild
);
1085 static HRESULT WINAPI
domdoc_get_previousSibling(
1086 IXMLDOMDocument3
*iface
,
1087 IXMLDOMNode
** previousSibling
)
1089 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1091 TRACE("(%p)->(%p)\n", This
, previousSibling
);
1093 return return_null_node(previousSibling
);
1097 static HRESULT WINAPI
domdoc_get_nextSibling(
1098 IXMLDOMDocument3
*iface
,
1099 IXMLDOMNode
** nextSibling
)
1101 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1103 TRACE("(%p)->(%p)\n", This
, nextSibling
);
1105 return return_null_node(nextSibling
);
1109 static HRESULT WINAPI
domdoc_get_attributes(
1110 IXMLDOMDocument3
*iface
,
1111 IXMLDOMNamedNodeMap
** attributeMap
)
1113 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1115 TRACE("(%p)->(%p)\n", This
, attributeMap
);
1117 return return_null_ptr((void**)attributeMap
);
1121 static HRESULT WINAPI
domdoc_insertBefore(
1122 IXMLDOMDocument3
*iface
,
1123 IXMLDOMNode
* newChild
,
1125 IXMLDOMNode
** outNewChild
)
1127 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1131 TRACE("(%p)->(%p %s %p)\n", This
, newChild
, debugstr_variant(&refChild
), outNewChild
);
1133 hr
= IXMLDOMNode_get_nodeType(newChild
, &type
);
1134 if (hr
!= S_OK
) return hr
;
1136 TRACE("new node type %d\n", type
);
1139 case NODE_ATTRIBUTE
:
1141 case NODE_CDATA_SECTION
:
1142 if (outNewChild
) *outNewChild
= NULL
;
1145 return node_insert_before(&This
->node
, newChild
, &refChild
, outNewChild
);
1149 static HRESULT WINAPI
domdoc_replaceChild(
1150 IXMLDOMDocument3
*iface
,
1151 IXMLDOMNode
* newChild
,
1152 IXMLDOMNode
* oldChild
,
1153 IXMLDOMNode
** outOldChild
)
1155 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1157 TRACE("(%p)->(%p %p %p)\n", This
, newChild
, oldChild
, outOldChild
);
1159 return node_replace_child(&This
->node
, newChild
, oldChild
, outOldChild
);
1163 static HRESULT WINAPI
domdoc_removeChild(
1164 IXMLDOMDocument3
*iface
,
1166 IXMLDOMNode
**oldChild
)
1168 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1169 TRACE("(%p)->(%p %p)\n", This
, child
, oldChild
);
1170 return node_remove_child(&This
->node
, child
, oldChild
);
1174 static HRESULT WINAPI
domdoc_appendChild(
1175 IXMLDOMDocument3
*iface
,
1177 IXMLDOMNode
**outChild
)
1179 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1180 TRACE("(%p)->(%p %p)\n", This
, child
, outChild
);
1181 return node_append_child(&This
->node
, child
, outChild
);
1185 static HRESULT WINAPI
domdoc_hasChildNodes(
1186 IXMLDOMDocument3
*iface
,
1189 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1190 TRACE("(%p)->(%p)\n", This
, ret
);
1191 return node_has_childnodes(&This
->node
, ret
);
1195 static HRESULT WINAPI
domdoc_get_ownerDocument(
1196 IXMLDOMDocument3
*iface
,
1197 IXMLDOMDocument
**doc
)
1199 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1200 TRACE("(%p)->(%p)\n", This
, doc
);
1201 return node_get_owner_doc(&This
->node
, doc
);
1205 static HRESULT WINAPI
domdoc_cloneNode(
1206 IXMLDOMDocument3
*iface
,
1208 IXMLDOMNode
** outNode
)
1210 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1211 TRACE("(%p)->(%d %p)\n", This
, deep
, outNode
);
1212 return node_clone( &This
->node
, deep
, outNode
);
1216 static HRESULT WINAPI
domdoc_get_nodeTypeString(
1217 IXMLDOMDocument3
*iface
,
1220 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1221 static const WCHAR documentW
[] = {'d','o','c','u','m','e','n','t',0};
1223 TRACE("(%p)->(%p)\n", This
, p
);
1225 return return_bstr(documentW
, p
);
1229 static HRESULT WINAPI
domdoc_get_text(
1230 IXMLDOMDocument3
*iface
,
1233 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1234 TRACE("(%p)->(%p)\n", This
, p
);
1235 return node_get_text(&This
->node
, p
);
1239 static HRESULT WINAPI
domdoc_put_text(
1240 IXMLDOMDocument3
*iface
,
1243 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1244 TRACE("(%p)->(%s)\n", This
, debugstr_w(text
));
1249 static HRESULT WINAPI
domdoc_get_specified(
1250 IXMLDOMDocument3
*iface
,
1251 VARIANT_BOOL
* isSpecified
)
1253 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1254 FIXME("(%p)->(%p) stub!\n", This
, isSpecified
);
1255 *isSpecified
= VARIANT_TRUE
;
1260 static HRESULT WINAPI
domdoc_get_definition(
1261 IXMLDOMDocument3
*iface
,
1262 IXMLDOMNode
** definitionNode
)
1264 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1265 FIXME("(%p)->(%p)\n", This
, definitionNode
);
1270 static HRESULT WINAPI
domdoc_get_nodeTypedValue(
1271 IXMLDOMDocument3
*iface
,
1274 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1275 TRACE("(%p)->(%p)\n", This
, v
);
1276 return return_null_var(v
);
1279 static HRESULT WINAPI
domdoc_put_nodeTypedValue(
1280 IXMLDOMDocument3
*iface
,
1281 VARIANT typedValue
)
1283 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1284 FIXME("(%p)->(%s)\n", This
, debugstr_variant(&typedValue
));
1289 static HRESULT WINAPI
domdoc_get_dataType(
1290 IXMLDOMDocument3
*iface
,
1293 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1294 TRACE("(%p)->(%p)\n", This
, typename
);
1295 return return_null_var( typename
);
1299 static HRESULT WINAPI
domdoc_put_dataType(
1300 IXMLDOMDocument3
*iface
,
1303 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1305 FIXME("(%p)->(%s)\n", This
, debugstr_w(dataTypeName
));
1308 return E_INVALIDARG
;
1313 static int XMLCALL
domdoc_get_xml_writecallback(void *ctx
, const char *data
, int len
)
1315 return xmlBufferAdd((xmlBufferPtr
)ctx
, (xmlChar
*)data
, len
) == 0 ? len
: 0;
1318 static HRESULT WINAPI
domdoc_get_xml(
1319 IXMLDOMDocument3
*iface
,
1322 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1323 xmlSaveCtxtPtr ctxt
;
1328 TRACE("(%p)->(%p)\n", This
, p
);
1331 return E_INVALIDARG
;
1335 buf
= xmlBufferCreate();
1337 return E_OUTOFMEMORY
;
1339 options
= XML_SAVE_FORMAT
| XML_SAVE_NO_DECL
;
1340 ctxt
= xmlSaveToIO(domdoc_get_xml_writecallback
, NULL
, buf
, "UTF-8", options
);
1345 return E_OUTOFMEMORY
;
1348 ret
= xmlSaveDoc(ctxt
, get_doc(This
));
1349 /* flushes on close */
1352 TRACE("%ld, len=%d\n", ret
, xmlBufferLength(buf
));
1353 if(ret
!= -1 && xmlBufferLength(buf
) > 0)
1357 content
= bstr_from_xmlChar(xmlBufferContent(buf
));
1358 content
= EnsureCorrectEOL(content
);
1364 *p
= SysAllocStringLen(NULL
, 0);
1369 return *p
? S_OK
: E_OUTOFMEMORY
;
1373 static HRESULT WINAPI
domdoc_transformNode(
1374 IXMLDOMDocument3
*iface
,
1378 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1379 TRACE("(%p)->(%p %p)\n", This
, node
, p
);
1380 return node_transform_node(&This
->node
, node
, p
);
1384 static HRESULT WINAPI
domdoc_selectNodes(
1385 IXMLDOMDocument3
*iface
,
1387 IXMLDOMNodeList
**outList
)
1389 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1390 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outList
);
1391 return node_select_nodes(&This
->node
, p
, outList
);
1395 static HRESULT WINAPI
domdoc_selectSingleNode(
1396 IXMLDOMDocument3
*iface
,
1398 IXMLDOMNode
**outNode
)
1400 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1401 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(p
), outNode
);
1402 return node_select_singlenode(&This
->node
, p
, outNode
);
1406 static HRESULT WINAPI
domdoc_get_parsed(
1407 IXMLDOMDocument3
*iface
,
1408 VARIANT_BOOL
* isParsed
)
1410 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1411 FIXME("(%p)->(%p) stub!\n", This
, isParsed
);
1412 *isParsed
= VARIANT_TRUE
;
1416 static HRESULT WINAPI
domdoc_get_namespaceURI(
1417 IXMLDOMDocument3
*iface
,
1418 BSTR
* namespaceURI
)
1420 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1421 TRACE("(%p)->(%p)\n", This
, namespaceURI
);
1422 return return_null_bstr( namespaceURI
);
1425 static HRESULT WINAPI
domdoc_get_prefix(
1426 IXMLDOMDocument3
*iface
,
1429 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1430 TRACE("(%p)->(%p)\n", This
, prefix
);
1431 return return_null_bstr( prefix
);
1435 static HRESULT WINAPI
domdoc_get_baseName(
1436 IXMLDOMDocument3
*iface
,
1439 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1440 TRACE("(%p)->(%p)\n", This
, name
);
1441 return return_null_bstr( name
);
1445 static HRESULT WINAPI
domdoc_transformNodeToObject(
1446 IXMLDOMDocument3
*iface
,
1447 IXMLDOMNode
* stylesheet
,
1448 VARIANT outputObject
)
1450 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1451 FIXME("(%p)->(%p %s)\n", This
, stylesheet
, debugstr_variant(&outputObject
));
1456 static HRESULT WINAPI
domdoc_get_doctype(
1457 IXMLDOMDocument3
*iface
,
1458 IXMLDOMDocumentType
** doctype
)
1460 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1465 TRACE("(%p)->(%p)\n", This
, doctype
);
1467 if (!doctype
) return E_INVALIDARG
;
1471 dtd
= xmlGetIntSubset(get_doc(This
));
1472 if (!dtd
) return S_FALSE
;
1474 node
= create_node((xmlNodePtr
)dtd
);
1475 if (!node
) return S_FALSE
;
1477 hr
= IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentType
, (void**)doctype
);
1478 IXMLDOMNode_Release(node
);
1484 static HRESULT WINAPI
domdoc_get_implementation(
1485 IXMLDOMDocument3
*iface
,
1486 IXMLDOMImplementation
** impl
)
1488 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
1490 TRACE("(%p)->(%p)\n", This
, impl
);
1493 return E_INVALIDARG
;
1495 *impl
= (IXMLDOMImplementation
*)create_doc_Implementation();
1500 static HRESULT WINAPI
domdoc_get_documentElement(
1501 IXMLDOMDocument3
*iface
,
1502 IXMLDOMElement
** DOMElement
)
1504 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1505 IXMLDOMNode
*element_node
;
1509 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1512 return E_INVALIDARG
;
1516 root
= xmlDocGetRootElement( get_doc(This
) );
1520 element_node
= create_node( root
);
1521 if(!element_node
) return S_FALSE
;
1523 hr
= IXMLDOMNode_QueryInterface(element_node
, &IID_IXMLDOMElement
, (void**)DOMElement
);
1524 IXMLDOMNode_Release(element_node
);
1530 static HRESULT WINAPI
domdoc_put_documentElement(
1531 IXMLDOMDocument3
*iface
,
1532 IXMLDOMElement
* DOMElement
)
1534 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1535 IXMLDOMNode
*elementNode
;
1542 TRACE("(%p)->(%p)\n", This
, DOMElement
);
1544 hr
= IXMLDOMElement_QueryInterface( DOMElement
, &IID_IXMLDOMNode
, (void**)&elementNode
);
1548 xmlNode
= get_node_obj( elementNode
);
1549 if(!xmlNode
) return E_FAIL
;
1551 if(!xmlNode
->node
->parent
)
1552 if(xmldoc_remove_orphan(xmlNode
->node
->doc
, xmlNode
->node
) != S_OK
)
1553 WARN("%p is not an orphan of %p\n", xmlNode
->node
->doc
, xmlNode
->node
);
1555 old_doc
= xmlNode
->node
->doc
;
1556 if (old_doc
!= get_doc(This
))
1557 refcount
= xmlnode_get_inst_cnt(xmlNode
);
1559 /* old root is still orphaned by its document, update refcount from new root */
1560 if (refcount
) xmldoc_add_refs(get_doc(This
), refcount
);
1561 oldRoot
= xmlDocSetRootElement( get_doc(This
), xmlNode
->node
);
1562 if (refcount
) xmldoc_release_refs(old_doc
, refcount
);
1563 IXMLDOMNode_Release( elementNode
);
1566 xmldoc_add_orphan(oldRoot
->doc
, oldRoot
);
1572 static HRESULT WINAPI
domdoc_createElement(
1573 IXMLDOMDocument3
*iface
,
1575 IXMLDOMElement
** element
)
1577 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1582 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(tagname
), element
);
1584 if (!element
|| !tagname
) return E_INVALIDARG
;
1586 V_VT(&type
) = VT_I1
;
1587 V_I1(&type
) = NODE_ELEMENT
;
1589 hr
= IXMLDOMDocument3_createNode(iface
, type
, tagname
, NULL
, &node
);
1592 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMElement
, (void**)element
);
1593 IXMLDOMNode_Release(node
);
1600 static HRESULT WINAPI
domdoc_createDocumentFragment(
1601 IXMLDOMDocument3
*iface
,
1602 IXMLDOMDocumentFragment
** frag
)
1604 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1609 TRACE("(%p)->(%p)\n", This
, frag
);
1611 if (!frag
) return E_INVALIDARG
;
1615 V_VT(&type
) = VT_I1
;
1616 V_I1(&type
) = NODE_DOCUMENT_FRAGMENT
;
1618 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1621 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMDocumentFragment
, (void**)frag
);
1622 IXMLDOMNode_Release(node
);
1629 static HRESULT WINAPI
domdoc_createTextNode(
1630 IXMLDOMDocument3
*iface
,
1632 IXMLDOMText
** text
)
1634 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1639 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), text
);
1641 if (!text
) return E_INVALIDARG
;
1645 V_VT(&type
) = VT_I1
;
1646 V_I1(&type
) = NODE_TEXT
;
1648 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1651 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMText
, (void**)text
);
1652 IXMLDOMNode_Release(node
);
1653 hr
= IXMLDOMText_put_data(*text
, data
);
1660 static HRESULT WINAPI
domdoc_createComment(
1661 IXMLDOMDocument3
*iface
,
1663 IXMLDOMComment
** comment
)
1665 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1670 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), comment
);
1672 if (!comment
) return E_INVALIDARG
;
1676 V_VT(&type
) = VT_I1
;
1677 V_I1(&type
) = NODE_COMMENT
;
1679 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1682 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMComment
, (void**)comment
);
1683 IXMLDOMNode_Release(node
);
1684 hr
= IXMLDOMComment_put_data(*comment
, data
);
1691 static HRESULT WINAPI
domdoc_createCDATASection(
1692 IXMLDOMDocument3
*iface
,
1694 IXMLDOMCDATASection
** cdata
)
1696 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1701 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), cdata
);
1703 if (!cdata
) return E_INVALIDARG
;
1707 V_VT(&type
) = VT_I1
;
1708 V_I1(&type
) = NODE_CDATA_SECTION
;
1710 hr
= IXMLDOMDocument3_createNode(iface
, type
, NULL
, NULL
, &node
);
1713 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMCDATASection
, (void**)cdata
);
1714 IXMLDOMNode_Release(node
);
1715 hr
= IXMLDOMCDATASection_put_data(*cdata
, data
);
1722 static HRESULT WINAPI
domdoc_createProcessingInstruction(
1723 IXMLDOMDocument3
*iface
,
1726 IXMLDOMProcessingInstruction
** pi
)
1728 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1733 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_w(target
), debugstr_w(data
), pi
);
1735 if (!pi
) return E_INVALIDARG
;
1739 V_VT(&type
) = VT_I1
;
1740 V_I1(&type
) = NODE_PROCESSING_INSTRUCTION
;
1742 hr
= IXMLDOMDocument3_createNode(iface
, type
, target
, NULL
, &node
);
1747 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1748 node_obj
= get_node_obj(node
);
1749 hr
= node_set_content(node_obj
, data
);
1751 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMProcessingInstruction
, (void**)pi
);
1752 IXMLDOMNode_Release(node
);
1759 static HRESULT WINAPI
domdoc_createAttribute(
1760 IXMLDOMDocument3
*iface
,
1762 IXMLDOMAttribute
** attribute
)
1764 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1769 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), attribute
);
1771 if (!attribute
|| !name
) return E_INVALIDARG
;
1773 V_VT(&type
) = VT_I1
;
1774 V_I1(&type
) = NODE_ATTRIBUTE
;
1776 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1779 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMAttribute
, (void**)attribute
);
1780 IXMLDOMNode_Release(node
);
1787 static HRESULT WINAPI
domdoc_createEntityReference(
1788 IXMLDOMDocument3
*iface
,
1790 IXMLDOMEntityReference
** entityref
)
1792 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1797 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), entityref
);
1799 if (!entityref
) return E_INVALIDARG
;
1803 V_VT(&type
) = VT_I1
;
1804 V_I1(&type
) = NODE_ENTITY_REFERENCE
;
1806 hr
= IXMLDOMDocument3_createNode(iface
, type
, name
, NULL
, &node
);
1809 IXMLDOMNode_QueryInterface(node
, &IID_IXMLDOMEntityReference
, (void**)entityref
);
1810 IXMLDOMNode_Release(node
);
1816 xmlChar
* tagName_to_XPath(const BSTR tagName
)
1818 xmlChar
*query
, *tmp
;
1819 static const xmlChar mod_pre
[] = "*[local-name()='";
1820 static const xmlChar mod_post
[] = "']";
1821 static const xmlChar prefix
[] = "descendant::";
1822 const WCHAR
*tokBegin
, *tokEnd
;
1825 query
= xmlStrdup(prefix
);
1828 while (tokBegin
&& *tokBegin
)
1833 query
= xmlStrcat(query
, BAD_CAST
"/");
1837 query
= xmlStrcat(query
, BAD_CAST
"*");
1841 query
= xmlStrcat(query
, mod_pre
);
1843 while (*tokEnd
&& *tokEnd
!= '/')
1845 len
= WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, NULL
, 0, NULL
, NULL
);
1846 tmp
= xmlMalloc(len
);
1847 WideCharToMultiByte(CP_UTF8
, 0, tokBegin
, tokEnd
-tokBegin
, (char*)tmp
, len
, NULL
, NULL
);
1848 query
= xmlStrncat(query
, tmp
, len
);
1851 query
= xmlStrcat(query
, mod_post
);
1858 static HRESULT WINAPI
domdoc_getElementsByTagName(
1859 IXMLDOMDocument3
*iface
,
1861 IXMLDOMNodeList
** resultList
)
1863 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1868 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(tagName
), resultList
);
1870 if (!tagName
|| !resultList
) return E_INVALIDARG
;
1872 XPath
= This
->properties
->XPath
;
1873 This
->properties
->XPath
= TRUE
;
1874 query
= tagName_to_XPath(tagName
);
1875 hr
= create_selection((xmlNodePtr
)get_doc(This
), query
, resultList
);
1877 This
->properties
->XPath
= XPath
;
1882 static HRESULT
get_node_type(VARIANT Type
, DOMNodeType
* type
)
1888 hr
= VariantChangeType(&tmp
, &Type
, 0, VT_I4
);
1890 return E_INVALIDARG
;
1897 static HRESULT WINAPI
domdoc_createNode(
1898 IXMLDOMDocument3
*iface
,
1902 IXMLDOMNode
** node
)
1904 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
1905 DOMNodeType node_type
;
1907 xmlChar
*xml_name
, *href
;
1910 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_variant(&Type
), debugstr_w(name
), debugstr_w(namespaceURI
), node
);
1912 if(!node
) return E_INVALIDARG
;
1914 hr
= get_node_type(Type
, &node_type
);
1915 if(FAILED(hr
)) return hr
;
1917 TRACE("node_type %d\n", node_type
);
1919 /* exit earlier for types that need name */
1923 case NODE_ATTRIBUTE
:
1924 case NODE_ENTITY_REFERENCE
:
1925 case NODE_PROCESSING_INSTRUCTION
:
1926 if (!name
|| *name
== 0) return E_FAIL
;
1932 xml_name
= xmlchar_from_wchar(name
);
1933 /* prevent empty href to be allocated */
1934 href
= namespaceURI
? xmlchar_from_wchar(namespaceURI
) : NULL
;
1940 xmlChar
*local
, *prefix
;
1942 local
= xmlSplitQName2(xml_name
, &prefix
);
1944 xmlnode
= xmlNewDocNode(get_doc(This
), NULL
, local
? local
: xml_name
, NULL
);
1946 /* allow to create default namespace xmlns= */
1947 if (local
|| (href
&& *href
))
1949 xmlNsPtr ns
= xmlNewNs(xmlnode
, href
, prefix
);
1950 xmlSetNs(xmlnode
, ns
);
1958 case NODE_ATTRIBUTE
:
1960 xmlChar
*local
, *prefix
;
1962 local
= xmlSplitQName2(xml_name
, &prefix
);
1964 xmlnode
= (xmlNodePtr
)xmlNewDocProp(get_doc(This
), local
? local
: xml_name
, NULL
);
1966 if (local
|| (href
&& *href
))
1968 /* we need a floating namespace here, it can't be created linked to attribute from
1970 xmlNsPtr ns
= xmlNewNs(NULL
, href
, prefix
);
1971 xmlSetNs(xmlnode
, ns
);
1980 xmlnode
= (xmlNodePtr
)xmlNewDocText(get_doc(This
), NULL
);
1982 case NODE_CDATA_SECTION
:
1983 xmlnode
= xmlNewCDataBlock(get_doc(This
), NULL
, 0);
1985 case NODE_ENTITY_REFERENCE
:
1986 xmlnode
= xmlNewReference(get_doc(This
), xml_name
);
1988 case NODE_PROCESSING_INSTRUCTION
:
1989 #ifdef HAVE_XMLNEWDOCPI
1990 xmlnode
= xmlNewDocPI(get_doc(This
), xml_name
, NULL
);
1992 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1997 xmlnode
= xmlNewDocComment(get_doc(This
), NULL
);
1999 case NODE_DOCUMENT_FRAGMENT
:
2000 xmlnode
= xmlNewDocFragment(get_doc(This
));
2002 /* unsupported types */
2004 case NODE_DOCUMENT_TYPE
:
2007 heap_free(xml_name
);
2008 return E_INVALIDARG
;
2010 FIXME("unhandled node type %d\n", node_type
);
2015 *node
= create_node(xmlnode
);
2016 heap_free(xml_name
);
2021 TRACE("created node (%d, %p, %p)\n", node_type
, *node
, xmlnode
);
2022 xmldoc_add_orphan(xmlnode
->doc
, xmlnode
);
2029 static HRESULT WINAPI
domdoc_nodeFromID(
2030 IXMLDOMDocument3
*iface
,
2032 IXMLDOMNode
** node
)
2034 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2035 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(idString
), node
);
2039 static HRESULT
domdoc_onDataAvailable(void *obj
, char *ptr
, DWORD len
)
2044 xmldoc
= doparse(This
, ptr
, len
, XML_CHAR_ENCODING_NONE
);
2046 xmldoc
->_private
= create_priv();
2047 return attach_xmldoc(This
, xmldoc
);
2053 static HRESULT
domdoc_load_moniker(domdoc
*This
, IMoniker
*mon
)
2058 hr
= bind_url(mon
, domdoc_onDataAvailable
, This
, &bsc
);
2063 hr
= detach_bsc(This
->bsc
);
2072 static HRESULT WINAPI
domdoc_load(
2073 IXMLDOMDocument3
*iface
,
2075 VARIANT_BOOL
* isSuccessful
)
2077 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2078 LPWSTR filename
= NULL
;
2079 HRESULT hr
= S_FALSE
;
2082 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&source
));
2086 *isSuccessful
= VARIANT_FALSE
;
2088 assert( &This
->node
);
2090 switch( V_VT(&source
) )
2093 filename
= V_BSTR(&source
);
2095 case VT_BSTR
|VT_BYREF
:
2096 if (!V_BSTRREF(&source
)) return E_INVALIDARG
;
2097 filename
= *V_BSTRREF(&source
);
2099 case VT_ARRAY
|VT_UI1
:
2101 SAFEARRAY
*psa
= V_ARRAY(&source
);
2104 UINT dim
= SafeArrayGetDim(psa
);
2109 ERR("SAFEARRAY == NULL\n");
2110 hr
= This
->error
= E_INVALIDARG
;
2113 /* Only takes UTF-8 strings.
2114 * NOT NULL-terminated. */
2115 SafeArrayAccessData(psa
, (void**)&str
);
2116 SafeArrayGetUBound(psa
, 1, &len
);
2118 if ((xmldoc
= doparse(This
, str
, ++len
, XML_CHAR_ENCODING_UTF8
)))
2120 hr
= This
->error
= S_OK
;
2121 *isSuccessful
= VARIANT_TRUE
;
2122 TRACE("parsed document %p\n", xmldoc
);
2126 This
->error
= E_FAIL
;
2127 TRACE("failed to parse document\n");
2130 SafeArrayUnaccessData(psa
);
2134 xmldoc
->_private
= create_priv();
2135 return attach_xmldoc(This
, xmldoc
);
2139 FIXME("unhandled SAFEARRAY dim: %d\n", dim
);
2140 hr
= This
->error
= E_NOTIMPL
;
2146 ISequentialStream
*stream
= NULL
;
2147 IXMLDOMDocument3
*newdoc
= NULL
;
2149 if (!V_UNKNOWN(&source
)) return E_INVALIDARG
;
2151 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IXMLDOMDocument3
, (void**)&newdoc
);
2156 domdoc
*newDoc
= impl_from_IXMLDOMDocument3( newdoc
);
2158 xmldoc
= xmlCopyDoc(get_doc(newDoc
), 1);
2159 xmldoc
->_private
= create_priv();
2160 hr
= attach_xmldoc(This
, xmldoc
);
2163 *isSuccessful
= VARIANT_TRUE
;
2169 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_IStream
, (void**)&stream
);
2171 hr
= IUnknown_QueryInterface(V_UNKNOWN(&source
), &IID_ISequentialStream
, (void**)&stream
);
2175 hr
= domdoc_load_from_stream(This
, stream
);
2177 *isSuccessful
= VARIANT_TRUE
;
2178 ISequentialStream_Release(stream
);
2182 FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr
, V_UNKNOWN(&source
)->lpVtbl
);
2186 FIXME("VT type not supported (%d)\n", V_VT(&source
));
2193 hr
= create_moniker_from_url( filename
, &mon
);
2194 if ( SUCCEEDED(hr
) )
2196 hr
= domdoc_load_moniker( This
, mon
);
2197 IMoniker_Release(mon
);
2201 This
->error
= E_FAIL
;
2204 hr
= This
->error
= S_OK
;
2205 *isSuccessful
= VARIANT_TRUE
;
2209 if(!filename
|| FAILED(hr
)) {
2210 xmldoc
= xmlNewDoc(NULL
);
2211 xmldoc
->_private
= create_priv();
2212 hr
= attach_xmldoc(This
, xmldoc
);
2217 TRACE("ret (%d)\n", hr
);
2223 static HRESULT WINAPI
domdoc_get_readyState(
2224 IXMLDOMDocument3
*iface
,
2227 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2228 FIXME("stub! (%p)->(%p)\n", This
, value
);
2231 return E_INVALIDARG
;
2233 *value
= READYSTATE_COMPLETE
;
2238 static HRESULT WINAPI
domdoc_get_parseError(
2239 IXMLDOMDocument3
*iface
,
2240 IXMLDOMParseError
** errorObj
)
2242 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2243 static const WCHAR err
[] = {'e','r','r','o','r',0};
2244 BSTR error_string
= NULL
;
2246 FIXME("(%p)->(%p): creating a dummy parseError\n", iface
, errorObj
);
2249 error_string
= SysAllocString(err
);
2251 *errorObj
= create_parseError(This
->error
, NULL
, error_string
, NULL
, 0, 0, 0);
2252 if(!*errorObj
) return E_OUTOFMEMORY
;
2257 static HRESULT WINAPI
domdoc_get_url(
2258 IXMLDOMDocument3
*iface
,
2261 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2262 FIXME("(%p)->(%p)\n", This
, urlString
);
2267 static HRESULT WINAPI
domdoc_get_async(
2268 IXMLDOMDocument3
*iface
,
2269 VARIANT_BOOL
* isAsync
)
2271 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2273 TRACE("(%p)->(%p: %d)\n", This
, isAsync
, This
->async
);
2274 *isAsync
= This
->async
;
2279 static HRESULT WINAPI
domdoc_put_async(
2280 IXMLDOMDocument3
*iface
,
2281 VARIANT_BOOL isAsync
)
2283 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2285 TRACE("(%p)->(%d)\n", This
, isAsync
);
2286 This
->async
= isAsync
;
2291 static HRESULT WINAPI
domdoc_abort(
2292 IXMLDOMDocument3
*iface
)
2294 domdoc
*This
= impl_from_IXMLDOMDocument3(iface
);
2295 FIXME("%p\n", This
);
2299 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2300 static HRESULT WINAPI
domdoc_loadXML(
2301 IXMLDOMDocument3
*iface
,
2303 VARIANT_BOOL
* isSuccessful
)
2305 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2306 xmlDocPtr xmldoc
= NULL
;
2307 HRESULT hr
= S_FALSE
, hr2
;
2309 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(data
), isSuccessful
);
2311 assert ( &This
->node
);
2315 *isSuccessful
= VARIANT_FALSE
;
2321 /* skip leading spaces if needed */
2322 if (This
->properties
->version
== MSXML_DEFAULT
|| This
->properties
->version
== MSXML26
)
2323 while (*ptr
&& isspaceW(*ptr
)) ptr
++;
2325 xmldoc
= doparse(This
, (char*)ptr
, strlenW(ptr
)*sizeof(WCHAR
), XML_CHAR_ENCODING_UTF16LE
);
2328 This
->error
= E_FAIL
;
2329 TRACE("failed to parse document\n");
2333 hr
= This
->error
= S_OK
;
2334 *isSuccessful
= VARIANT_TRUE
;
2335 TRACE("parsed document %p\n", xmldoc
);
2341 xmldoc
= xmlNewDoc(NULL
);
2342 xmldoc
->_private
= create_priv();
2343 hr2
= attach_xmldoc(This
, xmldoc
);
2350 static int XMLCALL
domdoc_save_writecallback(void *ctx
, const char *buffer
, int len
)
2354 if(!WriteFile(ctx
, buffer
, len
, &written
, NULL
))
2356 WARN("write error\n");
2363 static int XMLCALL
domdoc_save_closecallback(void *ctx
)
2365 return CloseHandle(ctx
) ? 0 : -1;
2368 static int XMLCALL
domdoc_stream_save_writecallback(void *ctx
, const char *buffer
, int len
)
2373 hr
= IStream_Write((IStream
*)ctx
, buffer
, len
, &written
);
2374 TRACE("0x%08x %p %d %u\n", hr
, buffer
, len
, written
);
2377 WARN("stream write error: 0x%08x\n", hr
);
2384 static int XMLCALL
domdoc_stream_save_closecallback(void *ctx
)
2386 IStream_Release((IStream
*)ctx
);
2390 static HRESULT WINAPI
domdoc_save(
2391 IXMLDOMDocument3
*iface
,
2392 VARIANT destination
)
2394 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2395 xmlSaveCtxtPtr ctx
= NULL
;
2399 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&destination
));
2401 switch (V_VT(&destination
))
2405 IUnknown
*pUnk
= V_UNKNOWN(&destination
);
2406 IXMLDOMDocument3
*document
;
2409 ret
= IUnknown_QueryInterface(pUnk
, &IID_IXMLDOMDocument3
, (void**)&document
);
2412 VARIANT_BOOL success
;
2415 ret
= IXMLDOMDocument3_get_xml(iface
, &xml
);
2418 ret
= IXMLDOMDocument3_loadXML(document
, xml
, &success
);
2422 IXMLDOMDocument3_Release(document
);
2426 ret
= IUnknown_QueryInterface(pUnk
, &IID_IStream
, (void**)&stream
);
2429 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2430 ctx
= xmlSaveToIO(domdoc_stream_save_writecallback
,
2431 domdoc_stream_save_closecallback
, stream
, NULL
, options
);
2435 IStream_Release(stream
);
2443 case VT_BSTR
| VT_BYREF
:
2445 int options
= get_doc(This
)->standalone
== -1 ? XML_SAVE_NO_DECL
: 0;
2447 /* save with file path */
2448 HANDLE handle
= CreateFileW( (V_VT(&destination
) & VT_BYREF
)? *V_BSTRREF(&destination
) : V_BSTR(&destination
),
2449 GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2450 if( handle
== INVALID_HANDLE_VALUE
)
2452 WARN("failed to create file\n");
2456 /* disable top XML declaration */
2457 ctx
= xmlSaveToIO(domdoc_save_writecallback
, domdoc_save_closecallback
,
2458 handle
, NULL
, options
);
2461 CloseHandle(handle
);
2468 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination
));
2472 xmldecl
= xmldoc_unlink_xmldecl(get_doc(This
));
2473 if (xmlSaveDoc(ctx
, get_doc(This
)) == -1) ret
= S_FALSE
;
2474 xmldoc_link_xmldecl(get_doc(This
), xmldecl
);
2476 /* will release resources through close callback */
2482 static HRESULT WINAPI
domdoc_get_validateOnParse(
2483 IXMLDOMDocument3
*iface
,
2484 VARIANT_BOOL
* isValidating
)
2486 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2487 TRACE("(%p)->(%p: %d)\n", This
, isValidating
, This
->validating
);
2488 *isValidating
= This
->validating
;
2493 static HRESULT WINAPI
domdoc_put_validateOnParse(
2494 IXMLDOMDocument3
*iface
,
2495 VARIANT_BOOL isValidating
)
2497 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2498 TRACE("(%p)->(%d)\n", This
, isValidating
);
2499 This
->validating
= isValidating
;
2504 static HRESULT WINAPI
domdoc_get_resolveExternals(
2505 IXMLDOMDocument3
*iface
,
2506 VARIANT_BOOL
* isResolving
)
2508 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2509 TRACE("(%p)->(%p: %d)\n", This
, isResolving
, This
->resolving
);
2510 *isResolving
= This
->resolving
;
2515 static HRESULT WINAPI
domdoc_put_resolveExternals(
2516 IXMLDOMDocument3
*iface
,
2517 VARIANT_BOOL isResolving
)
2519 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2520 TRACE("(%p)->(%d)\n", This
, isResolving
);
2521 This
->resolving
= isResolving
;
2526 static HRESULT WINAPI
domdoc_get_preserveWhiteSpace(
2527 IXMLDOMDocument3
*iface
,
2528 VARIANT_BOOL
* isPreserving
)
2530 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2531 TRACE("(%p)->(%p: %d)\n", This
, isPreserving
, This
->properties
->preserving
);
2532 *isPreserving
= This
->properties
->preserving
;
2537 static HRESULT WINAPI
domdoc_put_preserveWhiteSpace(
2538 IXMLDOMDocument3
*iface
,
2539 VARIANT_BOOL isPreserving
)
2541 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2542 TRACE("(%p)->(%d)\n", This
, isPreserving
);
2543 This
->properties
->preserving
= isPreserving
;
2548 static HRESULT WINAPI
domdoc_put_onreadystatechange(
2549 IXMLDOMDocument3
*iface
,
2552 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2554 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&event
));
2555 return set_doc_event(This
, EVENTID_READYSTATECHANGE
, &event
);
2559 static HRESULT WINAPI
domdoc_put_onDataAvailable(IXMLDOMDocument3
*iface
, VARIANT sink
)
2561 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2562 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2566 static HRESULT WINAPI
domdoc_put_onTransformNode(IXMLDOMDocument3
*iface
, VARIANT sink
)
2568 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2569 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&sink
));
2573 static HRESULT WINAPI
domdoc_get_namespaces(
2574 IXMLDOMDocument3
* iface
,
2575 IXMLDOMSchemaCollection
** collection
)
2577 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2580 FIXME("(%p)->(%p): semi-stub\n", This
, collection
);
2582 if (!collection
) return E_POINTER
;
2584 if (!This
->namespaces
)
2586 hr
= SchemaCache_create(This
->properties
->version
, NULL
, (void**)&This
->namespaces
);
2587 if (hr
!= S_OK
) return hr
;
2589 hr
= cache_from_doc_ns(This
->namespaces
, &This
->node
);
2591 release_namespaces(This
);
2594 if (This
->namespaces
)
2595 return IXMLDOMSchemaCollection2_QueryInterface(This
->namespaces
,
2596 &IID_IXMLDOMSchemaCollection
, (void**)collection
);
2601 static HRESULT WINAPI
domdoc_get_schemas(
2602 IXMLDOMDocument3
* iface
,
2605 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2606 IXMLDOMSchemaCollection2
* cur_schema
= This
->properties
->schemaCache
;
2607 HRESULT hr
= S_FALSE
;
2609 TRACE("(%p)->(%p)\n", This
, schema
);
2611 V_VT(schema
) = VT_NULL
;
2612 /* just to reset pointer part, cause that's what application is expected to use */
2613 V_DISPATCH(schema
) = NULL
;
2617 hr
= IXMLDOMSchemaCollection2_QueryInterface(cur_schema
, &IID_IDispatch
, (void**)&V_DISPATCH(schema
));
2619 V_VT(schema
) = VT_DISPATCH
;
2624 static HRESULT WINAPI
domdoc_putref_schemas(
2625 IXMLDOMDocument3
* iface
,
2628 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2629 HRESULT hr
= E_FAIL
;
2630 IXMLDOMSchemaCollection2
* new_schema
= NULL
;
2632 FIXME("(%p)->(%s): semi-stub\n", This
, debugstr_variant(&schema
));
2633 switch(V_VT(&schema
))
2636 if (V_UNKNOWN(&schema
))
2638 hr
= IUnknown_QueryInterface(V_UNKNOWN(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2643 if (V_DISPATCH(&schema
))
2645 hr
= IDispatch_QueryInterface(V_DISPATCH(&schema
), &IID_IXMLDOMSchemaCollection
, (void**)&new_schema
);
2655 WARN("Can't get schema from vt %x\n", V_VT(&schema
));
2660 IXMLDOMSchemaCollection2
* old_schema
= InterlockedExchangePointer((void**)&This
->properties
->schemaCache
, new_schema
);
2661 if(old_schema
) IXMLDOMSchemaCollection2_Release(old_schema
);
2667 static inline BOOL
is_wellformed(xmlDocPtr doc
)
2669 #ifdef HAVE_XMLDOC_PROPERTIES
2670 return doc
->properties
& XML_DOC_WELLFORMED
;
2672 /* Not a full check, but catches the worst violations */
2676 for (child
= doc
->children
; child
!= NULL
; child
= child
->next
)
2678 switch (child
->type
)
2680 case XML_ELEMENT_NODE
:
2685 case XML_CDATA_SECTION_NODE
:
2697 static void LIBXML2_LOG_CALLBACK
validate_error(void* ctx
, char const* msg
, ...)
2701 LIBXML2_CALLBACK_ERR(domdoc_validateNode
, msg
, ap
);
2705 static void LIBXML2_LOG_CALLBACK
validate_warning(void* ctx
, char const* msg
, ...)
2709 LIBXML2_CALLBACK_WARN(domdoc_validateNode
, msg
, ap
);
2713 static HRESULT WINAPI
domdoc_validateNode(
2714 IXMLDOMDocument3
* iface
,
2716 IXMLDOMParseError
** err
)
2718 domdoc
* This
= impl_from_IXMLDOMDocument3(iface
);
2719 LONG state
, err_code
= 0;
2723 TRACE("(%p)->(%p, %p)\n", This
, node
, err
);
2724 IXMLDOMDocument3_get_readyState(iface
, &state
);
2725 if (state
!= READYSTATE_COMPLETE
)
2728 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2735 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2739 if (!get_node_obj(node
)->node
|| get_node_obj(node
)->node
->doc
!= get_doc(This
))
2742 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2746 if (!is_wellformed(get_doc(This
)))
2748 ERR("doc not well-formed\n");
2750 *err
= create_parseError(E_XML_NOTWF
, NULL
, NULL
, NULL
, 0, 0, 0);
2754 /* DTD validation */
2755 if (get_doc(This
)->intSubset
|| get_doc(This
)->extSubset
)
2757 xmlValidCtxtPtr vctx
= xmlNewValidCtxt();
2758 vctx
->error
= validate_error
;
2759 vctx
->warning
= validate_warning
;
2762 if (!((node
== (IXMLDOMNode
*)iface
)?
2763 xmlValidateDocument(vctx
, get_doc(This
)) :
2764 xmlValidateElement(vctx
, get_doc(This
), get_node_obj(node
)->node
)))
2766 /* TODO: get a real error code here */
2767 TRACE("DTD validation failed\n");
2768 err_code
= E_XML_INVALID
;
2771 xmlFreeValidCtxt(vctx
);
2774 /* Schema validation */
2775 if (hr
== S_OK
&& This
->properties
->schemaCache
!= NULL
)
2778 hr
= SchemaCache_validate_tree(This
->properties
->schemaCache
, get_node_obj(node
)->node
);
2782 /* TODO: get a real error code here */
2785 TRACE("schema validation succeeded\n");
2789 ERR("schema validation failed\n");
2790 err_code
= E_XML_INVALID
;
2795 /* not really OK, just didn't find a schema for the ns */
2802 ERR("no DTD or schema found\n");
2803 err_code
= E_XML_NODTD
;
2808 *err
= create_parseError(err_code
, NULL
, NULL
, NULL
, 0, 0, 0);
2813 static HRESULT WINAPI
domdoc_validate(
2814 IXMLDOMDocument3
* iface
,
2815 IXMLDOMParseError
** err
)
2817 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2818 TRACE("(%p)->(%p)\n", This
, err
);
2819 return IXMLDOMDocument3_validateNode(iface
, (IXMLDOMNode
*)iface
, err
);
2822 static HRESULT WINAPI
domdoc_setProperty(
2823 IXMLDOMDocument3
* iface
,
2827 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
2829 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(p
), debugstr_variant(&value
));
2831 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
2837 V_VT(&varStr
) = VT_EMPTY
;
2838 if (V_VT(&value
) != VT_BSTR
)
2840 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2842 bstr
= V_BSTR(&varStr
);
2845 bstr
= V_BSTR(&value
);
2848 if (lstrcmpiW(bstr
, PropValueXPathW
) == 0)
2849 This
->properties
->XPath
= TRUE
;
2850 else if (lstrcmpiW(bstr
, PropValueXSLPatternW
) == 0)
2851 This
->properties
->XPath
= FALSE
;
2855 VariantClear(&varStr
);
2858 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
2860 xmlChar
*nsStr
= (xmlChar
*)This
->properties
->selectNsStr
;
2861 struct list
*pNsList
;
2866 V_VT(&varStr
) = VT_EMPTY
;
2867 if (V_VT(&value
) != VT_BSTR
)
2869 if (FAILED(hr
= VariantChangeType(&varStr
, &value
, 0, VT_BSTR
)))
2871 bstr
= V_BSTR(&varStr
);
2874 bstr
= V_BSTR(&value
);
2878 pNsList
= &(This
->properties
->selectNsList
);
2879 clear_selectNsList(pNsList
);
2881 nsStr
= xmlchar_from_wchar(bstr
);
2883 TRACE("property value: \"%s\"\n", debugstr_w(bstr
));
2885 This
->properties
->selectNsStr
= nsStr
;
2886 This
->properties
->selectNsStr_len
= xmlStrlen(nsStr
);
2889 xmlChar
*pTokBegin
, *pTokEnd
, *pTokInner
;
2890 select_ns_entry
* ns_entry
= NULL
;
2891 xmlXPathContextPtr ctx
;
2893 ctx
= xmlXPathNewContext(This
->node
.node
->doc
);
2896 /* skip leading spaces */
2897 while (*pTokBegin
== ' ' || *pTokBegin
== '\n' ||
2898 *pTokBegin
== '\t' || *pTokBegin
== '\r')
2901 for (; *pTokBegin
; pTokBegin
= pTokEnd
)
2904 memset(ns_entry
, 0, sizeof(select_ns_entry
));
2906 ns_entry
= heap_alloc_zero(sizeof(select_ns_entry
));
2908 while (*pTokBegin
== ' ')
2910 pTokEnd
= pTokBegin
;
2911 while (*pTokEnd
!= ' ' && *pTokEnd
!= 0)
2914 /* so it failed to advance which means we've got some trailing spaces */
2915 if (pTokEnd
== pTokBegin
) break;
2917 if (xmlStrncmp(pTokBegin
, (xmlChar
const*)"xmlns", 5) != 0)
2920 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2921 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2926 if (*pTokBegin
== '=')
2928 /*valid for XSLPattern?*/
2929 FIXME("Setting default xmlns not supported - skipping.\n");
2932 else if (*pTokBegin
== ':')
2934 ns_entry
->prefix
= ++pTokBegin
;
2935 for (pTokInner
= pTokBegin
; pTokInner
!= pTokEnd
&& *pTokInner
!= '='; ++pTokInner
)
2938 if (pTokInner
== pTokEnd
)
2941 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2942 debugstr_w(bstr
), debugstr_an((const char*)pTokBegin
, pTokEnd
-pTokBegin
));
2946 ns_entry
->prefix_end
= *pTokInner
;
2950 if (pTokEnd
-pTokInner
> 1 &&
2951 ((*pTokInner
== '\'' && *(pTokEnd
-1) == '\'') ||
2952 (*pTokInner
== '"' && *(pTokEnd
-1) == '"')))
2954 ns_entry
->href
= ++pTokInner
;
2955 ns_entry
->href_end
= *(pTokEnd
-1);
2957 list_add_tail(pNsList
, &ns_entry
->entry
);
2958 /*let libxml figure out if they're valid from here ;)*/
2959 if (xmlXPathRegisterNs(ctx
, ns_entry
->prefix
, ns_entry
->href
) != 0)
2968 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2969 debugstr_w(bstr
), debugstr_an((const char*)pTokInner
, pTokEnd
-pTokInner
));
2970 list_add_tail(pNsList
, &ns_entry
->entry
);
2983 heap_free(ns_entry
);
2984 xmlXPathFreeContext(ctx
);
2987 VariantClear(&varStr
);
2990 else if (lstrcmpiW(p
, PropertyProhibitDTDW
) == 0 ||
2991 lstrcmpiW(p
, PropertyNewParserW
) == 0 ||
2992 lstrcmpiW(p
, PropertyResolveExternalsW
) == 0)
2995 FIXME("Ignoring property %s, value %s\n", debugstr_w(p
), debugstr_variant(&value
));
2999 FIXME("Unknown property %s\n", debugstr_w(p
));
3003 static HRESULT WINAPI
domdoc_getProperty(
3004 IXMLDOMDocument3
* iface
,
3008 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3010 TRACE("(%p)->(%s)\n", This
, debugstr_w(p
));
3013 return E_INVALIDARG
;
3015 if (lstrcmpiW(p
, PropertySelectionLanguageW
) == 0)
3017 V_VT(var
) = VT_BSTR
;
3018 V_BSTR(var
) = This
->properties
->XPath
?
3019 SysAllocString(PropValueXPathW
) :
3020 SysAllocString(PropValueXSLPatternW
);
3021 return V_BSTR(var
) ? S_OK
: E_OUTOFMEMORY
;
3023 else if (lstrcmpiW(p
, PropertySelectionNamespacesW
) == 0)
3026 BSTR rebuiltStr
, cur
;
3027 const xmlChar
*nsStr
;
3028 struct list
*pNsList
;
3029 select_ns_entry
* pNsEntry
;
3031 V_VT(var
) = VT_BSTR
;
3032 nsStr
= This
->properties
->selectNsStr
;
3033 pNsList
= &This
->properties
->selectNsList
;
3034 lenA
= This
->properties
->selectNsStr_len
;
3035 lenW
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, NULL
, 0);
3036 rebuiltStr
= heap_alloc(lenW
*sizeof(WCHAR
));
3037 MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)nsStr
, lenA
+1, rebuiltStr
, lenW
);
3039 /* this is fine because all of the chars that end tokens are ASCII*/
3040 LIST_FOR_EACH_ENTRY(pNsEntry
, pNsList
, select_ns_entry
, entry
)
3042 while (*cur
!= 0) ++cur
;
3043 if (pNsEntry
->prefix_end
)
3045 *cur
= pNsEntry
->prefix_end
;
3046 while (*cur
!= 0) ++cur
;
3049 if (pNsEntry
->href_end
)
3051 *cur
= pNsEntry
->href_end
;
3054 V_BSTR(var
) = SysAllocString(rebuiltStr
);
3055 heap_free(rebuiltStr
);
3059 FIXME("Unknown property %s\n", debugstr_w(p
));
3063 static HRESULT WINAPI
domdoc_importNode(
3064 IXMLDOMDocument3
* iface
,
3067 IXMLDOMNode
** clone
)
3069 domdoc
*This
= impl_from_IXMLDOMDocument3( iface
);
3070 FIXME("(%p)->(%p %d %p): stub\n", This
, node
, deep
, clone
);
3074 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl
=
3076 domdoc_QueryInterface
,
3079 domdoc_GetTypeInfoCount
,
3081 domdoc_GetIDsOfNames
,
3083 domdoc_get_nodeName
,
3084 domdoc_get_nodeValue
,
3085 domdoc_put_nodeValue
,
3086 domdoc_get_nodeType
,
3087 domdoc_get_parentNode
,
3088 domdoc_get_childNodes
,
3089 domdoc_get_firstChild
,
3090 domdoc_get_lastChild
,
3091 domdoc_get_previousSibling
,
3092 domdoc_get_nextSibling
,
3093 domdoc_get_attributes
,
3094 domdoc_insertBefore
,
3095 domdoc_replaceChild
,
3098 domdoc_hasChildNodes
,
3099 domdoc_get_ownerDocument
,
3101 domdoc_get_nodeTypeString
,
3104 domdoc_get_specified
,
3105 domdoc_get_definition
,
3106 domdoc_get_nodeTypedValue
,
3107 domdoc_put_nodeTypedValue
,
3108 domdoc_get_dataType
,
3109 domdoc_put_dataType
,
3111 domdoc_transformNode
,
3113 domdoc_selectSingleNode
,
3115 domdoc_get_namespaceURI
,
3117 domdoc_get_baseName
,
3118 domdoc_transformNodeToObject
,
3120 domdoc_get_implementation
,
3121 domdoc_get_documentElement
,
3122 domdoc_put_documentElement
,
3123 domdoc_createElement
,
3124 domdoc_createDocumentFragment
,
3125 domdoc_createTextNode
,
3126 domdoc_createComment
,
3127 domdoc_createCDATASection
,
3128 domdoc_createProcessingInstruction
,
3129 domdoc_createAttribute
,
3130 domdoc_createEntityReference
,
3131 domdoc_getElementsByTagName
,
3135 domdoc_get_readyState
,
3136 domdoc_get_parseError
,
3143 domdoc_get_validateOnParse
,
3144 domdoc_put_validateOnParse
,
3145 domdoc_get_resolveExternals
,
3146 domdoc_put_resolveExternals
,
3147 domdoc_get_preserveWhiteSpace
,
3148 domdoc_put_preserveWhiteSpace
,
3149 domdoc_put_onreadystatechange
,
3150 domdoc_put_onDataAvailable
,
3151 domdoc_put_onTransformNode
,
3152 domdoc_get_namespaces
,
3154 domdoc_putref_schemas
,
3158 domdoc_validateNode
,
3162 /* IConnectionPointContainer */
3163 static HRESULT WINAPI
ConnectionPointContainer_QueryInterface(IConnectionPointContainer
*iface
,
3164 REFIID riid
, void **ppv
)
3166 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3167 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3170 static ULONG WINAPI
ConnectionPointContainer_AddRef(IConnectionPointContainer
*iface
)
3172 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3173 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3176 static ULONG WINAPI
ConnectionPointContainer_Release(IConnectionPointContainer
*iface
)
3178 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3179 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3182 static HRESULT WINAPI
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer
*iface
,
3183 IEnumConnectionPoints
**ppEnum
)
3185 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3186 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3190 static HRESULT WINAPI
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer
*iface
,
3191 REFIID riid
, IConnectionPoint
**cp
)
3193 domdoc
*This
= impl_from_IConnectionPointContainer(iface
);
3194 ConnectionPoint
*iter
;
3196 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), cp
);
3200 for(iter
= This
->cp_list
; iter
; iter
= iter
->next
)
3202 if (IsEqualGUID(iter
->iid
, riid
))
3203 *cp
= &iter
->IConnectionPoint_iface
;
3208 IConnectionPoint_AddRef(*cp
);
3212 FIXME("unsupported riid %s\n", debugstr_guid(riid
));
3213 return CONNECT_E_NOCONNECTION
;
3217 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl
=
3219 ConnectionPointContainer_QueryInterface
,
3220 ConnectionPointContainer_AddRef
,
3221 ConnectionPointContainer_Release
,
3222 ConnectionPointContainer_EnumConnectionPoints
,
3223 ConnectionPointContainer_FindConnectionPoint
3226 /* IConnectionPoint */
3227 static HRESULT WINAPI
ConnectionPoint_QueryInterface(IConnectionPoint
*iface
,
3228 REFIID riid
, void **ppv
)
3230 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3232 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
3236 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
3237 IsEqualGUID(&IID_IConnectionPoint
, riid
))
3244 IConnectionPoint_AddRef(iface
);
3248 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
3249 return E_NOINTERFACE
;
3252 static ULONG WINAPI
ConnectionPoint_AddRef(IConnectionPoint
*iface
)
3254 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3255 return IConnectionPointContainer_AddRef(This
->container
);
3258 static ULONG WINAPI
ConnectionPoint_Release(IConnectionPoint
*iface
)
3260 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3261 return IConnectionPointContainer_Release(This
->container
);
3264 static HRESULT WINAPI
ConnectionPoint_GetConnectionInterface(IConnectionPoint
*iface
, IID
*iid
)
3266 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3268 TRACE("(%p)->(%p)\n", This
, iid
);
3270 if (!iid
) return E_POINTER
;
3276 static HRESULT WINAPI
ConnectionPoint_GetConnectionPointContainer(IConnectionPoint
*iface
,
3277 IConnectionPointContainer
**container
)
3279 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3281 TRACE("(%p)->(%p)\n", This
, container
);
3283 if (!container
) return E_POINTER
;
3285 *container
= This
->container
;
3286 IConnectionPointContainer_AddRef(*container
);
3290 static HRESULT WINAPI
ConnectionPoint_Advise(IConnectionPoint
*iface
, IUnknown
*unk_sink
,
3293 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3298 TRACE("(%p)->(%p %p)\n", This
, unk_sink
, cookie
);
3300 hr
= IUnknown_QueryInterface(unk_sink
, This
->iid
, (void**)&sink
);
3301 if(FAILED(hr
) && !IsEqualGUID(&IID_IPropertyNotifySink
, This
->iid
))
3302 hr
= IUnknown_QueryInterface(unk_sink
, &IID_IDispatch
, (void**)&sink
);
3304 return CONNECT_E_CANNOTCONNECT
;
3308 for (i
= 0; i
< This
->sinks_size
; i
++)
3309 if (!This
->sinks
[i
].unk
)
3312 if (i
== This
->sinks_size
)
3313 This
->sinks
= heap_realloc(This
->sinks
,(++This
->sinks_size
)*sizeof(*This
->sinks
));
3317 This
->sinks
= heap_alloc(sizeof(*This
->sinks
));
3318 This
->sinks_size
= 1;
3322 This
->sinks
[i
].unk
= sink
;
3329 static HRESULT WINAPI
ConnectionPoint_Unadvise(IConnectionPoint
*iface
, DWORD cookie
)
3331 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3333 TRACE("(%p)->(%d)\n", This
, cookie
);
3335 if (cookie
== 0 || cookie
> This
->sinks_size
|| !This
->sinks
[cookie
-1].unk
)
3336 return CONNECT_E_NOCONNECTION
;
3338 IUnknown_Release(This
->sinks
[cookie
-1].unk
);
3339 This
->sinks
[cookie
-1].unk
= NULL
;
3344 static HRESULT WINAPI
ConnectionPoint_EnumConnections(IConnectionPoint
*iface
,
3345 IEnumConnections
**ppEnum
)
3347 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
3348 FIXME("(%p)->(%p): stub\n", This
, ppEnum
);
3352 static const IConnectionPointVtbl ConnectionPointVtbl
=
3354 ConnectionPoint_QueryInterface
,
3355 ConnectionPoint_AddRef
,
3356 ConnectionPoint_Release
,
3357 ConnectionPoint_GetConnectionInterface
,
3358 ConnectionPoint_GetConnectionPointContainer
,
3359 ConnectionPoint_Advise
,
3360 ConnectionPoint_Unadvise
,
3361 ConnectionPoint_EnumConnections
3364 static void ConnectionPoint_Init(ConnectionPoint
*cp
, struct domdoc
*doc
, REFIID riid
)
3366 cp
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointVtbl
;
3372 cp
->next
= doc
->cp_list
;
3375 cp
->container
= &doc
->IConnectionPointContainer_iface
;
3378 /* domdoc implementation of IObjectWithSite */
3379 static HRESULT WINAPI
3380 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
3382 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3383 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppvObject
);
3386 static ULONG WINAPI
domdoc_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
3388 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3389 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3392 static ULONG WINAPI
domdoc_ObjectWithSite_Release( IObjectWithSite
* iface
)
3394 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3395 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3398 static HRESULT WINAPI
domdoc_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
3400 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3402 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
3407 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
3410 static HRESULT WINAPI
domdoc_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
3412 domdoc
*This
= impl_from_IObjectWithSite(iface
);
3414 TRACE("(%p)->(%p)\n", iface
, punk
);
3420 IUnknown_Release( This
->site
);
3427 IUnknown_AddRef( punk
);
3430 IUnknown_Release( This
->site
);
3437 static const IObjectWithSiteVtbl domdocObjectSite
=
3439 domdoc_ObjectWithSite_QueryInterface
,
3440 domdoc_ObjectWithSite_AddRef
,
3441 domdoc_ObjectWithSite_Release
,
3442 domdoc_ObjectWithSite_SetSite
,
3443 domdoc_ObjectWithSite_GetSite
3446 static HRESULT WINAPI
domdoc_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
3448 domdoc
*This
= impl_from_IObjectSafety(iface
);
3449 return IXMLDOMDocument3_QueryInterface(&This
->IXMLDOMDocument3_iface
, riid
, ppv
);
3452 static ULONG WINAPI
domdoc_Safety_AddRef(IObjectSafety
*iface
)
3454 domdoc
*This
= impl_from_IObjectSafety(iface
);
3455 return IXMLDOMDocument3_AddRef(&This
->IXMLDOMDocument3_iface
);
3458 static ULONG WINAPI
domdoc_Safety_Release(IObjectSafety
*iface
)
3460 domdoc
*This
= impl_from_IObjectSafety(iface
);
3461 return IXMLDOMDocument3_Release(&This
->IXMLDOMDocument3_iface
);
3464 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3466 static HRESULT WINAPI
domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3467 DWORD
*supported
, DWORD
*enabled
)
3469 domdoc
*This
= impl_from_IObjectSafety(iface
);
3471 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
3473 if(!supported
|| !enabled
) return E_POINTER
;
3475 *supported
= SAFETY_SUPPORTED_OPTIONS
;
3476 *enabled
= This
->safeopt
;
3481 static HRESULT WINAPI
domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
3482 DWORD mask
, DWORD enabled
)
3484 domdoc
*This
= impl_from_IObjectSafety(iface
);
3485 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
3487 if ((mask
& ~SAFETY_SUPPORTED_OPTIONS
) != 0)
3490 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
3495 #undef SAFETY_SUPPORTED_OPTIONS
3497 static const IObjectSafetyVtbl domdocObjectSafetyVtbl
= {
3498 domdoc_Safety_QueryInterface
,
3499 domdoc_Safety_AddRef
,
3500 domdoc_Safety_Release
,
3501 domdoc_Safety_GetInterfaceSafetyOptions
,
3502 domdoc_Safety_SetInterfaceSafetyOptions
3505 static const tid_t domdoc_iface_tids
[] = {
3506 IXMLDOMDocument3_tid
,
3510 static dispex_static_data_t domdoc_dispex
= {
3512 IXMLDOMDocument3_tid
,
3517 HRESULT
get_domdoc_from_xmldoc(xmlDocPtr xmldoc
, IXMLDOMDocument3
**document
)
3521 doc
= heap_alloc( sizeof (*doc
) );
3523 return E_OUTOFMEMORY
;
3525 doc
->IXMLDOMDocument3_iface
.lpVtbl
= &XMLDOMDocument3Vtbl
;
3526 doc
->IPersistStreamInit_iface
.lpVtbl
= &xmldoc_IPersistStreamInit_VTable
;
3527 doc
->IObjectWithSite_iface
.lpVtbl
= &domdocObjectSite
;
3528 doc
->IObjectSafety_iface
.lpVtbl
= &domdocObjectSafetyVtbl
;
3529 doc
->IConnectionPointContainer_iface
.lpVtbl
= &ConnectionPointContainerVtbl
;
3531 doc
->async
= VARIANT_TRUE
;
3532 doc
->validating
= 0;
3534 doc
->properties
= properties_from_xmlDocPtr(xmldoc
);
3539 doc
->cp_list
= NULL
;
3540 doc
->namespaces
= NULL
;
3541 memset(doc
->events
, 0, sizeof(doc
->events
));
3543 /* events connection points */
3544 ConnectionPoint_Init(&doc
->cp_dispatch
, doc
, &IID_IDispatch
);
3545 ConnectionPoint_Init(&doc
->cp_propnotif
, doc
, &IID_IPropertyNotifySink
);
3546 ConnectionPoint_Init(&doc
->cp_domdocevents
, doc
, &DIID_XMLDOMDocumentEvents
);
3548 init_xmlnode(&doc
->node
, (xmlNodePtr
)xmldoc
, (IXMLDOMNode
*)&doc
->IXMLDOMDocument3_iface
,
3551 *document
= &doc
->IXMLDOMDocument3_iface
;
3553 TRACE("returning iface %p\n", *document
);
3557 HRESULT
DOMDocument_create(MSXML_VERSION version
, IUnknown
*pUnkOuter
, void **ppObj
)
3562 TRACE("(%d, %p, %p)\n", version
, pUnkOuter
, ppObj
);
3564 xmldoc
= xmlNewDoc(NULL
);
3566 return E_OUTOFMEMORY
;
3568 xmldoc_init(xmldoc
, version
);
3570 hr
= get_domdoc_from_xmldoc(xmldoc
, (IXMLDOMDocument3
**)ppObj
);
3573 free_properties(properties_from_xmlDocPtr(xmldoc
));
3574 heap_free(xmldoc
->_private
);
3582 IUnknown
* create_domdoc( xmlNodePtr document
)
3587 TRACE("(%p)\n", document
);
3589 hr
= get_domdoc_from_xmldoc((xmlDocPtr
)document
, (IXMLDOMDocument3
**)&pObj
);
3598 HRESULT
DOMDocument_create(MSXML_VERSION version
, IUnknown
*pUnkOuter
, void **ppObj
)
3600 MESSAGE("This program tried to use a DOMDocument object, but\n"
3601 "libxml2 support was not present at compile time.\n");