msxml3: Implement domdoc schema validation.
[wine.git] / dlls / msxml3 / domdoc.c
bloba5100f0cdadaa1e77edf5750522d0c291d4b78d7
1 /*
2 * DOM Document implementation
4 * Copyright 2005 Mike McCormack
5 * Copyright 2010 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
23 #define NONAMELESSUNION
25 #include "config.h"
27 #include <stdarg.h>
28 #include <assert.h>
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winuser.h"
32 #include "winnls.h"
33 #include "ole2.h"
34 #include "olectl.h"
35 #include "msxml6.h"
36 #include "wininet.h"
37 #include "winreg.h"
38 #include "shlwapi.h"
39 #include "ocidl.h"
40 #include "objsafe.h"
41 #include "dispex.h"
43 #include "wine/debug.h"
44 #include "wine/list.h"
46 #include "msxml_private.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
50 #ifdef HAVE_LIBXML2
52 #include <libxml/xpathInternals.h>
53 #include <libxml/xmlsave.h>
54 #include <libxml/SAX2.h>
55 #include <libxml/parserInternals.h>
57 /* not defined in older versions */
58 #define XML_SAVE_FORMAT 1
59 #define XML_SAVE_NO_DECL 2
60 #define XML_SAVE_NO_EMPTY 4
61 #define XML_SAVE_NO_XHTML 8
62 #define XML_SAVE_XHTML 16
63 #define XML_SAVE_AS_XML 32
64 #define XML_SAVE_AS_HTML 64
66 static const WCHAR PropertySelectionLanguageW[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
67 static const WCHAR PropertySelectionNamespacesW[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
68 static const WCHAR PropertyProhibitDTDW[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
69 static const WCHAR PropertyNewParserW[] = {'N','e','w','P','a','r','s','e','r',0};
70 static const WCHAR PropValueXPathW[] = {'X','P','a','t','h',0};
71 static const WCHAR PropValueXSLPatternW[] = {'X','S','L','P','a','t','t','e','r','n',0};
73 /* Data used by domdoc_getProperty()/domdoc_setProperty().
74 * We need to preserve this when reloading a document,
75 * and also need access to it from the libxml backend. */
76 typedef struct _domdoc_properties {
77 struct list selectNsList;
78 xmlChar const* selectNsStr;
79 LONG selectNsStr_len;
80 BOOL XPath;
81 } domdoc_properties;
83 typedef struct ConnectionPoint ConnectionPoint;
84 typedef struct domdoc domdoc;
86 struct ConnectionPoint
88 const IConnectionPointVtbl *lpVtblConnectionPoint;
89 const IID *iid;
91 ConnectionPoint *next;
92 IConnectionPointContainer *container;
93 domdoc *doc;
95 union
97 IUnknown *unk;
98 IDispatch *disp;
99 IPropertyNotifySink *propnotif;
100 } *sinks;
101 DWORD sinks_size;
104 struct domdoc
106 xmlnode node;
107 const struct IXMLDOMDocument3Vtbl *lpVtbl;
108 const struct IPersistStreamInitVtbl *lpvtblIPersistStreamInit;
109 const struct IObjectWithSiteVtbl *lpvtblIObjectWithSite;
110 const struct IObjectSafetyVtbl *lpvtblIObjectSafety;
111 const struct ISupportErrorInfoVtbl *lpvtblISupportErrorInfo;
112 const struct IConnectionPointContainerVtbl *lpVtblConnectionPointContainer;
113 LONG ref;
114 VARIANT_BOOL async;
115 VARIANT_BOOL validating;
116 VARIANT_BOOL resolving;
117 VARIANT_BOOL preserving;
118 domdoc_properties* properties;
119 IXMLDOMSchemaCollection2* schema;
120 bsc_t *bsc;
121 HRESULT error;
123 /* IPersistStream */
124 IStream *stream;
126 /* IObjectWithSite*/
127 IUnknown *site;
129 /* IObjectSafety */
130 DWORD safeopt;
132 /* connection list */
133 ConnectionPoint *cp_list;
134 ConnectionPoint cp_domdocevents;
135 ConnectionPoint cp_propnotif;
136 ConnectionPoint cp_dispatch;
139 static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface)
141 return (ConnectionPoint *)((char*)iface - FIELD_OFFSET(ConnectionPoint, lpVtblConnectionPoint));
145 In native windows, the whole lifetime management of XMLDOMNodes is
146 managed automatically using reference counts. Wine emulates that by
147 maintaining a reference count to the document that is increased for
148 each IXMLDOMNode pointer passed out for this document. If all these
149 pointers are gone, the document is unreachable and gets freed, that
150 is, all nodes in the tree of the document get freed.
152 You are able to create nodes that are associated to a document (in
153 fact, in msxml's XMLDOM model, all nodes are associated to a document),
154 but not in the tree of that document, for example using the createFoo
155 functions from IXMLDOMDocument. These nodes do not get cleaned up
156 by libxml, so we have to do it ourselves.
158 To catch these nodes, a list of "orphan nodes" is introduced.
159 It contains pointers to all roots of node trees that are
160 associated with the document without being part of the document
161 tree. All nodes with parent==NULL (except for the document root nodes)
162 should be in the orphan node list of their document. All orphan nodes
163 get freed together with the document itself.
166 typedef struct _xmldoc_priv {
167 LONG refs;
168 struct list orphans;
169 domdoc_properties* properties;
170 } xmldoc_priv;
172 typedef struct _orphan_entry {
173 struct list entry;
174 xmlNode * node;
175 } orphan_entry;
177 typedef struct _select_ns_entry {
178 struct list entry;
179 xmlChar const* prefix;
180 xmlChar prefix_end;
181 xmlChar const* href;
182 xmlChar href_end;
183 } select_ns_entry;
185 static inline xmldoc_priv * priv_from_xmlDocPtr(const xmlDocPtr doc)
187 return doc->_private;
190 static inline domdoc_properties * properties_from_xmlDocPtr(xmlDocPtr doc)
192 return priv_from_xmlDocPtr(doc)->properties;
195 BOOL is_xpathmode(const xmlDocPtr doc)
197 return properties_from_xmlDocPtr(doc)->XPath;
200 int registerNamespaces(xmlXPathContextPtr ctxt)
202 int n = 0;
203 const select_ns_entry* ns = NULL;
204 const struct list* pNsList = &properties_from_xmlDocPtr(ctxt->doc)->selectNsList;
206 TRACE("(%p)\n", ctxt);
208 LIST_FOR_EACH_ENTRY( ns, pNsList, select_ns_entry, entry )
210 xmlXPathRegisterNs(ctxt, ns->prefix, ns->href);
211 ++n;
214 return n;
217 static inline void clear_selectNsList(struct list* pNsList)
219 select_ns_entry *ns, *ns2;
220 LIST_FOR_EACH_ENTRY_SAFE( ns, ns2, pNsList, select_ns_entry, entry )
222 heap_free( ns );
224 list_init(pNsList);
227 static xmldoc_priv * create_priv(void)
229 xmldoc_priv *priv;
230 priv = heap_alloc( sizeof (*priv) );
232 if (priv)
234 priv->refs = 0;
235 list_init( &priv->orphans );
236 priv->properties = NULL;
239 return priv;
242 static domdoc_properties * create_properties(const GUID *clsid)
244 domdoc_properties *properties = heap_alloc(sizeof(domdoc_properties));
246 list_init( &properties->selectNsList );
247 properties->selectNsStr = heap_alloc_zero(sizeof(xmlChar));
248 properties->selectNsStr_len = 0;
249 properties->XPath = FALSE;
251 /* properties that are dependent on object versions */
252 if (IsEqualCLSID( clsid, &CLSID_DOMDocument40 ) ||
253 IsEqualCLSID( clsid, &CLSID_DOMDocument60 ))
255 properties->XPath = TRUE;
258 return properties;
261 static domdoc_properties* copy_properties(domdoc_properties const* properties)
263 domdoc_properties* pcopy = heap_alloc(sizeof(domdoc_properties));
264 select_ns_entry const* ns = NULL;
265 select_ns_entry* new_ns = NULL;
266 int len = (properties->selectNsStr_len+1)*sizeof(xmlChar);
267 ptrdiff_t offset;
269 if (pcopy)
271 pcopy->XPath = properties->XPath;
272 pcopy->selectNsStr_len = properties->selectNsStr_len;
273 list_init( &pcopy->selectNsList );
274 pcopy->selectNsStr = heap_alloc(len);
275 memcpy((xmlChar*)pcopy->selectNsStr, properties->selectNsStr, len);
276 offset = pcopy->selectNsStr - properties->selectNsStr;
278 LIST_FOR_EACH_ENTRY( ns, (&properties->selectNsList), select_ns_entry, entry )
280 new_ns = heap_alloc(sizeof(select_ns_entry));
281 memcpy(new_ns, ns, sizeof(select_ns_entry));
282 new_ns->href += offset;
283 new_ns->prefix += offset;
284 list_add_tail(&pcopy->selectNsList, &new_ns->entry);
289 return pcopy;
292 static void free_properties(domdoc_properties* properties)
294 if (properties)
296 clear_selectNsList(&properties->selectNsList);
297 heap_free((xmlChar*)properties->selectNsStr);
298 heap_free(properties);
302 /* links a "<?xml" node as a first child */
303 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
305 assert(doc != NULL);
306 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
309 /* unlinks a first "<?xml" child if it was created */
310 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
312 xmlNodePtr node;
314 assert(doc != NULL);
316 if (doc->standalone != -1)
318 node = doc->children;
319 xmlUnlinkNode( node );
321 else
322 node = NULL;
324 return node;
327 static inline BOOL strn_isspace(xmlChar const* str, int len)
329 for (; str && len > 0 && *str; ++str, --len)
330 if (!isspace(*str))
331 break;
333 return len == 0;
336 static void sax_characters(void *ctx, const xmlChar *ch, int len)
338 xmlParserCtxtPtr pctx;
339 domdoc const* This;
341 pctx = (xmlParserCtxtPtr) ctx;
342 This = (domdoc const*) pctx->_private;
344 if (!This->preserving)
346 xmlChar* ws = xmlGetNsProp(pctx->node, BAD_CAST "space", XML_XML_NAMESPACE);
347 if ((!ws || xmlStrcmp(ws, BAD_CAST "preserve") != 0) &&
348 strn_isspace(ch, len))
350 xmlFree(ws);
351 return;
353 xmlFree(ws);
356 xmlSAX2Characters(ctx, ch, len);
359 static void LIBXML2_LOG_CALLBACK sax_error(void* ctx, char const* msg, ...)
361 va_list ap;
362 va_start(ap, msg);
363 LIBXML2_CALLBACK_ERR(doparse, msg, ap);
364 va_end(ap);
367 static void LIBXML2_LOG_CALLBACK sax_warning(void* ctx, char const* msg, ...)
369 va_list ap;
370 va_start(ap, msg);
371 LIBXML2_CALLBACK_WARN(doparse, msg, ap);
372 va_end(ap);
375 static void sax_serror(void* ctx, xmlErrorPtr err)
377 LIBXML2_CALLBACK_SERROR(doparse, err);
380 static xmlDocPtr doparse(domdoc* This, char *ptr, int len, xmlChar const* encoding)
382 xmlDocPtr doc = NULL;
383 xmlParserCtxtPtr pctx;
384 static xmlSAXHandler sax_handler = {
385 xmlSAX2InternalSubset, /* internalSubset */
386 xmlSAX2IsStandalone, /* isStandalone */
387 xmlSAX2HasInternalSubset, /* hasInternalSubset */
388 xmlSAX2HasExternalSubset, /* hasExternalSubset */
389 xmlSAX2ResolveEntity, /* resolveEntity */
390 xmlSAX2GetEntity, /* getEntity */
391 xmlSAX2EntityDecl, /* entityDecl */
392 xmlSAX2NotationDecl, /* notationDecl */
393 xmlSAX2AttributeDecl, /* attributeDecl */
394 xmlSAX2ElementDecl, /* elementDecl */
395 xmlSAX2UnparsedEntityDecl, /* unparsedEntityDecl */
396 xmlSAX2SetDocumentLocator, /* setDocumentLocator */
397 xmlSAX2StartDocument, /* startDocument */
398 xmlSAX2EndDocument, /* endDocument */
399 xmlSAX2StartElement, /* startElement */
400 xmlSAX2EndElement, /* endElement */
401 xmlSAX2Reference, /* reference */
402 sax_characters, /* characters */
403 sax_characters, /* ignorableWhitespace */
404 xmlSAX2ProcessingInstruction, /* processingInstruction */
405 xmlSAX2Comment, /* comment */
406 sax_warning, /* warning */
407 sax_error, /* error */
408 sax_error, /* fatalError */
409 xmlSAX2GetParameterEntity, /* getParameterEntity */
410 xmlSAX2CDataBlock, /* cdataBlock */
411 xmlSAX2ExternalSubset, /* externalSubset */
412 0, /* initialized */
413 NULL, /* _private */
414 xmlSAX2StartElementNs, /* startElementNs */
415 xmlSAX2EndElementNs, /* endElementNs */
416 sax_serror /* serror */
418 xmlInitParser();
420 pctx = xmlCreateMemoryParserCtxt(ptr, len);
421 if (!pctx)
423 ERR("Failed to create parser context\n");
424 return NULL;
427 if (pctx->sax) xmlFree(pctx->sax);
428 pctx->sax = &sax_handler;
429 pctx->_private = This;
430 pctx->recovery = 0;
431 pctx->encoding = xmlStrdup(encoding);
432 xmlParseDocument(pctx);
434 if (pctx->wellFormed)
436 doc = pctx->myDoc;
438 else
440 xmlFreeDoc(pctx->myDoc);
441 pctx->myDoc = NULL;
443 pctx->sax = NULL;
444 xmlFreeParserCtxt(pctx);
446 /* TODO: put this in one of the SAX callbacks */
447 /* create first child as a <?xml...?> */
448 if (doc && doc->standalone != -1)
450 xmlNodePtr node;
451 char buff[30];
452 xmlChar *xmlbuff = (xmlChar*)buff;
454 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
456 /* version attribute can't be omitted */
457 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
458 xmlNodeAddContent( node, xmlbuff );
460 if (doc->encoding)
462 sprintf(buff, " encoding=\"%s\"", doc->encoding);
463 xmlNodeAddContent( node, xmlbuff );
466 if (doc->standalone != -2)
468 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
469 xmlNodeAddContent( node, xmlbuff );
472 xmldoc_link_xmldecl( doc, node );
475 return doc;
478 void xmldoc_init(xmlDocPtr doc, const GUID *clsid)
480 doc->_private = create_priv();
481 priv_from_xmlDocPtr(doc)->properties = create_properties(clsid);
484 LONG xmldoc_add_ref(xmlDocPtr doc)
486 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
487 TRACE("(%p)->(%d)\n", doc, ref);
488 return ref;
491 LONG xmldoc_release(xmlDocPtr doc)
493 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
494 LONG ref = InterlockedDecrement(&priv->refs);
495 TRACE("(%p)->(%d)\n", doc, ref);
496 if(ref == 0)
498 orphan_entry *orphan, *orphan2;
499 TRACE("freeing docptr %p\n", doc);
501 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
503 xmlFreeNode( orphan->node );
504 heap_free( orphan );
506 free_properties(priv->properties);
507 heap_free(doc->_private);
509 xmlFreeDoc(doc);
512 return ref;
515 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
517 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
518 orphan_entry *entry;
520 entry = heap_alloc( sizeof (*entry) );
521 if(!entry)
522 return E_OUTOFMEMORY;
524 entry->node = node;
525 list_add_head( &priv->orphans, &entry->entry );
526 return S_OK;
529 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
531 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
532 orphan_entry *entry, *entry2;
534 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
536 if( entry->node == node )
538 list_remove( &entry->entry );
539 heap_free( entry );
540 return S_OK;
544 return S_FALSE;
547 static inline xmlDocPtr get_doc( domdoc *This )
549 return (xmlDocPtr)This->node.node;
552 static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
554 if(This->node.node)
556 priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
557 if (xmldoc_release(get_doc(This)) != 0)
558 priv_from_xmlDocPtr(get_doc(This))->properties =
559 copy_properties(This->properties);
562 This->node.node = (xmlNodePtr) xml;
564 if(This->node.node)
566 xmldoc_add_ref(get_doc(This));
567 priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
570 return S_OK;
573 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
575 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
578 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
580 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStreamInit));
583 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
585 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
588 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
590 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
593 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
595 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblISupportErrorInfo));
598 static inline domdoc *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
600 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtblConnectionPointContainer));
603 /************************************************************************
604 * domdoc implementation of IPersistStream.
606 static HRESULT WINAPI domdoc_IPersistStreamInit_QueryInterface(
607 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
609 domdoc *this = impl_from_IPersistStreamInit(iface);
610 return IXMLDOMDocument2_QueryInterface((IXMLDOMDocument2 *)this, riid, ppvObj);
613 static ULONG WINAPI domdoc_IPersistStreamInit_AddRef(
614 IPersistStreamInit *iface)
616 domdoc *this = impl_from_IPersistStreamInit(iface);
617 return IXMLDOMDocument2_AddRef((IXMLDOMDocument2 *)this);
620 static ULONG WINAPI domdoc_IPersistStreamInit_Release(
621 IPersistStreamInit *iface)
623 domdoc *this = impl_from_IPersistStreamInit(iface);
624 return IXMLDOMDocument2_Release((IXMLDOMDocument2 *)this);
627 static HRESULT WINAPI domdoc_IPersistStreamInit_GetClassID(
628 IPersistStreamInit *iface, CLSID *classid)
630 TRACE("(%p,%p): stub!\n", iface, classid);
632 if(!classid)
633 return E_POINTER;
635 *classid = CLSID_DOMDocument2;
637 return S_OK;
640 static HRESULT WINAPI domdoc_IPersistStreamInit_IsDirty(
641 IPersistStreamInit *iface)
643 domdoc *This = impl_from_IPersistStreamInit(iface);
644 FIXME("(%p): stub!\n", This);
645 return S_FALSE;
648 static HRESULT WINAPI domdoc_IPersistStreamInit_Load(
649 IPersistStreamInit *iface, LPSTREAM pStm)
651 domdoc *This = impl_from_IPersistStreamInit(iface);
652 HRESULT hr;
653 HGLOBAL hglobal;
654 DWORD read, written, len;
655 BYTE buf[4096];
656 char *ptr;
657 xmlDocPtr xmldoc = NULL;
659 TRACE("(%p)->(%p)\n", This, pStm);
661 if (!pStm)
662 return E_INVALIDARG;
664 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
665 if (FAILED(hr))
666 return hr;
670 IStream_Read(pStm, buf, sizeof(buf), &read);
671 hr = IStream_Write(This->stream, buf, read, &written);
672 } while(SUCCEEDED(hr) && written != 0 && read != 0);
674 if (FAILED(hr))
676 ERR("Failed to copy stream\n");
677 return hr;
680 hr = GetHGlobalFromStream(This->stream, &hglobal);
681 if (FAILED(hr))
682 return hr;
684 len = GlobalSize(hglobal);
685 ptr = GlobalLock(hglobal);
686 if (len != 0)
687 xmldoc = doparse(This, ptr, len, NULL);
688 GlobalUnlock(hglobal);
690 if (!xmldoc)
692 ERR("Failed to parse xml\n");
693 return E_FAIL;
696 xmldoc->_private = create_priv();
698 return attach_xmldoc(This, xmldoc);
701 static HRESULT WINAPI domdoc_IPersistStreamInit_Save(
702 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
704 domdoc *This = impl_from_IPersistStreamInit(iface);
705 BSTR xmlString;
706 HRESULT hr;
708 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
710 hr = IXMLDOMDocument3_get_xml( (IXMLDOMDocument3*)&This->lpVtbl, &xmlString );
711 if(hr == S_OK)
713 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
715 hr = IStream_Write( stream, xmlString, len, NULL );
716 SysFreeString(xmlString);
719 TRACE("ret 0x%08x\n", hr);
721 return hr;
724 static HRESULT WINAPI domdoc_IPersistStreamInit_GetSizeMax(
725 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
727 domdoc *This = impl_from_IPersistStreamInit(iface);
728 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
729 return E_NOTIMPL;
732 static HRESULT WINAPI domdoc_IPersistStreamInit_InitNew(
733 IPersistStreamInit *iface)
735 domdoc *This = impl_from_IPersistStreamInit(iface);
736 TRACE("(%p)\n", This);
737 return S_OK;
740 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
742 domdoc_IPersistStreamInit_QueryInterface,
743 domdoc_IPersistStreamInit_AddRef,
744 domdoc_IPersistStreamInit_Release,
745 domdoc_IPersistStreamInit_GetClassID,
746 domdoc_IPersistStreamInit_IsDirty,
747 domdoc_IPersistStreamInit_Load,
748 domdoc_IPersistStreamInit_Save,
749 domdoc_IPersistStreamInit_GetSizeMax,
750 domdoc_IPersistStreamInit_InitNew
753 /* ISupportErrorInfo interface */
754 static HRESULT WINAPI support_error_QueryInterface(
755 ISupportErrorInfo *iface,
756 REFIID riid, void** ppvObj )
758 domdoc *This = impl_from_ISupportErrorInfo(iface);
759 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3 *)This, riid, ppvObj);
762 static ULONG WINAPI support_error_AddRef(
763 ISupportErrorInfo *iface )
765 domdoc *This = impl_from_ISupportErrorInfo(iface);
766 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
769 static ULONG WINAPI support_error_Release(
770 ISupportErrorInfo *iface )
772 domdoc *This = impl_from_ISupportErrorInfo(iface);
773 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
776 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
777 ISupportErrorInfo *iface,
778 REFIID riid )
780 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
781 return S_FALSE;
784 static const struct ISupportErrorInfoVtbl support_error_vtbl =
786 support_error_QueryInterface,
787 support_error_AddRef,
788 support_error_Release,
789 support_error_InterfaceSupportsErrorInfo
792 /* IXMLDOMDocument2 interface */
793 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
795 domdoc *This = impl_from_IXMLDOMDocument3( iface );
797 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
799 *ppvObject = NULL;
801 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
802 IsEqualGUID( riid, &IID_IDispatch ) ||
803 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
804 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
805 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
806 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
808 *ppvObject = iface;
810 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
811 IsEqualGUID(&IID_IPersistStreamInit, riid))
813 *ppvObject = &(This->lpvtblIPersistStreamInit);
815 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
817 *ppvObject = &(This->lpvtblIObjectWithSite);
819 else if (IsEqualGUID(&IID_IObjectSafety, riid))
821 *ppvObject = &(This->lpvtblIObjectSafety);
823 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
825 *ppvObject = &This->lpvtblISupportErrorInfo;
827 else if(node_query_interface(&This->node, riid, ppvObject))
829 return *ppvObject ? S_OK : E_NOINTERFACE;
831 else if (IsEqualGUID( riid, &IID_IConnectionPointContainer ))
833 *ppvObject = &This->lpVtblConnectionPointContainer;
835 else if(IsEqualGUID(&IID_IRunnableObject, riid))
837 TRACE("IID_IRunnableObject not supported returning NULL\n");
838 return E_NOINTERFACE;
840 else
842 FIXME("interface %s not implemented\n", debugstr_guid(riid));
843 return E_NOINTERFACE;
846 IUnknown_AddRef((IUnknown*)*ppvObject);
848 return S_OK;
852 static ULONG WINAPI domdoc_AddRef(
853 IXMLDOMDocument3 *iface )
855 domdoc *This = impl_from_IXMLDOMDocument3( iface );
856 TRACE("%p\n", This );
857 return InterlockedIncrement( &This->ref );
861 static ULONG WINAPI domdoc_Release(
862 IXMLDOMDocument3 *iface )
864 domdoc *This = impl_from_IXMLDOMDocument3( iface );
865 LONG ref;
867 TRACE("%p\n", This );
869 ref = InterlockedDecrement( &This->ref );
870 if ( ref == 0 )
872 if(This->bsc)
873 detach_bsc(This->bsc);
875 if (This->site)
876 IUnknown_Release( This->site );
877 destroy_xmlnode(&This->node);
878 if(This->schema) IXMLDOMSchemaCollection2_Release(This->schema);
879 if (This->stream) IStream_Release(This->stream);
880 HeapFree( GetProcessHeap(), 0, This );
883 return ref;
886 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
888 domdoc *This = impl_from_IXMLDOMDocument3( iface );
890 TRACE("(%p)->(%p)\n", This, pctinfo);
892 *pctinfo = 1;
894 return S_OK;
897 static HRESULT WINAPI domdoc_GetTypeInfo(
898 IXMLDOMDocument3 *iface,
899 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
901 domdoc *This = impl_from_IXMLDOMDocument3( iface );
902 HRESULT hr;
904 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
906 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
908 return hr;
911 static HRESULT WINAPI domdoc_GetIDsOfNames(
912 IXMLDOMDocument3 *iface,
913 REFIID riid,
914 LPOLESTR* rgszNames,
915 UINT cNames,
916 LCID lcid,
917 DISPID* rgDispId)
919 domdoc *This = impl_from_IXMLDOMDocument3( iface );
920 ITypeInfo *typeinfo;
921 HRESULT hr;
923 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
924 lcid, rgDispId);
926 if(!rgszNames || cNames == 0 || !rgDispId)
927 return E_INVALIDARG;
929 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
930 if(SUCCEEDED(hr))
932 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
933 ITypeInfo_Release(typeinfo);
936 return hr;
940 static HRESULT WINAPI domdoc_Invoke(
941 IXMLDOMDocument3 *iface,
942 DISPID dispIdMember,
943 REFIID riid,
944 LCID lcid,
945 WORD wFlags,
946 DISPPARAMS* pDispParams,
947 VARIANT* pVarResult,
948 EXCEPINFO* pExcepInfo,
949 UINT* puArgErr)
951 domdoc *This = impl_from_IXMLDOMDocument3( iface );
952 ITypeInfo *typeinfo;
953 HRESULT hr;
955 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
956 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
958 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
959 if(SUCCEEDED(hr))
961 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
962 pVarResult, pExcepInfo, puArgErr);
963 ITypeInfo_Release(typeinfo);
966 return hr;
970 static HRESULT WINAPI domdoc_get_nodeName(
971 IXMLDOMDocument3 *iface,
972 BSTR* name )
974 domdoc *This = impl_from_IXMLDOMDocument3( iface );
976 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
978 TRACE("(%p)->(%p)\n", This, name);
980 return return_bstr(documentW, name);
984 static HRESULT WINAPI domdoc_get_nodeValue(
985 IXMLDOMDocument3 *iface,
986 VARIANT* value )
988 domdoc *This = impl_from_IXMLDOMDocument3( iface );
990 TRACE("(%p)->(%p)\n", This, value);
992 if(!value)
993 return E_INVALIDARG;
995 V_VT(value) = VT_NULL;
996 V_BSTR(value) = NULL; /* tests show that we should do this */
997 return S_FALSE;
1001 static HRESULT WINAPI domdoc_put_nodeValue(
1002 IXMLDOMDocument3 *iface,
1003 VARIANT value)
1005 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1006 FIXME("(%p)->(v%d)\n", This, V_VT(&value));
1007 return E_FAIL;
1011 static HRESULT WINAPI domdoc_get_nodeType(
1012 IXMLDOMDocument3 *iface,
1013 DOMNodeType* type )
1015 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1017 TRACE("(%p)->(%p)\n", This, type);
1019 *type = NODE_DOCUMENT;
1020 return S_OK;
1024 static HRESULT WINAPI domdoc_get_parentNode(
1025 IXMLDOMDocument3 *iface,
1026 IXMLDOMNode** parent )
1028 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1030 TRACE("(%p)->(%p)\n", This, parent);
1032 return node_get_parent(&This->node, parent);
1036 static HRESULT WINAPI domdoc_get_childNodes(
1037 IXMLDOMDocument3 *iface,
1038 IXMLDOMNodeList** childList )
1040 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1042 TRACE("(%p)->(%p)\n", This, childList);
1044 return node_get_child_nodes(&This->node, childList);
1048 static HRESULT WINAPI domdoc_get_firstChild(
1049 IXMLDOMDocument3 *iface,
1050 IXMLDOMNode** firstChild )
1052 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1054 TRACE("(%p)->(%p)\n", This, firstChild);
1056 return node_get_first_child(&This->node, firstChild);
1060 static HRESULT WINAPI domdoc_get_lastChild(
1061 IXMLDOMDocument3 *iface,
1062 IXMLDOMNode** lastChild )
1064 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1066 TRACE("(%p)->(%p)\n", This, lastChild);
1068 return node_get_last_child(&This->node, lastChild);
1072 static HRESULT WINAPI domdoc_get_previousSibling(
1073 IXMLDOMDocument3 *iface,
1074 IXMLDOMNode** previousSibling )
1076 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1078 TRACE("(%p)->(%p)\n", This, previousSibling);
1080 return return_null_node(previousSibling);
1084 static HRESULT WINAPI domdoc_get_nextSibling(
1085 IXMLDOMDocument3 *iface,
1086 IXMLDOMNode** nextSibling )
1088 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1090 TRACE("(%p)->(%p)\n", This, nextSibling);
1092 return return_null_node(nextSibling);
1096 static HRESULT WINAPI domdoc_get_attributes(
1097 IXMLDOMDocument3 *iface,
1098 IXMLDOMNamedNodeMap** attributeMap )
1100 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1102 TRACE("(%p)->(%p)\n", This, attributeMap);
1104 return return_null_ptr((void**)attributeMap);
1108 static HRESULT WINAPI domdoc_insertBefore(
1109 IXMLDOMDocument3 *iface,
1110 IXMLDOMNode* newChild,
1111 VARIANT refChild,
1112 IXMLDOMNode** outNewChild )
1114 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1116 TRACE("(%p)->(%p x%d %p)\n", This, newChild, V_VT(&refChild), outNewChild);
1118 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1122 static HRESULT WINAPI domdoc_replaceChild(
1123 IXMLDOMDocument3 *iface,
1124 IXMLDOMNode* newChild,
1125 IXMLDOMNode* oldChild,
1126 IXMLDOMNode** outOldChild)
1128 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1130 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1132 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1136 static HRESULT WINAPI domdoc_removeChild(
1137 IXMLDOMDocument3 *iface,
1138 IXMLDOMNode* childNode,
1139 IXMLDOMNode** oldChild)
1141 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1142 return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), childNode, oldChild );
1146 static HRESULT WINAPI domdoc_appendChild(
1147 IXMLDOMDocument3 *iface,
1148 IXMLDOMNode* newChild,
1149 IXMLDOMNode** outNewChild)
1151 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1152 return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newChild, outNewChild );
1156 static HRESULT WINAPI domdoc_hasChildNodes(
1157 IXMLDOMDocument3 *iface,
1158 VARIANT_BOOL* hasChild)
1160 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1161 return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), hasChild );
1165 static HRESULT WINAPI domdoc_get_ownerDocument(
1166 IXMLDOMDocument3 *iface,
1167 IXMLDOMDocument** DOMDocument)
1169 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1170 return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), DOMDocument );
1174 static HRESULT WINAPI domdoc_cloneNode(
1175 IXMLDOMDocument3 *iface,
1176 VARIANT_BOOL deep,
1177 IXMLDOMNode** outNode)
1179 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1180 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
1181 return node_clone( &This->node, deep, outNode );
1185 static HRESULT WINAPI domdoc_get_nodeTypeString(
1186 IXMLDOMDocument3 *iface,
1187 BSTR* nodeType )
1189 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1190 return IXMLDOMNode_get_nodeTypeString( IXMLDOMNode_from_impl(&This->node), nodeType );
1194 static HRESULT WINAPI domdoc_get_text(
1195 IXMLDOMDocument3 *iface,
1196 BSTR* text )
1198 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1199 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), text );
1203 static HRESULT WINAPI domdoc_put_text(
1204 IXMLDOMDocument3 *iface,
1205 BSTR text )
1207 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1208 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1209 return E_FAIL;
1213 static HRESULT WINAPI domdoc_get_specified(
1214 IXMLDOMDocument3 *iface,
1215 VARIANT_BOOL* isSpecified )
1217 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1218 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1219 *isSpecified = VARIANT_TRUE;
1220 return S_OK;
1224 static HRESULT WINAPI domdoc_get_definition(
1225 IXMLDOMDocument3 *iface,
1226 IXMLDOMNode** definitionNode )
1228 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1229 FIXME("(%p)->(%p)\n", This, definitionNode);
1230 return E_NOTIMPL;
1234 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1235 IXMLDOMDocument3 *iface,
1236 VARIANT* typedValue )
1238 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1239 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
1242 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1243 IXMLDOMDocument3 *iface,
1244 VARIANT typedValue )
1246 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1247 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
1251 static HRESULT WINAPI domdoc_get_dataType(
1252 IXMLDOMDocument3 *iface,
1253 VARIANT* typename )
1255 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1256 TRACE("(%p)->(%p)\n", This, typename);
1257 return return_null_var( typename );
1261 static HRESULT WINAPI domdoc_put_dataType(
1262 IXMLDOMDocument3 *iface,
1263 BSTR dataTypeName )
1265 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1266 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
1270 static HRESULT WINAPI domdoc_get_xml(
1271 IXMLDOMDocument3 *iface,
1272 BSTR* p)
1274 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1276 TRACE("(%p)->(%p)\n", This, p);
1278 return node_get_xml(&This->node, TRUE, TRUE, p);
1282 static HRESULT WINAPI domdoc_transformNode(
1283 IXMLDOMDocument3 *iface,
1284 IXMLDOMNode* styleSheet,
1285 BSTR* xmlString )
1287 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1288 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), styleSheet, xmlString );
1292 static HRESULT WINAPI domdoc_selectNodes(
1293 IXMLDOMDocument3 *iface,
1294 BSTR queryString,
1295 IXMLDOMNodeList** resultList )
1297 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1298 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), queryString, resultList );
1302 static HRESULT WINAPI domdoc_selectSingleNode(
1303 IXMLDOMDocument3 *iface,
1304 BSTR queryString,
1305 IXMLDOMNode** resultNode )
1307 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1308 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), queryString, resultNode );
1312 static HRESULT WINAPI domdoc_get_parsed(
1313 IXMLDOMDocument3 *iface,
1314 VARIANT_BOOL* isParsed )
1316 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1317 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1318 *isParsed = VARIANT_TRUE;
1319 return S_OK;
1323 static HRESULT WINAPI domdoc_get_namespaceURI(
1324 IXMLDOMDocument3 *iface,
1325 BSTR* namespaceURI )
1327 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1328 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), namespaceURI );
1332 static HRESULT WINAPI domdoc_get_prefix(
1333 IXMLDOMDocument3 *iface,
1334 BSTR* prefix )
1336 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1337 TRACE("(%p)->(%p)\n", This, prefix);
1338 return return_null_bstr( prefix );
1342 static HRESULT WINAPI domdoc_get_baseName(
1343 IXMLDOMDocument3 *iface,
1344 BSTR* name )
1346 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1347 TRACE("(%p)->(%p)\n", This, name);
1348 return return_null_bstr( name );
1352 static HRESULT WINAPI domdoc_transformNodeToObject(
1353 IXMLDOMDocument3 *iface,
1354 IXMLDOMNode* stylesheet,
1355 VARIANT outputObject)
1357 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1358 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), stylesheet, outputObject );
1362 static HRESULT WINAPI domdoc_get_doctype(
1363 IXMLDOMDocument3 *iface,
1364 IXMLDOMDocumentType** documentType )
1366 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1367 FIXME("(%p)\n", This);
1368 return E_NOTIMPL;
1372 static HRESULT WINAPI domdoc_get_implementation(
1373 IXMLDOMDocument3 *iface,
1374 IXMLDOMImplementation** impl )
1376 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1378 TRACE("(%p)->(%p)\n", This, impl);
1380 if(!impl)
1381 return E_INVALIDARG;
1383 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1385 return S_OK;
1388 static HRESULT WINAPI domdoc_get_documentElement(
1389 IXMLDOMDocument3 *iface,
1390 IXMLDOMElement** DOMElement )
1392 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1393 IXMLDOMNode *element_node;
1394 xmlNodePtr root;
1395 HRESULT hr;
1397 TRACE("(%p)->(%p)\n", This, DOMElement);
1399 if(!DOMElement)
1400 return E_INVALIDARG;
1402 *DOMElement = NULL;
1404 root = xmlDocGetRootElement( get_doc(This) );
1405 if ( !root )
1406 return S_FALSE;
1408 element_node = create_node( root );
1409 if(!element_node) return S_FALSE;
1411 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1412 IXMLDOMNode_Release(element_node);
1414 return hr;
1418 static HRESULT WINAPI domdoc_put_documentElement(
1419 IXMLDOMDocument3 *iface,
1420 IXMLDOMElement* DOMElement )
1422 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1423 IXMLDOMNode *elementNode;
1424 xmlNodePtr oldRoot;
1425 xmlnode *xmlNode;
1426 HRESULT hr;
1428 TRACE("(%p)->(%p)\n", This, DOMElement);
1430 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1431 if(FAILED(hr))
1432 return hr;
1434 xmlNode = get_node_obj( elementNode );
1435 if(!xmlNode) {
1436 FIXME("elementNode is not our object\n");
1437 return E_FAIL;
1440 if(!xmlNode->node->parent)
1441 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1442 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1444 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1445 IXMLDOMNode_Release( elementNode );
1447 if(oldRoot)
1448 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1450 return S_OK;
1454 static HRESULT WINAPI domdoc_createElement(
1455 IXMLDOMDocument3 *iface,
1456 BSTR tagname,
1457 IXMLDOMElement** element )
1459 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1460 IXMLDOMNode *node;
1461 VARIANT type;
1462 HRESULT hr;
1464 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1466 if (!element || !tagname) return E_INVALIDARG;
1468 V_VT(&type) = VT_I1;
1469 V_I1(&type) = NODE_ELEMENT;
1471 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1472 if (hr == S_OK)
1474 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1475 IXMLDOMNode_Release(node);
1478 return hr;
1482 static HRESULT WINAPI domdoc_createDocumentFragment(
1483 IXMLDOMDocument3 *iface,
1484 IXMLDOMDocumentFragment** frag )
1486 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1487 IXMLDOMNode *node;
1488 VARIANT type;
1489 HRESULT hr;
1491 TRACE("(%p)->(%p)\n", This, frag);
1493 if (!frag) return E_INVALIDARG;
1495 *frag = NULL;
1497 V_VT(&type) = VT_I1;
1498 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1500 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1501 if (hr == S_OK)
1503 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1504 IXMLDOMNode_Release(node);
1507 return hr;
1511 static HRESULT WINAPI domdoc_createTextNode(
1512 IXMLDOMDocument3 *iface,
1513 BSTR data,
1514 IXMLDOMText** text )
1516 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1517 IXMLDOMNode *node;
1518 VARIANT type;
1519 HRESULT hr;
1521 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1523 if (!text) return E_INVALIDARG;
1525 *text = NULL;
1527 V_VT(&type) = VT_I1;
1528 V_I1(&type) = NODE_TEXT;
1530 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1531 if (hr == S_OK)
1533 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1534 IXMLDOMNode_Release(node);
1535 hr = IXMLDOMText_put_data(*text, data);
1538 return hr;
1542 static HRESULT WINAPI domdoc_createComment(
1543 IXMLDOMDocument3 *iface,
1544 BSTR data,
1545 IXMLDOMComment** comment )
1547 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1548 VARIANT type;
1549 HRESULT hr;
1550 IXMLDOMNode *node;
1552 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1554 if (!comment) return E_INVALIDARG;
1556 *comment = NULL;
1558 V_VT(&type) = VT_I1;
1559 V_I1(&type) = NODE_COMMENT;
1561 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1562 if (hr == S_OK)
1564 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1565 IXMLDOMNode_Release(node);
1566 hr = IXMLDOMComment_put_data(*comment, data);
1569 return hr;
1573 static HRESULT WINAPI domdoc_createCDATASection(
1574 IXMLDOMDocument3 *iface,
1575 BSTR data,
1576 IXMLDOMCDATASection** cdata )
1578 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1579 IXMLDOMNode *node;
1580 VARIANT type;
1581 HRESULT hr;
1583 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1585 if (!cdata) return E_INVALIDARG;
1587 *cdata = NULL;
1589 V_VT(&type) = VT_I1;
1590 V_I1(&type) = NODE_CDATA_SECTION;
1592 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1593 if (hr == S_OK)
1595 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1596 IXMLDOMNode_Release(node);
1597 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1600 return hr;
1604 static HRESULT WINAPI domdoc_createProcessingInstruction(
1605 IXMLDOMDocument3 *iface,
1606 BSTR target,
1607 BSTR data,
1608 IXMLDOMProcessingInstruction** pi )
1610 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1611 IXMLDOMNode *node;
1612 VARIANT type;
1613 HRESULT hr;
1615 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1617 if (!pi) return E_INVALIDARG;
1619 *pi = NULL;
1621 V_VT(&type) = VT_I1;
1622 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1624 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1625 if (hr == S_OK)
1627 xmlnode *node_obj;
1629 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1630 node_obj = get_node_obj(node);
1631 hr = node_set_content(node_obj, data);
1633 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1634 IXMLDOMNode_Release(node);
1637 return hr;
1641 static HRESULT WINAPI domdoc_createAttribute(
1642 IXMLDOMDocument3 *iface,
1643 BSTR name,
1644 IXMLDOMAttribute** attribute )
1646 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1647 IXMLDOMNode *node;
1648 VARIANT type;
1649 HRESULT hr;
1651 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1653 if (!attribute || !name) return E_INVALIDARG;
1655 V_VT(&type) = VT_I1;
1656 V_I1(&type) = NODE_ATTRIBUTE;
1658 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1659 if (hr == S_OK)
1661 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1662 IXMLDOMNode_Release(node);
1665 return hr;
1669 static HRESULT WINAPI domdoc_createEntityReference(
1670 IXMLDOMDocument3 *iface,
1671 BSTR name,
1672 IXMLDOMEntityReference** entityref )
1674 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1675 IXMLDOMNode *node;
1676 VARIANT type;
1677 HRESULT hr;
1679 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1681 if (!entityref) return E_INVALIDARG;
1683 *entityref = NULL;
1685 V_VT(&type) = VT_I1;
1686 V_I1(&type) = NODE_ENTITY_REFERENCE;
1688 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1689 if (hr == S_OK)
1691 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1692 IXMLDOMNode_Release(node);
1695 return hr;
1699 static HRESULT WINAPI domdoc_getElementsByTagName(
1700 IXMLDOMDocument3 *iface,
1701 BSTR tagName,
1702 IXMLDOMNodeList** resultList )
1704 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1705 HRESULT hr;
1707 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagName), resultList);
1709 if (!tagName || !resultList) return E_INVALIDARG;
1711 if (tagName[0] == '*' && tagName[1] == 0)
1713 static const WCHAR formatallW[] = {'/','/','*',0};
1714 hr = queryresult_create((xmlNodePtr)get_doc(This), formatallW, resultList);
1716 else
1718 static const WCHAR xpathformat[] =
1719 { '/','/','*','[','l','o','c','a','l','-','n','a','m','e','(',')','=','\'' };
1720 static const WCHAR closeW[] = { '\'',']',0 };
1722 LPWSTR pattern;
1723 WCHAR *ptr;
1724 INT length;
1726 length = lstrlenW(tagName);
1728 /* without two WCHARs from format specifier */
1729 ptr = pattern = heap_alloc(sizeof(xpathformat) + length*sizeof(WCHAR) + sizeof(closeW));
1731 memcpy(ptr, xpathformat, sizeof(xpathformat));
1732 ptr += sizeof(xpathformat)/sizeof(WCHAR);
1733 memcpy(ptr, tagName, length*sizeof(WCHAR));
1734 ptr += length;
1735 memcpy(ptr, closeW, sizeof(closeW));
1737 hr = queryresult_create((xmlNodePtr)get_doc(This), pattern, resultList);
1738 heap_free(pattern);
1741 return hr;
1744 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1746 VARIANT tmp;
1747 HRESULT hr;
1749 VariantInit(&tmp);
1750 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1751 if(FAILED(hr))
1752 return E_INVALIDARG;
1754 *type = V_I4(&tmp);
1756 return S_OK;
1759 static HRESULT WINAPI domdoc_createNode(
1760 IXMLDOMDocument3 *iface,
1761 VARIANT Type,
1762 BSTR name,
1763 BSTR namespaceURI,
1764 IXMLDOMNode** node )
1766 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1767 DOMNodeType node_type;
1768 xmlNodePtr xmlnode;
1769 xmlChar *xml_name, *href;
1770 HRESULT hr;
1772 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1774 if(!node) return E_INVALIDARG;
1776 hr = get_node_type(Type, &node_type);
1777 if(FAILED(hr)) return hr;
1779 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1780 FIXME("nodes with namespaces currently not supported.\n");
1782 TRACE("node_type %d\n", node_type);
1784 /* exit earlier for types that need name */
1785 switch(node_type)
1787 case NODE_ELEMENT:
1788 case NODE_ATTRIBUTE:
1789 case NODE_ENTITY_REFERENCE:
1790 case NODE_PROCESSING_INSTRUCTION:
1791 if (!name || *name == 0) return E_FAIL;
1792 default:
1793 break;
1796 xml_name = xmlChar_from_wchar(name);
1797 /* prevent empty href to be allocated */
1798 href = namespaceURI ? xmlChar_from_wchar(namespaceURI) : NULL;
1800 switch(node_type)
1802 case NODE_ELEMENT:
1804 xmlChar *local, *prefix;
1806 local = xmlSplitQName2(xml_name, &prefix);
1808 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
1810 /* allow to create default namespace xmlns= */
1811 if (local || (href && *href))
1813 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
1814 xmlSetNs(xmlnode, ns);
1817 xmlFree(local);
1818 xmlFree(prefix);
1820 break;
1822 case NODE_ATTRIBUTE:
1823 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1824 break;
1825 case NODE_TEXT:
1826 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1827 break;
1828 case NODE_CDATA_SECTION:
1829 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1830 break;
1831 case NODE_ENTITY_REFERENCE:
1832 xmlnode = xmlNewReference(get_doc(This), xml_name);
1833 break;
1834 case NODE_PROCESSING_INSTRUCTION:
1835 #ifdef HAVE_XMLNEWDOCPI
1836 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1837 #else
1838 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1839 xmlnode = NULL;
1840 #endif
1841 break;
1842 case NODE_COMMENT:
1843 xmlnode = xmlNewDocComment(get_doc(This), NULL);
1844 break;
1845 case NODE_DOCUMENT_FRAGMENT:
1846 xmlnode = xmlNewDocFragment(get_doc(This));
1847 break;
1848 /* unsupported types */
1849 case NODE_DOCUMENT:
1850 case NODE_DOCUMENT_TYPE:
1851 case NODE_ENTITY:
1852 case NODE_NOTATION:
1853 heap_free(xml_name);
1854 return E_INVALIDARG;
1855 default:
1856 FIXME("unhandled node type %d\n", node_type);
1857 xmlnode = NULL;
1858 break;
1861 *node = create_node(xmlnode);
1862 heap_free(xml_name);
1863 heap_free(href);
1865 if(*node)
1867 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1868 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1869 return S_OK;
1872 return E_FAIL;
1875 static HRESULT WINAPI domdoc_nodeFromID(
1876 IXMLDOMDocument3 *iface,
1877 BSTR idString,
1878 IXMLDOMNode** node )
1880 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1881 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1882 return E_NOTIMPL;
1885 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1887 domdoc *This = obj;
1888 xmlDocPtr xmldoc;
1890 xmldoc = doparse(This, ptr, len, NULL);
1891 if(xmldoc) {
1892 xmldoc->_private = create_priv();
1893 return attach_xmldoc(This, xmldoc);
1896 return S_OK;
1899 static HRESULT doread( domdoc *This, LPWSTR filename )
1901 bsc_t *bsc;
1902 HRESULT hr;
1904 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1905 if(FAILED(hr))
1906 return hr;
1908 if(This->bsc)
1909 detach_bsc(This->bsc);
1911 This->bsc = bsc;
1912 return S_OK;
1915 static HRESULT WINAPI domdoc_load(
1916 IXMLDOMDocument3 *iface,
1917 VARIANT xmlSource,
1918 VARIANT_BOOL* isSuccessful )
1920 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1921 LPWSTR filename = NULL;
1922 HRESULT hr = S_FALSE;
1923 IXMLDOMDocument3 *pNewDoc = NULL;
1924 IStream *pStream = NULL;
1925 xmlDocPtr xmldoc;
1927 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
1929 *isSuccessful = VARIANT_FALSE;
1931 assert( &This->node );
1933 switch( V_VT(&xmlSource) )
1935 case VT_BSTR:
1936 filename = V_BSTR(&xmlSource);
1937 break;
1938 case VT_UNKNOWN:
1939 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
1940 if(hr == S_OK)
1942 if(pNewDoc)
1944 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
1945 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1946 hr = attach_xmldoc(This, xmldoc);
1948 if(SUCCEEDED(hr))
1949 *isSuccessful = VARIANT_TRUE;
1951 return hr;
1954 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1955 if(hr == S_OK)
1957 IPersistStream *pDocStream;
1958 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1959 if(hr == S_OK)
1961 hr = IPersistStream_Load(pDocStream, pStream);
1962 IStream_Release(pStream);
1963 if(hr == S_OK)
1965 *isSuccessful = VARIANT_TRUE;
1967 TRACE("Using IStream to load Document\n");
1968 return S_OK;
1970 else
1972 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1975 else
1977 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1980 else
1982 /* ISequentialStream */
1983 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1985 break;
1986 default:
1987 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1990 TRACE("filename (%s)\n", debugstr_w(filename));
1992 if ( filename )
1994 hr = doread( This, filename );
1996 if ( FAILED(hr) )
1997 This->error = E_FAIL;
1998 else
2000 hr = This->error = S_OK;
2001 *isSuccessful = VARIANT_TRUE;
2005 if(!filename || FAILED(hr)) {
2006 xmldoc = xmlNewDoc(NULL);
2007 xmldoc->_private = create_priv();
2008 hr = attach_xmldoc(This, xmldoc);
2009 if(SUCCEEDED(hr))
2010 hr = S_FALSE;
2013 TRACE("ret (%d)\n", hr);
2015 return hr;
2019 static HRESULT WINAPI domdoc_get_readyState(
2020 IXMLDOMDocument3 *iface,
2021 LONG *value )
2023 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2024 FIXME("stub! (%p)->(%p)\n", This, value);
2026 if (!value)
2027 return E_INVALIDARG;
2029 *value = READYSTATE_COMPLETE;
2030 return S_OK;
2034 static HRESULT WINAPI domdoc_get_parseError(
2035 IXMLDOMDocument3 *iface,
2036 IXMLDOMParseError** errorObj )
2038 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2039 static const WCHAR err[] = {'e','r','r','o','r',0};
2040 BSTR error_string = NULL;
2042 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2044 if(This->error)
2045 error_string = SysAllocString(err);
2047 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2048 if(!*errorObj) return E_OUTOFMEMORY;
2049 return S_OK;
2053 static HRESULT WINAPI domdoc_get_url(
2054 IXMLDOMDocument3 *iface,
2055 BSTR* urlString )
2057 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2058 FIXME("(%p)->(%p)\n", This, urlString);
2059 return E_NOTIMPL;
2063 static HRESULT WINAPI domdoc_get_async(
2064 IXMLDOMDocument3 *iface,
2065 VARIANT_BOOL* isAsync )
2067 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2069 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2070 *isAsync = This->async;
2071 return S_OK;
2075 static HRESULT WINAPI domdoc_put_async(
2076 IXMLDOMDocument3 *iface,
2077 VARIANT_BOOL isAsync )
2079 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2081 TRACE("(%p)->(%d)\n", This, isAsync);
2082 This->async = isAsync;
2083 return S_OK;
2087 static HRESULT WINAPI domdoc_abort(
2088 IXMLDOMDocument3 *iface )
2090 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2091 FIXME("%p\n", This);
2092 return E_NOTIMPL;
2096 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
2098 UINT len;
2099 LPSTR str;
2101 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
2102 str = heap_alloc( len );
2103 if ( !str )
2104 return FALSE;
2105 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
2106 *plen = len;
2107 *pstr = str;
2108 return TRUE;
2111 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2112 static HRESULT WINAPI domdoc_loadXML(
2113 IXMLDOMDocument3 *iface,
2114 BSTR bstrXML,
2115 VARIANT_BOOL* isSuccessful )
2117 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2118 static const xmlChar encoding[] = "UTF-8";
2119 xmlDocPtr xmldoc = NULL;
2120 HRESULT hr = S_FALSE, hr2;
2121 char *str;
2122 int len;
2124 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2126 assert ( &This->node );
2128 if ( isSuccessful )
2130 *isSuccessful = VARIANT_FALSE;
2132 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
2134 xmldoc = doparse(This, str, len, encoding);
2135 heap_free( str );
2136 if ( !xmldoc )
2138 This->error = E_FAIL;
2139 TRACE("failed to parse document\n");
2141 else
2143 hr = This->error = S_OK;
2144 *isSuccessful = VARIANT_TRUE;
2145 TRACE("parsed document %p\n", xmldoc);
2149 if(!xmldoc)
2150 xmldoc = xmlNewDoc(NULL);
2152 xmldoc->_private = create_priv();
2154 hr2 = attach_xmldoc(This, xmldoc);
2155 if( FAILED(hr2) )
2156 hr = hr2;
2158 return hr;
2161 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2163 DWORD written = -1;
2165 if(!WriteFile(ctx, buffer, len, &written, NULL))
2167 WARN("write error\n");
2168 return -1;
2170 else
2171 return written;
2174 static int XMLCALL domdoc_save_closecallback(void *ctx)
2176 return CloseHandle(ctx) ? 0 : -1;
2179 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2181 ULONG written = 0;
2182 HRESULT hr;
2184 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2185 if (hr != S_OK)
2187 WARN("stream write error: 0x%08x\n", hr);
2188 return -1;
2190 else
2191 return written;
2194 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2196 IStream_Release((IStream*)ctx);
2197 return 0;
2200 static HRESULT WINAPI domdoc_save(
2201 IXMLDOMDocument3 *iface,
2202 VARIANT destination )
2204 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2205 xmlSaveCtxtPtr ctx = NULL;
2206 xmlNodePtr xmldecl;
2207 HRESULT ret = S_OK;
2209 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
2210 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
2212 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
2214 FIXME("Unhandled vt %d\n", V_VT(&destination));
2215 return S_FALSE;
2218 if(V_VT(&destination) == VT_UNKNOWN)
2220 IUnknown *pUnk = V_UNKNOWN(&destination);
2221 IXMLDOMDocument2 *document;
2222 IStream *stream;
2224 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2225 if(ret == S_OK)
2227 VARIANT_BOOL success;
2228 BSTR xml;
2230 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2231 if(ret == S_OK)
2233 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2234 SysFreeString(xml);
2237 IXMLDOMDocument3_Release(document);
2238 return ret;
2241 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2242 if(ret == S_OK)
2244 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2245 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2247 if(!ctx)
2249 IStream_Release(stream);
2250 return E_FAIL;
2254 else
2256 /* save with file path */
2257 HANDLE handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
2258 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2259 if( handle == INVALID_HANDLE_VALUE )
2261 WARN("failed to create file\n");
2262 return E_FAIL;
2265 /* disable top XML declaration */
2266 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2267 handle, NULL, XML_SAVE_NO_DECL);
2268 if (!ctx)
2270 CloseHandle(handle);
2271 return E_FAIL;
2275 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2276 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2277 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2279 /* will release resources through close callback */
2280 xmlSaveClose(ctx);
2282 return ret;
2285 static HRESULT WINAPI domdoc_get_validateOnParse(
2286 IXMLDOMDocument3 *iface,
2287 VARIANT_BOOL* isValidating )
2289 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2290 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2291 *isValidating = This->validating;
2292 return S_OK;
2296 static HRESULT WINAPI domdoc_put_validateOnParse(
2297 IXMLDOMDocument3 *iface,
2298 VARIANT_BOOL isValidating )
2300 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2301 TRACE("(%p)->(%d)\n", This, isValidating);
2302 This->validating = isValidating;
2303 return S_OK;
2307 static HRESULT WINAPI domdoc_get_resolveExternals(
2308 IXMLDOMDocument3 *iface,
2309 VARIANT_BOOL* isResolving )
2311 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2312 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2313 *isResolving = This->resolving;
2314 return S_OK;
2318 static HRESULT WINAPI domdoc_put_resolveExternals(
2319 IXMLDOMDocument3 *iface,
2320 VARIANT_BOOL isResolving )
2322 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2323 TRACE("(%p)->(%d)\n", This, isResolving);
2324 This->resolving = isResolving;
2325 return S_OK;
2329 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2330 IXMLDOMDocument3 *iface,
2331 VARIANT_BOOL* isPreserving )
2333 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2334 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->preserving);
2335 *isPreserving = This->preserving;
2336 return S_OK;
2340 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2341 IXMLDOMDocument3 *iface,
2342 VARIANT_BOOL isPreserving )
2344 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2345 TRACE("(%p)->(%d)\n", This, isPreserving);
2346 This->preserving = isPreserving;
2347 return S_OK;
2351 static HRESULT WINAPI domdoc_put_onReadyStateChange(
2352 IXMLDOMDocument3 *iface,
2353 VARIANT readyStateChangeSink )
2355 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2356 FIXME("%p\n", This);
2357 return E_NOTIMPL;
2361 static HRESULT WINAPI domdoc_put_onDataAvailable(
2362 IXMLDOMDocument3 *iface,
2363 VARIANT onDataAvailableSink )
2365 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2366 FIXME("%p\n", This);
2367 return E_NOTIMPL;
2370 static HRESULT WINAPI domdoc_put_onTransformNode(
2371 IXMLDOMDocument3 *iface,
2372 VARIANT onTransformNodeSink )
2374 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2375 FIXME("%p\n", This);
2376 return E_NOTIMPL;
2379 static HRESULT WINAPI domdoc_get_namespaces(
2380 IXMLDOMDocument3* iface,
2381 IXMLDOMSchemaCollection** schemaCollection )
2383 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2384 FIXME("(%p)->(%p)\n", This, schemaCollection);
2385 return E_NOTIMPL;
2388 static HRESULT WINAPI domdoc_get_schemas(
2389 IXMLDOMDocument3* iface,
2390 VARIANT* var1 )
2392 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2393 HRESULT hr = S_FALSE;
2394 IXMLDOMSchemaCollection2* cur_schema = This->schema;
2396 TRACE("(%p)->(%p)\n", This, var1);
2398 VariantInit(var1); /* Test shows we don't call VariantClear here */
2399 V_VT(var1) = VT_NULL;
2401 if(cur_schema)
2403 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2404 if(SUCCEEDED(hr))
2405 V_VT(var1) = VT_DISPATCH;
2407 return hr;
2410 static HRESULT WINAPI domdoc_putref_schemas(
2411 IXMLDOMDocument3* iface,
2412 VARIANT var1)
2414 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2415 HRESULT hr = E_FAIL;
2416 IXMLDOMSchemaCollection2* new_schema = NULL;
2418 FIXME("(%p): semi-stub\n", This);
2419 switch(V_VT(&var1))
2421 case VT_UNKNOWN:
2422 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2423 break;
2425 case VT_DISPATCH:
2426 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2427 break;
2429 case VT_NULL:
2430 case VT_EMPTY:
2431 hr = S_OK;
2432 break;
2434 default:
2435 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2438 if(SUCCEEDED(hr))
2440 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
2441 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2444 return hr;
2447 static inline BOOL is_wellformed(xmlDocPtr doc)
2449 #ifdef HAVE_XMLDOC_PROPERTIES
2450 return doc->properties & XML_DOC_WELLFORMED;
2451 #else
2452 /* Not a full check, but catches the worst violations */
2453 xmlNodePtr child;
2454 int root = 0;
2456 for (child = doc->children; child != NULL; child = child->next)
2458 switch (child->type)
2460 case XML_ELEMENT_NODE:
2461 if (++root > 1)
2462 return FALSE;
2463 break;
2464 case XML_TEXT_NODE:
2465 case XML_CDATA_SECTION_NODE:
2466 return FALSE;
2467 break;
2468 default:
2469 break;
2473 return root == 1;
2474 #endif
2477 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2479 va_list ap;
2480 va_start(ap, msg);
2481 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2482 va_end(ap);
2485 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2487 va_list ap;
2488 va_start(ap, msg);
2489 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2490 va_end(ap);
2493 static HRESULT WINAPI domdoc_validateNode(
2494 IXMLDOMDocument3* iface,
2495 IXMLDOMNode* node,
2496 IXMLDOMParseError** err)
2498 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2499 LONG state, err_code = 0;
2500 HRESULT hr = S_OK;
2501 int validated = 0;
2503 TRACE("(%p)->(%p, %p)\n", This, node, err);
2504 domdoc_get_readyState(iface, &state);
2505 if (state != READYSTATE_COMPLETE)
2507 if (err)
2508 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2509 return E_PENDING;
2512 if (!node)
2514 if (err)
2515 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2516 return E_POINTER;
2519 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2521 if (err)
2522 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2523 return E_FAIL;
2526 if (!is_wellformed(get_doc(This)))
2528 ERR("doc not well-formed");
2529 if (err)
2530 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2531 return S_FALSE;
2534 /* DTD validation */
2535 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2537 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2538 vctx->error = validate_error;
2539 vctx->warning = validate_warning;
2540 ++validated;
2542 if (!((node == (IXMLDOMNode*)iface)?
2543 xmlValidateDocument(vctx, get_doc(This)) :
2544 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2546 /* TODO: get a real error code here */
2547 TRACE("DTD validation failed\n");
2548 err_code = E_XML_INVALID;
2549 hr = S_FALSE;
2551 xmlFreeValidCtxt(vctx);
2554 /* Schema validation */
2555 if (hr == S_OK && This->schema != NULL)
2558 hr = SchemaCache_validate_tree(This->schema, get_node_obj(node)->node);
2559 if (!FAILED(hr))
2561 ++validated;
2562 /* TODO: get a real error code here */
2563 TRACE("schema validation failed\n");
2564 if (hr != S_OK)
2565 err_code = E_XML_INVALID;
2567 else
2569 /* not really OK, just didn't find a schema for the ns */
2570 hr = S_OK;
2574 if (!validated)
2576 TRACE("no DTD or schema found\n");
2577 err_code = E_XML_NODTD;
2578 hr = S_FALSE;
2581 if (err)
2582 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2584 return hr;
2587 static HRESULT WINAPI domdoc_validate(
2588 IXMLDOMDocument3* iface,
2589 IXMLDOMParseError** err)
2591 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2592 TRACE("(%p)->(%p)\n", This, err);
2593 return domdoc_validateNode(iface, (IXMLDOMNode*)iface, err);
2596 static HRESULT WINAPI domdoc_setProperty(
2597 IXMLDOMDocument3* iface,
2598 BSTR p,
2599 VARIANT var)
2601 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2603 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2605 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2607 VARIANT varStr;
2608 HRESULT hr;
2609 BSTR bstr;
2611 V_VT(&varStr) = VT_EMPTY;
2612 if (V_VT(&var) != VT_BSTR)
2614 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2615 return hr;
2616 bstr = V_BSTR(&varStr);
2618 else
2619 bstr = V_BSTR(&var);
2621 hr = S_OK;
2622 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2623 This->properties->XPath = TRUE;
2624 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2625 This->properties->XPath = FALSE;
2626 else
2627 hr = E_FAIL;
2629 VariantClear(&varStr);
2630 return hr;
2632 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2634 VARIANT varStr;
2635 HRESULT hr;
2636 BSTR bstr;
2637 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2638 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2639 xmlXPathContextPtr ctx;
2640 struct list *pNsList;
2641 select_ns_entry* pNsEntry = NULL;
2643 V_VT(&varStr) = VT_EMPTY;
2644 if (V_VT(&var) != VT_BSTR)
2646 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2647 return hr;
2648 bstr = V_BSTR(&varStr);
2650 else
2651 bstr = V_BSTR(&var);
2653 hr = S_OK;
2655 pNsList = &(This->properties->selectNsList);
2656 clear_selectNsList(pNsList);
2657 heap_free(nsStr);
2658 nsStr = xmlChar_from_wchar(bstr);
2661 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2663 This->properties->selectNsStr = nsStr;
2664 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2665 if (bstr && *bstr)
2667 ctx = xmlXPathNewContext(This->node.node->doc);
2668 pTokBegin = nsStr;
2669 pTokEnd = nsStr;
2670 for (; *pTokBegin; pTokBegin = pTokEnd)
2672 if (pNsEntry != NULL)
2673 memset(pNsEntry, 0, sizeof(select_ns_entry));
2674 else
2675 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2677 while (*pTokBegin == ' ')
2678 ++pTokBegin;
2679 pTokEnd = pTokBegin;
2680 while (*pTokEnd != ' ' && *pTokEnd != 0)
2681 ++pTokEnd;
2683 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2685 hr = E_FAIL;
2686 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2687 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2688 continue;
2691 pTokBegin += 5;
2692 if (*pTokBegin == '=')
2694 /*valid for XSLPattern?*/
2695 FIXME("Setting default xmlns not supported - skipping.\n");
2696 pTokBegin = pTokEnd;
2697 continue;
2699 else if (*pTokBegin == ':')
2701 pNsEntry->prefix = ++pTokBegin;
2702 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2705 if (pTokInner == pTokEnd)
2707 hr = E_FAIL;
2708 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2709 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2710 continue;
2713 pNsEntry->prefix_end = *pTokInner;
2714 *pTokInner = 0;
2715 ++pTokInner;
2717 if (pTokEnd-pTokInner > 1 &&
2718 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2719 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2721 pNsEntry->href = ++pTokInner;
2722 pNsEntry->href_end = *(pTokEnd-1);
2723 *(pTokEnd-1) = 0;
2724 list_add_tail(pNsList, &pNsEntry->entry);
2725 /*let libxml figure out if they're valid from here ;)*/
2726 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2728 hr = E_FAIL;
2730 pNsEntry = NULL;
2731 continue;
2733 else
2735 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2736 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2737 list_add_tail(pNsList, &pNsEntry->entry);
2739 pNsEntry = NULL;
2740 hr = E_FAIL;
2741 continue;
2744 else
2746 hr = E_FAIL;
2747 continue;
2750 heap_free(pNsEntry);
2751 xmlXPathFreeContext(ctx);
2754 VariantClear(&varStr);
2755 return hr;
2757 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2758 lstrcmpiW(p, PropertyNewParserW) == 0)
2760 /* Ignore */
2761 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2762 return S_OK;
2765 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2766 return E_FAIL;
2769 static HRESULT WINAPI domdoc_getProperty(
2770 IXMLDOMDocument3* iface,
2771 BSTR p,
2772 VARIANT* var)
2774 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2776 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2778 if (!var)
2779 return E_INVALIDARG;
2781 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2783 V_VT(var) = VT_BSTR;
2784 V_BSTR(var) = This->properties->XPath ?
2785 SysAllocString(PropValueXPathW) :
2786 SysAllocString(PropValueXSLPatternW);
2787 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2789 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2791 int lenA, lenW;
2792 BSTR rebuiltStr, cur;
2793 const xmlChar *nsStr;
2794 struct list *pNsList;
2795 select_ns_entry* pNsEntry;
2797 V_VT(var) = VT_BSTR;
2798 nsStr = This->properties->selectNsStr;
2799 pNsList = &This->properties->selectNsList;
2800 lenA = This->properties->selectNsStr_len;
2801 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
2802 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
2803 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
2804 cur = rebuiltStr;
2805 /* this is fine because all of the chars that end tokens are ASCII*/
2806 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
2808 while (*cur != 0) ++cur;
2809 if (pNsEntry->prefix_end)
2811 *cur = pNsEntry->prefix_end;
2812 while (*cur != 0) ++cur;
2815 if (pNsEntry->href_end)
2817 *cur = pNsEntry->href_end;
2820 V_BSTR(var) = SysAllocString(rebuiltStr);
2821 heap_free(rebuiltStr);
2822 return S_OK;
2825 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2826 return E_FAIL;
2829 static HRESULT WINAPI domdoc_importNode(
2830 IXMLDOMDocument3* iface,
2831 IXMLDOMNode* node,
2832 VARIANT_BOOL deep,
2833 IXMLDOMNode** clone)
2835 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2836 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
2837 return E_NOTIMPL;
2840 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
2842 domdoc_QueryInterface,
2843 domdoc_AddRef,
2844 domdoc_Release,
2845 domdoc_GetTypeInfoCount,
2846 domdoc_GetTypeInfo,
2847 domdoc_GetIDsOfNames,
2848 domdoc_Invoke,
2849 domdoc_get_nodeName,
2850 domdoc_get_nodeValue,
2851 domdoc_put_nodeValue,
2852 domdoc_get_nodeType,
2853 domdoc_get_parentNode,
2854 domdoc_get_childNodes,
2855 domdoc_get_firstChild,
2856 domdoc_get_lastChild,
2857 domdoc_get_previousSibling,
2858 domdoc_get_nextSibling,
2859 domdoc_get_attributes,
2860 domdoc_insertBefore,
2861 domdoc_replaceChild,
2862 domdoc_removeChild,
2863 domdoc_appendChild,
2864 domdoc_hasChildNodes,
2865 domdoc_get_ownerDocument,
2866 domdoc_cloneNode,
2867 domdoc_get_nodeTypeString,
2868 domdoc_get_text,
2869 domdoc_put_text,
2870 domdoc_get_specified,
2871 domdoc_get_definition,
2872 domdoc_get_nodeTypedValue,
2873 domdoc_put_nodeTypedValue,
2874 domdoc_get_dataType,
2875 domdoc_put_dataType,
2876 domdoc_get_xml,
2877 domdoc_transformNode,
2878 domdoc_selectNodes,
2879 domdoc_selectSingleNode,
2880 domdoc_get_parsed,
2881 domdoc_get_namespaceURI,
2882 domdoc_get_prefix,
2883 domdoc_get_baseName,
2884 domdoc_transformNodeToObject,
2885 domdoc_get_doctype,
2886 domdoc_get_implementation,
2887 domdoc_get_documentElement,
2888 domdoc_put_documentElement,
2889 domdoc_createElement,
2890 domdoc_createDocumentFragment,
2891 domdoc_createTextNode,
2892 domdoc_createComment,
2893 domdoc_createCDATASection,
2894 domdoc_createProcessingInstruction,
2895 domdoc_createAttribute,
2896 domdoc_createEntityReference,
2897 domdoc_getElementsByTagName,
2898 domdoc_createNode,
2899 domdoc_nodeFromID,
2900 domdoc_load,
2901 domdoc_get_readyState,
2902 domdoc_get_parseError,
2903 domdoc_get_url,
2904 domdoc_get_async,
2905 domdoc_put_async,
2906 domdoc_abort,
2907 domdoc_loadXML,
2908 domdoc_save,
2909 domdoc_get_validateOnParse,
2910 domdoc_put_validateOnParse,
2911 domdoc_get_resolveExternals,
2912 domdoc_put_resolveExternals,
2913 domdoc_get_preserveWhiteSpace,
2914 domdoc_put_preserveWhiteSpace,
2915 domdoc_put_onReadyStateChange,
2916 domdoc_put_onDataAvailable,
2917 domdoc_put_onTransformNode,
2918 domdoc_get_namespaces,
2919 domdoc_get_schemas,
2920 domdoc_putref_schemas,
2921 domdoc_validate,
2922 domdoc_setProperty,
2923 domdoc_getProperty,
2924 domdoc_validateNode,
2925 domdoc_importNode
2928 /* IConnectionPointContainer */
2929 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
2930 REFIID riid, void **ppv)
2932 domdoc *This = impl_from_IConnectionPointContainer(iface);
2933 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)This, riid, ppv);
2936 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
2938 domdoc *This = impl_from_IConnectionPointContainer(iface);
2939 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)This);
2942 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
2944 domdoc *This = impl_from_IConnectionPointContainer(iface);
2945 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)This);
2948 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
2949 IEnumConnectionPoints **ppEnum)
2951 domdoc *This = impl_from_IConnectionPointContainer(iface);
2952 FIXME("(%p)->(%p): stub\n", This, ppEnum);
2953 return E_NOTIMPL;
2956 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
2957 REFIID riid, IConnectionPoint **cp)
2959 domdoc *This = impl_from_IConnectionPointContainer(iface);
2960 ConnectionPoint *iter;
2962 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
2964 *cp = NULL;
2966 for(iter = This->cp_list; iter; iter = iter->next)
2968 if (IsEqualGUID(iter->iid, riid))
2969 *cp = (IConnectionPoint*)&iter->lpVtblConnectionPoint;
2972 if (*cp)
2974 IConnectionPoint_AddRef(*cp);
2975 return S_OK;
2978 FIXME("unsupported riid %s\n", debugstr_guid(riid));
2979 return CONNECT_E_NOCONNECTION;
2983 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
2985 ConnectionPointContainer_QueryInterface,
2986 ConnectionPointContainer_AddRef,
2987 ConnectionPointContainer_Release,
2988 ConnectionPointContainer_EnumConnectionPoints,
2989 ConnectionPointContainer_FindConnectionPoint
2992 /* IConnectionPoint */
2993 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
2994 REFIID riid, void **ppv)
2996 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2998 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3000 *ppv = NULL;
3002 if (IsEqualGUID(&IID_IUnknown, riid) ||
3003 IsEqualGUID(&IID_IConnectionPoint, riid))
3005 *ppv = iface;
3008 if (*ppv)
3010 IConnectionPoint_AddRef(iface);
3011 return S_OK;
3014 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3015 return E_NOINTERFACE;
3018 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3020 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3021 return IConnectionPointContainer_AddRef(This->container);
3024 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3026 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3027 return IConnectionPointContainer_Release(This->container);
3030 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3032 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3034 TRACE("(%p)->(%p)\n", This, iid);
3036 if (!iid) return E_POINTER;
3038 *iid = *This->iid;
3039 return S_OK;
3042 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3043 IConnectionPointContainer **container)
3045 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3047 TRACE("(%p)->(%p)\n", This, container);
3049 if (!container) return E_POINTER;
3051 *container = This->container;
3052 IConnectionPointContainer_AddRef(*container);
3053 return S_OK;
3056 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
3057 DWORD *pdwCookie)
3059 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3060 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
3061 return E_NOTIMPL;
3064 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3066 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3068 TRACE("(%p)->(%d)\n", This, cookie);
3070 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3071 return CONNECT_E_NOCONNECTION;
3073 IUnknown_Release(This->sinks[cookie-1].unk);
3074 This->sinks[cookie-1].unk = NULL;
3076 return S_OK;
3079 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3080 IEnumConnections **ppEnum)
3082 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3083 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3084 return E_NOTIMPL;
3087 static const IConnectionPointVtbl ConnectionPointVtbl =
3089 ConnectionPoint_QueryInterface,
3090 ConnectionPoint_AddRef,
3091 ConnectionPoint_Release,
3092 ConnectionPoint_GetConnectionInterface,
3093 ConnectionPoint_GetConnectionPointContainer,
3094 ConnectionPoint_Advise,
3095 ConnectionPoint_Unadvise,
3096 ConnectionPoint_EnumConnections
3099 void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3101 cp->lpVtblConnectionPoint = &ConnectionPointVtbl;
3102 cp->doc = doc;
3103 cp->iid = riid;
3104 cp->sinks = NULL;
3105 cp->sinks_size = 0;
3107 cp->next = doc->cp_list;
3108 doc->cp_list = cp;
3110 cp->container = (IConnectionPointContainer*)&doc->lpVtblConnectionPointContainer;
3113 /* domdoc implementation of IObjectWithSite */
3114 static HRESULT WINAPI
3115 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3117 domdoc *This = impl_from_IObjectWithSite(iface);
3118 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppvObject );
3121 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3123 domdoc *This = impl_from_IObjectWithSite(iface);
3124 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3127 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3129 domdoc *This = impl_from_IObjectWithSite(iface);
3130 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3133 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3135 domdoc *This = impl_from_IObjectWithSite(iface);
3137 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3139 if ( !This->site )
3140 return E_FAIL;
3142 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3145 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3147 domdoc *This = impl_from_IObjectWithSite(iface);
3149 TRACE("(%p)->(%p)\n", iface, punk);
3151 if(!punk)
3153 if(This->site)
3155 IUnknown_Release( This->site );
3156 This->site = NULL;
3159 return S_OK;
3162 IUnknown_AddRef( punk );
3164 if(This->site)
3165 IUnknown_Release( This->site );
3167 This->site = punk;
3169 return S_OK;
3172 static const IObjectWithSiteVtbl domdocObjectSite =
3174 domdoc_ObjectWithSite_QueryInterface,
3175 domdoc_ObjectWithSite_AddRef,
3176 domdoc_ObjectWithSite_Release,
3177 domdoc_ObjectWithSite_SetSite,
3178 domdoc_ObjectWithSite_GetSite
3181 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3183 domdoc *This = impl_from_IObjectSafety(iface);
3184 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppv );
3187 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3189 domdoc *This = impl_from_IObjectSafety(iface);
3190 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3193 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3195 domdoc *This = impl_from_IObjectSafety(iface);
3196 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3199 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3201 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3202 DWORD *supported, DWORD *enabled)
3204 domdoc *This = impl_from_IObjectSafety(iface);
3206 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3208 if(!supported || !enabled) return E_POINTER;
3210 *supported = SAFETY_SUPPORTED_OPTIONS;
3211 *enabled = This->safeopt;
3213 return S_OK;
3216 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3217 DWORD mask, DWORD enabled)
3219 domdoc *This = impl_from_IObjectSafety(iface);
3220 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3222 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3223 return E_FAIL;
3225 This->safeopt = enabled & mask & SAFETY_SUPPORTED_OPTIONS;
3226 return S_OK;
3229 #undef SAFETY_SUPPORTED_OPTIONS
3231 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3232 domdoc_Safety_QueryInterface,
3233 domdoc_Safety_AddRef,
3234 domdoc_Safety_Release,
3235 domdoc_Safety_GetInterfaceSafetyOptions,
3236 domdoc_Safety_SetInterfaceSafetyOptions
3239 static const tid_t domdoc_iface_tids[] = {
3240 IXMLDOMNode_tid,
3241 IXMLDOMDocument_tid,
3242 IXMLDOMDocument2_tid,
3245 static dispex_static_data_t domdoc_dispex = {
3246 NULL,
3247 IXMLDOMDocument2_tid,
3248 NULL,
3249 domdoc_iface_tids
3252 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3254 domdoc *doc;
3256 doc = heap_alloc( sizeof (*doc) );
3257 if( !doc )
3258 return E_OUTOFMEMORY;
3260 doc->lpVtbl = &domdoc_vtbl;
3261 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
3262 doc->lpvtblIObjectWithSite = &domdocObjectSite;
3263 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
3264 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
3265 doc->lpVtblConnectionPointContainer = &ConnectionPointContainerVtbl;
3266 doc->ref = 1;
3267 doc->async = VARIANT_TRUE;
3268 doc->validating = 0;
3269 doc->resolving = 0;
3270 doc->preserving = 0;
3271 doc->properties = properties_from_xmlDocPtr(xmldoc);
3272 doc->error = S_OK;
3273 doc->schema = NULL;
3274 doc->stream = NULL;
3275 doc->site = NULL;
3276 doc->safeopt = 0;
3277 doc->bsc = NULL;
3278 doc->cp_list = NULL;
3280 /* events connection points */
3281 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3282 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3283 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3285 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->lpVtbl, &domdoc_dispex);
3287 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
3289 TRACE("returning iface %p\n", *document);
3290 return S_OK;
3293 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3295 xmlDocPtr xmldoc;
3296 HRESULT hr;
3298 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
3300 xmldoc = xmlNewDoc(NULL);
3301 if(!xmldoc)
3302 return E_OUTOFMEMORY;
3304 xmldoc->_private = create_priv();
3305 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
3307 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3308 if(FAILED(hr))
3310 free_properties(properties_from_xmlDocPtr(xmldoc));
3311 heap_free(xmldoc->_private);
3312 xmlFreeDoc(xmldoc);
3313 return hr;
3316 return hr;
3319 IUnknown* create_domdoc( xmlNodePtr document )
3321 void* pObj = NULL;
3322 HRESULT hr;
3324 TRACE("(%p)\n", document);
3326 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3327 if (FAILED(hr))
3328 return NULL;
3330 return pObj;
3333 #else
3335 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3337 MESSAGE("This program tried to use a DOMDocument object, but\n"
3338 "libxml2 support was not present at compile time.\n");
3339 return E_NOTIMPL;
3342 #endif