dinput: Implement device creation using product GUID.
[wine/zf.git] / dlls / msxml3 / domdoc.c
blob80c32e9ba993f36ebd30607dadc8b73c48c47b5c
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;
138 IUri *base_uri;
140 /* IObjectSafety */
141 DWORD safeopt;
143 /* connection list */
144 ConnectionPoint *cp_list;
145 ConnectionPoint cp_domdocevents;
146 ConnectionPoint cp_propnotif;
147 ConnectionPoint cp_dispatch;
149 /* events */
150 IDispatch *events[EVENTID_LAST];
152 IXMLDOMSchemaCollection2 *namespaces;
155 static HRESULT set_doc_event(domdoc *doc, eventid_t eid, const VARIANT *v)
157 IDispatch *disp;
159 switch (V_VT(v))
161 case VT_UNKNOWN:
162 if (V_UNKNOWN(v))
163 IUnknown_QueryInterface(V_UNKNOWN(v), &IID_IDispatch, (void**)&disp);
164 else
165 disp = NULL;
166 break;
167 case VT_DISPATCH:
168 disp = V_DISPATCH(v);
169 if (disp) IDispatch_AddRef(disp);
170 break;
171 default:
172 return DISP_E_TYPEMISMATCH;
175 if (doc->events[eid]) IDispatch_Release(doc->events[eid]);
176 doc->events[eid] = disp;
178 return S_OK;
181 static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface)
183 return CONTAINING_RECORD(iface, ConnectionPoint, IConnectionPoint_iface);
187 In native windows, the whole lifetime management of XMLDOMNodes is
188 managed automatically using reference counts. Wine emulates that by
189 maintaining a reference count to the document that is increased for
190 each IXMLDOMNode pointer passed out for this document. If all these
191 pointers are gone, the document is unreachable and gets freed, that
192 is, all nodes in the tree of the document get freed.
194 You are able to create nodes that are associated to a document (in
195 fact, in msxml's XMLDOM model, all nodes are associated to a document),
196 but not in the tree of that document, for example using the createFoo
197 functions from IXMLDOMDocument. These nodes do not get cleaned up
198 by libxml, so we have to do it ourselves.
200 To catch these nodes, a list of "orphan nodes" is introduced.
201 It contains pointers to all roots of node trees that are
202 associated with the document without being part of the document
203 tree. All nodes with parent==NULL (except for the document root nodes)
204 should be in the orphan node list of their document. All orphan nodes
205 get freed together with the document itself.
208 typedef struct _xmldoc_priv {
209 LONG refs;
210 struct list orphans;
211 domdoc_properties* properties;
212 } xmldoc_priv;
214 typedef struct _orphan_entry {
215 struct list entry;
216 xmlNode * node;
217 } orphan_entry;
219 typedef struct _select_ns_entry {
220 struct list entry;
221 xmlChar const* prefix;
222 xmlChar prefix_end;
223 xmlChar const* href;
224 xmlChar href_end;
225 } select_ns_entry;
227 static inline xmldoc_priv * priv_from_xmlDocPtr(const xmlDocPtr doc)
229 return doc->_private;
232 static inline domdoc_properties * properties_from_xmlDocPtr(xmlDocPtr doc)
234 return priv_from_xmlDocPtr(doc)->properties;
237 BOOL is_xpathmode(const xmlDocPtr doc)
239 return properties_from_xmlDocPtr(doc)->XPath;
242 void set_xpathmode(xmlDocPtr doc, BOOL xpath)
244 properties_from_xmlDocPtr(doc)->XPath = xpath;
247 int registerNamespaces(xmlXPathContextPtr ctxt)
249 int n = 0;
250 const select_ns_entry* ns = NULL;
251 const struct list* pNsList = &properties_from_xmlDocPtr(ctxt->doc)->selectNsList;
253 TRACE("(%p)\n", ctxt);
255 LIST_FOR_EACH_ENTRY( ns, pNsList, select_ns_entry, entry )
257 xmlXPathRegisterNs(ctxt, ns->prefix, ns->href);
258 ++n;
261 return n;
264 static inline void clear_selectNsList(struct list* pNsList)
266 select_ns_entry *ns, *ns2;
267 LIST_FOR_EACH_ENTRY_SAFE( ns, ns2, pNsList, select_ns_entry, entry )
269 heap_free( ns );
271 list_init(pNsList);
274 static xmldoc_priv * create_priv(void)
276 xmldoc_priv *priv;
277 priv = heap_alloc( sizeof (*priv) );
279 if (priv)
281 priv->refs = 0;
282 list_init( &priv->orphans );
283 priv->properties = NULL;
286 return priv;
289 static domdoc_properties *create_properties(MSXML_VERSION version)
291 domdoc_properties *properties = heap_alloc(sizeof(domdoc_properties));
293 list_init(&properties->selectNsList);
294 properties->preserving = VARIANT_FALSE;
295 properties->schemaCache = NULL;
296 properties->selectNsStr = heap_alloc_zero(sizeof(xmlChar));
297 properties->selectNsStr_len = 0;
299 /* properties that are dependent on object versions */
300 properties->version = version;
301 properties->XPath = (version == MSXML4 || version == MSXML6);
303 /* document uri */
304 properties->uri = NULL;
306 return properties;
309 static domdoc_properties* copy_properties(domdoc_properties const* properties)
311 domdoc_properties* pcopy = heap_alloc(sizeof(domdoc_properties));
312 select_ns_entry const* ns = NULL;
313 select_ns_entry* new_ns = NULL;
314 int len = (properties->selectNsStr_len+1)*sizeof(xmlChar);
315 ptrdiff_t offset;
317 if (pcopy)
319 pcopy->version = properties->version;
320 pcopy->preserving = properties->preserving;
321 pcopy->schemaCache = properties->schemaCache;
322 if (pcopy->schemaCache)
323 IXMLDOMSchemaCollection2_AddRef(pcopy->schemaCache);
324 pcopy->XPath = properties->XPath;
325 pcopy->selectNsStr_len = properties->selectNsStr_len;
326 list_init( &pcopy->selectNsList );
327 pcopy->selectNsStr = heap_alloc(len);
328 memcpy((xmlChar*)pcopy->selectNsStr, properties->selectNsStr, len);
329 offset = pcopy->selectNsStr - properties->selectNsStr;
331 LIST_FOR_EACH_ENTRY( ns, (&properties->selectNsList), select_ns_entry, entry )
333 new_ns = heap_alloc(sizeof(select_ns_entry));
334 memcpy(new_ns, ns, sizeof(select_ns_entry));
335 new_ns->href += offset;
336 new_ns->prefix += offset;
337 list_add_tail(&pcopy->selectNsList, &new_ns->entry);
340 pcopy->uri = properties->uri;
341 if (pcopy->uri)
342 IUri_AddRef(pcopy->uri);
345 return pcopy;
348 static void free_properties(domdoc_properties* properties)
350 if (properties)
352 if (properties->schemaCache)
353 IXMLDOMSchemaCollection2_Release(properties->schemaCache);
354 clear_selectNsList(&properties->selectNsList);
355 heap_free((xmlChar*)properties->selectNsStr);
356 if (properties->uri)
357 IUri_Release(properties->uri);
358 heap_free(properties);
362 static void release_namespaces(domdoc *This)
364 if (This->namespaces)
366 IXMLDOMSchemaCollection2_Release(This->namespaces);
367 This->namespaces = NULL;
371 /* links a "<?xml" node as a first child */
372 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
374 assert(doc != NULL);
375 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
378 /* unlinks a first "<?xml" child if it was created */
379 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
381 static const xmlChar xmlA[] = "xml";
382 xmlNodePtr node, first_child;
384 assert(doc != NULL);
386 /* xml declaration node could be created automatically after parsing or added
387 to a tree later */
388 first_child = doc->children;
389 if (first_child && first_child->type == XML_PI_NODE && xmlStrEqual(first_child->name, xmlA))
391 node = first_child;
392 xmlUnlinkNode( node );
394 else
395 node = NULL;
397 return node;
400 MSXML_VERSION xmldoc_version(xmlDocPtr doc)
402 return properties_from_xmlDocPtr(doc)->version;
405 BOOL is_preserving_whitespace(xmlNodePtr node)
407 domdoc_properties* properties = NULL;
408 /* during parsing the xmlDoc._private stuff is not there */
409 if (priv_from_xmlDocPtr(node->doc))
410 properties = properties_from_xmlDocPtr(node->doc);
411 return ((properties && properties->preserving == VARIANT_TRUE) ||
412 xmlNodeGetSpacePreserve(node) == 1);
415 static inline BOOL strn_isspace(xmlChar const* str, int len)
417 for (; str && len > 0 && *str; ++str, --len)
418 if (!isspace(*str))
419 break;
421 return len == 0;
424 static void sax_characters(void *ctx, const xmlChar *ch, int len)
426 xmlParserCtxtPtr ctxt;
427 const domdoc *This;
429 ctxt = (xmlParserCtxtPtr) ctx;
430 This = (const domdoc*) ctxt->_private;
432 if (ctxt->node)
434 xmlChar cur = *(ctxt->input->cur);
436 /* Characters are reported with multiple calls, for example each charref is reported with a separate
437 call and then parser appends it to a single text node or creates a new node if not created.
438 It's not possible to tell if it's ignorable data or not just looking at data itself cause it could be
439 space chars that separate charrefs or similar case. We only need to skip leading and trailing spaces,
440 or whole node if it has nothing but space chars, so to detect leading space node->last is checked that
441 contains text node pointer if already created, trailing spaces are detected directly looking at parser input
442 for next '<' opening bracket - similar logic is used by libxml2 itself. Basically 'cur' == '<' means the last
443 chunk of char data, in case it's not the last chunk we check for previously added node type and if it's not
444 a text node it's safe to ignore.
446 Note that during domdoc_loadXML() the xmlDocPtr->_private data is not available. */
448 if (!This->properties->preserving &&
449 !is_preserving_whitespace(ctxt->node) &&
450 strn_isspace(ch, len) &&
451 (!ctxt->node->last ||
452 ((ctxt->node->last && (cur == '<' || ctxt->node->last->type != XML_TEXT_NODE))
455 /* Keep information about ignorable whitespace text node in previous or parent node */
456 if (ctxt->node->last)
457 *(DWORD*)&ctxt->node->last->_private |= NODE_PRIV_TRAILING_IGNORABLE_WS;
458 else if (ctxt->node->type != XML_DOCUMENT_NODE)
459 *(DWORD*)&ctxt->node->_private |= NODE_PRIV_CHILD_IGNORABLE_WS;
460 return;
464 xmlSAX2Characters(ctxt, ch, len);
467 static void LIBXML2_LOG_CALLBACK sax_error(void* ctx, char const* msg, ...)
469 va_list ap;
470 va_start(ap, msg);
471 LIBXML2_CALLBACK_ERR(doparse, msg, ap);
472 va_end(ap);
475 static void LIBXML2_LOG_CALLBACK sax_warning(void* ctx, char const* msg, ...)
477 va_list ap;
478 va_start(ap, msg);
479 LIBXML2_CALLBACK_WARN(doparse, msg, ap);
480 va_end(ap);
483 static void sax_serror(void* ctx, xmlErrorPtr err)
485 LIBXML2_CALLBACK_SERROR(doparse, err);
488 static xmlDocPtr doparse(domdoc* This, char const* ptr, int len, xmlCharEncoding encoding)
490 xmlDocPtr doc = NULL;
491 xmlParserCtxtPtr pctx;
492 static xmlSAXHandler sax_handler = {
493 xmlSAX2InternalSubset, /* internalSubset */
494 xmlSAX2IsStandalone, /* isStandalone */
495 xmlSAX2HasInternalSubset, /* hasInternalSubset */
496 xmlSAX2HasExternalSubset, /* hasExternalSubset */
497 xmlSAX2ResolveEntity, /* resolveEntity */
498 xmlSAX2GetEntity, /* getEntity */
499 xmlSAX2EntityDecl, /* entityDecl */
500 xmlSAX2NotationDecl, /* notationDecl */
501 xmlSAX2AttributeDecl, /* attributeDecl */
502 xmlSAX2ElementDecl, /* elementDecl */
503 xmlSAX2UnparsedEntityDecl, /* unparsedEntityDecl */
504 xmlSAX2SetDocumentLocator, /* setDocumentLocator */
505 xmlSAX2StartDocument, /* startDocument */
506 xmlSAX2EndDocument, /* endDocument */
507 xmlSAX2StartElement, /* startElement */
508 xmlSAX2EndElement, /* endElement */
509 xmlSAX2Reference, /* reference */
510 sax_characters, /* characters */
511 sax_characters, /* ignorableWhitespace */
512 xmlSAX2ProcessingInstruction, /* processingInstruction */
513 xmlSAX2Comment, /* comment */
514 sax_warning, /* warning */
515 sax_error, /* error */
516 sax_error, /* fatalError */
517 xmlSAX2GetParameterEntity, /* getParameterEntity */
518 xmlSAX2CDataBlock, /* cdataBlock */
519 xmlSAX2ExternalSubset, /* externalSubset */
520 0, /* initialized */
521 NULL, /* _private */
522 xmlSAX2StartElementNs, /* startElementNs */
523 xmlSAX2EndElementNs, /* endElementNs */
524 sax_serror /* serror */
527 pctx = xmlCreateMemoryParserCtxt(ptr, len);
528 if (!pctx)
530 ERR("Failed to create parser context\n");
531 return NULL;
534 if (pctx->sax) xmlFree(pctx->sax);
535 pctx->sax = &sax_handler;
536 pctx->_private = This;
537 pctx->recovery = 0;
539 if (encoding != XML_CHAR_ENCODING_NONE)
540 xmlSwitchEncoding(pctx, encoding);
542 xmlParseDocument(pctx);
544 if (pctx->wellFormed)
546 doc = pctx->myDoc;
548 else
550 xmlFreeDoc(pctx->myDoc);
551 pctx->myDoc = NULL;
553 pctx->sax = NULL;
554 xmlFreeParserCtxt(pctx);
556 /* TODO: put this in one of the SAX callbacks */
557 /* create first child as a <?xml...?> */
558 if (doc && doc->standalone != -1)
560 xmlNodePtr node;
561 char buff[30];
562 xmlChar *xmlbuff = (xmlChar*)buff;
564 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
566 /* version attribute can't be omitted */
567 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
568 xmlNodeAddContent( node, xmlbuff );
570 if (doc->encoding)
572 sprintf(buff, " encoding=\"%s\"", doc->encoding);
573 xmlNodeAddContent( node, xmlbuff );
576 if (doc->standalone != -2)
578 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
579 xmlNodeAddContent( node, xmlbuff );
582 xmldoc_link_xmldecl( doc, node );
585 return doc;
588 void xmldoc_init(xmlDocPtr doc, MSXML_VERSION version)
590 doc->_private = create_priv();
591 priv_from_xmlDocPtr(doc)->properties = create_properties(version);
594 LONG xmldoc_add_refs(xmlDocPtr doc, LONG refs)
596 LONG ref = InterlockedExchangeAdd(&priv_from_xmlDocPtr(doc)->refs, refs) + refs;
597 TRACE("(%p)->(%d)\n", doc, ref);
598 return ref;
601 LONG xmldoc_add_ref(xmlDocPtr doc)
603 return xmldoc_add_refs(doc, 1);
606 LONG xmldoc_release_refs(xmlDocPtr doc, LONG refs)
608 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
609 LONG ref = InterlockedExchangeAdd(&priv->refs, -refs) - refs;
610 TRACE("(%p)->(%d)\n", doc, ref);
612 if (ref < 0)
613 WARN("negative refcount, expect troubles\n");
615 if (ref == 0)
617 orphan_entry *orphan, *orphan2;
618 TRACE("freeing docptr %p\n", doc);
620 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
622 xmlFreeNode( orphan->node );
623 heap_free( orphan );
625 free_properties(priv->properties);
626 heap_free(doc->_private);
628 xmlFreeDoc(doc);
631 return ref;
634 LONG xmldoc_release(xmlDocPtr doc)
636 return xmldoc_release_refs(doc, 1);
639 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
641 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
642 orphan_entry *entry;
644 entry = heap_alloc( sizeof (*entry) );
645 if(!entry)
646 return E_OUTOFMEMORY;
648 entry->node = node;
649 list_add_head( &priv->orphans, &entry->entry );
650 return S_OK;
653 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
655 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
656 orphan_entry *entry, *entry2;
658 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
660 if( entry->node == node )
662 list_remove( &entry->entry );
663 heap_free( entry );
664 return S_OK;
668 return S_FALSE;
671 static inline xmlDocPtr get_doc( domdoc *This )
673 return This->node.node->doc;
676 static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
678 release_namespaces(This);
680 if(This->node.node)
682 priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
683 if (xmldoc_release(get_doc(This)) != 0)
684 priv_from_xmlDocPtr(get_doc(This))->properties =
685 copy_properties(This->properties);
688 This->node.node = (xmlNodePtr) xml;
690 if(This->node.node)
692 xmldoc_add_ref(get_doc(This));
693 priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
696 return S_OK;
699 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
701 return CONTAINING_RECORD(iface, domdoc, IXMLDOMDocument3_iface);
704 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
706 return CONTAINING_RECORD(iface, domdoc, IPersistStreamInit_iface);
709 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
711 return CONTAINING_RECORD(iface, domdoc, IObjectWithSite_iface);
714 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
716 return CONTAINING_RECORD(iface, domdoc, IObjectSafety_iface);
719 static inline domdoc *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
721 return CONTAINING_RECORD(iface, domdoc, IConnectionPointContainer_iface);
724 /************************************************************************
725 * domdoc implementation of IPersistStream.
727 static HRESULT WINAPI PersistStreamInit_QueryInterface(
728 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
730 domdoc* This = impl_from_IPersistStreamInit(iface);
731 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppvObj);
734 static ULONG WINAPI PersistStreamInit_AddRef(
735 IPersistStreamInit *iface)
737 domdoc* This = impl_from_IPersistStreamInit(iface);
738 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
741 static ULONG WINAPI PersistStreamInit_Release(
742 IPersistStreamInit *iface)
744 domdoc* This = impl_from_IPersistStreamInit(iface);
745 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
748 static HRESULT WINAPI PersistStreamInit_GetClassID(
749 IPersistStreamInit *iface, CLSID *classid)
751 domdoc* This = impl_from_IPersistStreamInit(iface);
752 TRACE("(%p)->(%p)\n", This, classid);
754 if(!classid)
755 return E_POINTER;
757 *classid = *DOMDocument_version(This->properties->version);
759 return S_OK;
762 static HRESULT WINAPI PersistStreamInit_IsDirty(
763 IPersistStreamInit *iface)
765 domdoc *This = impl_from_IPersistStreamInit(iface);
766 FIXME("(%p): stub!\n", This);
767 return S_FALSE;
770 static HRESULT domdoc_load_from_stream(domdoc *doc, ISequentialStream *stream)
772 DWORD read, written, len;
773 xmlDocPtr xmldoc = NULL;
774 IStream *hstream;
775 HGLOBAL hglobal;
776 BYTE buf[4096];
777 HRESULT hr;
778 char *ptr;
780 hstream = NULL;
781 hr = CreateStreamOnHGlobal(NULL, TRUE, &hstream);
782 if (FAILED(hr))
783 return hr;
787 ISequentialStream_Read(stream, buf, sizeof(buf), &read);
788 hr = IStream_Write(hstream, buf, read, &written);
789 } while(SUCCEEDED(hr) && written != 0 && read != 0);
791 if (FAILED(hr))
793 ERR("failed to copy stream 0x%08x\n", hr);
794 IStream_Release(hstream);
795 return hr;
798 hr = GetHGlobalFromStream(hstream, &hglobal);
799 if (FAILED(hr))
801 IStream_Release(hstream);
802 return hr;
805 len = GlobalSize(hglobal);
806 ptr = GlobalLock(hglobal);
807 if (len)
808 xmldoc = doparse(doc, ptr, len, XML_CHAR_ENCODING_NONE);
809 GlobalUnlock(hglobal);
810 IStream_Release(hstream);
812 if (!xmldoc)
814 ERR("Failed to parse xml\n");
815 return E_FAIL;
818 xmldoc->_private = create_priv();
820 return attach_xmldoc(doc, xmldoc);
823 static HRESULT WINAPI PersistStreamInit_Load(IPersistStreamInit *iface, IStream *stream)
825 domdoc *This = impl_from_IPersistStreamInit(iface);
827 TRACE("(%p)->(%p)\n", This, stream);
829 if (!stream)
830 return E_INVALIDARG;
832 return This->error = domdoc_load_from_stream(This, (ISequentialStream*)stream);
835 static HRESULT WINAPI PersistStreamInit_Save(
836 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
838 domdoc *This = impl_from_IPersistStreamInit(iface);
839 BSTR xmlString;
840 HRESULT hr;
842 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
844 hr = IXMLDOMDocument3_get_xml(&This->IXMLDOMDocument3_iface, &xmlString);
845 if(hr == S_OK)
847 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
849 hr = IStream_Write( stream, xmlString, len, NULL );
850 SysFreeString(xmlString);
853 TRACE("ret 0x%08x\n", hr);
855 return hr;
858 static HRESULT WINAPI PersistStreamInit_GetSizeMax(
859 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
861 domdoc *This = impl_from_IPersistStreamInit(iface);
862 TRACE("(%p)->(%p)\n", This, pcbSize);
863 return E_NOTIMPL;
866 static HRESULT WINAPI PersistStreamInit_InitNew(
867 IPersistStreamInit *iface)
869 domdoc *This = impl_from_IPersistStreamInit(iface);
870 TRACE("(%p)\n", This);
871 return S_OK;
874 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
876 PersistStreamInit_QueryInterface,
877 PersistStreamInit_AddRef,
878 PersistStreamInit_Release,
879 PersistStreamInit_GetClassID,
880 PersistStreamInit_IsDirty,
881 PersistStreamInit_Load,
882 PersistStreamInit_Save,
883 PersistStreamInit_GetSizeMax,
884 PersistStreamInit_InitNew
887 /* IXMLDOMDocument3 interface */
889 static const tid_t domdoc_se_tids[] = {
890 IXMLDOMNode_tid,
891 IXMLDOMDocument_tid,
892 IXMLDOMDocument2_tid,
893 IXMLDOMDocument3_tid,
894 NULL_tid
897 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
899 domdoc *This = impl_from_IXMLDOMDocument3( iface );
901 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
903 *ppvObject = NULL;
905 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
906 IsEqualGUID( riid, &IID_IDispatch ) ||
907 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
908 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
909 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
910 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
912 *ppvObject = iface;
914 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
915 IsEqualGUID(&IID_IPersistStreamInit, riid))
917 *ppvObject = &This->IPersistStreamInit_iface;
919 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
921 *ppvObject = &This->IObjectWithSite_iface;
923 else if (IsEqualGUID(&IID_IObjectSafety, riid))
925 *ppvObject = &This->IObjectSafety_iface;
927 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
929 return node_create_supporterrorinfo(domdoc_se_tids, ppvObject);
931 else if(node_query_interface(&This->node, riid, ppvObject))
933 return *ppvObject ? S_OK : E_NOINTERFACE;
935 else if (IsEqualGUID( riid, &IID_IConnectionPointContainer ))
937 *ppvObject = &This->IConnectionPointContainer_iface;
939 else
941 TRACE("interface %s not implemented\n", debugstr_guid(riid));
942 return E_NOINTERFACE;
945 IUnknown_AddRef((IUnknown*)*ppvObject);
947 return S_OK;
950 static ULONG WINAPI domdoc_AddRef( IXMLDOMDocument3 *iface )
952 domdoc *This = impl_from_IXMLDOMDocument3( iface );
953 ULONG ref = InterlockedIncrement( &This->ref );
954 TRACE("(%p)->(%d)\n", This, ref );
955 return ref;
958 static ULONG WINAPI domdoc_Release( IXMLDOMDocument3 *iface )
960 domdoc *This = impl_from_IXMLDOMDocument3( iface );
961 LONG ref = InterlockedDecrement( &This->ref );
963 TRACE("(%p)->(%d)\n", This, ref );
965 if ( ref == 0 )
967 int eid;
969 if (This->site)
970 IUnknown_Release( This->site );
971 if (This->base_uri)
972 IUri_Release( This->base_uri );
973 destroy_xmlnode(&This->node);
975 for (eid = 0; eid < EVENTID_LAST; eid++)
976 if (This->events[eid]) IDispatch_Release(This->events[eid]);
978 release_namespaces(This);
979 heap_free(This);
982 return ref;
985 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
987 domdoc *This = impl_from_IXMLDOMDocument3( iface );
988 return IDispatchEx_GetTypeInfoCount(&This->node.dispex.IDispatchEx_iface, pctinfo);
991 static HRESULT WINAPI domdoc_GetTypeInfo(
992 IXMLDOMDocument3 *iface,
993 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
995 domdoc *This = impl_from_IXMLDOMDocument3( iface );
996 return IDispatchEx_GetTypeInfo(&This->node.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
999 static HRESULT WINAPI domdoc_GetIDsOfNames(
1000 IXMLDOMDocument3 *iface,
1001 REFIID riid,
1002 LPOLESTR* rgszNames,
1003 UINT cNames,
1004 LCID lcid,
1005 DISPID* rgDispId)
1007 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1008 return IDispatchEx_GetIDsOfNames(&This->node.dispex.IDispatchEx_iface,
1009 riid, rgszNames, cNames, lcid, rgDispId);
1012 static HRESULT WINAPI domdoc_Invoke(
1013 IXMLDOMDocument3 *iface,
1014 DISPID dispIdMember,
1015 REFIID riid,
1016 LCID lcid,
1017 WORD wFlags,
1018 DISPPARAMS* pDispParams,
1019 VARIANT* pVarResult,
1020 EXCEPINFO* pExcepInfo,
1021 UINT* puArgErr)
1023 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1024 return IDispatchEx_Invoke(&This->node.dispex.IDispatchEx_iface,
1025 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1028 static HRESULT WINAPI domdoc_get_nodeName(
1029 IXMLDOMDocument3 *iface,
1030 BSTR* name )
1032 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1034 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
1036 TRACE("(%p)->(%p)\n", This, name);
1038 return return_bstr(documentW, name);
1042 static HRESULT WINAPI domdoc_get_nodeValue(
1043 IXMLDOMDocument3 *iface,
1044 VARIANT* value )
1046 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1048 TRACE("(%p)->(%p)\n", This, value);
1050 if(!value)
1051 return E_INVALIDARG;
1053 V_VT(value) = VT_NULL;
1054 V_BSTR(value) = NULL; /* tests show that we should do this */
1055 return S_FALSE;
1059 static HRESULT WINAPI domdoc_put_nodeValue(
1060 IXMLDOMDocument3 *iface,
1061 VARIANT value)
1063 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1064 TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
1065 return E_FAIL;
1069 static HRESULT WINAPI domdoc_get_nodeType(
1070 IXMLDOMDocument3 *iface,
1071 DOMNodeType* type )
1073 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1075 TRACE("(%p)->(%p)\n", This, type);
1077 *type = NODE_DOCUMENT;
1078 return S_OK;
1082 static HRESULT WINAPI domdoc_get_parentNode(
1083 IXMLDOMDocument3 *iface,
1084 IXMLDOMNode** parent )
1086 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1088 TRACE("(%p)->(%p)\n", This, parent);
1090 return node_get_parent(&This->node, parent);
1094 static HRESULT WINAPI domdoc_get_childNodes(
1095 IXMLDOMDocument3 *iface,
1096 IXMLDOMNodeList** childList )
1098 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1100 TRACE("(%p)->(%p)\n", This, childList);
1102 return node_get_child_nodes(&This->node, childList);
1106 static HRESULT WINAPI domdoc_get_firstChild(
1107 IXMLDOMDocument3 *iface,
1108 IXMLDOMNode** firstChild )
1110 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1112 TRACE("(%p)->(%p)\n", This, firstChild);
1114 return node_get_first_child(&This->node, firstChild);
1118 static HRESULT WINAPI domdoc_get_lastChild(
1119 IXMLDOMDocument3 *iface,
1120 IXMLDOMNode** lastChild )
1122 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1124 TRACE("(%p)->(%p)\n", This, lastChild);
1126 return node_get_last_child(&This->node, lastChild);
1130 static HRESULT WINAPI domdoc_get_previousSibling(
1131 IXMLDOMDocument3 *iface,
1132 IXMLDOMNode** previousSibling )
1134 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1136 TRACE("(%p)->(%p)\n", This, previousSibling);
1138 return return_null_node(previousSibling);
1142 static HRESULT WINAPI domdoc_get_nextSibling(
1143 IXMLDOMDocument3 *iface,
1144 IXMLDOMNode** nextSibling )
1146 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1148 TRACE("(%p)->(%p)\n", This, nextSibling);
1150 return return_null_node(nextSibling);
1154 static HRESULT WINAPI domdoc_get_attributes(
1155 IXMLDOMDocument3 *iface,
1156 IXMLDOMNamedNodeMap** attributeMap )
1158 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1160 TRACE("(%p)->(%p)\n", This, attributeMap);
1162 return return_null_ptr((void**)attributeMap);
1166 static HRESULT WINAPI domdoc_insertBefore(
1167 IXMLDOMDocument3 *iface,
1168 IXMLDOMNode* newChild,
1169 VARIANT refChild,
1170 IXMLDOMNode** outNewChild )
1172 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1173 DOMNodeType type;
1174 HRESULT hr;
1176 TRACE("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), outNewChild);
1178 hr = IXMLDOMNode_get_nodeType(newChild, &type);
1179 if (hr != S_OK) return hr;
1181 TRACE("new node type %d\n", type);
1182 switch (type)
1184 case NODE_ATTRIBUTE:
1185 case NODE_DOCUMENT:
1186 case NODE_CDATA_SECTION:
1187 if (outNewChild) *outNewChild = NULL;
1188 return E_FAIL;
1189 default:
1190 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1194 static HRESULT WINAPI domdoc_replaceChild(
1195 IXMLDOMDocument3 *iface,
1196 IXMLDOMNode* newChild,
1197 IXMLDOMNode* oldChild,
1198 IXMLDOMNode** outOldChild)
1200 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1202 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1204 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1208 static HRESULT WINAPI domdoc_removeChild(
1209 IXMLDOMDocument3 *iface,
1210 IXMLDOMNode *child,
1211 IXMLDOMNode **oldChild)
1213 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1214 TRACE("(%p)->(%p %p)\n", This, child, oldChild);
1215 return node_remove_child(&This->node, child, oldChild);
1219 static HRESULT WINAPI domdoc_appendChild(
1220 IXMLDOMDocument3 *iface,
1221 IXMLDOMNode *child,
1222 IXMLDOMNode **outChild)
1224 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1225 TRACE("(%p)->(%p %p)\n", This, child, outChild);
1226 return node_append_child(&This->node, child, outChild);
1230 static HRESULT WINAPI domdoc_hasChildNodes(
1231 IXMLDOMDocument3 *iface,
1232 VARIANT_BOOL *ret)
1234 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1235 TRACE("(%p)->(%p)\n", This, ret);
1236 return node_has_childnodes(&This->node, ret);
1240 static HRESULT WINAPI domdoc_get_ownerDocument(
1241 IXMLDOMDocument3 *iface,
1242 IXMLDOMDocument **doc)
1244 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1245 TRACE("(%p)->(%p)\n", This, doc);
1246 return node_get_owner_doc(&This->node, doc);
1250 static HRESULT WINAPI domdoc_cloneNode(
1251 IXMLDOMDocument3 *iface,
1252 VARIANT_BOOL deep,
1253 IXMLDOMNode** outNode)
1255 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1256 xmlNodePtr clone;
1258 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
1260 if (!outNode)
1261 return E_INVALIDARG;
1263 *outNode = NULL;
1265 clone = xmlCopyNode((xmlNodePtr)get_doc(This), deep ? 1 : 2);
1266 if (!clone)
1267 return E_FAIL;
1269 clone->doc->_private = create_priv();
1270 xmldoc_add_orphan(clone->doc, clone);
1271 xmldoc_add_ref(clone->doc);
1273 priv_from_xmlDocPtr(clone->doc)->properties = copy_properties(This->properties);
1274 if (!(*outNode = (IXMLDOMNode*)create_domdoc(clone)))
1276 xmldoc_release(clone->doc);
1277 return E_FAIL;
1280 return S_OK;
1284 static HRESULT WINAPI domdoc_get_nodeTypeString(
1285 IXMLDOMDocument3 *iface,
1286 BSTR *p)
1288 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1289 static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
1291 TRACE("(%p)->(%p)\n", This, p);
1293 return return_bstr(documentW, p);
1297 static HRESULT WINAPI domdoc_get_text(
1298 IXMLDOMDocument3 *iface,
1299 BSTR *p)
1301 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1302 TRACE("(%p)->(%p)\n", This, p);
1303 return node_get_text(&This->node, p);
1307 static HRESULT WINAPI domdoc_put_text(
1308 IXMLDOMDocument3 *iface,
1309 BSTR text )
1311 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1312 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1313 return E_FAIL;
1317 static HRESULT WINAPI domdoc_get_specified(
1318 IXMLDOMDocument3 *iface,
1319 VARIANT_BOOL* isSpecified )
1321 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1322 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1323 *isSpecified = VARIANT_TRUE;
1324 return S_OK;
1328 static HRESULT WINAPI domdoc_get_definition(
1329 IXMLDOMDocument3 *iface,
1330 IXMLDOMNode** definitionNode )
1332 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1333 FIXME("(%p)->(%p)\n", This, definitionNode);
1334 return E_NOTIMPL;
1338 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1339 IXMLDOMDocument3 *iface,
1340 VARIANT* v )
1342 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1343 TRACE("(%p)->(%p)\n", This, v);
1344 return return_null_var(v);
1347 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1348 IXMLDOMDocument3 *iface,
1349 VARIANT typedValue )
1351 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1352 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
1353 return E_NOTIMPL;
1357 static HRESULT WINAPI domdoc_get_dataType(
1358 IXMLDOMDocument3 *iface,
1359 VARIANT* typename )
1361 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1362 TRACE("(%p)->(%p)\n", This, typename);
1363 return return_null_var( typename );
1367 static HRESULT WINAPI domdoc_put_dataType(
1368 IXMLDOMDocument3 *iface,
1369 BSTR dataTypeName )
1371 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1373 FIXME("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
1375 if(!dataTypeName)
1376 return E_INVALIDARG;
1378 return E_FAIL;
1381 static int XMLCALL domdoc_get_xml_writecallback(void *ctx, const char *data, int len)
1383 return xmlBufferAdd((xmlBufferPtr)ctx, (xmlChar*)data, len) == 0 ? len : 0;
1386 static HRESULT WINAPI domdoc_get_xml(
1387 IXMLDOMDocument3 *iface,
1388 BSTR* p)
1390 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1391 xmlSaveCtxtPtr ctxt;
1392 xmlBufferPtr buf;
1393 int options;
1394 long ret;
1396 TRACE("(%p)->(%p)\n", This, p);
1398 if(!p)
1399 return E_INVALIDARG;
1401 *p = NULL;
1403 buf = xmlBufferCreate();
1404 if(!buf)
1405 return E_OUTOFMEMORY;
1407 options = XML_SAVE_FORMAT | XML_SAVE_NO_DECL;
1408 ctxt = xmlSaveToIO(domdoc_get_xml_writecallback, NULL, buf, "UTF-8", options);
1410 if(!ctxt)
1412 xmlBufferFree(buf);
1413 return E_OUTOFMEMORY;
1416 ret = xmlSaveDoc(ctxt, get_doc(This));
1417 /* flushes on close */
1418 xmlSaveClose(ctxt);
1420 TRACE("%ld, len=%d\n", ret, xmlBufferLength(buf));
1421 if(ret != -1 && xmlBufferLength(buf) > 0)
1423 BSTR content;
1425 content = bstr_from_xmlChar(xmlBufferContent(buf));
1426 content = EnsureCorrectEOL(content);
1428 *p = content;
1430 else
1432 *p = SysAllocStringLen(NULL, 0);
1435 xmlBufferFree(buf);
1437 return *p ? S_OK : E_OUTOFMEMORY;
1441 static HRESULT WINAPI domdoc_transformNode(
1442 IXMLDOMDocument3 *iface,
1443 IXMLDOMNode *node,
1444 BSTR *p)
1446 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1447 TRACE("(%p)->(%p %p)\n", This, node, p);
1448 return node_transform_node(&This->node, node, p);
1452 static HRESULT WINAPI domdoc_selectNodes(
1453 IXMLDOMDocument3 *iface,
1454 BSTR p,
1455 IXMLDOMNodeList **outList)
1457 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1458 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList);
1459 return node_select_nodes(&This->node, p, outList);
1463 static HRESULT WINAPI domdoc_selectSingleNode(
1464 IXMLDOMDocument3 *iface,
1465 BSTR p,
1466 IXMLDOMNode **outNode)
1468 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1469 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode);
1470 return node_select_singlenode(&This->node, p, outNode);
1474 static HRESULT WINAPI domdoc_get_parsed(
1475 IXMLDOMDocument3 *iface,
1476 VARIANT_BOOL* isParsed )
1478 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1479 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1480 *isParsed = VARIANT_TRUE;
1481 return S_OK;
1484 static HRESULT WINAPI domdoc_get_namespaceURI(
1485 IXMLDOMDocument3 *iface,
1486 BSTR* namespaceURI )
1488 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1489 TRACE("(%p)->(%p)\n", This, namespaceURI);
1490 return return_null_bstr( namespaceURI );
1493 static HRESULT WINAPI domdoc_get_prefix(
1494 IXMLDOMDocument3 *iface,
1495 BSTR* prefix )
1497 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1498 TRACE("(%p)->(%p)\n", This, prefix);
1499 return return_null_bstr( prefix );
1503 static HRESULT WINAPI domdoc_get_baseName(
1504 IXMLDOMDocument3 *iface,
1505 BSTR* name )
1507 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1508 TRACE("(%p)->(%p)\n", This, name);
1509 return return_null_bstr( name );
1513 static HRESULT WINAPI domdoc_transformNodeToObject(
1514 IXMLDOMDocument3 *iface,
1515 IXMLDOMNode* stylesheet,
1516 VARIANT output)
1518 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1520 TRACE("(%p)->(%p %s)\n", This, stylesheet, debugstr_variant(&output));
1522 switch (V_VT(&output))
1524 case VT_UNKNOWN:
1525 case VT_DISPATCH:
1527 ISequentialStream *stream;
1528 IXMLDOMDocument *doc;
1529 HRESULT hr;
1530 BSTR str;
1532 if (!V_UNKNOWN(&output))
1533 return E_INVALIDARG;
1535 /* FIXME: we're not supposed to query for document interface, should use IStream
1536 which we don't support currently. */
1537 if (IUnknown_QueryInterface(V_UNKNOWN(&output), &IID_IXMLDOMDocument, (void **)&doc) == S_OK)
1539 VARIANT_BOOL b;
1541 if (FAILED(hr = node_transform_node(&This->node, stylesheet, &str)))
1542 return hr;
1544 hr = IXMLDOMDocument_loadXML(doc, str, &b);
1545 SysFreeString(str);
1546 return hr;
1548 else if (IUnknown_QueryInterface(V_UNKNOWN(&output), &IID_ISequentialStream, (void**)&stream) == S_OK)
1550 hr = node_transform_node_params(&This->node, stylesheet, NULL, stream, NULL);
1551 ISequentialStream_Release(stream);
1552 return hr;
1554 else
1556 FIXME("Unsupported destination type.\n");
1557 return E_INVALIDARG;
1560 default:
1561 FIXME("Output type %d not handled.\n", V_VT(&output));
1562 return E_NOTIMPL;
1565 return E_NOTIMPL;
1569 static HRESULT WINAPI domdoc_get_doctype(
1570 IXMLDOMDocument3 *iface,
1571 IXMLDOMDocumentType** doctype )
1573 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1574 IXMLDOMNode *node;
1575 xmlDtdPtr dtd;
1576 HRESULT hr;
1578 TRACE("(%p)->(%p)\n", This, doctype);
1580 if (!doctype) return E_INVALIDARG;
1582 *doctype = NULL;
1584 dtd = xmlGetIntSubset(get_doc(This));
1585 if (!dtd) return S_FALSE;
1587 node = create_node((xmlNodePtr)dtd);
1588 if (!node) return S_FALSE;
1590 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentType, (void**)doctype);
1591 IXMLDOMNode_Release(node);
1593 return hr;
1597 static HRESULT WINAPI domdoc_get_implementation(
1598 IXMLDOMDocument3 *iface,
1599 IXMLDOMImplementation** impl )
1601 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1603 TRACE("(%p)->(%p)\n", This, impl);
1605 if(!impl)
1606 return E_INVALIDARG;
1608 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1610 return S_OK;
1613 static HRESULT WINAPI domdoc_get_documentElement(
1614 IXMLDOMDocument3 *iface,
1615 IXMLDOMElement** DOMElement )
1617 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1618 IXMLDOMNode *element_node;
1619 xmlNodePtr root;
1620 HRESULT hr;
1622 TRACE("(%p)->(%p)\n", This, DOMElement);
1624 if(!DOMElement)
1625 return E_INVALIDARG;
1627 *DOMElement = NULL;
1629 root = xmlDocGetRootElement( get_doc(This) );
1630 if ( !root )
1631 return S_FALSE;
1633 element_node = create_node( root );
1634 if(!element_node) return S_FALSE;
1636 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1637 IXMLDOMNode_Release(element_node);
1639 return hr;
1643 static HRESULT WINAPI domdoc_put_documentElement(
1644 IXMLDOMDocument3 *iface,
1645 IXMLDOMElement* DOMElement )
1647 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1648 IXMLDOMNode *elementNode;
1649 xmlNodePtr oldRoot;
1650 xmlDocPtr old_doc;
1651 xmlnode *xmlNode;
1652 int refcount = 0;
1653 HRESULT hr;
1655 TRACE("(%p)->(%p)\n", This, DOMElement);
1657 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1658 if(FAILED(hr))
1659 return hr;
1661 xmlNode = get_node_obj( elementNode );
1662 if(!xmlNode) return E_FAIL;
1664 if(!xmlNode->node->parent)
1665 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1666 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1668 old_doc = xmlNode->node->doc;
1669 if (old_doc != get_doc(This))
1670 refcount = xmlnode_get_inst_cnt(xmlNode);
1672 /* old root is still orphaned by its document, update refcount from new root */
1673 if (refcount) xmldoc_add_refs(get_doc(This), refcount);
1674 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1675 if (refcount) xmldoc_release_refs(old_doc, refcount);
1676 IXMLDOMNode_Release( elementNode );
1678 if(oldRoot)
1679 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1681 return S_OK;
1685 static HRESULT WINAPI domdoc_createElement(
1686 IXMLDOMDocument3 *iface,
1687 BSTR tagname,
1688 IXMLDOMElement** element )
1690 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1691 IXMLDOMNode *node;
1692 VARIANT type;
1693 HRESULT hr;
1695 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1697 if (!element || !tagname) return E_INVALIDARG;
1699 V_VT(&type) = VT_I1;
1700 V_I1(&type) = NODE_ELEMENT;
1702 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1703 if (hr == S_OK)
1705 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1706 IXMLDOMNode_Release(node);
1709 return hr;
1713 static HRESULT WINAPI domdoc_createDocumentFragment(
1714 IXMLDOMDocument3 *iface,
1715 IXMLDOMDocumentFragment** frag )
1717 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1718 IXMLDOMNode *node;
1719 VARIANT type;
1720 HRESULT hr;
1722 TRACE("(%p)->(%p)\n", This, frag);
1724 if (!frag) return E_INVALIDARG;
1726 *frag = NULL;
1728 V_VT(&type) = VT_I1;
1729 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1731 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1732 if (hr == S_OK)
1734 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1735 IXMLDOMNode_Release(node);
1738 return hr;
1742 static HRESULT WINAPI domdoc_createTextNode(
1743 IXMLDOMDocument3 *iface,
1744 BSTR data,
1745 IXMLDOMText** text )
1747 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1748 IXMLDOMNode *node;
1749 VARIANT type;
1750 HRESULT hr;
1752 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1754 if (!text) return E_INVALIDARG;
1756 *text = NULL;
1758 V_VT(&type) = VT_I1;
1759 V_I1(&type) = NODE_TEXT;
1761 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1762 if (hr == S_OK)
1764 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1765 IXMLDOMNode_Release(node);
1766 hr = IXMLDOMText_put_data(*text, data);
1769 return hr;
1773 static HRESULT WINAPI domdoc_createComment(
1774 IXMLDOMDocument3 *iface,
1775 BSTR data,
1776 IXMLDOMComment** comment )
1778 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1779 VARIANT type;
1780 HRESULT hr;
1781 IXMLDOMNode *node;
1783 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1785 if (!comment) return E_INVALIDARG;
1787 *comment = NULL;
1789 V_VT(&type) = VT_I1;
1790 V_I1(&type) = NODE_COMMENT;
1792 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1793 if (hr == S_OK)
1795 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1796 IXMLDOMNode_Release(node);
1797 hr = IXMLDOMComment_put_data(*comment, data);
1800 return hr;
1804 static HRESULT WINAPI domdoc_createCDATASection(
1805 IXMLDOMDocument3 *iface,
1806 BSTR data,
1807 IXMLDOMCDATASection** cdata )
1809 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1810 IXMLDOMNode *node;
1811 VARIANT type;
1812 HRESULT hr;
1814 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1816 if (!cdata) return E_INVALIDARG;
1818 *cdata = NULL;
1820 V_VT(&type) = VT_I1;
1821 V_I1(&type) = NODE_CDATA_SECTION;
1823 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1824 if (hr == S_OK)
1826 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1827 IXMLDOMNode_Release(node);
1828 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1831 return hr;
1835 static HRESULT WINAPI domdoc_createProcessingInstruction(
1836 IXMLDOMDocument3 *iface,
1837 BSTR target,
1838 BSTR data,
1839 IXMLDOMProcessingInstruction** pi )
1841 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1842 IXMLDOMNode *node;
1843 VARIANT type;
1844 HRESULT hr;
1846 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1848 if (!pi) return E_INVALIDARG;
1850 *pi = NULL;
1852 V_VT(&type) = VT_I1;
1853 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1855 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1856 if (hr == S_OK)
1858 xmlnode *node_obj;
1860 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1861 node_obj = get_node_obj(node);
1862 hr = node_set_content(node_obj, data);
1864 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1865 IXMLDOMNode_Release(node);
1868 return hr;
1872 static HRESULT WINAPI domdoc_createAttribute(
1873 IXMLDOMDocument3 *iface,
1874 BSTR name,
1875 IXMLDOMAttribute** attribute )
1877 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1878 IXMLDOMNode *node;
1879 VARIANT type;
1880 HRESULT hr;
1882 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1884 if (!attribute || !name) return E_INVALIDARG;
1886 V_VT(&type) = VT_I1;
1887 V_I1(&type) = NODE_ATTRIBUTE;
1889 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1890 if (hr == S_OK)
1892 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1893 IXMLDOMNode_Release(node);
1896 return hr;
1900 static HRESULT WINAPI domdoc_createEntityReference(
1901 IXMLDOMDocument3 *iface,
1902 BSTR name,
1903 IXMLDOMEntityReference** entityref )
1905 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1906 IXMLDOMNode *node;
1907 VARIANT type;
1908 HRESULT hr;
1910 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1912 if (!entityref) return E_INVALIDARG;
1914 *entityref = NULL;
1916 V_VT(&type) = VT_I1;
1917 V_I1(&type) = NODE_ENTITY_REFERENCE;
1919 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1920 if (hr == S_OK)
1922 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1923 IXMLDOMNode_Release(node);
1926 return hr;
1929 xmlChar* tagName_to_XPath(const BSTR tagName)
1931 xmlChar *query, *tmp;
1932 static const xmlChar everything[] = "/descendant::node()";
1933 static const xmlChar mod_pre[] = "*[local-name()='";
1934 static const xmlChar mod_post[] = "']";
1935 static const xmlChar prefix[] = "descendant::";
1936 const WCHAR *tokBegin, *tokEnd;
1937 int len;
1939 /* Special case - empty tagname - means select all nodes,
1940 except document itself. */
1941 if (!*tagName)
1942 return xmlStrdup(everything);
1944 query = xmlStrdup(prefix);
1946 tokBegin = tagName;
1947 while (tokBegin && *tokBegin)
1949 switch (*tokBegin)
1951 case '/':
1952 query = xmlStrcat(query, BAD_CAST "/");
1953 ++tokBegin;
1954 break;
1955 case '*':
1956 query = xmlStrcat(query, BAD_CAST "*");
1957 ++tokBegin;
1958 break;
1959 default:
1960 query = xmlStrcat(query, mod_pre);
1961 tokEnd = tokBegin;
1962 while (*tokEnd && *tokEnd != '/')
1963 ++tokEnd;
1964 len = WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, NULL, 0, NULL, NULL);
1965 tmp = xmlMalloc(len);
1966 WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, (char*)tmp, len, NULL, NULL);
1967 query = xmlStrncat(query, tmp, len);
1968 xmlFree(tmp);
1969 tokBegin = tokEnd;
1970 query = xmlStrcat(query, mod_post);
1974 return query;
1977 static HRESULT WINAPI domdoc_getElementsByTagName(
1978 IXMLDOMDocument3 *iface,
1979 BSTR tagName,
1980 IXMLDOMNodeList** resultList )
1982 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1983 xmlChar *query;
1984 HRESULT hr;
1985 BOOL XPath;
1987 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1989 if (!tagName || !resultList) return E_INVALIDARG;
1991 XPath = This->properties->XPath;
1992 This->properties->XPath = TRUE;
1993 query = tagName_to_XPath(tagName);
1994 hr = create_selection((xmlNodePtr)get_doc(This), query, resultList);
1995 xmlFree(query);
1996 This->properties->XPath = XPath;
1998 return hr;
2001 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
2003 VARIANT tmp;
2004 HRESULT hr;
2006 VariantInit(&tmp);
2007 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
2008 if(FAILED(hr))
2009 return E_INVALIDARG;
2011 *type = V_I4(&tmp);
2013 return S_OK;
2016 static HRESULT WINAPI domdoc_createNode(
2017 IXMLDOMDocument3 *iface,
2018 VARIANT Type,
2019 BSTR name,
2020 BSTR namespaceURI,
2021 IXMLDOMNode** node )
2023 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2024 DOMNodeType node_type;
2025 xmlNodePtr xmlnode;
2026 xmlChar *xml_name, *href;
2027 HRESULT hr;
2029 TRACE("(%p)->(%s %s %s %p)\n", This, debugstr_variant(&Type), debugstr_w(name), debugstr_w(namespaceURI), node);
2031 if(!node) return E_INVALIDARG;
2033 hr = get_node_type(Type, &node_type);
2034 if(FAILED(hr)) return hr;
2036 TRACE("node_type %d\n", node_type);
2038 /* exit earlier for types that need name */
2039 switch(node_type)
2041 case NODE_ELEMENT:
2042 case NODE_ATTRIBUTE:
2043 case NODE_ENTITY_REFERENCE:
2044 case NODE_PROCESSING_INSTRUCTION:
2045 if (!name || *name == 0) return E_FAIL;
2046 break;
2047 default:
2048 break;
2051 xml_name = xmlchar_from_wchar(name);
2052 /* prevent empty href from being allocated */
2053 href = namespaceURI ? xmlchar_from_wchar(namespaceURI) : NULL;
2055 switch(node_type)
2057 case NODE_ELEMENT:
2059 xmlChar *local, *prefix;
2061 local = xmlSplitQName2(xml_name, &prefix);
2063 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
2065 /* allow creating the default namespace xmlns= */
2066 if (local || (href && *href))
2068 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
2069 xmlSetNs(xmlnode, ns);
2072 xmlFree(local);
2073 xmlFree(prefix);
2075 break;
2077 case NODE_ATTRIBUTE:
2079 xmlChar *local, *prefix;
2081 local = xmlSplitQName2(xml_name, &prefix);
2083 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), local ? local : xml_name, NULL);
2085 if (local || (href && *href))
2087 /* we need a floating namespace here, it can't be created linked to attribute from
2088 a start */
2089 xmlNsPtr ns = xmlNewNs(NULL, href, prefix);
2090 xmlSetNs(xmlnode, ns);
2093 xmlFree(local);
2094 xmlFree(prefix);
2096 break;
2098 case NODE_TEXT:
2099 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
2100 break;
2101 case NODE_CDATA_SECTION:
2102 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
2103 break;
2104 case NODE_ENTITY_REFERENCE:
2105 xmlnode = xmlNewReference(get_doc(This), xml_name);
2106 break;
2107 case NODE_PROCESSING_INSTRUCTION:
2108 #ifdef HAVE_XMLNEWDOCPI
2109 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
2110 #else
2111 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
2112 xmlnode = NULL;
2113 #endif
2114 break;
2115 case NODE_COMMENT:
2116 xmlnode = xmlNewDocComment(get_doc(This), NULL);
2117 break;
2118 case NODE_DOCUMENT_FRAGMENT:
2119 xmlnode = xmlNewDocFragment(get_doc(This));
2120 break;
2121 /* unsupported types */
2122 case NODE_DOCUMENT:
2123 case NODE_DOCUMENT_TYPE:
2124 case NODE_ENTITY:
2125 case NODE_NOTATION:
2126 heap_free(xml_name);
2127 return E_INVALIDARG;
2128 default:
2129 FIXME("unhandled node type %d\n", node_type);
2130 xmlnode = NULL;
2131 break;
2134 *node = create_node(xmlnode);
2135 heap_free(xml_name);
2136 heap_free(href);
2138 if(*node)
2140 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
2141 xmldoc_add_orphan(xmlnode->doc, xmlnode);
2142 return S_OK;
2145 return E_FAIL;
2148 static HRESULT WINAPI domdoc_nodeFromID(
2149 IXMLDOMDocument3 *iface,
2150 BSTR idString,
2151 IXMLDOMNode** node )
2153 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2154 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
2155 return E_NOTIMPL;
2158 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
2160 domdoc *This = obj;
2161 xmlDocPtr xmldoc;
2163 xmldoc = doparse(This, ptr, len, XML_CHAR_ENCODING_NONE);
2164 if(xmldoc) {
2165 xmldoc->_private = create_priv();
2166 return attach_xmldoc(This, xmldoc);
2169 return E_FAIL;
2172 static HRESULT domdoc_load_moniker(domdoc *This, IMoniker *mon)
2174 bsc_t *bsc;
2175 HRESULT hr;
2177 hr = bind_url(mon, domdoc_onDataAvailable, This, &bsc);
2178 if(FAILED(hr))
2179 return hr;
2181 return detach_bsc(bsc);
2184 static HRESULT WINAPI domdoc_load(
2185 IXMLDOMDocument3 *iface,
2186 VARIANT source,
2187 VARIANT_BOOL* isSuccessful )
2189 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2190 LPWSTR filename = NULL;
2191 HRESULT hr = S_FALSE;
2192 xmlDocPtr xmldoc;
2194 TRACE("(%p)->(%s)\n", This, debugstr_variant(&source));
2196 if (!isSuccessful)
2197 return E_POINTER;
2198 *isSuccessful = VARIANT_FALSE;
2200 assert( &This->node );
2202 switch( V_VT(&source) )
2204 case VT_BSTR:
2205 filename = V_BSTR(&source);
2206 break;
2207 case VT_BSTR|VT_BYREF:
2208 if (!V_BSTRREF(&source)) return E_INVALIDARG;
2209 filename = *V_BSTRREF(&source);
2210 break;
2211 case VT_ARRAY|VT_UI1:
2213 SAFEARRAY *psa = V_ARRAY(&source);
2214 char *str;
2215 LONG len;
2216 UINT dim = SafeArrayGetDim(psa);
2218 switch (dim)
2220 case 0:
2221 ERR("SAFEARRAY == NULL\n");
2222 hr = This->error = E_INVALIDARG;
2223 break;
2224 case 1:
2225 /* Only takes UTF-8 strings.
2226 * NOT NULL-terminated. */
2227 hr = SafeArrayAccessData(psa, (void**)&str);
2228 if (FAILED(hr))
2230 This->error = hr;
2231 WARN("failed to access array data, 0x%08x\n", hr);
2232 break;
2234 SafeArrayGetUBound(psa, 1, &len);
2236 if ((xmldoc = doparse(This, str, ++len, XML_CHAR_ENCODING_UTF8)))
2238 hr = This->error = S_OK;
2239 *isSuccessful = VARIANT_TRUE;
2240 TRACE("parsed document %p\n", xmldoc);
2242 else
2244 This->error = E_FAIL;
2245 TRACE("failed to parse document\n");
2248 SafeArrayUnaccessData(psa);
2250 if(xmldoc)
2252 xmldoc->_private = create_priv();
2253 return attach_xmldoc(This, xmldoc);
2255 break;
2256 default:
2257 FIXME("unhandled SAFEARRAY dim: %d\n", dim);
2258 hr = This->error = E_NOTIMPL;
2261 break;
2262 case VT_UNKNOWN:
2264 ISequentialStream *stream = NULL;
2265 IXMLDOMDocument3 *newdoc = NULL;
2267 if (!V_UNKNOWN(&source)) return E_INVALIDARG;
2269 hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IXMLDOMDocument3, (void**)&newdoc);
2270 if(hr == S_OK)
2272 if(newdoc)
2274 domdoc *newDoc = impl_from_IXMLDOMDocument3( newdoc );
2276 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
2277 xmldoc->_private = create_priv();
2278 hr = attach_xmldoc(This, xmldoc);
2280 if(SUCCEEDED(hr))
2281 *isSuccessful = VARIANT_TRUE;
2283 return hr;
2287 hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_IStream, (void**)&stream);
2288 if (FAILED(hr))
2289 hr = IUnknown_QueryInterface(V_UNKNOWN(&source), &IID_ISequentialStream, (void**)&stream);
2291 if (hr == S_OK)
2293 hr = This->error = domdoc_load_from_stream(This, stream);
2294 if (hr == S_OK)
2295 *isSuccessful = VARIANT_TRUE;
2296 ISequentialStream_Release(stream);
2297 return hr;
2300 FIXME("unsupported IUnknown type (0x%08x) (%p)\n", hr, V_UNKNOWN(&source)->lpVtbl);
2301 break;
2303 default:
2304 FIXME("VT type not supported (%d)\n", V_VT(&source));
2307 if ( filename )
2309 IUri *uri = NULL;
2310 IMoniker *mon;
2312 if (This->properties->uri)
2314 IUri_Release(This->properties->uri);
2315 This->properties->uri = NULL;
2318 hr = create_uri(This->base_uri, filename, &uri);
2319 if (SUCCEEDED(hr))
2320 hr = CreateURLMonikerEx2(NULL, uri, &mon, 0);
2321 if ( SUCCEEDED(hr) )
2323 hr = domdoc_load_moniker( This, mon );
2324 IMoniker_Release(mon);
2327 if (SUCCEEDED(hr))
2329 get_doc(This)->name = (char *)xmlchar_from_wcharn(filename, -1, TRUE);
2330 This->properties->uri = uri;
2331 hr = This->error = S_OK;
2332 *isSuccessful = VARIANT_TRUE;
2334 else
2336 if (uri)
2337 IUri_Release(uri);
2338 This->error = E_FAIL;
2342 if(!filename || FAILED(hr)) {
2343 xmldoc = xmlNewDoc(NULL);
2344 xmldoc->_private = create_priv();
2345 hr = attach_xmldoc(This, xmldoc);
2346 if(SUCCEEDED(hr))
2347 hr = S_FALSE;
2350 TRACE("ret (%d)\n", hr);
2352 return hr;
2356 static HRESULT WINAPI domdoc_get_readyState(
2357 IXMLDOMDocument3 *iface,
2358 LONG *value )
2360 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2361 FIXME("stub! (%p)->(%p)\n", This, value);
2363 if (!value)
2364 return E_INVALIDARG;
2366 *value = READYSTATE_COMPLETE;
2367 return S_OK;
2371 static HRESULT WINAPI domdoc_get_parseError(
2372 IXMLDOMDocument3 *iface,
2373 IXMLDOMParseError** errorObj )
2375 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2376 static const WCHAR err[] = {'e','r','r','o','r',0};
2377 BSTR error_string = NULL;
2379 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2381 if(This->error)
2382 error_string = SysAllocString(err);
2384 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2385 if(!*errorObj) return E_OUTOFMEMORY;
2386 return S_OK;
2390 static HRESULT WINAPI domdoc_get_url(
2391 IXMLDOMDocument3 *iface,
2392 BSTR* url )
2394 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2396 TRACE("(%p)->(%p)\n", This, url);
2398 if (!url)
2399 return E_INVALIDARG;
2401 if (!This->properties->uri)
2402 return return_null_bstr(url);
2404 return IUri_GetPropertyBSTR(This->properties->uri, Uri_PROPERTY_DISPLAY_URI, url, 0);
2408 static HRESULT WINAPI domdoc_get_async(
2409 IXMLDOMDocument3 *iface,
2410 VARIANT_BOOL* isAsync )
2412 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2414 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2415 *isAsync = This->async;
2416 return S_OK;
2420 static HRESULT WINAPI domdoc_put_async(
2421 IXMLDOMDocument3 *iface,
2422 VARIANT_BOOL isAsync )
2424 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2426 TRACE("(%p)->(%d)\n", This, isAsync);
2427 This->async = isAsync;
2428 return S_OK;
2432 static HRESULT WINAPI domdoc_abort(
2433 IXMLDOMDocument3 *iface )
2435 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2436 FIXME("%p\n", This);
2437 return E_NOTIMPL;
2440 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2441 static HRESULT WINAPI domdoc_loadXML(
2442 IXMLDOMDocument3 *iface,
2443 BSTR data,
2444 VARIANT_BOOL* isSuccessful )
2446 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2447 xmlDocPtr xmldoc = NULL;
2448 HRESULT hr = S_FALSE, hr2;
2450 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), isSuccessful );
2452 assert ( &This->node );
2454 if ( isSuccessful )
2456 *isSuccessful = VARIANT_FALSE;
2458 if (data)
2460 WCHAR *ptr = data;
2462 /* skip leading spaces if needed */
2463 if (This->properties->version == MSXML_DEFAULT || This->properties->version == MSXML26)
2464 while (*ptr && isspaceW(*ptr)) ptr++;
2466 xmldoc = doparse(This, (char*)ptr, strlenW(ptr)*sizeof(WCHAR), XML_CHAR_ENCODING_UTF16LE);
2467 if ( !xmldoc )
2469 This->error = E_FAIL;
2470 TRACE("failed to parse document\n");
2472 else
2474 hr = This->error = S_OK;
2475 *isSuccessful = VARIANT_TRUE;
2476 TRACE("parsed document %p\n", xmldoc);
2481 if(!xmldoc)
2482 xmldoc = xmlNewDoc(NULL);
2483 xmldoc->_private = create_priv();
2484 hr2 = attach_xmldoc(This, xmldoc);
2485 if( FAILED(hr2) )
2486 hr = hr2;
2488 return hr;
2491 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2493 DWORD written = -1;
2495 if(!WriteFile(ctx, buffer, len, &written, NULL))
2497 WARN("write error\n");
2498 return -1;
2500 else
2501 return written;
2504 static int XMLCALL domdoc_save_closecallback(void *ctx)
2506 return CloseHandle(ctx) ? 0 : -1;
2509 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2511 ULONG written = 0;
2512 HRESULT hr;
2514 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2515 TRACE("0x%08x %p %d %u\n", hr, buffer, len, written);
2516 if (hr != S_OK)
2518 WARN("stream write error: 0x%08x\n", hr);
2519 return -1;
2521 else
2522 return len;
2525 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2527 IStream_Release((IStream*)ctx);
2528 return 0;
2531 static HRESULT WINAPI domdoc_save(
2532 IXMLDOMDocument3 *iface,
2533 VARIANT destination )
2535 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2536 xmlSaveCtxtPtr ctx = NULL;
2537 xmlNodePtr xmldecl;
2538 HRESULT ret = S_OK;
2540 TRACE("(%p)->(%s)\n", This, debugstr_variant(&destination));
2542 switch (V_VT(&destination))
2544 case VT_UNKNOWN:
2546 IUnknown *pUnk = V_UNKNOWN(&destination);
2547 IXMLDOMDocument3 *document;
2548 IStream *stream;
2550 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2551 if(ret == S_OK)
2553 VARIANT_BOOL success;
2554 BSTR xml;
2556 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2557 if(ret == S_OK)
2559 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2560 SysFreeString(xml);
2563 IXMLDOMDocument3_Release(document);
2564 return ret;
2567 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2568 if(ret == S_OK)
2570 int options = get_doc(This)->standalone == -1 ? XML_SAVE_NO_DECL : 0;
2571 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2572 domdoc_stream_save_closecallback, stream, NULL, options);
2574 if(!ctx)
2576 IStream_Release(stream);
2577 return E_FAIL;
2581 break;
2583 case VT_BSTR:
2584 case VT_BSTR | VT_BYREF:
2586 int options = get_doc(This)->standalone == -1 ? XML_SAVE_NO_DECL : 0;
2588 /* save with file path */
2589 HANDLE handle = CreateFileW( (V_VT(&destination) & VT_BYREF)? *V_BSTRREF(&destination) : V_BSTR(&destination),
2590 GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2591 if( handle == INVALID_HANDLE_VALUE )
2593 WARN("failed to create file\n");
2594 return E_FAIL;
2597 /* disable top XML declaration */
2598 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2599 handle, NULL, options);
2600 if (!ctx)
2602 CloseHandle(handle);
2603 return E_FAIL;
2606 break;
2608 default:
2609 FIXME("Unhandled VARIANT: %s\n", debugstr_variant(&destination));
2610 return S_FALSE;
2613 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2614 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2615 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2617 /* will release resources through close callback */
2618 xmlSaveClose(ctx);
2620 return ret;
2623 static HRESULT WINAPI domdoc_get_validateOnParse(
2624 IXMLDOMDocument3 *iface,
2625 VARIANT_BOOL* isValidating )
2627 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2628 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2629 *isValidating = This->validating;
2630 return S_OK;
2634 static HRESULT WINAPI domdoc_put_validateOnParse(
2635 IXMLDOMDocument3 *iface,
2636 VARIANT_BOOL isValidating )
2638 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2639 TRACE("(%p)->(%d)\n", This, isValidating);
2640 This->validating = isValidating;
2641 return S_OK;
2645 static HRESULT WINAPI domdoc_get_resolveExternals(
2646 IXMLDOMDocument3 *iface,
2647 VARIANT_BOOL* isResolving )
2649 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2650 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2651 *isResolving = This->resolving;
2652 return S_OK;
2656 static HRESULT WINAPI domdoc_put_resolveExternals(
2657 IXMLDOMDocument3 *iface,
2658 VARIANT_BOOL isResolving )
2660 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2661 TRACE("(%p)->(%d)\n", This, isResolving);
2662 This->resolving = isResolving;
2663 return S_OK;
2667 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2668 IXMLDOMDocument3 *iface,
2669 VARIANT_BOOL* isPreserving )
2671 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2672 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->properties->preserving);
2673 *isPreserving = This->properties->preserving;
2674 return S_OK;
2678 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2679 IXMLDOMDocument3 *iface,
2680 VARIANT_BOOL isPreserving )
2682 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2683 TRACE("(%p)->(%d)\n", This, isPreserving);
2684 This->properties->preserving = isPreserving;
2685 return S_OK;
2689 static HRESULT WINAPI domdoc_put_onreadystatechange(
2690 IXMLDOMDocument3 *iface,
2691 VARIANT event )
2693 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2695 TRACE("(%p)->(%s)\n", This, debugstr_variant(&event));
2696 return set_doc_event(This, EVENTID_READYSTATECHANGE, &event);
2700 static HRESULT WINAPI domdoc_put_onDataAvailable(IXMLDOMDocument3 *iface, VARIANT sink)
2702 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2703 FIXME("(%p)->(%s): stub\n", This, debugstr_variant(&sink));
2704 return E_NOTIMPL;
2707 static HRESULT WINAPI domdoc_put_onTransformNode(IXMLDOMDocument3 *iface, VARIANT sink )
2709 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2710 FIXME("(%p)->(%s): stub\n", This, debugstr_variant(&sink));
2711 return E_NOTIMPL;
2714 static HRESULT WINAPI domdoc_get_namespaces(
2715 IXMLDOMDocument3* iface,
2716 IXMLDOMSchemaCollection** collection )
2718 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2719 HRESULT hr;
2721 FIXME("(%p)->(%p): semi-stub\n", This, collection);
2723 if (!collection) return E_POINTER;
2725 if (!This->namespaces)
2727 hr = SchemaCache_create(This->properties->version, (void**)&This->namespaces);
2728 if (hr != S_OK) return hr;
2730 hr = cache_from_doc_ns(This->namespaces, &This->node);
2731 if (hr != S_OK)
2732 release_namespaces(This);
2735 if (This->namespaces)
2736 return IXMLDOMSchemaCollection2_QueryInterface(This->namespaces,
2737 &IID_IXMLDOMSchemaCollection, (void**)collection);
2739 return hr;
2742 static HRESULT WINAPI domdoc_get_schemas(
2743 IXMLDOMDocument3* iface,
2744 VARIANT* schema )
2746 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2747 IXMLDOMSchemaCollection2* cur_schema = This->properties->schemaCache;
2748 HRESULT hr = S_FALSE;
2750 TRACE("(%p)->(%p)\n", This, schema);
2752 V_VT(schema) = VT_NULL;
2753 /* just to reset pointer part, cause that's what application is expected to use */
2754 V_DISPATCH(schema) = NULL;
2756 if(cur_schema)
2758 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(schema));
2759 if(SUCCEEDED(hr))
2760 V_VT(schema) = VT_DISPATCH;
2762 return hr;
2765 static HRESULT WINAPI domdoc_putref_schemas(
2766 IXMLDOMDocument3* iface,
2767 VARIANT schema)
2769 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2770 HRESULT hr = E_FAIL;
2771 IXMLDOMSchemaCollection2* new_schema = NULL;
2773 FIXME("(%p)->(%s): semi-stub\n", This, debugstr_variant(&schema));
2774 switch(V_VT(&schema))
2776 case VT_UNKNOWN:
2777 if (V_UNKNOWN(&schema))
2779 hr = IUnknown_QueryInterface(V_UNKNOWN(&schema), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2780 break;
2782 /* fallthrough */
2783 case VT_DISPATCH:
2784 if (V_DISPATCH(&schema))
2786 hr = IDispatch_QueryInterface(V_DISPATCH(&schema), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2787 break;
2789 /* fallthrough */
2790 case VT_NULL:
2791 case VT_EMPTY:
2792 hr = S_OK;
2793 break;
2795 default:
2796 WARN("Can't get schema from vt %x\n", V_VT(&schema));
2799 if(SUCCEEDED(hr))
2801 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->properties->schemaCache, new_schema);
2802 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2805 return hr;
2808 static inline BOOL is_wellformed(xmlDocPtr doc)
2810 #ifdef HAVE_XMLDOC_PROPERTIES
2811 return doc->properties & XML_DOC_WELLFORMED;
2812 #else
2813 /* Not a full check, but catches the worst violations */
2814 xmlNodePtr child;
2815 int root = 0;
2817 for (child = doc->children; child != NULL; child = child->next)
2819 switch (child->type)
2821 case XML_ELEMENT_NODE:
2822 if (++root > 1)
2823 return FALSE;
2824 break;
2825 case XML_TEXT_NODE:
2826 case XML_CDATA_SECTION_NODE:
2827 return FALSE;
2828 break;
2829 default:
2830 break;
2834 return root == 1;
2835 #endif
2838 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2840 va_list ap;
2841 va_start(ap, msg);
2842 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2843 va_end(ap);
2846 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2848 va_list ap;
2849 va_start(ap, msg);
2850 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2851 va_end(ap);
2854 static HRESULT WINAPI domdoc_validateNode(
2855 IXMLDOMDocument3* iface,
2856 IXMLDOMNode* node,
2857 IXMLDOMParseError** err)
2859 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2860 LONG state, err_code = 0;
2861 HRESULT hr = S_OK;
2862 int validated = 0;
2864 TRACE("(%p)->(%p, %p)\n", This, node, err);
2865 IXMLDOMDocument3_get_readyState(iface, &state);
2866 if (state != READYSTATE_COMPLETE)
2868 if (err)
2869 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2870 return E_PENDING;
2873 if (!node)
2875 if (err)
2876 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2877 return E_POINTER;
2880 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2882 if (err)
2883 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2884 return E_FAIL;
2887 if (!is_wellformed(get_doc(This)))
2889 ERR("doc not well-formed\n");
2890 if (err)
2891 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2892 return S_FALSE;
2895 /* DTD validation */
2896 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2898 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2899 vctx->error = validate_error;
2900 vctx->warning = validate_warning;
2901 ++validated;
2903 if (!((node == (IXMLDOMNode*)iface)?
2904 xmlValidateDocument(vctx, get_doc(This)) :
2905 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2907 /* TODO: get a real error code here */
2908 TRACE("DTD validation failed\n");
2909 err_code = E_XML_INVALID;
2910 hr = S_FALSE;
2912 xmlFreeValidCtxt(vctx);
2915 /* Schema validation */
2916 if (hr == S_OK && This->properties->schemaCache != NULL)
2919 hr = SchemaCache_validate_tree(This->properties->schemaCache, get_node_obj(node)->node);
2920 if (SUCCEEDED(hr))
2922 ++validated;
2923 /* TODO: get a real error code here */
2924 if (hr == S_OK)
2926 TRACE("schema validation succeeded\n");
2928 else
2930 ERR("schema validation failed\n");
2931 err_code = E_XML_INVALID;
2934 else
2936 /* not really OK, just didn't find a schema for the ns */
2937 hr = S_OK;
2941 if (!validated)
2943 ERR("no DTD or schema found\n");
2944 err_code = E_XML_NODTD;
2945 hr = S_FALSE;
2948 if (err)
2949 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2951 return hr;
2954 static HRESULT WINAPI domdoc_validate(
2955 IXMLDOMDocument3* iface,
2956 IXMLDOMParseError** err)
2958 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2959 TRACE("(%p)->(%p)\n", This, err);
2960 return IXMLDOMDocument3_validateNode(iface, (IXMLDOMNode*)iface, err);
2963 static HRESULT WINAPI domdoc_setProperty(
2964 IXMLDOMDocument3* iface,
2965 BSTR p,
2966 VARIANT value)
2968 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2970 TRACE("(%p)->(%s %s)\n", This, debugstr_w(p), debugstr_variant(&value));
2972 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2974 VARIANT varStr;
2975 HRESULT hr;
2976 BSTR bstr;
2978 V_VT(&varStr) = VT_EMPTY;
2979 if (V_VT(&value) != VT_BSTR)
2981 if (FAILED(hr = VariantChangeType(&varStr, &value, 0, VT_BSTR)))
2982 return hr;
2983 bstr = V_BSTR(&varStr);
2985 else
2986 bstr = V_BSTR(&value);
2988 hr = S_OK;
2989 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2990 This->properties->XPath = TRUE;
2991 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2992 This->properties->XPath = FALSE;
2993 else
2994 hr = E_FAIL;
2996 VariantClear(&varStr);
2997 return hr;
2999 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
3001 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
3002 struct list *pNsList;
3003 VARIANT varStr;
3004 HRESULT hr;
3005 BSTR bstr;
3007 V_VT(&varStr) = VT_EMPTY;
3008 if (V_VT(&value) != VT_BSTR)
3010 if (FAILED(hr = VariantChangeType(&varStr, &value, 0, VT_BSTR)))
3011 return hr;
3012 bstr = V_BSTR(&varStr);
3014 else
3015 bstr = V_BSTR(&value);
3017 hr = S_OK;
3019 pNsList = &(This->properties->selectNsList);
3020 clear_selectNsList(pNsList);
3021 heap_free(nsStr);
3022 nsStr = xmlchar_from_wchar(bstr);
3024 TRACE("property value: \"%s\"\n", debugstr_w(bstr));
3026 This->properties->selectNsStr = nsStr;
3027 This->properties->selectNsStr_len = xmlStrlen(nsStr);
3028 if (bstr && *bstr)
3030 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
3031 select_ns_entry* ns_entry = NULL;
3032 xmlXPathContextPtr ctx;
3034 ctx = xmlXPathNewContext(This->node.node->doc);
3035 pTokBegin = nsStr;
3037 /* skip leading spaces */
3038 while (*pTokBegin == ' ' || *pTokBegin == '\n' ||
3039 *pTokBegin == '\t' || *pTokBegin == '\r')
3040 ++pTokBegin;
3042 for (; *pTokBegin; pTokBegin = pTokEnd)
3044 if (ns_entry)
3045 memset(ns_entry, 0, sizeof(select_ns_entry));
3046 else
3047 ns_entry = heap_alloc_zero(sizeof(select_ns_entry));
3049 while (*pTokBegin == ' ')
3050 ++pTokBegin;
3051 pTokEnd = pTokBegin;
3052 while (*pTokEnd != ' ' && *pTokEnd != 0)
3053 ++pTokEnd;
3055 /* so it failed to advance which means we've got some trailing spaces */
3056 if (pTokEnd == pTokBegin) break;
3058 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
3060 hr = E_FAIL;
3061 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3062 debugstr_w(bstr), debugstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
3063 continue;
3066 pTokBegin += 5;
3067 if (*pTokBegin == '=')
3069 /*valid for XSLPattern?*/
3070 FIXME("Setting default xmlns not supported - skipping.\n");
3071 continue;
3073 else if (*pTokBegin == ':')
3075 ns_entry->prefix = ++pTokBegin;
3076 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
3079 if (pTokInner == pTokEnd)
3081 hr = E_FAIL;
3082 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3083 debugstr_w(bstr), debugstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
3084 continue;
3087 ns_entry->prefix_end = *pTokInner;
3088 *pTokInner = 0;
3089 ++pTokInner;
3091 if (pTokEnd-pTokInner > 1 &&
3092 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
3093 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
3095 ns_entry->href = ++pTokInner;
3096 ns_entry->href_end = *(pTokEnd-1);
3097 *(pTokEnd-1) = 0;
3098 list_add_tail(pNsList, &ns_entry->entry);
3099 /*let libxml figure out if they're valid from here ;)*/
3100 if (xmlXPathRegisterNs(ctx, ns_entry->prefix, ns_entry->href) != 0)
3102 hr = E_FAIL;
3104 ns_entry = NULL;
3105 continue;
3107 else
3109 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
3110 debugstr_w(bstr), debugstr_an((const char*)pTokInner, pTokEnd-pTokInner));
3111 list_add_tail(pNsList, &ns_entry->entry);
3113 ns_entry = NULL;
3114 hr = E_FAIL;
3115 continue;
3118 else
3120 hr = E_FAIL;
3121 continue;
3124 heap_free(ns_entry);
3125 xmlXPathFreeContext(ctx);
3128 VariantClear(&varStr);
3129 return hr;
3131 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
3132 lstrcmpiW(p, PropertyNewParserW) == 0 ||
3133 lstrcmpiW(p, PropertyResolveExternalsW) == 0 ||
3134 lstrcmpiW(p, PropertyAllowXsltScriptW) == 0 ||
3135 lstrcmpiW(p, PropertyNormalizeAttributeValuesW) == 0 ||
3136 lstrcmpiW(p, PropertyAllowDocumentFunctionW) == 0)
3138 /* Ignore */
3139 FIXME("Ignoring property %s, value %s\n", debugstr_w(p), debugstr_variant(&value));
3140 return S_OK;
3143 FIXME("Unknown property %s\n", debugstr_w(p));
3144 return E_FAIL;
3147 static HRESULT WINAPI domdoc_getProperty(
3148 IXMLDOMDocument3* iface,
3149 BSTR p,
3150 VARIANT* var)
3152 domdoc *This = impl_from_IXMLDOMDocument3( iface );
3154 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
3156 if (!var)
3157 return E_INVALIDARG;
3159 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
3161 V_VT(var) = VT_BSTR;
3162 V_BSTR(var) = This->properties->XPath ?
3163 SysAllocString(PropValueXPathW) :
3164 SysAllocString(PropValueXSLPatternW);
3165 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
3167 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
3169 int lenA, lenW;
3170 BSTR rebuiltStr, cur;
3171 const xmlChar *nsStr;
3172 struct list *pNsList;
3173 select_ns_entry* pNsEntry;
3175 V_VT(var) = VT_BSTR;
3176 nsStr = This->properties->selectNsStr;
3177 pNsList = &This->properties->selectNsList;
3178 lenA = This->properties->selectNsStr_len;
3179 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
3180 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
3181 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
3182 cur = rebuiltStr;
3183 /* this is fine because all of the chars that end tokens are ASCII*/
3184 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
3186 while (*cur != 0) ++cur;
3187 if (pNsEntry->prefix_end)
3189 *cur = pNsEntry->prefix_end;
3190 while (*cur != 0) ++cur;
3193 if (pNsEntry->href_end)
3195 *cur = pNsEntry->href_end;
3198 V_BSTR(var) = SysAllocString(rebuiltStr);
3199 heap_free(rebuiltStr);
3200 return S_OK;
3203 FIXME("Unknown property %s\n", debugstr_w(p));
3204 return E_FAIL;
3207 static HRESULT WINAPI domdoc_importNode(
3208 IXMLDOMDocument3* iface,
3209 IXMLDOMNode* node,
3210 VARIANT_BOOL deep,
3211 IXMLDOMNode** clone)
3213 domdoc *This = impl_from_IXMLDOMDocument3( iface );
3214 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
3215 return E_NOTIMPL;
3218 static const struct IXMLDOMDocument3Vtbl XMLDOMDocument3Vtbl =
3220 domdoc_QueryInterface,
3221 domdoc_AddRef,
3222 domdoc_Release,
3223 domdoc_GetTypeInfoCount,
3224 domdoc_GetTypeInfo,
3225 domdoc_GetIDsOfNames,
3226 domdoc_Invoke,
3227 domdoc_get_nodeName,
3228 domdoc_get_nodeValue,
3229 domdoc_put_nodeValue,
3230 domdoc_get_nodeType,
3231 domdoc_get_parentNode,
3232 domdoc_get_childNodes,
3233 domdoc_get_firstChild,
3234 domdoc_get_lastChild,
3235 domdoc_get_previousSibling,
3236 domdoc_get_nextSibling,
3237 domdoc_get_attributes,
3238 domdoc_insertBefore,
3239 domdoc_replaceChild,
3240 domdoc_removeChild,
3241 domdoc_appendChild,
3242 domdoc_hasChildNodes,
3243 domdoc_get_ownerDocument,
3244 domdoc_cloneNode,
3245 domdoc_get_nodeTypeString,
3246 domdoc_get_text,
3247 domdoc_put_text,
3248 domdoc_get_specified,
3249 domdoc_get_definition,
3250 domdoc_get_nodeTypedValue,
3251 domdoc_put_nodeTypedValue,
3252 domdoc_get_dataType,
3253 domdoc_put_dataType,
3254 domdoc_get_xml,
3255 domdoc_transformNode,
3256 domdoc_selectNodes,
3257 domdoc_selectSingleNode,
3258 domdoc_get_parsed,
3259 domdoc_get_namespaceURI,
3260 domdoc_get_prefix,
3261 domdoc_get_baseName,
3262 domdoc_transformNodeToObject,
3263 domdoc_get_doctype,
3264 domdoc_get_implementation,
3265 domdoc_get_documentElement,
3266 domdoc_put_documentElement,
3267 domdoc_createElement,
3268 domdoc_createDocumentFragment,
3269 domdoc_createTextNode,
3270 domdoc_createComment,
3271 domdoc_createCDATASection,
3272 domdoc_createProcessingInstruction,
3273 domdoc_createAttribute,
3274 domdoc_createEntityReference,
3275 domdoc_getElementsByTagName,
3276 domdoc_createNode,
3277 domdoc_nodeFromID,
3278 domdoc_load,
3279 domdoc_get_readyState,
3280 domdoc_get_parseError,
3281 domdoc_get_url,
3282 domdoc_get_async,
3283 domdoc_put_async,
3284 domdoc_abort,
3285 domdoc_loadXML,
3286 domdoc_save,
3287 domdoc_get_validateOnParse,
3288 domdoc_put_validateOnParse,
3289 domdoc_get_resolveExternals,
3290 domdoc_put_resolveExternals,
3291 domdoc_get_preserveWhiteSpace,
3292 domdoc_put_preserveWhiteSpace,
3293 domdoc_put_onreadystatechange,
3294 domdoc_put_onDataAvailable,
3295 domdoc_put_onTransformNode,
3296 domdoc_get_namespaces,
3297 domdoc_get_schemas,
3298 domdoc_putref_schemas,
3299 domdoc_validate,
3300 domdoc_setProperty,
3301 domdoc_getProperty,
3302 domdoc_validateNode,
3303 domdoc_importNode
3306 /* IConnectionPointContainer */
3307 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
3308 REFIID riid, void **ppv)
3310 domdoc *This = impl_from_IConnectionPointContainer(iface);
3311 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppv);
3314 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
3316 domdoc *This = impl_from_IConnectionPointContainer(iface);
3317 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3320 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
3322 domdoc *This = impl_from_IConnectionPointContainer(iface);
3323 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3326 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
3327 IEnumConnectionPoints **ppEnum)
3329 domdoc *This = impl_from_IConnectionPointContainer(iface);
3330 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3331 return E_NOTIMPL;
3334 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
3335 REFIID riid, IConnectionPoint **cp)
3337 domdoc *This = impl_from_IConnectionPointContainer(iface);
3338 ConnectionPoint *iter;
3340 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
3342 *cp = NULL;
3344 for(iter = This->cp_list; iter; iter = iter->next)
3346 if (IsEqualGUID(iter->iid, riid))
3347 *cp = &iter->IConnectionPoint_iface;
3350 if (*cp)
3352 IConnectionPoint_AddRef(*cp);
3353 return S_OK;
3356 FIXME("unsupported riid %s\n", debugstr_guid(riid));
3357 return CONNECT_E_NOCONNECTION;
3361 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
3363 ConnectionPointContainer_QueryInterface,
3364 ConnectionPointContainer_AddRef,
3365 ConnectionPointContainer_Release,
3366 ConnectionPointContainer_EnumConnectionPoints,
3367 ConnectionPointContainer_FindConnectionPoint
3370 /* IConnectionPoint */
3371 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
3372 REFIID riid, void **ppv)
3374 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3376 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3378 *ppv = NULL;
3380 if (IsEqualGUID(&IID_IUnknown, riid) ||
3381 IsEqualGUID(&IID_IConnectionPoint, riid))
3383 *ppv = iface;
3386 if (*ppv)
3388 IConnectionPoint_AddRef(iface);
3389 return S_OK;
3392 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3393 return E_NOINTERFACE;
3396 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3398 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3399 return IConnectionPointContainer_AddRef(This->container);
3402 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3404 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3405 return IConnectionPointContainer_Release(This->container);
3408 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3410 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3412 TRACE("(%p)->(%p)\n", This, iid);
3414 if (!iid) return E_POINTER;
3416 *iid = *This->iid;
3417 return S_OK;
3420 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3421 IConnectionPointContainer **container)
3423 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3425 TRACE("(%p)->(%p)\n", This, container);
3427 if (!container) return E_POINTER;
3429 *container = This->container;
3430 IConnectionPointContainer_AddRef(*container);
3431 return S_OK;
3434 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *unk_sink,
3435 DWORD *cookie)
3437 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3438 IUnknown *sink;
3439 HRESULT hr;
3440 DWORD i;
3442 TRACE("(%p)->(%p %p)\n", This, unk_sink, cookie);
3444 hr = IUnknown_QueryInterface(unk_sink, This->iid, (void**)&sink);
3445 if(FAILED(hr) && !IsEqualGUID(&IID_IPropertyNotifySink, This->iid))
3446 hr = IUnknown_QueryInterface(unk_sink, &IID_IDispatch, (void**)&sink);
3447 if(FAILED(hr))
3448 return CONNECT_E_CANNOTCONNECT;
3450 if(This->sinks)
3452 for (i = 0; i < This->sinks_size; i++)
3453 if (!This->sinks[i].unk)
3454 break;
3456 if (i == This->sinks_size)
3457 This->sinks = heap_realloc(This->sinks,(++This->sinks_size)*sizeof(*This->sinks));
3459 else
3461 This->sinks = heap_alloc(sizeof(*This->sinks));
3462 This->sinks_size = 1;
3463 i = 0;
3466 This->sinks[i].unk = sink;
3467 if (cookie)
3468 *cookie = i+1;
3470 return S_OK;
3473 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3475 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3477 TRACE("(%p)->(%d)\n", This, cookie);
3479 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3480 return CONNECT_E_NOCONNECTION;
3482 IUnknown_Release(This->sinks[cookie-1].unk);
3483 This->sinks[cookie-1].unk = NULL;
3485 return S_OK;
3488 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3489 IEnumConnections **ppEnum)
3491 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3492 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3493 return E_NOTIMPL;
3496 static const IConnectionPointVtbl ConnectionPointVtbl =
3498 ConnectionPoint_QueryInterface,
3499 ConnectionPoint_AddRef,
3500 ConnectionPoint_Release,
3501 ConnectionPoint_GetConnectionInterface,
3502 ConnectionPoint_GetConnectionPointContainer,
3503 ConnectionPoint_Advise,
3504 ConnectionPoint_Unadvise,
3505 ConnectionPoint_EnumConnections
3508 static void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3510 cp->IConnectionPoint_iface.lpVtbl = &ConnectionPointVtbl;
3511 cp->doc = doc;
3512 cp->iid = riid;
3513 cp->sinks = NULL;
3514 cp->sinks_size = 0;
3516 cp->next = doc->cp_list;
3517 doc->cp_list = cp;
3519 cp->container = &doc->IConnectionPointContainer_iface;
3522 /* domdoc implementation of IObjectWithSite */
3523 static HRESULT WINAPI
3524 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3526 domdoc *This = impl_from_IObjectWithSite(iface);
3527 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppvObject);
3530 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3532 domdoc *This = impl_from_IObjectWithSite(iface);
3533 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3536 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3538 domdoc *This = impl_from_IObjectWithSite(iface);
3539 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3542 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3544 domdoc *This = impl_from_IObjectWithSite(iface);
3546 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3548 if ( !This->site )
3549 return E_FAIL;
3551 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3554 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3556 domdoc *This = impl_from_IObjectWithSite(iface);
3558 TRACE("(%p)->(%p)\n", iface, punk);
3560 if(!punk)
3562 if(This->site)
3564 IUnknown_Release( This->site );
3565 This->site = NULL;
3568 if(This->base_uri)
3570 IUri_Release(This->base_uri);
3571 This->base_uri = NULL;
3574 return S_OK;
3577 IUnknown_AddRef( punk );
3579 if(This->site)
3580 IUnknown_Release( This->site );
3582 This->site = punk;
3583 This->base_uri = get_base_uri(This->site);
3585 return S_OK;
3588 static const IObjectWithSiteVtbl domdocObjectSite =
3590 domdoc_ObjectWithSite_QueryInterface,
3591 domdoc_ObjectWithSite_AddRef,
3592 domdoc_ObjectWithSite_Release,
3593 domdoc_ObjectWithSite_SetSite,
3594 domdoc_ObjectWithSite_GetSite
3597 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3599 domdoc *This = impl_from_IObjectSafety(iface);
3600 return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppv);
3603 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3605 domdoc *This = impl_from_IObjectSafety(iface);
3606 return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
3609 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3611 domdoc *This = impl_from_IObjectSafety(iface);
3612 return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
3615 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3617 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3618 DWORD *supported, DWORD *enabled)
3620 domdoc *This = impl_from_IObjectSafety(iface);
3622 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3624 if(!supported || !enabled) return E_POINTER;
3626 *supported = SAFETY_SUPPORTED_OPTIONS;
3627 *enabled = This->safeopt;
3629 return S_OK;
3632 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3633 DWORD mask, DWORD enabled)
3635 domdoc *This = impl_from_IObjectSafety(iface);
3636 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3638 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3639 return E_FAIL;
3641 This->safeopt = (This->safeopt & ~mask) | (mask & enabled);
3643 return S_OK;
3646 #undef SAFETY_SUPPORTED_OPTIONS
3648 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3649 domdoc_Safety_QueryInterface,
3650 domdoc_Safety_AddRef,
3651 domdoc_Safety_Release,
3652 domdoc_Safety_GetInterfaceSafetyOptions,
3653 domdoc_Safety_SetInterfaceSafetyOptions
3656 static const tid_t domdoc_iface_tids[] = {
3657 IXMLDOMDocument3_tid,
3661 static dispex_static_data_t domdoc_dispex = {
3662 NULL,
3663 IXMLDOMDocument3_tid,
3664 NULL,
3665 domdoc_iface_tids
3668 HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3670 domdoc *doc;
3672 doc = heap_alloc( sizeof (*doc) );
3673 if( !doc )
3674 return E_OUTOFMEMORY;
3676 doc->IXMLDOMDocument3_iface.lpVtbl = &XMLDOMDocument3Vtbl;
3677 doc->IPersistStreamInit_iface.lpVtbl = &xmldoc_IPersistStreamInit_VTable;
3678 doc->IObjectWithSite_iface.lpVtbl = &domdocObjectSite;
3679 doc->IObjectSafety_iface.lpVtbl = &domdocObjectSafetyVtbl;
3680 doc->IConnectionPointContainer_iface.lpVtbl = &ConnectionPointContainerVtbl;
3681 doc->ref = 1;
3682 doc->async = VARIANT_TRUE;
3683 doc->validating = 0;
3684 doc->resolving = 0;
3685 doc->properties = properties_from_xmlDocPtr(xmldoc);
3686 doc->error = S_OK;
3687 doc->site = NULL;
3688 doc->base_uri = NULL;
3689 doc->safeopt = 0;
3690 doc->cp_list = NULL;
3691 doc->namespaces = NULL;
3692 memset(doc->events, 0, sizeof(doc->events));
3694 /* events connection points */
3695 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3696 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3697 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3699 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->IXMLDOMDocument3_iface,
3700 &domdoc_dispex);
3702 *document = &doc->IXMLDOMDocument3_iface;
3704 TRACE("returning iface %p\n", *document);
3705 return S_OK;
3708 HRESULT DOMDocument_create(MSXML_VERSION version, void **ppObj)
3710 xmlDocPtr xmldoc;
3711 HRESULT hr;
3713 TRACE("(%d, %p)\n", version, ppObj);
3715 xmldoc = xmlNewDoc(NULL);
3716 if(!xmldoc)
3717 return E_OUTOFMEMORY;
3719 xmldoc_init(xmldoc, version);
3721 hr = get_domdoc_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3722 if(FAILED(hr))
3724 free_properties(properties_from_xmlDocPtr(xmldoc));
3725 heap_free(xmldoc->_private);
3726 xmlFreeDoc(xmldoc);
3727 return hr;
3730 return hr;
3733 IUnknown* create_domdoc( xmlNodePtr document )
3735 IUnknown *obj = NULL;
3736 HRESULT hr;
3738 TRACE("(%p)\n", document);
3740 hr = get_domdoc_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&obj);
3741 if (FAILED(hr))
3742 return NULL;
3744 return obj;
3747 #else
3749 HRESULT DOMDocument_create(MSXML_VERSION version, void **ppObj)
3751 MESSAGE("This program tried to use a DOMDocument object, but\n"
3752 "libxml2 support was not present at compile time.\n");
3753 return E_NOTIMPL;
3756 #endif