msxml3: libxml2 error/warning callback functions.
[wine.git] / dlls / msxml3 / domdoc.c
blob8a214023bdaa802f1e73f1ef319c538ccc764dac
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 IXMLDOMSchemaCollection *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) IXMLDOMSchemaCollection_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** cloneRoot)
1179 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1180 return IXMLDOMNode_cloneNode( IXMLDOMNode_from_impl(&This->node), deep, cloneRoot );
1184 static HRESULT WINAPI domdoc_get_nodeTypeString(
1185 IXMLDOMDocument3 *iface,
1186 BSTR* nodeType )
1188 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1189 return IXMLDOMNode_get_nodeTypeString( IXMLDOMNode_from_impl(&This->node), nodeType );
1193 static HRESULT WINAPI domdoc_get_text(
1194 IXMLDOMDocument3 *iface,
1195 BSTR* text )
1197 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1198 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), text );
1202 static HRESULT WINAPI domdoc_put_text(
1203 IXMLDOMDocument3 *iface,
1204 BSTR text )
1206 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1207 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1208 return E_FAIL;
1212 static HRESULT WINAPI domdoc_get_specified(
1213 IXMLDOMDocument3 *iface,
1214 VARIANT_BOOL* isSpecified )
1216 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1217 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1218 *isSpecified = VARIANT_TRUE;
1219 return S_OK;
1223 static HRESULT WINAPI domdoc_get_definition(
1224 IXMLDOMDocument3 *iface,
1225 IXMLDOMNode** definitionNode )
1227 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1228 FIXME("(%p)->(%p)\n", This, definitionNode);
1229 return E_NOTIMPL;
1233 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1234 IXMLDOMDocument3 *iface,
1235 VARIANT* typedValue )
1237 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1238 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
1241 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1242 IXMLDOMDocument3 *iface,
1243 VARIANT typedValue )
1245 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1246 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
1250 static HRESULT WINAPI domdoc_get_dataType(
1251 IXMLDOMDocument3 *iface,
1252 VARIANT* typename )
1254 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1255 TRACE("(%p)->(%p)\n", This, typename);
1256 return return_null_var( typename );
1260 static HRESULT WINAPI domdoc_put_dataType(
1261 IXMLDOMDocument3 *iface,
1262 BSTR dataTypeName )
1264 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1265 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
1269 static HRESULT WINAPI domdoc_get_xml(
1270 IXMLDOMDocument3 *iface,
1271 BSTR* xmlString )
1273 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1274 return IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), xmlString );
1278 static HRESULT WINAPI domdoc_transformNode(
1279 IXMLDOMDocument3 *iface,
1280 IXMLDOMNode* styleSheet,
1281 BSTR* xmlString )
1283 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1284 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), styleSheet, xmlString );
1288 static HRESULT WINAPI domdoc_selectNodes(
1289 IXMLDOMDocument3 *iface,
1290 BSTR queryString,
1291 IXMLDOMNodeList** resultList )
1293 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1294 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), queryString, resultList );
1298 static HRESULT WINAPI domdoc_selectSingleNode(
1299 IXMLDOMDocument3 *iface,
1300 BSTR queryString,
1301 IXMLDOMNode** resultNode )
1303 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1304 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), queryString, resultNode );
1308 static HRESULT WINAPI domdoc_get_parsed(
1309 IXMLDOMDocument3 *iface,
1310 VARIANT_BOOL* isParsed )
1312 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1313 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1314 *isParsed = VARIANT_TRUE;
1315 return S_OK;
1319 static HRESULT WINAPI domdoc_get_namespaceURI(
1320 IXMLDOMDocument3 *iface,
1321 BSTR* namespaceURI )
1323 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1324 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), namespaceURI );
1328 static HRESULT WINAPI domdoc_get_prefix(
1329 IXMLDOMDocument3 *iface,
1330 BSTR* prefixString )
1332 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1333 return IXMLDOMNode_get_prefix( IXMLDOMNode_from_impl(&This->node), prefixString );
1337 static HRESULT WINAPI domdoc_get_baseName(
1338 IXMLDOMDocument3 *iface,
1339 BSTR* nameString )
1341 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1342 return IXMLDOMNode_get_baseName( IXMLDOMNode_from_impl(&This->node), nameString );
1346 static HRESULT WINAPI domdoc_transformNodeToObject(
1347 IXMLDOMDocument3 *iface,
1348 IXMLDOMNode* stylesheet,
1349 VARIANT outputObject)
1351 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1352 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), stylesheet, outputObject );
1356 static HRESULT WINAPI domdoc_get_doctype(
1357 IXMLDOMDocument3 *iface,
1358 IXMLDOMDocumentType** documentType )
1360 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1361 FIXME("(%p)\n", This);
1362 return E_NOTIMPL;
1366 static HRESULT WINAPI domdoc_get_implementation(
1367 IXMLDOMDocument3 *iface,
1368 IXMLDOMImplementation** impl )
1370 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1372 TRACE("(%p)->(%p)\n", This, impl);
1374 if(!impl)
1375 return E_INVALIDARG;
1377 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1379 return S_OK;
1382 static HRESULT WINAPI domdoc_get_documentElement(
1383 IXMLDOMDocument3 *iface,
1384 IXMLDOMElement** DOMElement )
1386 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1387 IXMLDOMNode *element_node;
1388 xmlNodePtr root;
1389 HRESULT hr;
1391 TRACE("(%p)->(%p)\n", This, DOMElement);
1393 if(!DOMElement)
1394 return E_INVALIDARG;
1396 *DOMElement = NULL;
1398 root = xmlDocGetRootElement( get_doc(This) );
1399 if ( !root )
1400 return S_FALSE;
1402 element_node = create_node( root );
1403 if(!element_node) return S_FALSE;
1405 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1406 IXMLDOMNode_Release(element_node);
1408 return hr;
1412 static HRESULT WINAPI domdoc_put_documentElement(
1413 IXMLDOMDocument3 *iface,
1414 IXMLDOMElement* DOMElement )
1416 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1417 IXMLDOMNode *elementNode;
1418 xmlNodePtr oldRoot;
1419 xmlnode *xmlNode;
1420 HRESULT hr;
1422 TRACE("(%p)->(%p)\n", This, DOMElement);
1424 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1425 if(FAILED(hr))
1426 return hr;
1428 xmlNode = get_node_obj( elementNode );
1429 if(!xmlNode) {
1430 FIXME("elementNode is not our object\n");
1431 return E_FAIL;
1434 if(!xmlNode->node->parent)
1435 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1436 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1438 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1439 IXMLDOMNode_Release( elementNode );
1441 if(oldRoot)
1442 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1444 return S_OK;
1448 static HRESULT WINAPI domdoc_createElement(
1449 IXMLDOMDocument3 *iface,
1450 BSTR tagname,
1451 IXMLDOMElement** element )
1453 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1454 IXMLDOMNode *node;
1455 VARIANT type;
1456 HRESULT hr;
1458 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1460 if (!element || !tagname) return E_INVALIDARG;
1462 V_VT(&type) = VT_I1;
1463 V_I1(&type) = NODE_ELEMENT;
1465 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1466 if (hr == S_OK)
1468 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1469 IXMLDOMNode_Release(node);
1472 return hr;
1476 static HRESULT WINAPI domdoc_createDocumentFragment(
1477 IXMLDOMDocument3 *iface,
1478 IXMLDOMDocumentFragment** frag )
1480 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1481 IXMLDOMNode *node;
1482 VARIANT type;
1483 HRESULT hr;
1485 TRACE("(%p)->(%p)\n", This, frag);
1487 if (!frag) return E_INVALIDARG;
1489 *frag = NULL;
1491 V_VT(&type) = VT_I1;
1492 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1494 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1495 if (hr == S_OK)
1497 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1498 IXMLDOMNode_Release(node);
1501 return hr;
1505 static HRESULT WINAPI domdoc_createTextNode(
1506 IXMLDOMDocument3 *iface,
1507 BSTR data,
1508 IXMLDOMText** text )
1510 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1511 IXMLDOMNode *node;
1512 VARIANT type;
1513 HRESULT hr;
1515 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1517 if (!text) return E_INVALIDARG;
1519 *text = NULL;
1521 V_VT(&type) = VT_I1;
1522 V_I1(&type) = NODE_TEXT;
1524 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1525 if (hr == S_OK)
1527 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1528 IXMLDOMNode_Release(node);
1529 hr = IXMLDOMText_put_data(*text, data);
1532 return hr;
1536 static HRESULT WINAPI domdoc_createComment(
1537 IXMLDOMDocument3 *iface,
1538 BSTR data,
1539 IXMLDOMComment** comment )
1541 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1542 VARIANT type;
1543 HRESULT hr;
1544 IXMLDOMNode *node;
1546 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1548 if (!comment) return E_INVALIDARG;
1550 *comment = NULL;
1552 V_VT(&type) = VT_I1;
1553 V_I1(&type) = NODE_COMMENT;
1555 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1556 if (hr == S_OK)
1558 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1559 IXMLDOMNode_Release(node);
1560 hr = IXMLDOMComment_put_data(*comment, data);
1563 return hr;
1567 static HRESULT WINAPI domdoc_createCDATASection(
1568 IXMLDOMDocument3 *iface,
1569 BSTR data,
1570 IXMLDOMCDATASection** cdata )
1572 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1573 IXMLDOMNode *node;
1574 VARIANT type;
1575 HRESULT hr;
1577 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1579 if (!cdata) return E_INVALIDARG;
1581 *cdata = NULL;
1583 V_VT(&type) = VT_I1;
1584 V_I1(&type) = NODE_CDATA_SECTION;
1586 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1587 if (hr == S_OK)
1589 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1590 IXMLDOMNode_Release(node);
1591 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1594 return hr;
1598 static HRESULT WINAPI domdoc_createProcessingInstruction(
1599 IXMLDOMDocument3 *iface,
1600 BSTR target,
1601 BSTR data,
1602 IXMLDOMProcessingInstruction** pi )
1604 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1605 IXMLDOMNode *node;
1606 VARIANT type;
1607 HRESULT hr;
1609 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1611 if (!pi) return E_INVALIDARG;
1613 *pi = NULL;
1615 V_VT(&type) = VT_I1;
1616 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1618 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1619 if (hr == S_OK)
1621 xmlnode *node_obj;
1623 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1624 node_obj = get_node_obj(node);
1625 hr = node_set_content(node_obj, data);
1627 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1628 IXMLDOMNode_Release(node);
1631 return hr;
1635 static HRESULT WINAPI domdoc_createAttribute(
1636 IXMLDOMDocument3 *iface,
1637 BSTR name,
1638 IXMLDOMAttribute** attribute )
1640 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1641 IXMLDOMNode *node;
1642 VARIANT type;
1643 HRESULT hr;
1645 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1647 if (!attribute || !name) return E_INVALIDARG;
1649 V_VT(&type) = VT_I1;
1650 V_I1(&type) = NODE_ATTRIBUTE;
1652 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1653 if (hr == S_OK)
1655 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1656 IXMLDOMNode_Release(node);
1659 return hr;
1663 static HRESULT WINAPI domdoc_createEntityReference(
1664 IXMLDOMDocument3 *iface,
1665 BSTR name,
1666 IXMLDOMEntityReference** entityref )
1668 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1669 IXMLDOMNode *node;
1670 VARIANT type;
1671 HRESULT hr;
1673 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1675 if (!entityref) return E_INVALIDARG;
1677 *entityref = NULL;
1679 V_VT(&type) = VT_I1;
1680 V_I1(&type) = NODE_ENTITY_REFERENCE;
1682 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1683 if (hr == S_OK)
1685 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1686 IXMLDOMNode_Release(node);
1689 return hr;
1693 static HRESULT WINAPI domdoc_getElementsByTagName(
1694 IXMLDOMDocument3 *iface,
1695 BSTR tagName,
1696 IXMLDOMNodeList** resultList )
1698 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1699 HRESULT hr;
1701 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagName), resultList);
1703 if (!tagName || !resultList) return E_INVALIDARG;
1705 if (tagName[0] == '*' && tagName[1] == 0)
1707 static const WCHAR formatallW[] = {'/','/','*',0};
1708 hr = queryresult_create((xmlNodePtr)get_doc(This), formatallW, resultList);
1710 else
1712 static const WCHAR xpathformat[] =
1713 { '/','/','*','[','l','o','c','a','l','-','n','a','m','e','(',')','=','\'' };
1714 static const WCHAR closeW[] = { '\'',']',0 };
1716 LPWSTR pattern;
1717 WCHAR *ptr;
1718 INT length;
1720 length = lstrlenW(tagName);
1722 /* without two WCHARs from format specifier */
1723 ptr = pattern = heap_alloc(sizeof(xpathformat) + length*sizeof(WCHAR) + sizeof(closeW));
1725 memcpy(ptr, xpathformat, sizeof(xpathformat));
1726 ptr += sizeof(xpathformat)/sizeof(WCHAR);
1727 memcpy(ptr, tagName, length*sizeof(WCHAR));
1728 ptr += length;
1729 memcpy(ptr, closeW, sizeof(closeW));
1731 hr = queryresult_create((xmlNodePtr)get_doc(This), pattern, resultList);
1732 heap_free(pattern);
1735 return hr;
1738 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1740 VARIANT tmp;
1741 HRESULT hr;
1743 VariantInit(&tmp);
1744 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1745 if(FAILED(hr))
1746 return E_INVALIDARG;
1748 *type = V_I4(&tmp);
1750 return S_OK;
1753 static HRESULT WINAPI domdoc_createNode(
1754 IXMLDOMDocument3 *iface,
1755 VARIANT Type,
1756 BSTR name,
1757 BSTR namespaceURI,
1758 IXMLDOMNode** node )
1760 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1761 DOMNodeType node_type;
1762 xmlNodePtr xmlnode;
1763 xmlChar *xml_name, *href;
1764 HRESULT hr;
1766 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1768 if(!node) return E_INVALIDARG;
1770 hr = get_node_type(Type, &node_type);
1771 if(FAILED(hr)) return hr;
1773 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1774 FIXME("nodes with namespaces currently not supported.\n");
1776 TRACE("node_type %d\n", node_type);
1778 /* exit earlier for types that need name */
1779 switch(node_type)
1781 case NODE_ELEMENT:
1782 case NODE_ATTRIBUTE:
1783 case NODE_ENTITY_REFERENCE:
1784 case NODE_PROCESSING_INSTRUCTION:
1785 if (!name || *name == 0) return E_FAIL;
1786 default:
1787 break;
1790 xml_name = xmlChar_from_wchar(name);
1791 /* prevent empty href to be allocated */
1792 href = namespaceURI ? xmlChar_from_wchar(namespaceURI) : NULL;
1794 switch(node_type)
1796 case NODE_ELEMENT:
1798 xmlChar *local, *prefix;
1800 local = xmlSplitQName2(xml_name, &prefix);
1802 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
1804 /* allow to create default namespace xmlns= */
1805 if (local || (href && *href))
1807 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
1808 xmlSetNs(xmlnode, ns);
1811 xmlFree(local);
1812 xmlFree(prefix);
1814 break;
1816 case NODE_ATTRIBUTE:
1817 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1818 break;
1819 case NODE_TEXT:
1820 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1821 break;
1822 case NODE_CDATA_SECTION:
1823 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1824 break;
1825 case NODE_ENTITY_REFERENCE:
1826 xmlnode = xmlNewReference(get_doc(This), xml_name);
1827 break;
1828 case NODE_PROCESSING_INSTRUCTION:
1829 #ifdef HAVE_XMLNEWDOCPI
1830 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1831 #else
1832 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1833 xmlnode = NULL;
1834 #endif
1835 break;
1836 case NODE_COMMENT:
1837 xmlnode = xmlNewDocComment(get_doc(This), NULL);
1838 break;
1839 case NODE_DOCUMENT_FRAGMENT:
1840 xmlnode = xmlNewDocFragment(get_doc(This));
1841 break;
1842 /* unsupported types */
1843 case NODE_DOCUMENT:
1844 case NODE_DOCUMENT_TYPE:
1845 case NODE_ENTITY:
1846 case NODE_NOTATION:
1847 heap_free(xml_name);
1848 return E_INVALIDARG;
1849 default:
1850 FIXME("unhandled node type %d\n", node_type);
1851 xmlnode = NULL;
1852 break;
1855 *node = create_node(xmlnode);
1856 heap_free(xml_name);
1857 heap_free(href);
1859 if(*node)
1861 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1862 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1863 return S_OK;
1866 return E_FAIL;
1869 static HRESULT WINAPI domdoc_nodeFromID(
1870 IXMLDOMDocument3 *iface,
1871 BSTR idString,
1872 IXMLDOMNode** node )
1874 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1875 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1876 return E_NOTIMPL;
1879 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1881 domdoc *This = obj;
1882 xmlDocPtr xmldoc;
1884 xmldoc = doparse(This, ptr, len, NULL);
1885 if(xmldoc) {
1886 xmldoc->_private = create_priv();
1887 return attach_xmldoc(This, xmldoc);
1890 return S_OK;
1893 static HRESULT doread( domdoc *This, LPWSTR filename )
1895 bsc_t *bsc;
1896 HRESULT hr;
1898 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1899 if(FAILED(hr))
1900 return hr;
1902 if(This->bsc)
1903 detach_bsc(This->bsc);
1905 This->bsc = bsc;
1906 return S_OK;
1909 static HRESULT WINAPI domdoc_load(
1910 IXMLDOMDocument3 *iface,
1911 VARIANT xmlSource,
1912 VARIANT_BOOL* isSuccessful )
1914 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1915 LPWSTR filename = NULL;
1916 HRESULT hr = S_FALSE;
1917 IXMLDOMDocument3 *pNewDoc = NULL;
1918 IStream *pStream = NULL;
1919 xmlDocPtr xmldoc;
1921 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
1923 *isSuccessful = VARIANT_FALSE;
1925 assert( &This->node );
1927 switch( V_VT(&xmlSource) )
1929 case VT_BSTR:
1930 filename = V_BSTR(&xmlSource);
1931 break;
1932 case VT_UNKNOWN:
1933 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
1934 if(hr == S_OK)
1936 if(pNewDoc)
1938 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
1939 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1940 hr = attach_xmldoc(This, xmldoc);
1942 if(SUCCEEDED(hr))
1943 *isSuccessful = VARIANT_TRUE;
1945 return hr;
1948 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1949 if(hr == S_OK)
1951 IPersistStream *pDocStream;
1952 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1953 if(hr == S_OK)
1955 hr = IPersistStream_Load(pDocStream, pStream);
1956 IStream_Release(pStream);
1957 if(hr == S_OK)
1959 *isSuccessful = VARIANT_TRUE;
1961 TRACE("Using IStream to load Document\n");
1962 return S_OK;
1964 else
1966 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1969 else
1971 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1974 else
1976 /* ISequentialStream */
1977 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1979 break;
1980 default:
1981 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1984 TRACE("filename (%s)\n", debugstr_w(filename));
1986 if ( filename )
1988 hr = doread( This, filename );
1990 if ( FAILED(hr) )
1991 This->error = E_FAIL;
1992 else
1994 hr = This->error = S_OK;
1995 *isSuccessful = VARIANT_TRUE;
1999 if(!filename || FAILED(hr)) {
2000 xmldoc = xmlNewDoc(NULL);
2001 xmldoc->_private = create_priv();
2002 hr = attach_xmldoc(This, xmldoc);
2003 if(SUCCEEDED(hr))
2004 hr = S_FALSE;
2007 TRACE("ret (%d)\n", hr);
2009 return hr;
2013 static HRESULT WINAPI domdoc_get_readyState(
2014 IXMLDOMDocument3 *iface,
2015 LONG *value )
2017 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2018 FIXME("stub! (%p)->(%p)\n", This, value);
2020 if (!value)
2021 return E_INVALIDARG;
2023 *value = READYSTATE_COMPLETE;
2024 return S_OK;
2028 static HRESULT WINAPI domdoc_get_parseError(
2029 IXMLDOMDocument3 *iface,
2030 IXMLDOMParseError** errorObj )
2032 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2033 static const WCHAR err[] = {'e','r','r','o','r',0};
2034 BSTR error_string = NULL;
2036 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2038 if(This->error)
2039 error_string = SysAllocString(err);
2041 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2042 if(!*errorObj) return E_OUTOFMEMORY;
2043 return S_OK;
2047 static HRESULT WINAPI domdoc_get_url(
2048 IXMLDOMDocument3 *iface,
2049 BSTR* urlString )
2051 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2052 FIXME("(%p)->(%p)\n", This, urlString);
2053 return E_NOTIMPL;
2057 static HRESULT WINAPI domdoc_get_async(
2058 IXMLDOMDocument3 *iface,
2059 VARIANT_BOOL* isAsync )
2061 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2063 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2064 *isAsync = This->async;
2065 return S_OK;
2069 static HRESULT WINAPI domdoc_put_async(
2070 IXMLDOMDocument3 *iface,
2071 VARIANT_BOOL isAsync )
2073 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2075 TRACE("(%p)->(%d)\n", This, isAsync);
2076 This->async = isAsync;
2077 return S_OK;
2081 static HRESULT WINAPI domdoc_abort(
2082 IXMLDOMDocument3 *iface )
2084 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2085 FIXME("%p\n", This);
2086 return E_NOTIMPL;
2090 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
2092 UINT len;
2093 LPSTR str;
2095 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
2096 str = heap_alloc( len );
2097 if ( !str )
2098 return FALSE;
2099 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
2100 *plen = len;
2101 *pstr = str;
2102 return TRUE;
2105 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2106 static HRESULT WINAPI domdoc_loadXML(
2107 IXMLDOMDocument3 *iface,
2108 BSTR bstrXML,
2109 VARIANT_BOOL* isSuccessful )
2111 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2112 static const xmlChar encoding[] = "UTF-8";
2113 xmlDocPtr xmldoc = NULL;
2114 HRESULT hr = S_FALSE, hr2;
2115 char *str;
2116 int len;
2118 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2120 assert ( &This->node );
2122 if ( isSuccessful )
2124 *isSuccessful = VARIANT_FALSE;
2126 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
2128 xmldoc = doparse(This, str, len, encoding);
2129 heap_free( str );
2130 if ( !xmldoc )
2132 This->error = E_FAIL;
2133 TRACE("failed to parse document\n");
2135 else
2137 hr = This->error = S_OK;
2138 *isSuccessful = VARIANT_TRUE;
2139 TRACE("parsed document %p\n", xmldoc);
2143 if(!xmldoc)
2144 xmldoc = xmlNewDoc(NULL);
2146 xmldoc->_private = create_priv();
2148 hr2 = attach_xmldoc(This, xmldoc);
2149 if( FAILED(hr2) )
2150 hr = hr2;
2152 return hr;
2155 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2157 DWORD written = -1;
2159 if(!WriteFile(ctx, buffer, len, &written, NULL))
2161 WARN("write error\n");
2162 return -1;
2164 else
2165 return written;
2168 static int XMLCALL domdoc_save_closecallback(void *ctx)
2170 return CloseHandle(ctx) ? 0 : -1;
2173 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2175 ULONG written = 0;
2176 HRESULT hr;
2178 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2179 if (hr != S_OK)
2181 WARN("stream write error: 0x%08x\n", hr);
2182 return -1;
2184 else
2185 return written;
2188 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2190 IStream_Release((IStream*)ctx);
2191 return 0;
2194 static HRESULT WINAPI domdoc_save(
2195 IXMLDOMDocument3 *iface,
2196 VARIANT destination )
2198 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2199 xmlSaveCtxtPtr ctx = NULL;
2200 xmlNodePtr xmldecl;
2201 HRESULT ret = S_OK;
2203 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
2204 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
2206 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
2208 FIXME("Unhandled vt %d\n", V_VT(&destination));
2209 return S_FALSE;
2212 if(V_VT(&destination) == VT_UNKNOWN)
2214 IUnknown *pUnk = V_UNKNOWN(&destination);
2215 IXMLDOMDocument2 *document;
2216 IStream *stream;
2218 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2219 if(ret == S_OK)
2221 VARIANT_BOOL success;
2222 BSTR xml;
2224 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2225 if(ret == S_OK)
2227 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2228 SysFreeString(xml);
2231 IXMLDOMDocument3_Release(document);
2232 return ret;
2235 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2236 if(ret == S_OK)
2238 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2239 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2241 if(!ctx)
2243 IStream_Release(stream);
2244 return E_FAIL;
2248 else
2250 /* save with file path */
2251 HANDLE handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
2252 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2253 if( handle == INVALID_HANDLE_VALUE )
2255 WARN("failed to create file\n");
2256 return E_FAIL;
2259 /* disable top XML declaration */
2260 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2261 handle, NULL, XML_SAVE_NO_DECL);
2262 if (!ctx)
2264 CloseHandle(handle);
2265 return E_FAIL;
2269 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2270 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2271 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2273 /* will release resources through close callback */
2274 xmlSaveClose(ctx);
2276 return ret;
2279 static HRESULT WINAPI domdoc_get_validateOnParse(
2280 IXMLDOMDocument3 *iface,
2281 VARIANT_BOOL* isValidating )
2283 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2284 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2285 *isValidating = This->validating;
2286 return S_OK;
2290 static HRESULT WINAPI domdoc_put_validateOnParse(
2291 IXMLDOMDocument3 *iface,
2292 VARIANT_BOOL isValidating )
2294 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2295 TRACE("(%p)->(%d)\n", This, isValidating);
2296 This->validating = isValidating;
2297 return S_OK;
2301 static HRESULT WINAPI domdoc_get_resolveExternals(
2302 IXMLDOMDocument3 *iface,
2303 VARIANT_BOOL* isResolving )
2305 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2306 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2307 *isResolving = This->resolving;
2308 return S_OK;
2312 static HRESULT WINAPI domdoc_put_resolveExternals(
2313 IXMLDOMDocument3 *iface,
2314 VARIANT_BOOL isResolving )
2316 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2317 TRACE("(%p)->(%d)\n", This, isResolving);
2318 This->resolving = isResolving;
2319 return S_OK;
2323 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2324 IXMLDOMDocument3 *iface,
2325 VARIANT_BOOL* isPreserving )
2327 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2328 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->preserving);
2329 *isPreserving = This->preserving;
2330 return S_OK;
2334 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2335 IXMLDOMDocument3 *iface,
2336 VARIANT_BOOL isPreserving )
2338 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2339 TRACE("(%p)->(%d)\n", This, isPreserving);
2340 This->preserving = isPreserving;
2341 return S_OK;
2345 static HRESULT WINAPI domdoc_put_onReadyStateChange(
2346 IXMLDOMDocument3 *iface,
2347 VARIANT readyStateChangeSink )
2349 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2350 FIXME("%p\n", This);
2351 return E_NOTIMPL;
2355 static HRESULT WINAPI domdoc_put_onDataAvailable(
2356 IXMLDOMDocument3 *iface,
2357 VARIANT onDataAvailableSink )
2359 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2360 FIXME("%p\n", This);
2361 return E_NOTIMPL;
2364 static HRESULT WINAPI domdoc_put_onTransformNode(
2365 IXMLDOMDocument3 *iface,
2366 VARIANT onTransformNodeSink )
2368 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2369 FIXME("%p\n", This);
2370 return E_NOTIMPL;
2373 static HRESULT WINAPI domdoc_get_namespaces(
2374 IXMLDOMDocument3* iface,
2375 IXMLDOMSchemaCollection** schemaCollection )
2377 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2378 FIXME("(%p)->(%p)\n", This, schemaCollection);
2379 return E_NOTIMPL;
2382 static HRESULT WINAPI domdoc_get_schemas(
2383 IXMLDOMDocument3* iface,
2384 VARIANT* var1 )
2386 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2387 HRESULT hr = S_FALSE;
2388 IXMLDOMSchemaCollection *cur_schema = This->schema;
2390 TRACE("(%p)->(%p)\n", This, var1);
2392 VariantInit(var1); /* Test shows we don't call VariantClear here */
2393 V_VT(var1) = VT_NULL;
2395 if(cur_schema)
2397 hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2398 if(SUCCEEDED(hr))
2399 V_VT(var1) = VT_DISPATCH;
2401 return hr;
2404 static HRESULT WINAPI domdoc_putref_schemas(
2405 IXMLDOMDocument3* iface,
2406 VARIANT var1)
2408 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2409 HRESULT hr = E_FAIL;
2410 IXMLDOMSchemaCollection *new_schema = NULL;
2412 FIXME("(%p): semi-stub\n", This);
2413 switch(V_VT(&var1))
2415 case VT_UNKNOWN:
2416 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2417 break;
2419 case VT_DISPATCH:
2420 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2421 break;
2423 case VT_NULL:
2424 case VT_EMPTY:
2425 hr = S_OK;
2426 break;
2428 default:
2429 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2432 if(SUCCEEDED(hr))
2434 IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
2435 if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
2438 return hr;
2441 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2443 va_list ap;
2444 va_start(ap, msg);
2445 LIBXML2_CALLBACK_ERR(domdoc_validate, msg, ap);
2446 va_end(ap);
2449 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2451 va_list ap;
2452 va_start(ap, msg);
2453 LIBXML2_CALLBACK_WARN(domdoc_validate, msg, ap);
2454 va_end(ap);
2457 static HRESULT WINAPI domdoc_validate(
2458 IXMLDOMDocument3* iface,
2459 IXMLDOMParseError** err)
2461 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2462 LONG state;
2463 xmlValidCtxtPtr vctx;
2465 TRACE("(%p)->(%p)\n", This, err);
2466 domdoc_get_readyState(iface, &state);
2467 if (state != READYSTATE_COMPLETE)
2469 if (err)
2470 *err = create_parseError(0, NULL, NULL, NULL, 0, 0, 0);
2471 return E_PENDING;
2474 vctx = xmlNewValidCtxt();
2475 vctx->error = validate_error;
2476 vctx->warning = validate_warning;
2478 if (xmlValidateDocument(vctx, get_doc(This)))
2480 if (err)
2481 *err = create_parseError(0, NULL, NULL, NULL, 0, 0, 0);
2482 xmlFreeValidCtxt(vctx);
2483 return S_OK;
2486 FIXME("partial stub!\n");
2487 if (err)
2488 *err = create_parseError(0xC00CE223, NULL, NULL, NULL, 0, 0, 0);
2489 xmlFreeValidCtxt(vctx);
2490 return S_FALSE;
2493 static HRESULT WINAPI domdoc_setProperty(
2494 IXMLDOMDocument3* iface,
2495 BSTR p,
2496 VARIANT var)
2498 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2500 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2502 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2504 VARIANT varStr;
2505 HRESULT hr;
2506 BSTR bstr;
2508 V_VT(&varStr) = VT_EMPTY;
2509 if (V_VT(&var) != VT_BSTR)
2511 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2512 return hr;
2513 bstr = V_BSTR(&varStr);
2515 else
2516 bstr = V_BSTR(&var);
2518 hr = S_OK;
2519 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2520 This->properties->XPath = TRUE;
2521 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2522 This->properties->XPath = FALSE;
2523 else
2524 hr = E_FAIL;
2526 VariantClear(&varStr);
2527 return hr;
2529 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2531 VARIANT varStr;
2532 HRESULT hr;
2533 BSTR bstr;
2534 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2535 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2536 xmlXPathContextPtr ctx;
2537 struct list *pNsList;
2538 select_ns_entry* pNsEntry = NULL;
2540 V_VT(&varStr) = VT_EMPTY;
2541 if (V_VT(&var) != VT_BSTR)
2543 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2544 return hr;
2545 bstr = V_BSTR(&varStr);
2547 else
2548 bstr = V_BSTR(&var);
2550 hr = S_OK;
2552 pNsList = &(This->properties->selectNsList);
2553 clear_selectNsList(pNsList);
2554 heap_free(nsStr);
2555 nsStr = xmlChar_from_wchar(bstr);
2558 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2560 This->properties->selectNsStr = nsStr;
2561 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2562 if (bstr && *bstr)
2564 ctx = xmlXPathNewContext(This->node.node->doc);
2565 pTokBegin = nsStr;
2566 pTokEnd = nsStr;
2567 for (; *pTokBegin; pTokBegin = pTokEnd)
2569 if (pNsEntry != NULL)
2570 memset(pNsEntry, 0, sizeof(select_ns_entry));
2571 else
2572 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2574 while (*pTokBegin == ' ')
2575 ++pTokBegin;
2576 pTokEnd = pTokBegin;
2577 while (*pTokEnd != ' ' && *pTokEnd != 0)
2578 ++pTokEnd;
2580 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2582 hr = E_FAIL;
2583 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2584 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2585 continue;
2588 pTokBegin += 5;
2589 if (*pTokBegin == '=')
2591 /*valid for XSLPattern?*/
2592 FIXME("Setting default xmlns not supported - skipping.\n");
2593 pTokBegin = pTokEnd;
2594 continue;
2596 else if (*pTokBegin == ':')
2598 pNsEntry->prefix = ++pTokBegin;
2599 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2602 if (pTokInner == pTokEnd)
2604 hr = E_FAIL;
2605 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2606 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2607 continue;
2610 pNsEntry->prefix_end = *pTokInner;
2611 *pTokInner = 0;
2612 ++pTokInner;
2614 if (pTokEnd-pTokInner > 1 &&
2615 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2616 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2618 pNsEntry->href = ++pTokInner;
2619 pNsEntry->href_end = *(pTokEnd-1);
2620 *(pTokEnd-1) = 0;
2621 list_add_tail(pNsList, &pNsEntry->entry);
2622 /*let libxml figure out if they're valid from here ;)*/
2623 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2625 hr = E_FAIL;
2627 pNsEntry = NULL;
2628 continue;
2630 else
2632 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2633 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2634 list_add_tail(pNsList, &pNsEntry->entry);
2636 pNsEntry = NULL;
2637 hr = E_FAIL;
2638 continue;
2641 else
2643 hr = E_FAIL;
2644 continue;
2647 heap_free(pNsEntry);
2648 xmlXPathFreeContext(ctx);
2651 VariantClear(&varStr);
2652 return hr;
2654 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2655 lstrcmpiW(p, PropertyNewParserW) == 0)
2657 /* Ignore */
2658 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2659 return S_OK;
2662 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2663 return E_FAIL;
2666 static HRESULT WINAPI domdoc_getProperty(
2667 IXMLDOMDocument3* iface,
2668 BSTR p,
2669 VARIANT* var)
2671 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2673 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2675 if (!var)
2676 return E_INVALIDARG;
2678 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2680 V_VT(var) = VT_BSTR;
2681 V_BSTR(var) = This->properties->XPath ?
2682 SysAllocString(PropValueXPathW) :
2683 SysAllocString(PropValueXSLPatternW);
2684 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2686 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2688 int lenA, lenW;
2689 BSTR rebuiltStr, cur;
2690 const xmlChar *nsStr;
2691 struct list *pNsList;
2692 select_ns_entry* pNsEntry;
2694 V_VT(var) = VT_BSTR;
2695 nsStr = This->properties->selectNsStr;
2696 pNsList = &This->properties->selectNsList;
2697 lenA = This->properties->selectNsStr_len;
2698 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
2699 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
2700 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
2701 cur = rebuiltStr;
2702 /* this is fine because all of the chars that end tokens are ASCII*/
2703 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
2705 while (*cur != 0) ++cur;
2706 if (pNsEntry->prefix_end)
2708 *cur = pNsEntry->prefix_end;
2709 while (*cur != 0) ++cur;
2712 if (pNsEntry->href_end)
2714 *cur = pNsEntry->href_end;
2717 V_BSTR(var) = SysAllocString(rebuiltStr);
2718 heap_free(rebuiltStr);
2719 return S_OK;
2722 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2723 return E_FAIL;
2726 static HRESULT WINAPI domdoc_validateNode(
2727 IXMLDOMDocument3* iface,
2728 IXMLDOMNode* node,
2729 IXMLDOMParseError** error)
2731 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2732 FIXME("(%p)->(%p %p): stub\n", This, node, error);
2733 return E_NOTIMPL;
2736 static HRESULT WINAPI domdoc_importNode(
2737 IXMLDOMDocument3* iface,
2738 IXMLDOMNode* node,
2739 VARIANT_BOOL deep,
2740 IXMLDOMNode** clone)
2742 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2743 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
2744 return E_NOTIMPL;
2747 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
2749 domdoc_QueryInterface,
2750 domdoc_AddRef,
2751 domdoc_Release,
2752 domdoc_GetTypeInfoCount,
2753 domdoc_GetTypeInfo,
2754 domdoc_GetIDsOfNames,
2755 domdoc_Invoke,
2756 domdoc_get_nodeName,
2757 domdoc_get_nodeValue,
2758 domdoc_put_nodeValue,
2759 domdoc_get_nodeType,
2760 domdoc_get_parentNode,
2761 domdoc_get_childNodes,
2762 domdoc_get_firstChild,
2763 domdoc_get_lastChild,
2764 domdoc_get_previousSibling,
2765 domdoc_get_nextSibling,
2766 domdoc_get_attributes,
2767 domdoc_insertBefore,
2768 domdoc_replaceChild,
2769 domdoc_removeChild,
2770 domdoc_appendChild,
2771 domdoc_hasChildNodes,
2772 domdoc_get_ownerDocument,
2773 domdoc_cloneNode,
2774 domdoc_get_nodeTypeString,
2775 domdoc_get_text,
2776 domdoc_put_text,
2777 domdoc_get_specified,
2778 domdoc_get_definition,
2779 domdoc_get_nodeTypedValue,
2780 domdoc_put_nodeTypedValue,
2781 domdoc_get_dataType,
2782 domdoc_put_dataType,
2783 domdoc_get_xml,
2784 domdoc_transformNode,
2785 domdoc_selectNodes,
2786 domdoc_selectSingleNode,
2787 domdoc_get_parsed,
2788 domdoc_get_namespaceURI,
2789 domdoc_get_prefix,
2790 domdoc_get_baseName,
2791 domdoc_transformNodeToObject,
2792 domdoc_get_doctype,
2793 domdoc_get_implementation,
2794 domdoc_get_documentElement,
2795 domdoc_put_documentElement,
2796 domdoc_createElement,
2797 domdoc_createDocumentFragment,
2798 domdoc_createTextNode,
2799 domdoc_createComment,
2800 domdoc_createCDATASection,
2801 domdoc_createProcessingInstruction,
2802 domdoc_createAttribute,
2803 domdoc_createEntityReference,
2804 domdoc_getElementsByTagName,
2805 domdoc_createNode,
2806 domdoc_nodeFromID,
2807 domdoc_load,
2808 domdoc_get_readyState,
2809 domdoc_get_parseError,
2810 domdoc_get_url,
2811 domdoc_get_async,
2812 domdoc_put_async,
2813 domdoc_abort,
2814 domdoc_loadXML,
2815 domdoc_save,
2816 domdoc_get_validateOnParse,
2817 domdoc_put_validateOnParse,
2818 domdoc_get_resolveExternals,
2819 domdoc_put_resolveExternals,
2820 domdoc_get_preserveWhiteSpace,
2821 domdoc_put_preserveWhiteSpace,
2822 domdoc_put_onReadyStateChange,
2823 domdoc_put_onDataAvailable,
2824 domdoc_put_onTransformNode,
2825 domdoc_get_namespaces,
2826 domdoc_get_schemas,
2827 domdoc_putref_schemas,
2828 domdoc_validate,
2829 domdoc_setProperty,
2830 domdoc_getProperty,
2831 domdoc_validateNode,
2832 domdoc_importNode
2835 /* IConnectionPointContainer */
2836 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
2837 REFIID riid, void **ppv)
2839 domdoc *This = impl_from_IConnectionPointContainer(iface);
2840 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)This, riid, ppv);
2843 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
2845 domdoc *This = impl_from_IConnectionPointContainer(iface);
2846 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)This);
2849 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
2851 domdoc *This = impl_from_IConnectionPointContainer(iface);
2852 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)This);
2855 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
2856 IEnumConnectionPoints **ppEnum)
2858 domdoc *This = impl_from_IConnectionPointContainer(iface);
2859 FIXME("(%p)->(%p): stub\n", This, ppEnum);
2860 return E_NOTIMPL;
2863 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
2864 REFIID riid, IConnectionPoint **cp)
2866 domdoc *This = impl_from_IConnectionPointContainer(iface);
2867 ConnectionPoint *iter;
2869 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
2871 *cp = NULL;
2873 for(iter = This->cp_list; iter; iter = iter->next)
2875 if (IsEqualGUID(iter->iid, riid))
2876 *cp = (IConnectionPoint*)&iter->lpVtblConnectionPoint;
2879 if (*cp)
2881 IConnectionPoint_AddRef(*cp);
2882 return S_OK;
2885 FIXME("unsupported riid %s\n", debugstr_guid(riid));
2886 return CONNECT_E_NOCONNECTION;
2890 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
2892 ConnectionPointContainer_QueryInterface,
2893 ConnectionPointContainer_AddRef,
2894 ConnectionPointContainer_Release,
2895 ConnectionPointContainer_EnumConnectionPoints,
2896 ConnectionPointContainer_FindConnectionPoint
2899 /* IConnectionPoint */
2900 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
2901 REFIID riid, void **ppv)
2903 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2905 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
2907 *ppv = NULL;
2909 if (IsEqualGUID(&IID_IUnknown, riid) ||
2910 IsEqualGUID(&IID_IConnectionPoint, riid))
2912 *ppv = iface;
2915 if (*ppv)
2917 IConnectionPoint_AddRef(iface);
2918 return S_OK;
2921 WARN("Unsupported interface %s\n", debugstr_guid(riid));
2922 return E_NOINTERFACE;
2925 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
2927 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2928 return IConnectionPointContainer_AddRef(This->container);
2931 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
2933 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2934 return IConnectionPointContainer_Release(This->container);
2937 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
2939 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2941 TRACE("(%p)->(%p)\n", This, iid);
2943 if (!iid) return E_POINTER;
2945 *iid = *This->iid;
2946 return S_OK;
2949 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
2950 IConnectionPointContainer **container)
2952 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2954 TRACE("(%p)->(%p)\n", This, container);
2956 if (!container) return E_POINTER;
2958 *container = This->container;
2959 IConnectionPointContainer_AddRef(*container);
2960 return S_OK;
2963 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
2964 DWORD *pdwCookie)
2966 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2967 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
2968 return E_NOTIMPL;
2971 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
2973 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2975 TRACE("(%p)->(%d)\n", This, cookie);
2977 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
2978 return CONNECT_E_NOCONNECTION;
2980 IUnknown_Release(This->sinks[cookie-1].unk);
2981 This->sinks[cookie-1].unk = NULL;
2983 return S_OK;
2986 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
2987 IEnumConnections **ppEnum)
2989 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
2990 FIXME("(%p)->(%p): stub\n", This, ppEnum);
2991 return E_NOTIMPL;
2994 static const IConnectionPointVtbl ConnectionPointVtbl =
2996 ConnectionPoint_QueryInterface,
2997 ConnectionPoint_AddRef,
2998 ConnectionPoint_Release,
2999 ConnectionPoint_GetConnectionInterface,
3000 ConnectionPoint_GetConnectionPointContainer,
3001 ConnectionPoint_Advise,
3002 ConnectionPoint_Unadvise,
3003 ConnectionPoint_EnumConnections
3006 void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3008 cp->lpVtblConnectionPoint = &ConnectionPointVtbl;
3009 cp->doc = doc;
3010 cp->iid = riid;
3011 cp->sinks = NULL;
3012 cp->sinks_size = 0;
3014 cp->next = doc->cp_list;
3015 doc->cp_list = cp;
3017 cp->container = (IConnectionPointContainer*)&doc->lpVtblConnectionPointContainer;
3020 /* domdoc implementation of IObjectWithSite */
3021 static HRESULT WINAPI
3022 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3024 domdoc *This = impl_from_IObjectWithSite(iface);
3025 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppvObject );
3028 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3030 domdoc *This = impl_from_IObjectWithSite(iface);
3031 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3034 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3036 domdoc *This = impl_from_IObjectWithSite(iface);
3037 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3040 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3042 domdoc *This = impl_from_IObjectWithSite(iface);
3044 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3046 if ( !This->site )
3047 return E_FAIL;
3049 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3052 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3054 domdoc *This = impl_from_IObjectWithSite(iface);
3056 TRACE("(%p)->(%p)\n", iface, punk);
3058 if(!punk)
3060 if(This->site)
3062 IUnknown_Release( This->site );
3063 This->site = NULL;
3066 return S_OK;
3069 IUnknown_AddRef( punk );
3071 if(This->site)
3072 IUnknown_Release( This->site );
3074 This->site = punk;
3076 return S_OK;
3079 static const IObjectWithSiteVtbl domdocObjectSite =
3081 domdoc_ObjectWithSite_QueryInterface,
3082 domdoc_ObjectWithSite_AddRef,
3083 domdoc_ObjectWithSite_Release,
3084 domdoc_ObjectWithSite_SetSite,
3085 domdoc_ObjectWithSite_GetSite
3088 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3090 domdoc *This = impl_from_IObjectSafety(iface);
3091 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppv );
3094 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3096 domdoc *This = impl_from_IObjectSafety(iface);
3097 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3100 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3102 domdoc *This = impl_from_IObjectSafety(iface);
3103 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3106 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3108 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3109 DWORD *supported, DWORD *enabled)
3111 domdoc *This = impl_from_IObjectSafety(iface);
3113 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3115 if(!supported || !enabled) return E_POINTER;
3117 *supported = SAFETY_SUPPORTED_OPTIONS;
3118 *enabled = This->safeopt;
3120 return S_OK;
3123 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3124 DWORD mask, DWORD enabled)
3126 domdoc *This = impl_from_IObjectSafety(iface);
3127 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3129 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3130 return E_FAIL;
3132 This->safeopt = enabled & mask & SAFETY_SUPPORTED_OPTIONS;
3133 return S_OK;
3136 #undef SAFETY_SUPPORTED_OPTIONS
3138 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3139 domdoc_Safety_QueryInterface,
3140 domdoc_Safety_AddRef,
3141 domdoc_Safety_Release,
3142 domdoc_Safety_GetInterfaceSafetyOptions,
3143 domdoc_Safety_SetInterfaceSafetyOptions
3146 static const tid_t domdoc_iface_tids[] = {
3147 IXMLDOMNode_tid,
3148 IXMLDOMDocument_tid,
3149 IXMLDOMDocument2_tid,
3152 static dispex_static_data_t domdoc_dispex = {
3153 NULL,
3154 IXMLDOMDocument2_tid,
3155 NULL,
3156 domdoc_iface_tids
3159 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3161 domdoc *doc;
3163 doc = heap_alloc( sizeof (*doc) );
3164 if( !doc )
3165 return E_OUTOFMEMORY;
3167 doc->lpVtbl = &domdoc_vtbl;
3168 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
3169 doc->lpvtblIObjectWithSite = &domdocObjectSite;
3170 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
3171 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
3172 doc->lpVtblConnectionPointContainer = &ConnectionPointContainerVtbl;
3173 doc->ref = 1;
3174 doc->async = VARIANT_TRUE;
3175 doc->validating = 0;
3176 doc->resolving = 0;
3177 doc->preserving = 0;
3178 doc->properties = properties_from_xmlDocPtr(xmldoc);
3179 doc->error = S_OK;
3180 doc->schema = NULL;
3181 doc->stream = NULL;
3182 doc->site = NULL;
3183 doc->safeopt = 0;
3184 doc->bsc = NULL;
3185 doc->cp_list = NULL;
3187 /* events connection points */
3188 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3189 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3190 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3192 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->lpVtbl, &domdoc_dispex);
3194 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
3196 TRACE("returning iface %p\n", *document);
3197 return S_OK;
3200 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3202 xmlDocPtr xmldoc;
3203 HRESULT hr;
3205 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
3207 xmldoc = xmlNewDoc(NULL);
3208 if(!xmldoc)
3209 return E_OUTOFMEMORY;
3211 xmldoc->_private = create_priv();
3212 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
3214 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3215 if(FAILED(hr))
3217 free_properties(properties_from_xmlDocPtr(xmldoc));
3218 heap_free(xmldoc->_private);
3219 xmlFreeDoc(xmldoc);
3220 return hr;
3223 return hr;
3226 IUnknown* create_domdoc( xmlNodePtr document )
3228 void* pObj = NULL;
3229 HRESULT hr;
3231 TRACE("(%p)\n", document);
3233 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3234 if (FAILED(hr))
3235 return NULL;
3237 return pObj;
3240 #else
3242 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3244 MESSAGE("This program tried to use a DOMDocument object, but\n"
3245 "libxml2 support was not present at compile time.\n");
3246 return E_NOTIMPL;
3249 #endif