rpcrt4: Write the function header into the procedure format string.
[wine.git] / dlls / msxml3 / domdoc.c
blob445caaee69b46c05ab43d57edbf5b4f88554fdff
1 /*
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 COBJMACROS
24 #include "config.h"
26 #include <stdarg.h>
27 #include <assert.h>
28 #ifdef HAVE_LIBXML2
29 # include <libxml/parser.h>
30 # include <libxml/xmlerror.h>
31 # include <libxml/xpathInternals.h>
32 # include <libxml/xmlsave.h>
33 # include <libxml/SAX2.h>
34 # include <libxml/parserInternals.h>
35 #endif
37 #include "windef.h"
38 #include "winbase.h"
39 #include "winuser.h"
40 #include "winnls.h"
41 #include "ole2.h"
42 #include "olectl.h"
43 #include "msxml6.h"
44 #include "wininet.h"
45 #include "winreg.h"
46 #include "shlwapi.h"
47 #include "ocidl.h"
48 #include "objsafe.h"
50 #include "wine/debug.h"
52 #include "msxml_private.h"
54 #ifdef HAVE_LIBXML2
56 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
58 /* not defined in older versions */
59 #define XML_SAVE_FORMAT 1
60 #define XML_SAVE_NO_DECL 2
61 #define XML_SAVE_NO_EMPTY 4
62 #define XML_SAVE_NO_XHTML 8
63 #define XML_SAVE_XHTML 16
64 #define XML_SAVE_AS_XML 32
65 #define XML_SAVE_AS_HTML 64
67 static const WCHAR PropertySelectionLanguageW[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
68 static const WCHAR PropertySelectionNamespacesW[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
69 static const WCHAR PropertyProhibitDTDW[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
70 static const WCHAR PropertyNewParserW[] = {'N','e','w','P','a','r','s','e','r',0};
71 static const WCHAR PropValueXPathW[] = {'X','P','a','t','h',0};
72 static const WCHAR PropValueXSLPatternW[] = {'X','S','L','P','a','t','t','e','r','n',0};
73 static const WCHAR PropertyResolveExternalsW[] = {'R','e','s','o','l','v','e','E','x','t','e','r','n','a','l','s',0};
74 static const WCHAR PropertyAllowXsltScriptW[] = {'A','l','l','o','w','X','s','l','t','S','c','r','i','p','t',0};
75 static const WCHAR PropertyAllowDocumentFunctionW[] = {'A','l','l','o','w','D','o','c','u','m','e','n','t','F','u','n','c','t','i','o','n',0};
76 static const WCHAR PropertyNormalizeAttributeValuesW[] = {'N','o','r','m','a','l','i','z','e','A','t','t','r','i','b','u','t','e','V','a','l','u','e','s',0};
78 /* Anything that passes the test_get_ownerDocument()
79 * tests can go here (data shared between all instances).
80 * We need to preserve this when reloading a document,
81 * and also need access to it from the libxml backend. */
82 typedef struct {
83 MSXML_VERSION version;
84 VARIANT_BOOL preserving;
85 IXMLDOMSchemaCollection2* schemaCache;
86 struct list selectNsList;
87 xmlChar const* selectNsStr;
88 LONG selectNsStr_len;
89 BOOL XPath;
90 IUri *uri;
91 } domdoc_properties;
93 typedef struct ConnectionPoint ConnectionPoint;
94 typedef struct domdoc domdoc;
96 struct ConnectionPoint
98 IConnectionPoint IConnectionPoint_iface;
99 const IID *iid;
101 ConnectionPoint *next;
102 IConnectionPointContainer *container;
103 domdoc *doc;
105 union
107 IUnknown *unk;
108 IDispatch *disp;
109 IPropertyNotifySink *propnotif;
110 } *sinks;
111 DWORD sinks_size;
114 typedef enum {
115 EVENTID_READYSTATECHANGE = 0,
116 EVENTID_DATAAVAILABLE,
117 EVENTID_TRANSFORMNODE,
118 EVENTID_LAST
119 } eventid_t;
121 struct domdoc
123 xmlnode node;
124 IXMLDOMDocument3 IXMLDOMDocument3_iface;
125 IPersistStreamInit IPersistStreamInit_iface;
126 IObjectWithSite IObjectWithSite_iface;
127 IObjectSafety IObjectSafety_iface;
128 IConnectionPointContainer IConnectionPointContainer_iface;
129 LONG ref;
130 VARIANT_BOOL async;
131 VARIANT_BOOL validating;
132 VARIANT_BOOL resolving;
133 domdoc_properties* properties;
134 HRESULT error;
136 /* IObjectWithSite */
137 IUnknown *site;
139 /* IObjectSafety */
140 DWORD safeopt;
142 /* connection list */
143 ConnectionPoint *cp_list;
144 ConnectionPoint cp_domdocevents;
145 ConnectionPoint cp_propnotif;
146 ConnectionPoint cp_dispatch;
148 /* events */
149 IDispatch *events[EVENTID_LAST];
151 IXMLDOMSchemaCollection2 *namespaces;
154 static HRESULT set_doc_event(domdoc *doc, eventid_t eid, const VARIANT *v)
156 IDispatch *disp;
158 switch (V_VT(v))
160 case VT_UNKNOWN:
161 if (V_UNKNOWN(v))
162 IUnknown_QueryInterface(V_UNKNOWN(v), &IID_IDispatch, (void**)&disp);
163 else
164 disp = NULL;
165 break;
166 case VT_DISPATCH:
167 disp = V_DISPATCH(v);
168 if (disp) IDispatch_AddRef(disp);
169 break;
170 default:
171 return DISP_E_TYPEMISMATCH;
174 if (doc->events[eid]) IDispatch_Release(doc->events[eid]);
175 doc->events[eid] = disp;
177 return S_OK;
180 static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface)
182 return CONTAINING_RECORD(iface, ConnectionPoint, IConnectionPoint_iface);
186 In native windows, the whole lifetime management of XMLDOMNodes is
187 managed automatically using reference counts. Wine emulates that by
188 maintaining a reference count to the document that is increased for
189 each IXMLDOMNode pointer passed out for this document. If all these
190 pointers are gone, the document is unreachable and gets freed, that
191 is, all nodes in the tree of the document get freed.
193 You are able to create nodes that are associated to a document (in
194 fact, in msxml's XMLDOM model, all nodes are associated to a document),
195 but not in the tree of that document, for example using the createFoo
196 functions from IXMLDOMDocument. These nodes do not get cleaned up
197 by libxml, so we have to do it ourselves.
199 To catch these nodes, a list of "orphan nodes" is introduced.
200 It contains pointers to all roots of node trees that are
201 associated with the document without being part of the document
202 tree. All nodes with parent==NULL (except for the document root nodes)
203 should be in the orphan node list of their document. All orphan nodes
204 get freed together with the document itself.
207 typedef struct _xmldoc_priv {
208 LONG refs;
209 struct list orphans;
210 domdoc_properties* properties;
211 } xmldoc_priv;
213 typedef struct _orphan_entry {
214 struct list entry;
215 xmlNode * node;
216 } orphan_entry;
218 typedef struct _select_ns_entry {
219 struct list entry;
220 xmlChar const* prefix;
221 xmlChar prefix_end;
222 xmlChar const* href;
223 xmlChar href_end;
224 } select_ns_entry;
226 static inline xmldoc_priv * priv_from_xmlDocPtr(const xmlDocPtr doc)
228 return doc->_private;
231 static inline domdoc_properties * properties_from_xmlDocPtr(xmlDocPtr doc)
233 return priv_from_xmlDocPtr(doc)->properties;
236 BOOL is_xpathmode(const xmlDocPtr doc)
238 return properties_from_xmlDocPtr(doc)->XPath;
241 void set_xpathmode(xmlDocPtr doc, BOOL xpath)
243 properties_from_xmlDocPtr(doc)->XPath = xpath;
246 int registerNamespaces(xmlXPathContextPtr ctxt)
248 int n = 0;
249 const select_ns_entry* ns = NULL;
250 const struct list* pNsList = &properties_from_xmlDocPtr(ctxt->doc)->selectNsList;
252 TRACE("(%p)\n", ctxt);
254 LIST_FOR_EACH_ENTRY( ns, pNsList, select_ns_entry, entry )
256 xmlXPathRegisterNs(ctxt, ns->prefix, ns->href);
257 ++n;
260 return n;
263 static inline void clear_selectNsList(struct list* pNsList)
265 select_ns_entry *ns, *ns2;
266 LIST_FOR_EACH_ENTRY_SAFE( ns, ns2, pNsList, select_ns_entry, entry )
268 heap_free( ns );
270 list_init(pNsList);
273 static xmldoc_priv * create_priv(void)
275 xmldoc_priv *priv;
276 priv = heap_alloc( sizeof (*priv) );
278 if (priv)
280 priv->refs = 0;
281 list_init( &priv->orphans );
282 priv->properties = NULL;
285 return priv;
288 static domdoc_properties *create_properties(MSXML_VERSION version)
290 domdoc_properties *properties = heap_alloc(sizeof(domdoc_properties));
292 list_init(&properties->selectNsList);
293 properties->preserving = VARIANT_FALSE;
294 properties->schemaCache = NULL;
295 properties->selectNsStr = heap_alloc_zero(sizeof(xmlChar));
296 properties->selectNsStr_len = 0;
298 /* properties that are dependent on object versions */
299 properties->version = version;
300 properties->XPath = (version == MSXML4 || version == MSXML6);
302 /* document uri */
303 properties->uri = NULL;
305 return properties;
308 static domdoc_properties* copy_properties(domdoc_properties const* properties)
310 domdoc_properties* pcopy = heap_alloc(sizeof(domdoc_properties));
311 select_ns_entry const* ns = NULL;
312 select_ns_entry* new_ns = NULL;
313 int len = (properties->selectNsStr_len+1)*sizeof(xmlChar);
314 ptrdiff_t offset;
316 if (pcopy)
318 pcopy->version = properties->version;
319 pcopy->preserving = properties->preserving;
320 pcopy->schemaCache = properties->schemaCache;
321 if (pcopy->schemaCache)
322 IXMLDOMSchemaCollection2_AddRef(pcopy->schemaCache);
323 pcopy->XPath = properties->XPath;
324 pcopy->selectNsStr_len = properties->selectNsStr_len;
325 list_init( &pcopy->selectNsList );
326 pcopy->selectNsStr = heap_alloc(len);
327 memcpy((xmlChar*)pcopy->selectNsStr, properties->selectNsStr, len);
328 offset = pcopy->selectNsStr - properties->selectNsStr;
330 LIST_FOR_EACH_ENTRY( ns, (&properties->selectNsList), select_ns_entry, entry )
332 new_ns = heap_alloc(sizeof(select_ns_entry));
333 memcpy(new_ns, ns, sizeof(select_ns_entry));
334 new_ns->href += offset;
335 new_ns->prefix += offset;
336 list_add_tail(&pcopy->selectNsList, &new_ns->entry);
339 pcopy->uri = properties->uri;
340 if (pcopy->uri)
341 IUri_AddRef(pcopy->uri);
344 return pcopy;
347 static void free_properties(domdoc_properties* properties)
349 if (properties)
351 if (properties->schemaCache)
352 IXMLDOMSchemaCollection2_Release(properties->schemaCache);
353 clear_selectNsList(&properties->selectNsList);
354 heap_free((xmlChar*)properties->selectNsStr);
355 if (properties->uri)
356 IUri_Release(properties->uri);
357 heap_free(properties);
361 static void release_namespaces(domdoc *This)
363 if (This->namespaces)
365 IXMLDOMSchemaCollection2_Release(This->namespaces);
366 This->namespaces = NULL;
370 /* links a "<?xml" node as a first child */
371 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
373 assert(doc != NULL);
374 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
377 /* unlinks a first "<?xml" child if it was created */
378 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
380 static const xmlChar xmlA[] = "xml";
381 xmlNodePtr node, first_child;
383 assert(doc != NULL);
385 /* xml declaration node could be created automatically after parsing or added
386 to a tree later */
387 first_child = doc->children;
388 if (first_child && first_child->type == XML_PI_NODE && xmlStrEqual(first_child->name, xmlA))
390 node = first_child;
391 xmlUnlinkNode( node );
393 else
394 node = NULL;
396 return node;
399 MSXML_VERSION xmldoc_version(xmlDocPtr doc)
401 return properties_from_xmlDocPtr(doc)->version;
404 BOOL is_preserving_whitespace(xmlNodePtr node)
406 domdoc_properties* properties = NULL;
407 /* during parsing the xmlDoc._private stuff is not there */
408 if (priv_from_xmlDocPtr(node->doc))
409 properties = properties_from_xmlDocPtr(node->doc);
410 return ((properties && properties->preserving == VARIANT_TRUE) ||
411 xmlNodeGetSpacePreserve(node) == 1);
414 static inline BOOL strn_isspace(xmlChar const* str, int len)
416 for (; str && len > 0 && *str; ++str, --len)
417 if (!isspace(*str))
418 break;
420 return len == 0;
423 static void sax_characters(void *ctx, const xmlChar *ch, int len)
425 xmlParserCtxtPtr ctxt;
426 const domdoc *This;
428 ctxt = (xmlParserCtxtPtr) ctx;
429 This = (const domdoc*) ctxt->_private;
431 if (ctxt->node)
433 xmlChar cur = *(ctxt->input->cur);
435 /* Characters are reported with multiple calls, for example each charref is reported with a separate
436 call and then parser appends it to a single text node or creates a new node if not created.
437 It's not possible to tell if it's ignorable data or not just looking at data itself cause it could be
438 space chars that separate charrefs or similar case. We only need to skip leading and trailing spaces,
439 or whole node if it has nothing but space chars, so to detect leading space node->last is checked that
440 contains text node pointer if already created, trailing spaces are detected directly looking at parser input
441 for next '<' opening bracket - similar logic is used by libxml2 itself. Basically 'cur' == '<' means the last
442 chunk of char data, in case it's not the last chunk we check for previously added node type and if it's not
443 a text node it's safe to ignore.
445 Note that during domdoc_loadXML() the xmlDocPtr->_private data is not available. */
447 if (!This->properties->preserving &&
448 !is_preserving_whitespace(ctxt->node) &&
449 strn_isspace(ch, len) &&
450 (!ctxt->node->last ||
451 ((ctxt->node->last && (cur == '<' || ctxt->node->last->type != XML_TEXT_NODE))
454 /* Keep information about ignorable whitespace text node in previous or parent node */
455 if (ctxt->node->last)
456 *(DWORD*)&ctxt->node->last->_private |= NODE_PRIV_TRAILING_IGNORABLE_WS;
457 else if (ctxt->node->type != XML_DOCUMENT_NODE)
458 *(DWORD*)&ctxt->node->_private |= NODE_PRIV_CHILD_IGNORABLE_WS;
459 return;
463 xmlSAX2Characters(ctxt, ch, len);
466 static void LIBXML2_LOG_CALLBACK sax_error(void* ctx, char const* msg, ...)
468 va_list ap;
469 va_start(ap, msg);
470 LIBXML2_CALLBACK_ERR(doparse, msg, ap);
471 va_end(ap);
474 static void LIBXML2_LOG_CALLBACK sax_warning(void* ctx, char const* msg, ...)
476 va_list ap;
477 va_start(ap, msg);
478 LIBXML2_CALLBACK_WARN(doparse, msg, ap);
479 va_end(ap);
482 static void sax_serror(void* ctx, xmlErrorPtr err)
484 LIBXML2_CALLBACK_SERROR(doparse, err);
487 static xmlDocPtr doparse(domdoc* This, char const* ptr, int len, xmlCharEncoding encoding)
489 xmlDocPtr doc = NULL;
490 xmlParserCtxtPtr pctx;
491 static xmlSAXHandler sax_handler = {
492 xmlSAX2InternalSubset, /* internalSubset */
493 xmlSAX2IsStandalone, /* isStandalone */
494 xmlSAX2HasInternalSubset, /* hasInternalSubset */
495 xmlSAX2HasExternalSubset, /* hasExternalSubset */
496 xmlSAX2ResolveEntity, /* resolveEntity */
497 xmlSAX2GetEntity, /* getEntity */
498 xmlSAX2EntityDecl, /* entityDecl */
499 xmlSAX2NotationDecl, /* notationDecl */
500 xmlSAX2AttributeDecl, /* attributeDecl */
501 xmlSAX2ElementDecl, /* elementDecl */
502 xmlSAX2UnparsedEntityDecl, /* unparsedEntityDecl */
503 xmlSAX2SetDocumentLocator, /* setDocumentLocator */
504 xmlSAX2StartDocument, /* startDocument */
505 xmlSAX2EndDocument, /* endDocument */
506 xmlSAX2StartElement, /* startElement */
507 xmlSAX2EndElement, /* endElement */
508 xmlSAX2Reference, /* reference */
509 sax_characters, /* characters */
510 sax_characters, /* ignorableWhitespace */
511 xmlSAX2ProcessingInstruction, /* processingInstruction */
512 xmlSAX2Comment, /* comment */
513 sax_warning, /* warning */
514 sax_error, /* error */
515 sax_error, /* fatalError */
516 xmlSAX2GetParameterEntity, /* getParameterEntity */
517 xmlSAX2CDataBlock, /* cdataBlock */
518 xmlSAX2ExternalSubset, /* externalSubset */
519 0, /* initialized */
520 NULL, /* _private */
521 xmlSAX2StartElementNs, /* startElementNs */
522 xmlSAX2EndElementNs, /* endElementNs */
523 sax_serror /* serror */
526 pctx = xmlCreateMemoryParserCtxt(ptr, len);
527 if (!pctx)
529 ERR("Failed to create parser context\n");
530 return NULL;
533 if (pctx->sax) xmlFree(pctx->sax);
534 pctx->sax = &sax_handler;
535 pctx->_private = This;
536 pctx->recovery = 0;
538 if (encoding != XML_CHAR_ENCODING_NONE)
539 xmlSwitchEncoding(pctx, encoding);
541 xmlParseDocument(pctx);
543 if (pctx->wellFormed)
545 doc = pctx->myDoc;
547 else
549 xmlFreeDoc(pctx->myDoc);
550 pctx->myDoc = NULL;
552 pctx->sax = NULL;
553 xmlFreeParserCtxt(pctx);
555 /* TODO: put this in one of the SAX callbacks */
556 /* create first child as a <?xml...?> */
557 if (doc && doc->standalone != -1)
559 xmlNodePtr node;
560 char buff[30];
561 xmlChar *xmlbuff = (xmlChar*)buff;
563 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
565 /* version attribute can't be omitted */
566 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
567 xmlNodeAddContent( node, xmlbuff );
569 if (doc->encoding)
571 sprintf(buff, " encoding=\"%s\"", doc->encoding);
572 xmlNodeAddContent( node, xmlbuff );
575 if (doc->standalone != -2)
577 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
578 xmlNodeAddContent( node, xmlbuff );
581 xmldoc_link_xmldecl( doc, node );
584 return doc;
587 void xmldoc_init(xmlDocPtr doc, MSXML_VERSION version)
589 doc->_private = create_priv();
590 priv_from_xmlDocPtr(doc)->properties = create_properties(version);
593 LONG xmldoc_add_refs(xmlDocPtr doc, LONG refs)
595 LONG ref = InterlockedExchangeAdd(&priv_from_xmlDocPtr(doc)->refs, refs) + refs;
596 TRACE("(%p)->(%d)\n", doc, ref);
597 return ref;
600 LONG xmldoc_add_ref(xmlDocPtr doc)
602 return xmldoc_add_refs(doc, 1);
605 LONG xmldoc_release_refs(xmlDocPtr doc, LONG refs)
607 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
608 LONG ref = InterlockedExchangeAdd(&priv->refs, -refs) - refs;
609 TRACE("(%p)->(%d)\n", doc, ref);
611 if (ref < 0)
612 WARN("negative refcount, expect troubles\n");
614 if (ref == 0)
616 orphan_entry *orphan, *orphan2;
617 TRACE("freeing docptr %p\n", doc);
619 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
621 xmlFreeNode( orphan->node );
622 heap_free( orphan );
624 free_properties(priv->properties);
625 heap_free(doc->_private);
627 xmlFreeDoc(doc);
630 return ref;
633 LONG xmldoc_release(xmlDocPtr doc)
635 return xmldoc_release_refs(doc, 1);
638 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
640 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
641 orphan_entry *entry;
643 entry = heap_alloc( sizeof (*entry) );
644 if(!entry)
645 return E_OUTOFMEMORY;
647 entry->node = node;
648 list_add_head( &priv->orphans, &entry->entry );
649 return S_OK;
652 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
654 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
655 orphan_entry *entry, *entry2;
657 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
659 if( entry->node == node )
661 list_remove( &entry->entry );
662 heap_free( entry );
663 return S_OK;
667 return S_FALSE;
670 static inline xmlDocPtr get_doc( domdoc *This )
672 return This->node.node->doc;
675 static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
677 release_namespaces(This);
679 if(This->node.node)
681 priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
682 if (xmldoc_release(get_doc(This)) != 0)
683 priv_from_xmlDocPtr(get_doc(This))->properties =
684 copy_properties(This->properties);
687 This->node.node = (xmlNodePtr) xml;
689 if(This->node.node)
691 xmldoc_add_ref(get_doc(This));
692 priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
695 return S_OK;
698 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
700 return CONTAINING_RECORD(iface, domdoc, IXMLDOMDocument3_iface);
703 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
705 return CONTAINING_RECORD(iface, domdoc, IPersistStreamInit_iface);
708 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
710 return CONTAINING_RECORD(iface, domdoc, IObjectWithSite_iface);
713 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
715 return CONTAINING_RECORD(iface, domdoc, IObjectSafety_iface);
718 static inline domdoc *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
720 return CONTAINING_RECORD(iface, domdoc, IConnectionPointContainer_iface);
723 /************************************************************************
724 * domdoc implementation of IPersistStream.
726 static HRESULT WINAPI PersistStreamInit_QueryInterface(
727 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
729 domdoc* This = impl_from_IPersistStreamInit(iface);
730 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppvObj);
733 static ULONG WINAPI PersistStreamInit_AddRef(
734 IPersistStreamInit *iface)
736 domdoc* This = impl_from_IPersistStreamInit(iface);
737 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
740 static ULONG WINAPI PersistStreamInit_Release(
741 IPersistStreamInit *iface)
743 domdoc* This = impl_from_IPersistStreamInit(iface);
744 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
747 static HRESULT WINAPI PersistStreamInit_GetClassID(
748 IPersistStreamInit *iface, CLSID *classid)
750 domdoc* This = impl_from_IPersistStreamInit(iface);
751 TRACE("(%p)->(%p)\n", This, classid);
753 if(!classid)
754 return E_POINTER;
756 *classid = *DOMDocument_version(This->properties->version);
758 return S_OK;
761 static HRESULT WINAPI PersistStreamInit_IsDirty(
762 IPersistStreamInit *iface)
764 domdoc *This = impl_from_IPersistStreamInit(iface);
765 FIXME("(%p): stub!\n", This);
766 return S_FALSE;
769 static HRESULT domdoc_load_from_stream(domdoc *doc, ISequentialStream *stream)
771 DWORD read, written, len;
772 xmlDocPtr xmldoc = NULL;
773 IStream *hstream;
774 HGLOBAL hglobal;
775 BYTE buf[4096];
776 HRESULT hr;
777 char *ptr;
779 hstream = NULL;
780 hr = CreateStreamOnHGlobal(NULL, TRUE, &hstream);
781 if (FAILED(hr))
782 return hr;
786 ISequentialStream_Read(stream, buf, sizeof(buf), &read);
787 hr = IStream_Write(hstream, buf, read, &written);
788 } while(SUCCEEDED(hr) && written != 0 && read != 0);
790 if (FAILED(hr))
792 ERR("failed to copy stream 0x%08x\n", hr);
793 IStream_Release(hstream);
794 return hr;
797 hr = GetHGlobalFromStream(hstream, &hglobal);
798 if (FAILED(hr))
799 return hr;
801 len = GlobalSize(hglobal);
802 ptr = GlobalLock(hglobal);
803 if (len)
804 xmldoc = doparse(doc, ptr, len, XML_CHAR_ENCODING_NONE);
805 GlobalUnlock(hglobal);
807 if (!xmldoc)
809 ERR("Failed to parse xml\n");
810 return E_FAIL;
813 xmldoc->_private = create_priv();
815 return attach_xmldoc(doc, xmldoc);
818 static HRESULT WINAPI PersistStreamInit_Load(IPersistStreamInit *iface, IStream *stream)
820 domdoc *This = impl_from_IPersistStreamInit(iface);
822 TRACE("(%p)->(%p)\n", This, stream);
824 if (!stream)
825 return E_INVALIDARG;
827 return domdoc_load_from_stream(This, (ISequentialStream*)stream);
830 static HRESULT WINAPI PersistStreamInit_Save(
831 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
833 domdoc *This = impl_from_IPersistStreamInit(iface);
834 BSTR xmlString;
835 HRESULT hr;
837 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
839 hr = IXMLDOMDocument3_get_xml(&This->IXMLDOMDocument3_iface, &xmlString);
840 if(hr == S_OK)
842 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
844 hr = IStream_Write( stream, xmlString, len, NULL );
845 SysFreeString(xmlString);
848 TRACE("ret 0x%08x\n", hr);
850 return hr;
853 static HRESULT WINAPI PersistStreamInit_GetSizeMax(
854 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
856 domdoc *This = impl_from_IPersistStreamInit(iface);
857 TRACE("(%p)->(%p)\n", This, pcbSize);
858 return E_NOTIMPL;
861 static HRESULT WINAPI PersistStreamInit_InitNew(
862 IPersistStreamInit *iface)
864 domdoc *This = impl_from_IPersistStreamInit(iface);
865 TRACE("(%p)\n", This);
866 return S_OK;
869 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
871 PersistStreamInit_QueryInterface,
872 PersistStreamInit_AddRef,
873 PersistStreamInit_Release,
874 PersistStreamInit_GetClassID,
875 PersistStreamInit_IsDirty,
876 PersistStreamInit_Load,
877 PersistStreamInit_Save,
878 PersistStreamInit_GetSizeMax,
879 PersistStreamInit_InitNew
882 /* IXMLDOMDocument3 interface */
884 static const tid_t domdoc_se_tids[] = {
885 IXMLDOMNode_tid,
886 IXMLDOMDocument_tid,
887 IXMLDOMDocument2_tid,
888 IXMLDOMDocument3_tid,
889 NULL_tid
892 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
894 domdoc *This = impl_from_IXMLDOMDocument3( iface );
896 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
898 *ppvObject = NULL;
900 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
901 IsEqualGUID( riid, &IID_IDispatch ) ||
902 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
903 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
904 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
905 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
907 *ppvObject = iface;
909 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
910 IsEqualGUID(&IID_IPersistStreamInit, riid))
912 *ppvObject = &This->IPersistStreamInit_iface;
914 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
916 *ppvObject = &This->IObjectWithSite_iface;
918 else if (IsEqualGUID(&IID_IObjectSafety, riid))
920 *ppvObject = &This->IObjectSafety_iface;
922 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
924 return node_create_supporterrorinfo(domdoc_se_tids, ppvObject);
926 else if(node_query_interface(&This->node, riid, ppvObject))
928 return *ppvObject ? S_OK : E_NOINTERFACE;
930 else if (IsEqualGUID( riid, &IID_IConnectionPointContainer ))
932 *ppvObject = &This->IConnectionPointContainer_iface;
934 else
936 TRACE("interface %s not implemented\n", debugstr_guid(riid));
937 return E_NOINTERFACE;
940 IUnknown_AddRef((IUnknown*)*ppvObject);
942 return S_OK;
945 static ULONG WINAPI domdoc_AddRef( IXMLDOMDocument3 *iface )
947 domdoc *This = impl_from_IXMLDOMDocument3( iface );
948 ULONG ref = InterlockedIncrement( &This->ref );
949 TRACE("(%p)->(%d)\n", This, ref );
950 return ref;
953 static ULONG WINAPI domdoc_Release( IXMLDOMDocument3 *iface )
955 domdoc *This = impl_from_IXMLDOMDocument3( iface );
956 LONG ref = InterlockedDecrement( &This->ref );
958 TRACE("(%p)->(%d)\n", This, ref );
960 if ( ref == 0 )
962 int eid;
964 if (This->site)
965 IUnknown_Release( This->site );
966 destroy_xmlnode(&This->node);
968 for (eid = 0; eid < EVENTID_LAST; eid++)
969 if (This->events[eid]) IDispatch_Release(This->events[eid]);
971 release_namespaces(This);
972 heap_free(This);
975 return ref;
978 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
980 domdoc *This = impl_from_IXMLDOMDocument3( iface );
981 return IDispatchEx_GetTypeInfoCount(&This->node.dispex.IDispatchEx_iface, pctinfo);
984 static HRESULT WINAPI domdoc_GetTypeInfo(
985 IXMLDOMDocument3 *iface,
986 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
988 domdoc *This = impl_from_IXMLDOMDocument3( iface );
989 return IDispatchEx_GetTypeInfo(&This->node.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
992 static HRESULT WINAPI domdoc_GetIDsOfNames(
993 IXMLDOMDocument3 *iface,
994 REFIID riid,
995 LPOLESTR* rgszNames,
996 UINT cNames,
997 LCID lcid,
998 DISPID* rgDispId)
1000 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1001 return IDispatchEx_GetIDsOfNames(&This->node.dispex.IDispatchEx_iface,
1002 riid, rgszNames, cNames, lcid, rgDispId);
1005 static HRESULT WINAPI domdoc_Invoke(
1006 IXMLDOMDocument3 *iface,
1007 DISPID dispIdMember,
1008 REFIID riid,
1009 LCID lcid,
1010 WORD wFlags,
1011 DISPPARAMS* pDispParams,
1012 VARIANT* pVarResult,
1013 EXCEPINFO* pExcepInfo,
1014 UINT* puArgErr)
1016 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1017 return IDispatchEx_Invoke(&This->node.dispex.IDispatchEx_iface,
1018 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1021 static HRESULT WINAPI domdoc_get_nodeName(
1022 IXMLDOMDocument3 *iface,
1023 BSTR* name )
1025 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1027 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
1029 TRACE("(%p)->(%p)\n", This, name);
1031 return return_bstr(documentW, name);
1035 static HRESULT WINAPI domdoc_get_nodeValue(
1036 IXMLDOMDocument3 *iface,
1037 VARIANT* value )
1039 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1041 TRACE("(%p)->(%p)\n", This, value);
1043 if(!value)
1044 return E_INVALIDARG;
1046 V_VT(value) = VT_NULL;
1047 V_BSTR(value) = NULL; /* tests show that we should do this */
1048 return S_FALSE;
1052 static HRESULT WINAPI domdoc_put_nodeValue(
1053 IXMLDOMDocument3 *iface,
1054 VARIANT value)
1056 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1057 TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
1058 return E_FAIL;
1062 static HRESULT WINAPI domdoc_get_nodeType(
1063 IXMLDOMDocument3 *iface,
1064 DOMNodeType* type )
1066 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1068 TRACE("(%p)->(%p)\n", This, type);
1070 *type = NODE_DOCUMENT;
1071 return S_OK;
1075 static HRESULT WINAPI domdoc_get_parentNode(
1076 IXMLDOMDocument3 *iface,
1077 IXMLDOMNode** parent )
1079 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1081 TRACE("(%p)->(%p)\n", This, parent);
1083 return node_get_parent(&This->node, parent);
1087 static HRESULT WINAPI domdoc_get_childNodes(
1088 IXMLDOMDocument3 *iface,
1089 IXMLDOMNodeList** childList )
1091 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1093 TRACE("(%p)->(%p)\n", This, childList);
1095 return node_get_child_nodes(&This->node, childList);
1099 static HRESULT WINAPI domdoc_get_firstChild(
1100 IXMLDOMDocument3 *iface,
1101 IXMLDOMNode** firstChild )
1103 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1105 TRACE("(%p)->(%p)\n", This, firstChild);
1107 return node_get_first_child(&This->node, firstChild);
1111 static HRESULT WINAPI domdoc_get_lastChild(
1112 IXMLDOMDocument3 *iface,
1113 IXMLDOMNode** lastChild )
1115 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1117 TRACE("(%p)->(%p)\n", This, lastChild);
1119 return node_get_last_child(&This->node, lastChild);
1123 static HRESULT WINAPI domdoc_get_previousSibling(
1124 IXMLDOMDocument3 *iface,
1125 IXMLDOMNode** previousSibling )
1127 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1129 TRACE("(%p)->(%p)\n", This, previousSibling);
1131 return return_null_node(previousSibling);
1135 static HRESULT WINAPI domdoc_get_nextSibling(
1136 IXMLDOMDocument3 *iface,
1137 IXMLDOMNode** nextSibling )
1139 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1141 TRACE("(%p)->(%p)\n", This, nextSibling);
1143 return return_null_node(nextSibling);
1147 static HRESULT WINAPI domdoc_get_attributes(
1148 IXMLDOMDocument3 *iface,
1149 IXMLDOMNamedNodeMap** attributeMap )
1151 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1153 TRACE("(%p)->(%p)\n", This, attributeMap);
1155 return return_null_ptr((void**)attributeMap);
1159 static HRESULT WINAPI domdoc_insertBefore(
1160 IXMLDOMDocument3 *iface,
1161 IXMLDOMNode* newChild,
1162 VARIANT refChild,
1163 IXMLDOMNode** outNewChild )
1165 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1166 DOMNodeType type;
1167 HRESULT hr;
1169 TRACE("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), outNewChild);
1171 hr = IXMLDOMNode_get_nodeType(newChild, &type);
1172 if (hr != S_OK) return hr;
1174 TRACE("new node type %d\n", type);
1175 switch (type)
1177 case NODE_ATTRIBUTE:
1178 case NODE_DOCUMENT:
1179 case NODE_CDATA_SECTION:
1180 if (outNewChild) *outNewChild = NULL;
1181 return E_FAIL;
1182 default:
1183 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1187 static HRESULT WINAPI domdoc_replaceChild(
1188 IXMLDOMDocument3 *iface,
1189 IXMLDOMNode* newChild,
1190 IXMLDOMNode* oldChild,
1191 IXMLDOMNode** outOldChild)
1193 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1195 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1197 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1201 static HRESULT WINAPI domdoc_removeChild(
1202 IXMLDOMDocument3 *iface,
1203 IXMLDOMNode *child,
1204 IXMLDOMNode **oldChild)
1206 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1207 TRACE("(%p)->(%p %p)\n", This, child, oldChild);
1208 return node_remove_child(&This->node, child, oldChild);
1212 static HRESULT WINAPI domdoc_appendChild(
1213 IXMLDOMDocument3 *iface,
1214 IXMLDOMNode *child,
1215 IXMLDOMNode **outChild)
1217 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1218 TRACE("(%p)->(%p %p)\n", This, child, outChild);
1219 return node_append_child(&This->node, child, outChild);
1223 static HRESULT WINAPI domdoc_hasChildNodes(
1224 IXMLDOMDocument3 *iface,
1225 VARIANT_BOOL *ret)
1227 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1228 TRACE("(%p)->(%p)\n", This, ret);
1229 return node_has_childnodes(&This->node, ret);
1233 static HRESULT WINAPI domdoc_get_ownerDocument(
1234 IXMLDOMDocument3 *iface,
1235 IXMLDOMDocument **doc)
1237 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1238 TRACE("(%p)->(%p)\n", This, doc);
1239 return node_get_owner_doc(&This->node, doc);
1243 static HRESULT WINAPI domdoc_cloneNode(
1244 IXMLDOMDocument3 *iface,
1245 VARIANT_BOOL deep,
1246 IXMLDOMNode** outNode)
1248 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1249 xmlNodePtr clone;
1251 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
1253 if (!outNode)
1254 return E_INVALIDARG;
1256 *outNode = NULL;
1258 clone = xmlCopyNode((xmlNodePtr)get_doc(This), deep ? 1 : 2);
1259 if (!clone)
1260 return E_FAIL;
1262 clone->doc->_private = create_priv();
1263 xmldoc_add_orphan(clone->doc, clone);
1264 xmldoc_add_ref(clone->doc);
1266 priv_from_xmlDocPtr(clone->doc)->properties = copy_properties(This->properties);
1267 if (!(*outNode = (IXMLDOMNode*)create_domdoc(clone)))
1269 xmldoc_release(clone->doc);
1270 return E_FAIL;
1273 return S_OK;
1277 static HRESULT WINAPI domdoc_get_nodeTypeString(
1278 IXMLDOMDocument3 *iface,
1279 BSTR *p)
1281 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1282 static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
1284 TRACE("(%p)->(%p)\n", This, p);
1286 return return_bstr(documentW, p);
1290 static HRESULT WINAPI domdoc_get_text(
1291 IXMLDOMDocument3 *iface,
1292 BSTR *p)
1294 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1295 TRACE("(%p)->(%p)\n", This, p);
1296 return node_get_text(&This->node, p);
1300 static HRESULT WINAPI domdoc_put_text(
1301 IXMLDOMDocument3 *iface,
1302 BSTR text )
1304 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1305 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1306 return E_FAIL;
1310 static HRESULT WINAPI domdoc_get_specified(
1311 IXMLDOMDocument3 *iface,
1312 VARIANT_BOOL* isSpecified )
1314 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1315 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1316 *isSpecified = VARIANT_TRUE;
1317 return S_OK;
1321 static HRESULT WINAPI domdoc_get_definition(
1322 IXMLDOMDocument3 *iface,
1323 IXMLDOMNode** definitionNode )
1325 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1326 FIXME("(%p)->(%p)\n", This, definitionNode);
1327 return E_NOTIMPL;
1331 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1332 IXMLDOMDocument3 *iface,
1333 VARIANT* v )
1335 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1336 TRACE("(%p)->(%p)\n", This, v);
1337 return return_null_var(v);
1340 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1341 IXMLDOMDocument3 *iface,
1342 VARIANT typedValue )
1344 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1345 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1346 return E_NOTIMPL;
1350 static HRESULT WINAPI domdoc_get_dataType(
1351 IXMLDOMDocument3 *iface,
1352 VARIANT* typename )
1354 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1355 TRACE("(%p)->(%p)\n", This, typename);
1356 return return_null_var( typename );
1360 static HRESULT WINAPI domdoc_put_dataType(
1361 IXMLDOMDocument3 *iface,
1362 BSTR dataTypeName )
1364 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1366 FIXME("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
1368 if(!dataTypeName)
1369 return E_INVALIDARG;
1371 return E_FAIL;
1374 static int XMLCALL domdoc_get_xml_writecallback(void *ctx, const char *data, int len)
1376 return xmlBufferAdd((xmlBufferPtr)ctx, (xmlChar*)data, len) == 0 ? len : 0;
1379 static HRESULT WINAPI domdoc_get_xml(
1380 IXMLDOMDocument3 *iface,
1381 BSTR* p)
1383 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1384 xmlSaveCtxtPtr ctxt;
1385 xmlBufferPtr buf;
1386 int options;
1387 long ret;
1389 TRACE("(%p)->(%p)\n", This, p);
1391 if(!p)
1392 return E_INVALIDARG;
1394 *p = NULL;
1396 buf = xmlBufferCreate();
1397 if(!buf)
1398 return E_OUTOFMEMORY;
1400 options = XML_SAVE_FORMAT | XML_SAVE_NO_DECL;
1401 ctxt = xmlSaveToIO(domdoc_get_xml_writecallback, NULL, buf, "UTF-8", options);
1403 if(!ctxt)
1405 xmlBufferFree(buf);
1406 return E_OUTOFMEMORY;
1409 ret = xmlSaveDoc(ctxt, get_doc(This));
1410 /* flushes on close */
1411 xmlSaveClose(ctxt);
1413 TRACE("%ld, len=%d\n", ret, xmlBufferLength(buf));
1414 if(ret != -1 && xmlBufferLength(buf) > 0)
1416 BSTR content;
1418 content = bstr_from_xmlChar(xmlBufferContent(buf));
1419 content = EnsureCorrectEOL(content);
1421 *p = content;
1423 else
1425 *p = SysAllocStringLen(NULL, 0);
1428 xmlBufferFree(buf);
1430 return *p ? S_OK : E_OUTOFMEMORY;
1434 static HRESULT WINAPI domdoc_transformNode(
1435 IXMLDOMDocument3 *iface,
1436 IXMLDOMNode *node,
1437 BSTR *p)
1439 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1440 TRACE("(%p)->(%p %p)\n", This, node, p);
1441 return node_transform_node(&This->node, node, p);
1445 static HRESULT WINAPI domdoc_selectNodes(
1446 IXMLDOMDocument3 *iface,
1447 BSTR p,
1448 IXMLDOMNodeList **outList)
1450 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1451 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList);
1452 return node_select_nodes(&This->node, p, outList);
1456 static HRESULT WINAPI domdoc_selectSingleNode(
1457 IXMLDOMDocument3 *iface,
1458 BSTR p,
1459 IXMLDOMNode **outNode)
1461 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1462 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode);
1463 return node_select_singlenode(&This->node, p, outNode);
1467 static HRESULT WINAPI domdoc_get_parsed(
1468 IXMLDOMDocument3 *iface,
1469 VARIANT_BOOL* isParsed )
1471 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1472 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1473 *isParsed = VARIANT_TRUE;
1474 return S_OK;
1477 static HRESULT WINAPI domdoc_get_namespaceURI(
1478 IXMLDOMDocument3 *iface,
1479 BSTR* namespaceURI )
1481 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1482 TRACE("(%p)->(%p)\n", This, namespaceURI);
1483 return return_null_bstr( namespaceURI );
1486 static HRESULT WINAPI domdoc_get_prefix(
1487 IXMLDOMDocument3 *iface,
1488 BSTR* prefix )
1490 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1491 TRACE("(%p)->(%p)\n", This, prefix);
1492 return return_null_bstr( prefix );
1496 static HRESULT WINAPI domdoc_get_baseName(
1497 IXMLDOMDocument3 *iface,
1498 BSTR* name )
1500 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1501 TRACE("(%p)->(%p)\n", This, name);
1502 return return_null_bstr( name );
1506 static HRESULT WINAPI domdoc_transformNodeToObject(
1507 IXMLDOMDocument3 *iface,
1508 IXMLDOMNode* stylesheet,
1509 VARIANT output)
1511 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1513 TRACE("(%p)->(%p %s)\n", This, stylesheet, debugstr_variant(&output));
1515 switch (V_VT(&output))
1517 case VT_UNKNOWN:
1518 case VT_DISPATCH:
1520 IXMLDOMDocument *doc;
1521 HRESULT hr;
1523 if (!V_UNKNOWN(&output))
1524 return E_INVALIDARG;
1526 /* FIXME: we're not supposed to query for document interface, should use IStream
1527 which we don't support currently. */
1528 if (IUnknown_QueryInterface(V_UNKNOWN(&output), &IID_IXMLDOMDocument, (void **)&doc) == S_OK)
1530 VARIANT_BOOL b;
1531 BSTR str;
1533 if (FAILED(hr = node_transform_node(&This->node, stylesheet, &str)))
1534 return hr;
1536 hr = IXMLDOMDocument_loadXML(doc, str, &b);
1537 SysFreeString(str);
1538 return hr;
1540 else
1542 FIXME("Unsupported destination type.\n");
1543 return E_INVALIDARG;
1546 default:
1547 FIXME("Output type %d not handled.\n", V_VT(&output));
1548 return E_NOTIMPL;
1551 return E_NOTIMPL;
1555 static HRESULT WINAPI domdoc_get_doctype(
1556 IXMLDOMDocument3 *iface,
1557 IXMLDOMDocumentType** doctype )
1559 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1560 IXMLDOMNode *node;
1561 xmlDtdPtr dtd;
1562 HRESULT hr;
1564 TRACE("(%p)->(%p)\n", This, doctype);
1566 if (!doctype) return E_INVALIDARG;
1568 *doctype = NULL;
1570 dtd = xmlGetIntSubset(get_doc(This));
1571 if (!dtd) return S_FALSE;
1573 node = create_node((xmlNodePtr)dtd);
1574 if (!node) return S_FALSE;
1576 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentType, (void**)doctype);
1577 IXMLDOMNode_Release(node);
1579 return hr;
1583 static HRESULT WINAPI domdoc_get_implementation(
1584 IXMLDOMDocument3 *iface,
1585 IXMLDOMImplementation** impl )
1587 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1589 TRACE("(%p)->(%p)\n", This, impl);
1591 if(!impl)
1592 return E_INVALIDARG;
1594 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1596 return S_OK;
1599 static HRESULT WINAPI domdoc_get_documentElement(
1600 IXMLDOMDocument3 *iface,
1601 IXMLDOMElement** DOMElement )
1603 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1604 IXMLDOMNode *element_node;
1605 xmlNodePtr root;
1606 HRESULT hr;
1608 TRACE("(%p)->(%p)\n", This, DOMElement);
1610 if(!DOMElement)
1611 return E_INVALIDARG;
1613 *DOMElement = NULL;
1615 root = xmlDocGetRootElement( get_doc(This) );
1616 if ( !root )
1617 return S_FALSE;
1619 element_node = create_node( root );
1620 if(!element_node) return S_FALSE;
1622 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1623 IXMLDOMNode_Release(element_node);
1625 return hr;
1629 static HRESULT WINAPI domdoc_put_documentElement(
1630 IXMLDOMDocument3 *iface,
1631 IXMLDOMElement* DOMElement )
1633 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1634 IXMLDOMNode *elementNode;
1635 xmlNodePtr oldRoot;
1636 xmlDocPtr old_doc;
1637 xmlnode *xmlNode;
1638 int refcount = 0;
1639 HRESULT hr;
1641 TRACE("(%p)->(%p)\n", This, DOMElement);
1643 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1644 if(FAILED(hr))
1645 return hr;
1647 xmlNode = get_node_obj( elementNode );
1648 if(!xmlNode) return E_FAIL;
1650 if(!xmlNode->node->parent)
1651 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1652 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1654 old_doc = xmlNode->node->doc;
1655 if (old_doc != get_doc(This))
1656 refcount = xmlnode_get_inst_cnt(xmlNode);
1658 /* old root is still orphaned by its document, update refcount from new root */
1659 if (refcount) xmldoc_add_refs(get_doc(This), refcount);
1660 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1661 if (refcount) xmldoc_release_refs(old_doc, refcount);
1662 IXMLDOMNode_Release( elementNode );
1664 if(oldRoot)
1665 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1667 return S_OK;
1671 static HRESULT WINAPI domdoc_createElement(
1672 IXMLDOMDocument3 *iface,
1673 BSTR tagname,
1674 IXMLDOMElement** element )
1676 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1677 IXMLDOMNode *node;
1678 VARIANT type;
1679 HRESULT hr;
1681 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1683 if (!element || !tagname) return E_INVALIDARG;
1685 V_VT(&type) = VT_I1;
1686 V_I1(&type) = NODE_ELEMENT;
1688 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1689 if (hr == S_OK)
1691 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1692 IXMLDOMNode_Release(node);
1695 return hr;
1699 static HRESULT WINAPI domdoc_createDocumentFragment(
1700 IXMLDOMDocument3 *iface,
1701 IXMLDOMDocumentFragment** frag )
1703 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1704 IXMLDOMNode *node;
1705 VARIANT type;
1706 HRESULT hr;
1708 TRACE("(%p)->(%p)\n", This, frag);
1710 if (!frag) return E_INVALIDARG;
1712 *frag = NULL;
1714 V_VT(&type) = VT_I1;
1715 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1717 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1718 if (hr == S_OK)
1720 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1721 IXMLDOMNode_Release(node);
1724 return hr;
1728 static HRESULT WINAPI domdoc_createTextNode(
1729 IXMLDOMDocument3 *iface,
1730 BSTR data,
1731 IXMLDOMText** text )
1733 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1734 IXMLDOMNode *node;
1735 VARIANT type;
1736 HRESULT hr;
1738 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1740 if (!text) return E_INVALIDARG;
1742 *text = NULL;
1744 V_VT(&type) = VT_I1;
1745 V_I1(&type) = NODE_TEXT;
1747 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1748 if (hr == S_OK)
1750 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1751 IXMLDOMNode_Release(node);
1752 hr = IXMLDOMText_put_data(*text, data);
1755 return hr;
1759 static HRESULT WINAPI domdoc_createComment(
1760 IXMLDOMDocument3 *iface,
1761 BSTR data,
1762 IXMLDOMComment** comment )
1764 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1765 VARIANT type;
1766 HRESULT hr;
1767 IXMLDOMNode *node;
1769 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1771 if (!comment) return E_INVALIDARG;
1773 *comment = NULL;
1775 V_VT(&type) = VT_I1;
1776 V_I1(&type) = NODE_COMMENT;
1778 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1779 if (hr == S_OK)
1781 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1782 IXMLDOMNode_Release(node);
1783 hr = IXMLDOMComment_put_data(*comment, data);
1786 return hr;
1790 static HRESULT WINAPI domdoc_createCDATASection(
1791 IXMLDOMDocument3 *iface,
1792 BSTR data,
1793 IXMLDOMCDATASection** cdata )
1795 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1796 IXMLDOMNode *node;
1797 VARIANT type;
1798 HRESULT hr;
1800 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1802 if (!cdata) return E_INVALIDARG;
1804 *cdata = NULL;
1806 V_VT(&type) = VT_I1;
1807 V_I1(&type) = NODE_CDATA_SECTION;
1809 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1810 if (hr == S_OK)
1812 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1813 IXMLDOMNode_Release(node);
1814 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1817 return hr;
1821 static HRESULT WINAPI domdoc_createProcessingInstruction(
1822 IXMLDOMDocument3 *iface,
1823 BSTR target,
1824 BSTR data,
1825 IXMLDOMProcessingInstruction** pi )
1827 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1828 IXMLDOMNode *node;
1829 VARIANT type;
1830 HRESULT hr;
1832 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1834 if (!pi) return E_INVALIDARG;
1836 *pi = NULL;
1838 V_VT(&type) = VT_I1;
1839 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1841 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1842 if (hr == S_OK)
1844 xmlnode *node_obj;
1846 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1847 node_obj = get_node_obj(node);
1848 hr = node_set_content(node_obj, data);
1850 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1851 IXMLDOMNode_Release(node);
1854 return hr;
1858 static HRESULT WINAPI domdoc_createAttribute(
1859 IXMLDOMDocument3 *iface,
1860 BSTR name,
1861 IXMLDOMAttribute** attribute )
1863 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1864 IXMLDOMNode *node;
1865 VARIANT type;
1866 HRESULT hr;
1868 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1870 if (!attribute || !name) return E_INVALIDARG;
1872 V_VT(&type) = VT_I1;
1873 V_I1(&type) = NODE_ATTRIBUTE;
1875 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1876 if (hr == S_OK)
1878 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1879 IXMLDOMNode_Release(node);
1882 return hr;
1886 static HRESULT WINAPI domdoc_createEntityReference(
1887 IXMLDOMDocument3 *iface,
1888 BSTR name,
1889 IXMLDOMEntityReference** entityref )
1891 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1892 IXMLDOMNode *node;
1893 VARIANT type;
1894 HRESULT hr;
1896 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1898 if (!entityref) return E_INVALIDARG;
1900 *entityref = NULL;
1902 V_VT(&type) = VT_I1;
1903 V_I1(&type) = NODE_ENTITY_REFERENCE;
1905 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1906 if (hr == S_OK)
1908 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1909 IXMLDOMNode_Release(node);
1912 return hr;
1915 xmlChar* tagName_to_XPath(const BSTR tagName)
1917 xmlChar *query, *tmp;
1918 static const xmlChar everything[] = "/descendant::node()";
1919 static const xmlChar mod_pre[] = "*[local-name()='";
1920 static const xmlChar mod_post[] = "']";
1921 static const xmlChar prefix[] = "descendant::";
1922 const WCHAR *tokBegin, *tokEnd;
1923 int len;
1925 /* Special case - empty tagname - means select all nodes,
1926 except document itself. */
1927 if (!*tagName)
1928 return xmlStrdup(everything);
1930 query = xmlStrdup(prefix);
1932 tokBegin = tagName;
1933 while (tokBegin && *tokBegin)
1935 switch (*tokBegin)
1937 case '/':
1938 query = xmlStrcat(query, BAD_CAST "/");
1939 ++tokBegin;
1940 break;
1941 case '*':
1942 query = xmlStrcat(query, BAD_CAST "*");
1943 ++tokBegin;
1944 break;
1945 default:
1946 query = xmlStrcat(query, mod_pre);
1947 tokEnd = tokBegin;
1948 while (*tokEnd && *tokEnd != '/')
1949 ++tokEnd;
1950 len = WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, NULL, 0, NULL, NULL);
1951 tmp = xmlMalloc(len);
1952 WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, (char*)tmp, len, NULL, NULL);
1953 query = xmlStrncat(query, tmp, len);
1954 xmlFree(tmp);
1955 tokBegin = tokEnd;
1956 query = xmlStrcat(query, mod_post);
1960 return query;
1963 static HRESULT WINAPI domdoc_getElementsByTagName(
1964 IXMLDOMDocument3 *iface,
1965 BSTR tagName,
1966 IXMLDOMNodeList** resultList )
1968 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1969 xmlChar *query;
1970 HRESULT hr;
1971 BOOL XPath;
1973 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1975 if (!tagName || !resultList) return E_INVALIDARG;
1977 XPath = This->properties->XPath;
1978 This->properties->XPath = TRUE;
1979 query = tagName_to_XPath(tagName);
1980 hr = create_selection((xmlNodePtr)get_doc(This), query, resultList);
1981 xmlFree(query);
1982 This->properties->XPath = XPath;
1984 return hr;
1987 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1989 VARIANT tmp;
1990 HRESULT hr;
1992 VariantInit(&tmp);
1993 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1994 if(FAILED(hr))
1995 return E_INVALIDARG;
1997 *type = V_I4(&tmp);
1999 return S_OK;
2002 static HRESULT WINAPI domdoc_createNode(
2003 IXMLDOMDocument3 *iface,
2004 VARIANT Type,
2005 BSTR name,
2006 BSTR namespaceURI,
2007 IXMLDOMNode** node )
2009 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2010 DOMNodeType node_type;
2011 xmlNodePtr xmlnode;
2012 xmlChar *xml_name, *href;
2013 HRESULT hr;
2015 TRACE("(%p)->(%s %s %s %p)\n", This, debugstr_variant(&Type), debugstr_w(name), debugstr_w(namespaceURI), node);
2017 if(!node) return E_INVALIDARG;
2019 hr = get_node_type(Type, &node_type);
2020 if(FAILED(hr)) return hr;
2022 TRACE("node_type %d\n", node_type);
2024 /* exit earlier for types that need name */
2025 switch(node_type)
2027 case NODE_ELEMENT:
2028 case NODE_ATTRIBUTE:
2029 case NODE_ENTITY_REFERENCE:
2030 case NODE_PROCESSING_INSTRUCTION:
2031 if (!name || *name == 0) return E_FAIL;
2032 break;
2033 default:
2034 break;
2037 xml_name = xmlchar_from_wchar(name);
2038 /* prevent empty href from being allocated */
2039 href = namespaceURI ? xmlchar_from_wchar(namespaceURI) : NULL;
2041 switch(node_type)
2043 case NODE_ELEMENT:
2045 xmlChar *local, *prefix;
2047 local = xmlSplitQName2(xml_name, &prefix);
2049 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
2051 /* allow creating the default namespace xmlns= */
2052 if (local || (href && *href))
2054 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
2055 xmlSetNs(xmlnode, ns);
2058 xmlFree(local);
2059 xmlFree(prefix);
2061 break;
2063 case NODE_ATTRIBUTE:
2065 xmlChar *local, *prefix;
2067 local = xmlSplitQName2(xml_name, &prefix);
2069 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), local ? local : xml_name, NULL);
2071 if (local || (href && *href))
2073 /* we need a floating namespace here, it can't be created linked to attribute from
2074 a start */
2075 xmlNsPtr ns = xmlNewNs(NULL, href, prefix);
2076 xmlSetNs(xmlnode, ns);
2079 xmlFree(local);
2080 xmlFree(prefix);
2082 break;
2084 case NODE_TEXT:
2085 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
2086 break;
2087 case NODE_CDATA_SECTION:
2088 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
2089 break;
2090 case NODE_ENTITY_REFERENCE:
2091 xmlnode = xmlNewReference(get_doc(This), xml_name);
2092 break;
2093 case NODE_PROCESSING_INSTRUCTION:
2094 #ifdef HAVE_XMLNEWDOCPI
2095 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
2096 #else
2097 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2098 xmlnode = NULL;
2099 #endif
2100 break;
2101 case NODE_COMMENT:
2102 xmlnode = xmlNewDocComment(get_doc(This), NULL);
2103 break;
2104 case NODE_DOCUMENT_FRAGMENT:
2105 xmlnode = xmlNewDocFragment(get_doc(This));
2106 break;
2107 /* unsupported types */
2108 case NODE_DOCUMENT:
2109 case NODE_DOCUMENT_TYPE:
2110 case NODE_ENTITY:
2111 case NODE_NOTATION:
2112 heap_free(xml_name);
2113 return E_INVALIDARG;
2114 default:
2115 FIXME("unhandled node type %d\n", node_type);
2116 xmlnode = NULL;
2117 break;
2120 *node = create_node(xmlnode);
2121 heap_free(xml_name);
2122 heap_free(href);
2124 if(*node)
2126 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
2127 xmldoc_add_orphan(xmlnode->doc, xmlnode);
2128 return S_OK;
2131 return E_FAIL;
2134 static HRESULT WINAPI domdoc_nodeFromID(
2135 IXMLDOMDocument3 *iface,
2136 BSTR idString,
2137 IXMLDOMNode** node )
2139 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2140 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
2141 return E_NOTIMPL;
2144 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
2146 domdoc *This = obj;
2147 xmlDocPtr xmldoc;
2149 xmldoc = doparse(This, ptr, len, XML_CHAR_ENCODING_NONE);
2150 if(xmldoc) {
2151 xmldoc->_private = create_priv();
2152 return attach_xmldoc(This, xmldoc);
2155 return E_FAIL;
2158 static HRESULT domdoc_load_moniker(domdoc *This, IMoniker *mon)
2160 bsc_t *bsc;
2161 HRESULT hr;
2163 hr = bind_url(mon, domdoc_onDataAvailable, This, &bsc);
2164 if(FAILED(hr))
2165 return hr;
2167 return detach_bsc(bsc);
2170 static HRESULT WINAPI domdoc_load(
2171 IXMLDOMDocument3 *iface,
2172 VARIANT source,
2173 VARIANT_BOOL* isSuccessful )
2175 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2176 LPWSTR filename = NULL;
2177 HRESULT hr = S_FALSE;
2178 xmlDocPtr xmldoc;
2180 TRACE("(%p)->(%s)\n", This, debugstr_variant(&source));
2182 if (!isSuccessful)
2183 return E_POINTER;
2184 *isSuccessful = VARIANT_FALSE;
2186 assert( &This->node );
2188 switch( V_VT(&source) )
2190 case VT_BSTR:
2191 filename = V_BSTR(&source);
2192 break;
2193 case VT_BSTR|VT_BYREF:
2194 if (!V_BSTRREF(&source)) return E_INVALIDARG;
2195 filename = *V_BSTRREF(&source);
2196 break;
2197 case VT_ARRAY|VT_UI1:
2199 SAFEARRAY *psa = V_ARRAY(&source);
2200 char *str;
2201 LONG len;
2202 UINT dim = SafeArrayGetDim(psa);
2204 switch (dim)
2206 case 0:
2207 ERR("SAFEARRAY == NULL\n");
2208 hr = This->error = E_INVALIDARG;
2209 break;
2210 case 1:
2211 /* Only takes UTF-8 strings.
2212 * NOT NULL-terminated. */
2213 hr = SafeArrayAccessData(psa, (void**)&str);
2214 if (FAILED(hr))
2216 This->error = hr;
2217 WARN("failed to access array data, 0x%08x\n", hr);
2218 break;
2220 SafeArrayGetUBound(psa, 1, &len);
2222 if ((xmldoc = doparse(This, str, ++len, XML_CHAR_ENCODING_UTF8)))
2224 hr = This->error = S_OK;
2225 *isSuccessful = VARIANT_TRUE;
2226 TRACE("parsed document %p\n", xmldoc);
2228 else
2230 This->error = E_FAIL;
2231 TRACE("failed to parse document\n");
2234 SafeArrayUnaccessData(psa);
2236 if(xmldoc)
2238 xmldoc->_private = create_priv();
2239 return attach_xmldoc(This, xmldoc);
2241 break;
2242 default:
2243 FIXME("unhandled SAFEARRAY dim: %d\n", dim);
2244 hr = This->error = E_NOTIMPL;
2247 break;
2248 case VT_UNKNOWN:
2250 ISequentialStream *stream = NULL;
2251 IXMLDOMDocument3 *newdoc = NULL;
2253 if (!V_UNKNOWN(&source)) return E_INVALIDARG;
2255 hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IXMLDOMDocument3, (void**)&newdoc);
2256 if(hr == S_OK)
2258 if(newdoc)
2260 domdoc *newDoc = impl_from_IXMLDOMDocument3( newdoc );
2262 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
2263 xmldoc->_private = create_priv();
2264 hr = attach_xmldoc(This, xmldoc);
2266 if(SUCCEEDED(hr))
2267 *isSuccessful = VARIANT_TRUE;
2269 return hr;
2273 hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IStream, (void**)&stream);
2274 if (FAILED(hr))
2275 hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_ISequentialStream, (void**)&stream);
2277 if (hr == S_OK)
2279 hr = domdoc_load_from_stream(This, stream);
2280 if (hr == S_OK)
2281 *isSuccessful = VARIANT_TRUE;
2282 ISequentialStream_Release(stream);
2283 return hr;
2286 FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr, V_UNKNOWN(&source)->lpVtbl);
2287 break;
2289 default:
2290 FIXME("VT type not supported (%d)\n", V_VT(&source));
2293 if ( filename )
2295 IMoniker *mon;
2296 IUri *uri;
2298 if (This->properties->uri)
2300 IUri_Release(This->properties->uri);
2301 This->properties->uri = NULL;
2304 hr = create_uri(filename, &uri);
2305 if (SUCCEEDED(hr))
2306 hr = CreateURLMonikerEx2(NULL, uri, &mon, 0);
2307 if ( SUCCEEDED(hr) )
2309 hr = domdoc_load_moniker( This, mon );
2310 IMoniker_Release(mon);
2313 if ( FAILED(hr) )
2314 This->error = E_FAIL;
2315 else
2317 get_doc(This)->name = (char *)xmlchar_from_wcharn(filename, -1, TRUE);
2318 This->properties->uri = uri;
2319 hr = This->error = S_OK;
2320 *isSuccessful = VARIANT_TRUE;
2324 if(!filename || FAILED(hr)) {
2325 xmldoc = xmlNewDoc(NULL);
2326 xmldoc->_private = create_priv();
2327 hr = attach_xmldoc(This, xmldoc);
2328 if(SUCCEEDED(hr))
2329 hr = S_FALSE;
2332 TRACE("ret (%d)\n", hr);
2334 return hr;
2338 static HRESULT WINAPI domdoc_get_readyState(
2339 IXMLDOMDocument3 *iface,
2340 LONG *value )
2342 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2343 FIXME("stub! (%p)->(%p)\n", This, value);
2345 if (!value)
2346 return E_INVALIDARG;
2348 *value = READYSTATE_COMPLETE;
2349 return S_OK;
2353 static HRESULT WINAPI domdoc_get_parseError(
2354 IXMLDOMDocument3 *iface,
2355 IXMLDOMParseError** errorObj )
2357 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2358 static const WCHAR err[] = {'e','r','r','o','r',0};
2359 BSTR error_string = NULL;
2361 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2363 if(This->error)
2364 error_string = SysAllocString(err);
2366 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2367 if(!*errorObj) return E_OUTOFMEMORY;
2368 return S_OK;
2372 static HRESULT WINAPI domdoc_get_url(
2373 IXMLDOMDocument3 *iface,
2374 BSTR* url )
2376 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2378 TRACE("(%p)->(%p)\n", This, url);
2380 if (!url)
2381 return E_INVALIDARG;
2383 if (!This->properties->uri)
2384 return return_null_bstr(url);
2386 return IUri_GetPropertyBSTR(This->properties->uri, Uri_PROPERTY_DISPLAY_URI, url, 0);
2390 static HRESULT WINAPI domdoc_get_async(
2391 IXMLDOMDocument3 *iface,
2392 VARIANT_BOOL* isAsync )
2394 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2396 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2397 *isAsync = This->async;
2398 return S_OK;
2402 static HRESULT WINAPI domdoc_put_async(
2403 IXMLDOMDocument3 *iface,
2404 VARIANT_BOOL isAsync )
2406 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2408 TRACE("(%p)->(%d)\n", This, isAsync);
2409 This->async = isAsync;
2410 return S_OK;
2414 static HRESULT WINAPI domdoc_abort(
2415 IXMLDOMDocument3 *iface )
2417 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2418 FIXME("%p\n", This);
2419 return E_NOTIMPL;
2422 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2423 static HRESULT WINAPI domdoc_loadXML(
2424 IXMLDOMDocument3 *iface,
2425 BSTR data,
2426 VARIANT_BOOL* isSuccessful )
2428 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2429 xmlDocPtr xmldoc = NULL;
2430 HRESULT hr = S_FALSE, hr2;
2432 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), isSuccessful );
2434 assert ( &This->node );
2436 if ( isSuccessful )
2438 *isSuccessful = VARIANT_FALSE;
2440 if (data)
2442 WCHAR *ptr = data;
2444 /* skip leading spaces if needed */
2445 if (This->properties->version == MSXML_DEFAULT || This->properties->version == MSXML26)
2446 while (*ptr && isspaceW(*ptr)) ptr++;
2448 xmldoc = doparse(This, (char*)ptr, strlenW(ptr)*sizeof(WCHAR), XML_CHAR_ENCODING_UTF16LE);
2449 if ( !xmldoc )
2451 This->error = E_FAIL;
2452 TRACE("failed to parse document\n");
2454 else
2456 hr = This->error = S_OK;
2457 *isSuccessful = VARIANT_TRUE;
2458 TRACE("parsed document %p\n", xmldoc);
2463 if(!xmldoc)
2464 xmldoc = xmlNewDoc(NULL);
2465 xmldoc->_private = create_priv();
2466 hr2 = attach_xmldoc(This, xmldoc);
2467 if( FAILED(hr2) )
2468 hr = hr2;
2470 return hr;
2473 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2475 DWORD written = -1;
2477 if(!WriteFile(ctx, buffer, len, &written, NULL))
2479 WARN("write error\n");
2480 return -1;
2482 else
2483 return written;
2486 static int XMLCALL domdoc_save_closecallback(void *ctx)
2488 return CloseHandle(ctx) ? 0 : -1;
2491 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2493 ULONG written = 0;
2494 HRESULT hr;
2496 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2497 TRACE("0x%08x %p %d %u\n", hr, buffer, len, written);
2498 if (hr != S_OK)
2500 WARN("stream write error: 0x%08x\n", hr);
2501 return -1;
2503 else
2504 return len;
2507 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2509 IStream_Release((IStream*)ctx);
2510 return 0;
2513 static HRESULT WINAPI domdoc_save(
2514 IXMLDOMDocument3 *iface,
2515 VARIANT destination )
2517 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2518 xmlSaveCtxtPtr ctx = NULL;
2519 xmlNodePtr xmldecl;
2520 HRESULT ret = S_OK;
2522 TRACE("(%p)->(%s)\n", This, debugstr_variant(&destination));
2524 switch (V_VT(&destination))
2526 case VT_UNKNOWN:
2528 IUnknown *pUnk = V_UNKNOWN(&destination);
2529 IXMLDOMDocument3 *document;
2530 IStream *stream;
2532 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2533 if(ret == S_OK)
2535 VARIANT_BOOL success;
2536 BSTR xml;
2538 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2539 if(ret == S_OK)
2541 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2542 SysFreeString(xml);
2545 IXMLDOMDocument3_Release(document);
2546 return ret;
2549 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2550 if(ret == S_OK)
2552 int options = get_doc(This)->standalone == -1 ? XML_SAVE_NO_DECL : 0;
2553 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2554 domdoc_stream_save_closecallback, stream, NULL, options);
2556 if(!ctx)
2558 IStream_Release(stream);
2559 return E_FAIL;
2563 break;
2565 case VT_BSTR:
2566 case VT_BSTR | VT_BYREF:
2568 int options = get_doc(This)->standalone == -1 ? XML_SAVE_NO_DECL : 0;
2570 /* save with file path */
2571 HANDLE handle = CreateFileW( (V_VT(&destination) & VT_BYREF)? *V_BSTRREF(&destination) : V_BSTR(&destination),
2572 GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2573 if( handle == INVALID_HANDLE_VALUE )
2575 WARN("failed to create file\n");
2576 return E_FAIL;
2579 /* disable top XML declaration */
2580 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2581 handle, NULL, options);
2582 if (!ctx)
2584 CloseHandle(handle);
2585 return E_FAIL;
2588 break;
2590 default:
2591 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination));
2592 return S_FALSE;
2595 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2596 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2597 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2599 /* will release resources through close callback */
2600 xmlSaveClose(ctx);
2602 return ret;
2605 static HRESULT WINAPI domdoc_get_validateOnParse(
2606 IXMLDOMDocument3 *iface,
2607 VARIANT_BOOL* isValidating )
2609 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2610 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2611 *isValidating = This->validating;
2612 return S_OK;
2616 static HRESULT WINAPI domdoc_put_validateOnParse(
2617 IXMLDOMDocument3 *iface,
2618 VARIANT_BOOL isValidating )
2620 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2621 TRACE("(%p)->(%d)\n", This, isValidating);
2622 This->validating = isValidating;
2623 return S_OK;
2627 static HRESULT WINAPI domdoc_get_resolveExternals(
2628 IXMLDOMDocument3 *iface,
2629 VARIANT_BOOL* isResolving )
2631 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2632 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2633 *isResolving = This->resolving;
2634 return S_OK;
2638 static HRESULT WINAPI domdoc_put_resolveExternals(
2639 IXMLDOMDocument3 *iface,
2640 VARIANT_BOOL isResolving )
2642 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2643 TRACE("(%p)->(%d)\n", This, isResolving);
2644 This->resolving = isResolving;
2645 return S_OK;
2649 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2650 IXMLDOMDocument3 *iface,
2651 VARIANT_BOOL* isPreserving )
2653 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2654 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->properties->preserving);
2655 *isPreserving = This->properties->preserving;
2656 return S_OK;
2660 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2661 IXMLDOMDocument3 *iface,
2662 VARIANT_BOOL isPreserving )
2664 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2665 TRACE("(%p)->(%d)\n", This, isPreserving);
2666 This->properties->preserving = isPreserving;
2667 return S_OK;
2671 static HRESULT WINAPI domdoc_put_onreadystatechange(
2672 IXMLDOMDocument3 *iface,
2673 VARIANT event )
2675 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2677 TRACE("(%p)->(%s)\n", This, debugstr_variant(&event));
2678 return set_doc_event(This, EVENTID_READYSTATECHANGE, &event);
2682 static HRESULT WINAPI domdoc_put_onDataAvailable(IXMLDOMDocument3 *iface, VARIANT sink)
2684 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2685 FIXME("(%p)->(%s): stub\n", This, debugstr_variant(&sink));
2686 return E_NOTIMPL;
2689 static HRESULT WINAPI domdoc_put_onTransformNode(IXMLDOMDocument3 *iface, VARIANT sink )
2691 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2692 FIXME("(%p)->(%s): stub\n", This, debugstr_variant(&sink));
2693 return E_NOTIMPL;
2696 static HRESULT WINAPI domdoc_get_namespaces(
2697 IXMLDOMDocument3* iface,
2698 IXMLDOMSchemaCollection** collection )
2700 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2701 HRESULT hr;
2703 FIXME("(%p)->(%p): semi-stub\n", This, collection);
2705 if (!collection) return E_POINTER;
2707 if (!This->namespaces)
2709 hr = SchemaCache_create(This->properties->version, (void**)&This->namespaces);
2710 if (hr != S_OK) return hr;
2712 hr = cache_from_doc_ns(This->namespaces, &This->node);
2713 if (hr != S_OK)
2714 release_namespaces(This);
2717 if (This->namespaces)
2718 return IXMLDOMSchemaCollection2_QueryInterface(This->namespaces,
2719 &IID_IXMLDOMSchemaCollection, (void**)collection);
2721 return hr;
2724 static HRESULT WINAPI domdoc_get_schemas(
2725 IXMLDOMDocument3* iface,
2726 VARIANT* schema )
2728 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2729 IXMLDOMSchemaCollection2* cur_schema = This->properties->schemaCache;
2730 HRESULT hr = S_FALSE;
2732 TRACE("(%p)->(%p)\n", This, schema);
2734 V_VT(schema) = VT_NULL;
2735 /* just to reset pointer part, cause that's what application is expected to use */
2736 V_DISPATCH(schema) = NULL;
2738 if(cur_schema)
2740 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(schema));
2741 if(SUCCEEDED(hr))
2742 V_VT(schema) = VT_DISPATCH;
2744 return hr;
2747 static HRESULT WINAPI domdoc_putref_schemas(
2748 IXMLDOMDocument3* iface,
2749 VARIANT schema)
2751 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2752 HRESULT hr = E_FAIL;
2753 IXMLDOMSchemaCollection2* new_schema = NULL;
2755 FIXME("(%p)->(%s): semi-stub\n", This, debugstr_variant(&schema));
2756 switch(V_VT(&schema))
2758 case VT_UNKNOWN:
2759 if (V_UNKNOWN(&schema))
2761 hr = IUnknown_QueryInterface(V_UNKNOWN(&schema), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2762 break;
2764 /* fallthrough */
2765 case VT_DISPATCH:
2766 if (V_DISPATCH(&schema))
2768 hr = IDispatch_QueryInterface(V_DISPATCH(&schema), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2769 break;
2771 /* fallthrough */
2772 case VT_NULL:
2773 case VT_EMPTY:
2774 hr = S_OK;
2775 break;
2777 default:
2778 WARN("Can't get schema from vt %x\n", V_VT(&schema));
2781 if(SUCCEEDED(hr))
2783 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->properties->schemaCache, new_schema);
2784 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2787 return hr;
2790 static inline BOOL is_wellformed(xmlDocPtr doc)
2792 #ifdef HAVE_XMLDOC_PROPERTIES
2793 return doc->properties & XML_DOC_WELLFORMED;
2794 #else
2795 /* Not a full check, but catches the worst violations */
2796 xmlNodePtr child;
2797 int root = 0;
2799 for (child = doc->children; child != NULL; child = child->next)
2801 switch (child->type)
2803 case XML_ELEMENT_NODE:
2804 if (++root > 1)
2805 return FALSE;
2806 break;
2807 case XML_TEXT_NODE:
2808 case XML_CDATA_SECTION_NODE:
2809 return FALSE;
2810 break;
2811 default:
2812 break;
2816 return root == 1;
2817 #endif
2820 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2822 va_list ap;
2823 va_start(ap, msg);
2824 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2825 va_end(ap);
2828 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2830 va_list ap;
2831 va_start(ap, msg);
2832 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2833 va_end(ap);
2836 static HRESULT WINAPI domdoc_validateNode(
2837 IXMLDOMDocument3* iface,
2838 IXMLDOMNode* node,
2839 IXMLDOMParseError** err)
2841 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2842 LONG state, err_code = 0;
2843 HRESULT hr = S_OK;
2844 int validated = 0;
2846 TRACE("(%p)->(%p, %p)\n", This, node, err);
2847 IXMLDOMDocument3_get_readyState(iface, &state);
2848 if (state != READYSTATE_COMPLETE)
2850 if (err)
2851 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2852 return E_PENDING;
2855 if (!node)
2857 if (err)
2858 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2859 return E_POINTER;
2862 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2864 if (err)
2865 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2866 return E_FAIL;
2869 if (!is_wellformed(get_doc(This)))
2871 ERR("doc not well-formed\n");
2872 if (err)
2873 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2874 return S_FALSE;
2877 /* DTD validation */
2878 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2880 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2881 vctx->error = validate_error;
2882 vctx->warning = validate_warning;
2883 ++validated;
2885 if (!((node == (IXMLDOMNode*)iface)?
2886 xmlValidateDocument(vctx, get_doc(This)) :
2887 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2889 /* TODO: get a real error code here */
2890 TRACE("DTD validation failed\n");
2891 err_code = E_XML_INVALID;
2892 hr = S_FALSE;
2894 xmlFreeValidCtxt(vctx);
2897 /* Schema validation */
2898 if (hr == S_OK && This->properties->schemaCache != NULL)
2901 hr = SchemaCache_validate_tree(This->properties->schemaCache, get_node_obj(node)->node);
2902 if (SUCCEEDED(hr))
2904 ++validated;
2905 /* TODO: get a real error code here */
2906 if (hr == S_OK)
2908 TRACE("schema validation succeeded\n");
2910 else
2912 ERR("schema validation failed\n");
2913 err_code = E_XML_INVALID;
2916 else
2918 /* not really OK, just didn't find a schema for the ns */
2919 hr = S_OK;
2923 if (!validated)
2925 ERR("no DTD or schema found\n");
2926 err_code = E_XML_NODTD;
2927 hr = S_FALSE;
2930 if (err)
2931 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2933 return hr;
2936 static HRESULT WINAPI domdoc_validate(
2937 IXMLDOMDocument3* iface,
2938 IXMLDOMParseError** err)
2940 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2941 TRACE("(%p)->(%p)\n", This, err);
2942 return IXMLDOMDocument3_validateNode(iface, (IXMLDOMNode*)iface, err);
2945 static HRESULT WINAPI domdoc_setProperty(
2946 IXMLDOMDocument3* iface,
2947 BSTR p,
2948 VARIANT value)
2950 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2952 TRACE("(%p)->(%s %s)\n", This, debugstr_w(p), debugstr_variant(&value));
2954 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2956 VARIANT varStr;
2957 HRESULT hr;
2958 BSTR bstr;
2960 V_VT(&varStr) = VT_EMPTY;
2961 if (V_VT(&value) != VT_BSTR)
2963 if (FAILED(hr = VariantChangeType(&varStr, &value, 0, VT_BSTR)))
2964 return hr;
2965 bstr = V_BSTR(&varStr);
2967 else
2968 bstr = V_BSTR(&value);
2970 hr = S_OK;
2971 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2972 This->properties->XPath = TRUE;
2973 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2974 This->properties->XPath = FALSE;
2975 else
2976 hr = E_FAIL;
2978 VariantClear(&varStr);
2979 return hr;
2981 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2983 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2984 struct list *pNsList;
2985 VARIANT varStr;
2986 HRESULT hr;
2987 BSTR bstr;
2989 V_VT(&varStr) = VT_EMPTY;
2990 if (V_VT(&value) != VT_BSTR)
2992 if (FAILED(hr = VariantChangeType(&varStr, &value, 0, VT_BSTR)))
2993 return hr;
2994 bstr = V_BSTR(&varStr);
2996 else
2997 bstr = V_BSTR(&value);
2999 hr = S_OK;
3001 pNsList = &(This->properties->selectNsList);
3002 clear_selectNsList(pNsList);
3003 heap_free(nsStr);
3004 nsStr = xmlchar_from_wchar(bstr);
3006 TRACE("property value: \"%s\"\n", debugstr_w(bstr));
3008 This->properties->selectNsStr = nsStr;
3009 This->properties->selectNsStr_len = xmlStrlen(nsStr);
3010 if (bstr && *bstr)
3012 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
3013 select_ns_entry* ns_entry = NULL;
3014 xmlXPathContextPtr ctx;
3016 ctx = xmlXPathNewContext(This->node.node->doc);
3017 pTokBegin = nsStr;
3019 /* skip leading spaces */
3020 while (*pTokBegin == ' ' || *pTokBegin == '\n' ||
3021 *pTokBegin == '\t' || *pTokBegin == '\r')
3022 ++pTokBegin;
3024 for (; *pTokBegin; pTokBegin = pTokEnd)
3026 if (ns_entry)
3027 memset(ns_entry, 0, sizeof(select_ns_entry));
3028 else
3029 ns_entry = heap_alloc_zero(sizeof(select_ns_entry));
3031 while (*pTokBegin == ' ')
3032 ++pTokBegin;
3033 pTokEnd = pTokBegin;
3034 while (*pTokEnd != ' ' && *pTokEnd != 0)
3035 ++pTokEnd;
3037 /* so it failed to advance which means we've got some trailing spaces */
3038 if (pTokEnd == pTokBegin) break;
3040 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
3042 hr = E_FAIL;
3043 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3044 debugstr_w(bstr), debugstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
3045 continue;
3048 pTokBegin += 5;
3049 if (*pTokBegin == '=')
3051 /*valid for XSLPattern?*/
3052 FIXME("Setting default xmlns not supported - skipping.\n");
3053 continue;
3055 else if (*pTokBegin == ':')
3057 ns_entry->prefix = ++pTokBegin;
3058 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
3061 if (pTokInner == pTokEnd)
3063 hr = E_FAIL;
3064 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3065 debugstr_w(bstr), debugstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
3066 continue;
3069 ns_entry->prefix_end = *pTokInner;
3070 *pTokInner = 0;
3071 ++pTokInner;
3073 if (pTokEnd-pTokInner > 1 &&
3074 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
3075 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
3077 ns_entry->href = ++pTokInner;
3078 ns_entry->href_end = *(pTokEnd-1);
3079 *(pTokEnd-1) = 0;
3080 list_add_tail(pNsList, &ns_entry->entry);
3081 /*let libxml figure out if they're valid from here ;)*/
3082 if (xmlXPathRegisterNs(ctx, ns_entry->prefix, ns_entry->href) != 0)
3084 hr = E_FAIL;
3086 ns_entry = NULL;
3087 continue;
3089 else
3091 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3092 debugstr_w(bstr), debugstr_an((const char*)pTokInner, pTokEnd-pTokInner));
3093 list_add_tail(pNsList, &ns_entry->entry);
3095 ns_entry = NULL;
3096 hr = E_FAIL;
3097 continue;
3100 else
3102 hr = E_FAIL;
3103 continue;
3106 heap_free(ns_entry);
3107 xmlXPathFreeContext(ctx);
3110 VariantClear(&varStr);
3111 return hr;
3113 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
3114 lstrcmpiW(p, PropertyNewParserW) == 0 ||
3115 lstrcmpiW(p, PropertyResolveExternalsW) == 0 ||
3116 lstrcmpiW(p, PropertyAllowXsltScriptW) == 0 ||
3117 lstrcmpiW(p, PropertyNormalizeAttributeValuesW) == 0 ||
3118 lstrcmpiW(p, PropertyAllowDocumentFunctionW) == 0)
3120 /* Ignore */
3121 FIXME("Ignoring property %s, value %s\n", debugstr_w(p), debugstr_variant(&value));
3122 return S_OK;
3125 FIXME("Unknown property %s\n", debugstr_w(p));
3126 return E_FAIL;
3129 static HRESULT WINAPI domdoc_getProperty(
3130 IXMLDOMDocument3* iface,
3131 BSTR p,
3132 VARIANT* var)
3134 domdoc *This = impl_from_IXMLDOMDocument3( iface );
3136 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
3138 if (!var)
3139 return E_INVALIDARG;
3141 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
3143 V_VT(var) = VT_BSTR;
3144 V_BSTR(var) = This->properties->XPath ?
3145 SysAllocString(PropValueXPathW) :
3146 SysAllocString(PropValueXSLPatternW);
3147 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
3149 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
3151 int lenA, lenW;
3152 BSTR rebuiltStr, cur;
3153 const xmlChar *nsStr;
3154 struct list *pNsList;
3155 select_ns_entry* pNsEntry;
3157 V_VT(var) = VT_BSTR;
3158 nsStr = This->properties->selectNsStr;
3159 pNsList = &This->properties->selectNsList;
3160 lenA = This->properties->selectNsStr_len;
3161 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
3162 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
3163 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
3164 cur = rebuiltStr;
3165 /* this is fine because all of the chars that end tokens are ASCII*/
3166 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
3168 while (*cur != 0) ++cur;
3169 if (pNsEntry->prefix_end)
3171 *cur = pNsEntry->prefix_end;
3172 while (*cur != 0) ++cur;
3175 if (pNsEntry->href_end)
3177 *cur = pNsEntry->href_end;
3180 V_BSTR(var) = SysAllocString(rebuiltStr);
3181 heap_free(rebuiltStr);
3182 return S_OK;
3185 FIXME("Unknown property %s\n", debugstr_w(p));
3186 return E_FAIL;
3189 static HRESULT WINAPI domdoc_importNode(
3190 IXMLDOMDocument3* iface,
3191 IXMLDOMNode* node,
3192 VARIANT_BOOL deep,
3193 IXMLDOMNode** clone)
3195 domdoc *This = impl_from_IXMLDOMDocument3( iface );
3196 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
3197 return E_NOTIMPL;
3200 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl =
3202 domdoc_QueryInterface,
3203 domdoc_AddRef,
3204 domdoc_Release,
3205 domdoc_GetTypeInfoCount,
3206 domdoc_GetTypeInfo,
3207 domdoc_GetIDsOfNames,
3208 domdoc_Invoke,
3209 domdoc_get_nodeName,
3210 domdoc_get_nodeValue,
3211 domdoc_put_nodeValue,
3212 domdoc_get_nodeType,
3213 domdoc_get_parentNode,
3214 domdoc_get_childNodes,
3215 domdoc_get_firstChild,
3216 domdoc_get_lastChild,
3217 domdoc_get_previousSibling,
3218 domdoc_get_nextSibling,
3219 domdoc_get_attributes,
3220 domdoc_insertBefore,
3221 domdoc_replaceChild,
3222 domdoc_removeChild,
3223 domdoc_appendChild,
3224 domdoc_hasChildNodes,
3225 domdoc_get_ownerDocument,
3226 domdoc_cloneNode,
3227 domdoc_get_nodeTypeString,
3228 domdoc_get_text,
3229 domdoc_put_text,
3230 domdoc_get_specified,
3231 domdoc_get_definition,
3232 domdoc_get_nodeTypedValue,
3233 domdoc_put_nodeTypedValue,
3234 domdoc_get_dataType,
3235 domdoc_put_dataType,
3236 domdoc_get_xml,
3237 domdoc_transformNode,
3238 domdoc_selectNodes,
3239 domdoc_selectSingleNode,
3240 domdoc_get_parsed,
3241 domdoc_get_namespaceURI,
3242 domdoc_get_prefix,
3243 domdoc_get_baseName,
3244 domdoc_transformNodeToObject,
3245 domdoc_get_doctype,
3246 domdoc_get_implementation,
3247 domdoc_get_documentElement,
3248 domdoc_put_documentElement,
3249 domdoc_createElement,
3250 domdoc_createDocumentFragment,
3251 domdoc_createTextNode,
3252 domdoc_createComment,
3253 domdoc_createCDATASection,
3254 domdoc_createProcessingInstruction,
3255 domdoc_createAttribute,
3256 domdoc_createEntityReference,
3257 domdoc_getElementsByTagName,
3258 domdoc_createNode,
3259 domdoc_nodeFromID,
3260 domdoc_load,
3261 domdoc_get_readyState,
3262 domdoc_get_parseError,
3263 domdoc_get_url,
3264 domdoc_get_async,
3265 domdoc_put_async,
3266 domdoc_abort,
3267 domdoc_loadXML,
3268 domdoc_save,
3269 domdoc_get_validateOnParse,
3270 domdoc_put_validateOnParse,
3271 domdoc_get_resolveExternals,
3272 domdoc_put_resolveExternals,
3273 domdoc_get_preserveWhiteSpace,
3274 domdoc_put_preserveWhiteSpace,
3275 domdoc_put_onreadystatechange,
3276 domdoc_put_onDataAvailable,
3277 domdoc_put_onTransformNode,
3278 domdoc_get_namespaces,
3279 domdoc_get_schemas,
3280 domdoc_putref_schemas,
3281 domdoc_validate,
3282 domdoc_setProperty,
3283 domdoc_getProperty,
3284 domdoc_validateNode,
3285 domdoc_importNode
3288 /* IConnectionPointContainer */
3289 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
3290 REFIID riid, void **ppv)
3292 domdoc *This = impl_from_IConnectionPointContainer(iface);
3293 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppv);
3296 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
3298 domdoc *This = impl_from_IConnectionPointContainer(iface);
3299 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3302 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
3304 domdoc *This = impl_from_IConnectionPointContainer(iface);
3305 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3308 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
3309 IEnumConnectionPoints **ppEnum)
3311 domdoc *This = impl_from_IConnectionPointContainer(iface);
3312 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3313 return E_NOTIMPL;
3316 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
3317 REFIID riid, IConnectionPoint **cp)
3319 domdoc *This = impl_from_IConnectionPointContainer(iface);
3320 ConnectionPoint *iter;
3322 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
3324 *cp = NULL;
3326 for(iter = This->cp_list; iter; iter = iter->next)
3328 if (IsEqualGUID(iter->iid, riid))
3329 *cp = &iter->IConnectionPoint_iface;
3332 if (*cp)
3334 IConnectionPoint_AddRef(*cp);
3335 return S_OK;
3338 FIXME("unsupported riid %s\n", debugstr_guid(riid));
3339 return CONNECT_E_NOCONNECTION;
3343 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
3345 ConnectionPointContainer_QueryInterface,
3346 ConnectionPointContainer_AddRef,
3347 ConnectionPointContainer_Release,
3348 ConnectionPointContainer_EnumConnectionPoints,
3349 ConnectionPointContainer_FindConnectionPoint
3352 /* IConnectionPoint */
3353 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
3354 REFIID riid, void **ppv)
3356 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3358 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3360 *ppv = NULL;
3362 if (IsEqualGUID(&IID_IUnknown, riid) ||
3363 IsEqualGUID(&IID_IConnectionPoint, riid))
3365 *ppv = iface;
3368 if (*ppv)
3370 IConnectionPoint_AddRef(iface);
3371 return S_OK;
3374 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3375 return E_NOINTERFACE;
3378 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3380 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3381 return IConnectionPointContainer_AddRef(This->container);
3384 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3386 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3387 return IConnectionPointContainer_Release(This->container);
3390 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3392 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3394 TRACE("(%p)->(%p)\n", This, iid);
3396 if (!iid) return E_POINTER;
3398 *iid = *This->iid;
3399 return S_OK;
3402 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3403 IConnectionPointContainer **container)
3405 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3407 TRACE("(%p)->(%p)\n", This, container);
3409 if (!container) return E_POINTER;
3411 *container = This->container;
3412 IConnectionPointContainer_AddRef(*container);
3413 return S_OK;
3416 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *unk_sink,
3417 DWORD *cookie)
3419 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3420 IUnknown *sink;
3421 HRESULT hr;
3422 DWORD i;
3424 TRACE("(%p)->(%p %p)\n", This, unk_sink, cookie);
3426 hr = IUnknown_QueryInterface(unk_sink, This->iid, (void**)&sink);
3427 if(FAILED(hr) && !IsEqualGUID(&IID_IPropertyNotifySink, This->iid))
3428 hr = IUnknown_QueryInterface(unk_sink, &IID_IDispatch, (void**)&sink);
3429 if(FAILED(hr))
3430 return CONNECT_E_CANNOTCONNECT;
3432 if(This->sinks)
3434 for (i = 0; i < This->sinks_size; i++)
3435 if (!This->sinks[i].unk)
3436 break;
3438 if (i == This->sinks_size)
3439 This->sinks = heap_realloc(This->sinks,(++This->sinks_size)*sizeof(*This->sinks));
3441 else
3443 This->sinks = heap_alloc(sizeof(*This->sinks));
3444 This->sinks_size = 1;
3445 i = 0;
3448 This->sinks[i].unk = sink;
3449 if (cookie)
3450 *cookie = i+1;
3452 return S_OK;
3455 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3457 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3459 TRACE("(%p)->(%d)\n", This, cookie);
3461 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3462 return CONNECT_E_NOCONNECTION;
3464 IUnknown_Release(This->sinks[cookie-1].unk);
3465 This->sinks[cookie-1].unk = NULL;
3467 return S_OK;
3470 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3471 IEnumConnections **ppEnum)
3473 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3474 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3475 return E_NOTIMPL;
3478 static const IConnectionPointVtbl ConnectionPointVtbl =
3480 ConnectionPoint_QueryInterface,
3481 ConnectionPoint_AddRef,
3482 ConnectionPoint_Release,
3483 ConnectionPoint_GetConnectionInterface,
3484 ConnectionPoint_GetConnectionPointContainer,
3485 ConnectionPoint_Advise,
3486 ConnectionPoint_Unadvise,
3487 ConnectionPoint_EnumConnections
3490 static void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3492 cp->IConnectionPoint_iface.lpVtbl = &ConnectionPointVtbl;
3493 cp->doc = doc;
3494 cp->iid = riid;
3495 cp->sinks = NULL;
3496 cp->sinks_size = 0;
3498 cp->next = doc->cp_list;
3499 doc->cp_list = cp;
3501 cp->container = &doc->IConnectionPointContainer_iface;
3504 /* domdoc implementation of IObjectWithSite */
3505 static HRESULT WINAPI
3506 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3508 domdoc *This = impl_from_IObjectWithSite(iface);
3509 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppvObject);
3512 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3514 domdoc *This = impl_from_IObjectWithSite(iface);
3515 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3518 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3520 domdoc *This = impl_from_IObjectWithSite(iface);
3521 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3524 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3526 domdoc *This = impl_from_IObjectWithSite(iface);
3528 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3530 if ( !This->site )
3531 return E_FAIL;
3533 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3536 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3538 domdoc *This = impl_from_IObjectWithSite(iface);
3540 TRACE("(%p)->(%p)\n", iface, punk);
3542 if(!punk)
3544 if(This->site)
3546 IUnknown_Release( This->site );
3547 This->site = NULL;
3550 return S_OK;
3553 IUnknown_AddRef( punk );
3555 if(This->site)
3556 IUnknown_Release( This->site );
3558 This->site = punk;
3560 return S_OK;
3563 static const IObjectWithSiteVtbl domdocObjectSite =
3565 domdoc_ObjectWithSite_QueryInterface,
3566 domdoc_ObjectWithSite_AddRef,
3567 domdoc_ObjectWithSite_Release,
3568 domdoc_ObjectWithSite_SetSite,
3569 domdoc_ObjectWithSite_GetSite
3572 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3574 domdoc *This = impl_from_IObjectSafety(iface);
3575 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppv);
3578 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3580 domdoc *This = impl_from_IObjectSafety(iface);
3581 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3584 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3586 domdoc *This = impl_from_IObjectSafety(iface);
3587 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3590 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3592 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3593 DWORD *supported, DWORD *enabled)
3595 domdoc *This = impl_from_IObjectSafety(iface);
3597 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3599 if(!supported || !enabled) return E_POINTER;
3601 *supported = SAFETY_SUPPORTED_OPTIONS;
3602 *enabled = This->safeopt;
3604 return S_OK;
3607 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3608 DWORD mask, DWORD enabled)
3610 domdoc *This = impl_from_IObjectSafety(iface);
3611 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3613 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3614 return E_FAIL;
3616 This->safeopt = (This->safeopt & ~mask) | (mask & enabled);
3618 return S_OK;
3621 #undef SAFETY_SUPPORTED_OPTIONS
3623 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3624 domdoc_Safety_QueryInterface,
3625 domdoc_Safety_AddRef,
3626 domdoc_Safety_Release,
3627 domdoc_Safety_GetInterfaceSafetyOptions,
3628 domdoc_Safety_SetInterfaceSafetyOptions
3631 static const tid_t domdoc_iface_tids[] = {
3632 IXMLDOMDocument3_tid,
3636 static dispex_static_data_t domdoc_dispex = {
3637 NULL,
3638 IXMLDOMDocument3_tid,
3639 NULL,
3640 domdoc_iface_tids
3643 HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3645 domdoc *doc;
3647 doc = heap_alloc( sizeof (*doc) );
3648 if( !doc )
3649 return E_OUTOFMEMORY;
3651 doc->IXMLDOMDocument3_iface.lpVtbl = &XMLDOMDocument3Vtbl;
3652 doc->IPersistStreamInit_iface.lpVtbl = &xmldoc_IPersistStreamInit_VTable;
3653 doc->IObjectWithSite_iface.lpVtbl = &domdocObjectSite;
3654 doc->IObjectSafety_iface.lpVtbl = &domdocObjectSafetyVtbl;
3655 doc->IConnectionPointContainer_iface.lpVtbl = &ConnectionPointContainerVtbl;
3656 doc->ref = 1;
3657 doc->async = VARIANT_TRUE;
3658 doc->validating = 0;
3659 doc->resolving = 0;
3660 doc->properties = properties_from_xmlDocPtr(xmldoc);
3661 doc->error = S_OK;
3662 doc->site = NULL;
3663 doc->safeopt = 0;
3664 doc->cp_list = NULL;
3665 doc->namespaces = NULL;
3666 memset(doc->events, 0, sizeof(doc->events));
3668 /* events connection points */
3669 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3670 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3671 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3673 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->IXMLDOMDocument3_iface,
3674 &domdoc_dispex);
3676 *document = &doc->IXMLDOMDocument3_iface;
3678 TRACE("returning iface %p\n", *document);
3679 return S_OK;
3682 HRESULT DOMDocument_create(MSXML_VERSION version, void **ppObj)
3684 xmlDocPtr xmldoc;
3685 HRESULT hr;
3687 TRACE("(%d, %p)\n", version, ppObj);
3689 xmldoc = xmlNewDoc(NULL);
3690 if(!xmldoc)
3691 return E_OUTOFMEMORY;
3693 xmldoc_init(xmldoc, version);
3695 hr = get_domdoc_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3696 if(FAILED(hr))
3698 free_properties(properties_from_xmlDocPtr(xmldoc));
3699 heap_free(xmldoc->_private);
3700 xmlFreeDoc(xmldoc);
3701 return hr;
3704 return hr;
3707 IUnknown* create_domdoc( xmlNodePtr document )
3709 IUnknown *obj = NULL;
3710 HRESULT hr;
3712 TRACE("(%p)\n", document);
3714 hr = get_domdoc_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&obj);
3715 if (FAILED(hr))
3716 return NULL;
3718 return obj;
3721 #else
3723 HRESULT DOMDocument_create(MSXML_VERSION version, void **ppObj)
3725 MESSAGE("This program tried to use a DOMDocument object, but\n"
3726 "libxml2 support was not present at compile time.\n");
3727 return E_NOTIMPL;
3730 #endif