msxml3: Fix a few error messages.
[wine.git] / dlls / msxml3 / domdoc.c
blobe06b03d3ab26f883122d15206d0e166779fc7f9c
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 /* Anything that passes the test_get_ownerDocument()
74 * tests can go here (data shared between all instances).
75 * We need to preserve this when reloading a document,
76 * and also need access to it from the libxml backend. */
77 typedef struct _domdoc_properties {
78 VARIANT_BOOL preserving;
79 IXMLDOMSchemaCollection2* schemaCache;
80 struct list selectNsList;
81 xmlChar const* selectNsStr;
82 LONG selectNsStr_len;
83 BOOL XPath;
84 } domdoc_properties;
86 typedef struct ConnectionPoint ConnectionPoint;
87 typedef struct domdoc domdoc;
89 struct ConnectionPoint
91 const IConnectionPointVtbl *lpVtblConnectionPoint;
92 const IID *iid;
94 ConnectionPoint *next;
95 IConnectionPointContainer *container;
96 domdoc *doc;
98 union
100 IUnknown *unk;
101 IDispatch *disp;
102 IPropertyNotifySink *propnotif;
103 } *sinks;
104 DWORD sinks_size;
107 struct domdoc
109 xmlnode node;
110 const struct IXMLDOMDocument3Vtbl *lpVtbl;
111 const struct IPersistStreamInitVtbl *lpvtblIPersistStreamInit;
112 const struct IObjectWithSiteVtbl *lpvtblIObjectWithSite;
113 const struct IObjectSafetyVtbl *lpvtblIObjectSafety;
114 const struct ISupportErrorInfoVtbl *lpvtblISupportErrorInfo;
115 const struct IConnectionPointContainerVtbl *lpVtblConnectionPointContainer;
116 LONG ref;
117 VARIANT_BOOL async;
118 VARIANT_BOOL validating;
119 VARIANT_BOOL resolving;
120 domdoc_properties* properties;
121 bsc_t *bsc;
122 HRESULT error;
124 /* IPersistStream */
125 IStream *stream;
127 /* IObjectWithSite*/
128 IUnknown *site;
130 /* IObjectSafety */
131 DWORD safeopt;
133 /* connection list */
134 ConnectionPoint *cp_list;
135 ConnectionPoint cp_domdocevents;
136 ConnectionPoint cp_propnotif;
137 ConnectionPoint cp_dispatch;
140 static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface)
142 return (ConnectionPoint *)((char*)iface - FIELD_OFFSET(ConnectionPoint, lpVtblConnectionPoint));
146 In native windows, the whole lifetime management of XMLDOMNodes is
147 managed automatically using reference counts. Wine emulates that by
148 maintaining a reference count to the document that is increased for
149 each IXMLDOMNode pointer passed out for this document. If all these
150 pointers are gone, the document is unreachable and gets freed, that
151 is, all nodes in the tree of the document get freed.
153 You are able to create nodes that are associated to a document (in
154 fact, in msxml's XMLDOM model, all nodes are associated to a document),
155 but not in the tree of that document, for example using the createFoo
156 functions from IXMLDOMDocument. These nodes do not get cleaned up
157 by libxml, so we have to do it ourselves.
159 To catch these nodes, a list of "orphan nodes" is introduced.
160 It contains pointers to all roots of node trees that are
161 associated with the document without being part of the document
162 tree. All nodes with parent==NULL (except for the document root nodes)
163 should be in the orphan node list of their document. All orphan nodes
164 get freed together with the document itself.
167 typedef struct _xmldoc_priv {
168 LONG refs;
169 struct list orphans;
170 domdoc_properties* properties;
171 } xmldoc_priv;
173 typedef struct _orphan_entry {
174 struct list entry;
175 xmlNode * node;
176 } orphan_entry;
178 typedef struct _select_ns_entry {
179 struct list entry;
180 xmlChar const* prefix;
181 xmlChar prefix_end;
182 xmlChar const* href;
183 xmlChar href_end;
184 } select_ns_entry;
186 static inline xmldoc_priv * priv_from_xmlDocPtr(const xmlDocPtr doc)
188 return doc->_private;
191 static inline domdoc_properties * properties_from_xmlDocPtr(xmlDocPtr doc)
193 return priv_from_xmlDocPtr(doc)->properties;
196 BOOL is_xpathmode(const xmlDocPtr doc)
198 return properties_from_xmlDocPtr(doc)->XPath;
201 void set_xpathmode(xmlDocPtr doc, BOOL xpath)
203 properties_from_xmlDocPtr(doc)->XPath = xpath;
206 int registerNamespaces(xmlXPathContextPtr ctxt)
208 int n = 0;
209 const select_ns_entry* ns = NULL;
210 const struct list* pNsList = &properties_from_xmlDocPtr(ctxt->doc)->selectNsList;
212 TRACE("(%p)\n", ctxt);
214 LIST_FOR_EACH_ENTRY( ns, pNsList, select_ns_entry, entry )
216 xmlXPathRegisterNs(ctxt, ns->prefix, ns->href);
217 ++n;
220 return n;
223 static inline void clear_selectNsList(struct list* pNsList)
225 select_ns_entry *ns, *ns2;
226 LIST_FOR_EACH_ENTRY_SAFE( ns, ns2, pNsList, select_ns_entry, entry )
228 heap_free( ns );
230 list_init(pNsList);
233 static xmldoc_priv * create_priv(void)
235 xmldoc_priv *priv;
236 priv = heap_alloc( sizeof (*priv) );
238 if (priv)
240 priv->refs = 0;
241 list_init( &priv->orphans );
242 priv->properties = NULL;
245 return priv;
248 static domdoc_properties * create_properties(const GUID *clsid)
250 domdoc_properties *properties = heap_alloc(sizeof(domdoc_properties));
252 list_init( &properties->selectNsList );
253 properties->preserving = VARIANT_FALSE;
254 properties->schemaCache = NULL;
255 properties->selectNsStr = heap_alloc_zero(sizeof(xmlChar));
256 properties->selectNsStr_len = 0;
258 /* properties that are dependent on object versions */
259 if (IsEqualCLSID( clsid, &CLSID_DOMDocument40 ) ||
260 IsEqualCLSID( clsid, &CLSID_DOMDocument60 ))
262 properties->XPath = TRUE;
264 else
266 properties->XPath = FALSE;
269 return properties;
272 static domdoc_properties* copy_properties(domdoc_properties const* properties)
274 domdoc_properties* pcopy = heap_alloc(sizeof(domdoc_properties));
275 select_ns_entry const* ns = NULL;
276 select_ns_entry* new_ns = NULL;
277 int len = (properties->selectNsStr_len+1)*sizeof(xmlChar);
278 ptrdiff_t offset;
280 if (pcopy)
282 pcopy->preserving = properties->preserving;
283 pcopy->schemaCache = properties->schemaCache;
284 pcopy->XPath = properties->XPath;
285 pcopy->selectNsStr_len = properties->selectNsStr_len;
286 list_init( &pcopy->selectNsList );
287 pcopy->selectNsStr = heap_alloc(len);
288 memcpy((xmlChar*)pcopy->selectNsStr, properties->selectNsStr, len);
289 offset = pcopy->selectNsStr - properties->selectNsStr;
291 LIST_FOR_EACH_ENTRY( ns, (&properties->selectNsList), select_ns_entry, entry )
293 new_ns = heap_alloc(sizeof(select_ns_entry));
294 memcpy(new_ns, ns, sizeof(select_ns_entry));
295 new_ns->href += offset;
296 new_ns->prefix += offset;
297 list_add_tail(&pcopy->selectNsList, &new_ns->entry);
302 return pcopy;
305 static void free_properties(domdoc_properties* properties)
307 if (properties)
309 if (properties->schemaCache)
310 IXMLDOMSchemaCollection2_Release(properties->schemaCache);
311 clear_selectNsList(&properties->selectNsList);
312 heap_free((xmlChar*)properties->selectNsStr);
313 heap_free(properties);
317 static BOOL xmldoc_has_decl(xmlDocPtr doc)
319 return doc->children && (xmlStrEqual(doc->children->name, (xmlChar*)"xml") == 1);
322 /* links a "<?xml" node as a first child */
323 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
325 assert(doc != NULL);
326 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
329 /* unlinks a first "<?xml" child if it was created */
330 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
332 xmlNodePtr node;
334 assert(doc != NULL);
336 if (doc->standalone != -1)
338 node = doc->children;
339 xmlUnlinkNode( node );
341 else
342 node = NULL;
344 return node;
347 BOOL is_preserving_whitespace(xmlNodePtr node)
349 domdoc_properties* properties = NULL;
350 /* during parsing the xmlDoc._private stuff is not there */
351 if (priv_from_xmlDocPtr(node->doc))
352 properties = properties_from_xmlDocPtr(node->doc);
353 return ((properties && properties->preserving == VARIANT_TRUE) ||
354 xmlNodeGetSpacePreserve(node) == 1);
357 static inline BOOL strn_isspace(xmlChar const* str, int len)
359 for (; str && len > 0 && *str; ++str, --len)
360 if (!isspace(*str))
361 break;
363 return len == 0;
366 static void sax_characters(void *ctx, const xmlChar *ch, int len)
368 xmlParserCtxtPtr pctx;
369 domdoc const* This;
371 pctx = (xmlParserCtxtPtr) ctx;
372 This = (domdoc const*) pctx->_private;
374 /* during domdoc_loadXML() the xmlDocPtr->_private data is not available */
375 if (!This->properties->preserving &&
376 !is_preserving_whitespace(pctx->node) &&
377 strn_isspace(ch, len))
378 return;
380 xmlSAX2Characters(ctx, ch, len);
383 static void LIBXML2_LOG_CALLBACK sax_error(void* ctx, char const* msg, ...)
385 va_list ap;
386 va_start(ap, msg);
387 LIBXML2_CALLBACK_ERR(doparse, msg, ap);
388 va_end(ap);
391 static void LIBXML2_LOG_CALLBACK sax_warning(void* ctx, char const* msg, ...)
393 va_list ap;
394 va_start(ap, msg);
395 LIBXML2_CALLBACK_WARN(doparse, msg, ap);
396 va_end(ap);
399 static void sax_serror(void* ctx, xmlErrorPtr err)
401 LIBXML2_CALLBACK_SERROR(doparse, err);
404 static xmlDocPtr doparse(domdoc* This, char *ptr, int len, xmlChar const* encoding)
406 xmlDocPtr doc = NULL;
407 xmlParserCtxtPtr pctx;
408 static xmlSAXHandler sax_handler = {
409 xmlSAX2InternalSubset, /* internalSubset */
410 xmlSAX2IsStandalone, /* isStandalone */
411 xmlSAX2HasInternalSubset, /* hasInternalSubset */
412 xmlSAX2HasExternalSubset, /* hasExternalSubset */
413 xmlSAX2ResolveEntity, /* resolveEntity */
414 xmlSAX2GetEntity, /* getEntity */
415 xmlSAX2EntityDecl, /* entityDecl */
416 xmlSAX2NotationDecl, /* notationDecl */
417 xmlSAX2AttributeDecl, /* attributeDecl */
418 xmlSAX2ElementDecl, /* elementDecl */
419 xmlSAX2UnparsedEntityDecl, /* unparsedEntityDecl */
420 xmlSAX2SetDocumentLocator, /* setDocumentLocator */
421 xmlSAX2StartDocument, /* startDocument */
422 xmlSAX2EndDocument, /* endDocument */
423 xmlSAX2StartElement, /* startElement */
424 xmlSAX2EndElement, /* endElement */
425 xmlSAX2Reference, /* reference */
426 sax_characters, /* characters */
427 sax_characters, /* ignorableWhitespace */
428 xmlSAX2ProcessingInstruction, /* processingInstruction */
429 xmlSAX2Comment, /* comment */
430 sax_warning, /* warning */
431 sax_error, /* error */
432 sax_error, /* fatalError */
433 xmlSAX2GetParameterEntity, /* getParameterEntity */
434 xmlSAX2CDataBlock, /* cdataBlock */
435 xmlSAX2ExternalSubset, /* externalSubset */
436 0, /* initialized */
437 NULL, /* _private */
438 xmlSAX2StartElementNs, /* startElementNs */
439 xmlSAX2EndElementNs, /* endElementNs */
440 sax_serror /* serror */
442 xmlInitParser();
444 pctx = xmlCreateMemoryParserCtxt(ptr, len);
445 if (!pctx)
447 ERR("Failed to create parser context\n");
448 return NULL;
451 if (pctx->sax) xmlFree(pctx->sax);
452 pctx->sax = &sax_handler;
453 pctx->_private = This;
454 pctx->recovery = 0;
455 pctx->encoding = xmlStrdup(encoding);
456 xmlParseDocument(pctx);
458 if (pctx->wellFormed)
460 doc = pctx->myDoc;
462 else
464 xmlFreeDoc(pctx->myDoc);
465 pctx->myDoc = NULL;
467 pctx->sax = NULL;
468 xmlFreeParserCtxt(pctx);
470 /* TODO: put this in one of the SAX callbacks */
471 /* create first child as a <?xml...?> */
472 if (doc && doc->standalone != -1)
474 xmlNodePtr node;
475 char buff[30];
476 xmlChar *xmlbuff = (xmlChar*)buff;
478 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
480 /* version attribute can't be omitted */
481 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
482 xmlNodeAddContent( node, xmlbuff );
484 if (doc->encoding)
486 sprintf(buff, " encoding=\"%s\"", doc->encoding);
487 xmlNodeAddContent( node, xmlbuff );
490 if (doc->standalone != -2)
492 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
493 xmlNodeAddContent( node, xmlbuff );
496 xmldoc_link_xmldecl( doc, node );
499 return doc;
502 void xmldoc_init(xmlDocPtr doc, const GUID *clsid)
504 doc->_private = create_priv();
505 priv_from_xmlDocPtr(doc)->properties = create_properties(clsid);
508 LONG xmldoc_add_ref(xmlDocPtr doc)
510 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
511 TRACE("(%p)->(%d)\n", doc, ref);
512 return ref;
515 LONG xmldoc_release(xmlDocPtr doc)
517 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
518 LONG ref = InterlockedDecrement(&priv->refs);
519 TRACE("(%p)->(%d)\n", doc, ref);
520 if(ref == 0)
522 orphan_entry *orphan, *orphan2;
523 TRACE("freeing docptr %p\n", doc);
525 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
527 xmlFreeNode( orphan->node );
528 heap_free( orphan );
530 free_properties(priv->properties);
531 heap_free(doc->_private);
533 xmlFreeDoc(doc);
536 return ref;
539 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
541 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
542 orphan_entry *entry;
544 entry = heap_alloc( sizeof (*entry) );
545 if(!entry)
546 return E_OUTOFMEMORY;
548 entry->node = node;
549 list_add_head( &priv->orphans, &entry->entry );
550 return S_OK;
553 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
555 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
556 orphan_entry *entry, *entry2;
558 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
560 if( entry->node == node )
562 list_remove( &entry->entry );
563 heap_free( entry );
564 return S_OK;
568 return S_FALSE;
571 static inline xmlDocPtr get_doc( domdoc *This )
573 return (xmlDocPtr)This->node.node;
576 static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
578 if(This->node.node)
580 priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
581 if (xmldoc_release(get_doc(This)) != 0)
582 priv_from_xmlDocPtr(get_doc(This))->properties =
583 copy_properties(This->properties);
586 This->node.node = (xmlNodePtr) xml;
588 if(This->node.node)
590 xmldoc_add_ref(get_doc(This));
591 priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
594 return S_OK;
597 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
599 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
602 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
604 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStreamInit));
607 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
609 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
612 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
614 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
617 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
619 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblISupportErrorInfo));
622 static inline domdoc *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
624 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtblConnectionPointContainer));
627 /************************************************************************
628 * domdoc implementation of IPersistStream.
630 static HRESULT WINAPI domdoc_IPersistStreamInit_QueryInterface(
631 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
633 domdoc *this = impl_from_IPersistStreamInit(iface);
634 return IXMLDOMDocument2_QueryInterface((IXMLDOMDocument2 *)this, riid, ppvObj);
637 static ULONG WINAPI domdoc_IPersistStreamInit_AddRef(
638 IPersistStreamInit *iface)
640 domdoc *this = impl_from_IPersistStreamInit(iface);
641 return IXMLDOMDocument2_AddRef((IXMLDOMDocument2 *)this);
644 static ULONG WINAPI domdoc_IPersistStreamInit_Release(
645 IPersistStreamInit *iface)
647 domdoc *this = impl_from_IPersistStreamInit(iface);
648 return IXMLDOMDocument2_Release((IXMLDOMDocument2 *)this);
651 static HRESULT WINAPI domdoc_IPersistStreamInit_GetClassID(
652 IPersistStreamInit *iface, CLSID *classid)
654 TRACE("(%p,%p): stub!\n", iface, classid);
656 if(!classid)
657 return E_POINTER;
659 *classid = CLSID_DOMDocument2;
661 return S_OK;
664 static HRESULT WINAPI domdoc_IPersistStreamInit_IsDirty(
665 IPersistStreamInit *iface)
667 domdoc *This = impl_from_IPersistStreamInit(iface);
668 FIXME("(%p): stub!\n", This);
669 return S_FALSE;
672 static HRESULT WINAPI domdoc_IPersistStreamInit_Load(
673 IPersistStreamInit *iface, LPSTREAM pStm)
675 domdoc *This = impl_from_IPersistStreamInit(iface);
676 HRESULT hr;
677 HGLOBAL hglobal;
678 DWORD read, written, len;
679 BYTE buf[4096];
680 char *ptr;
681 xmlDocPtr xmldoc = NULL;
683 TRACE("(%p)->(%p)\n", This, pStm);
685 if (!pStm)
686 return E_INVALIDARG;
688 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
689 if (FAILED(hr))
690 return hr;
694 IStream_Read(pStm, buf, sizeof(buf), &read);
695 hr = IStream_Write(This->stream, buf, read, &written);
696 } while(SUCCEEDED(hr) && written != 0 && read != 0);
698 if (FAILED(hr))
700 ERR("Failed to copy stream\n");
701 return hr;
704 hr = GetHGlobalFromStream(This->stream, &hglobal);
705 if (FAILED(hr))
706 return hr;
708 len = GlobalSize(hglobal);
709 ptr = GlobalLock(hglobal);
710 if (len != 0)
711 xmldoc = doparse(This, ptr, len, NULL);
712 GlobalUnlock(hglobal);
714 if (!xmldoc)
716 ERR("Failed to parse xml\n");
717 return E_FAIL;
720 xmldoc->_private = create_priv();
722 return attach_xmldoc(This, xmldoc);
725 static HRESULT WINAPI domdoc_IPersistStreamInit_Save(
726 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
728 domdoc *This = impl_from_IPersistStreamInit(iface);
729 BSTR xmlString;
730 HRESULT hr;
732 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
734 hr = IXMLDOMDocument3_get_xml( (IXMLDOMDocument3*)&This->lpVtbl, &xmlString );
735 if(hr == S_OK)
737 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
739 hr = IStream_Write( stream, xmlString, len, NULL );
740 SysFreeString(xmlString);
743 TRACE("ret 0x%08x\n", hr);
745 return hr;
748 static HRESULT WINAPI domdoc_IPersistStreamInit_GetSizeMax(
749 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
751 domdoc *This = impl_from_IPersistStreamInit(iface);
752 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
753 return E_NOTIMPL;
756 static HRESULT WINAPI domdoc_IPersistStreamInit_InitNew(
757 IPersistStreamInit *iface)
759 domdoc *This = impl_from_IPersistStreamInit(iface);
760 TRACE("(%p)\n", This);
761 return S_OK;
764 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
766 domdoc_IPersistStreamInit_QueryInterface,
767 domdoc_IPersistStreamInit_AddRef,
768 domdoc_IPersistStreamInit_Release,
769 domdoc_IPersistStreamInit_GetClassID,
770 domdoc_IPersistStreamInit_IsDirty,
771 domdoc_IPersistStreamInit_Load,
772 domdoc_IPersistStreamInit_Save,
773 domdoc_IPersistStreamInit_GetSizeMax,
774 domdoc_IPersistStreamInit_InitNew
777 /* ISupportErrorInfo interface */
778 static HRESULT WINAPI support_error_QueryInterface(
779 ISupportErrorInfo *iface,
780 REFIID riid, void** ppvObj )
782 domdoc *This = impl_from_ISupportErrorInfo(iface);
783 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3 *)This, riid, ppvObj);
786 static ULONG WINAPI support_error_AddRef(
787 ISupportErrorInfo *iface )
789 domdoc *This = impl_from_ISupportErrorInfo(iface);
790 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
793 static ULONG WINAPI support_error_Release(
794 ISupportErrorInfo *iface )
796 domdoc *This = impl_from_ISupportErrorInfo(iface);
797 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
800 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
801 ISupportErrorInfo *iface,
802 REFIID riid )
804 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
805 return S_FALSE;
808 static const struct ISupportErrorInfoVtbl support_error_vtbl =
810 support_error_QueryInterface,
811 support_error_AddRef,
812 support_error_Release,
813 support_error_InterfaceSupportsErrorInfo
816 /* IXMLDOMDocument2 interface */
817 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
819 domdoc *This = impl_from_IXMLDOMDocument3( iface );
821 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
823 *ppvObject = NULL;
825 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
826 IsEqualGUID( riid, &IID_IDispatch ) ||
827 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
828 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
829 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
830 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
832 *ppvObject = iface;
834 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
835 IsEqualGUID(&IID_IPersistStreamInit, riid))
837 *ppvObject = &(This->lpvtblIPersistStreamInit);
839 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
841 *ppvObject = &(This->lpvtblIObjectWithSite);
843 else if (IsEqualGUID(&IID_IObjectSafety, riid))
845 *ppvObject = &(This->lpvtblIObjectSafety);
847 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
849 *ppvObject = &This->lpvtblISupportErrorInfo;
851 else if(node_query_interface(&This->node, riid, ppvObject))
853 return *ppvObject ? S_OK : E_NOINTERFACE;
855 else if (IsEqualGUID( riid, &IID_IConnectionPointContainer ))
857 *ppvObject = &This->lpVtblConnectionPointContainer;
859 else if(IsEqualGUID(&IID_IRunnableObject, riid))
861 TRACE("IID_IRunnableObject not supported returning NULL\n");
862 return E_NOINTERFACE;
864 else
866 FIXME("interface %s not implemented\n", debugstr_guid(riid));
867 return E_NOINTERFACE;
870 IUnknown_AddRef((IUnknown*)*ppvObject);
872 return S_OK;
876 static ULONG WINAPI domdoc_AddRef(
877 IXMLDOMDocument3 *iface )
879 domdoc *This = impl_from_IXMLDOMDocument3( iface );
880 ULONG ref = InterlockedIncrement( &This->ref );
881 TRACE("(%p)->(%d)\n", This, ref );
882 return ref;
886 static ULONG WINAPI domdoc_Release(
887 IXMLDOMDocument3 *iface )
889 domdoc *This = impl_from_IXMLDOMDocument3( iface );
890 LONG ref = InterlockedDecrement( &This->ref );
892 TRACE("(%p)->(%d)\n", This, ref );
894 if ( ref == 0 )
896 if(This->bsc)
897 detach_bsc(This->bsc);
899 if (This->site)
900 IUnknown_Release( This->site );
901 destroy_xmlnode(&This->node);
902 if (This->stream)
903 IStream_Release(This->stream);
904 heap_free(This);
907 return ref;
910 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
912 domdoc *This = impl_from_IXMLDOMDocument3( iface );
914 TRACE("(%p)->(%p)\n", This, pctinfo);
916 *pctinfo = 1;
918 return S_OK;
921 static HRESULT WINAPI domdoc_GetTypeInfo(
922 IXMLDOMDocument3 *iface,
923 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
925 domdoc *This = impl_from_IXMLDOMDocument3( iface );
926 HRESULT hr;
928 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
930 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
932 return hr;
935 static HRESULT WINAPI domdoc_GetIDsOfNames(
936 IXMLDOMDocument3 *iface,
937 REFIID riid,
938 LPOLESTR* rgszNames,
939 UINT cNames,
940 LCID lcid,
941 DISPID* rgDispId)
943 domdoc *This = impl_from_IXMLDOMDocument3( iface );
944 ITypeInfo *typeinfo;
945 HRESULT hr;
947 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
948 lcid, rgDispId);
950 if(!rgszNames || cNames == 0 || !rgDispId)
951 return E_INVALIDARG;
953 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
954 if(SUCCEEDED(hr))
956 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
957 ITypeInfo_Release(typeinfo);
960 return hr;
964 static HRESULT WINAPI domdoc_Invoke(
965 IXMLDOMDocument3 *iface,
966 DISPID dispIdMember,
967 REFIID riid,
968 LCID lcid,
969 WORD wFlags,
970 DISPPARAMS* pDispParams,
971 VARIANT* pVarResult,
972 EXCEPINFO* pExcepInfo,
973 UINT* puArgErr)
975 domdoc *This = impl_from_IXMLDOMDocument3( iface );
976 ITypeInfo *typeinfo;
977 HRESULT hr;
979 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
980 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
982 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
983 if(SUCCEEDED(hr))
985 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
986 pVarResult, pExcepInfo, puArgErr);
987 ITypeInfo_Release(typeinfo);
990 return hr;
994 static HRESULT WINAPI domdoc_get_nodeName(
995 IXMLDOMDocument3 *iface,
996 BSTR* name )
998 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1000 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
1002 TRACE("(%p)->(%p)\n", This, name);
1004 return return_bstr(documentW, name);
1008 static HRESULT WINAPI domdoc_get_nodeValue(
1009 IXMLDOMDocument3 *iface,
1010 VARIANT* value )
1012 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1014 TRACE("(%p)->(%p)\n", This, value);
1016 if(!value)
1017 return E_INVALIDARG;
1019 V_VT(value) = VT_NULL;
1020 V_BSTR(value) = NULL; /* tests show that we should do this */
1021 return S_FALSE;
1025 static HRESULT WINAPI domdoc_put_nodeValue(
1026 IXMLDOMDocument3 *iface,
1027 VARIANT value)
1029 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1030 TRACE("(%p)->(v%d)\n", This, V_VT(&value));
1031 return E_FAIL;
1035 static HRESULT WINAPI domdoc_get_nodeType(
1036 IXMLDOMDocument3 *iface,
1037 DOMNodeType* type )
1039 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1041 TRACE("(%p)->(%p)\n", This, type);
1043 *type = NODE_DOCUMENT;
1044 return S_OK;
1048 static HRESULT WINAPI domdoc_get_parentNode(
1049 IXMLDOMDocument3 *iface,
1050 IXMLDOMNode** parent )
1052 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1054 TRACE("(%p)->(%p)\n", This, parent);
1056 return node_get_parent(&This->node, parent);
1060 static HRESULT WINAPI domdoc_get_childNodes(
1061 IXMLDOMDocument3 *iface,
1062 IXMLDOMNodeList** childList )
1064 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1066 TRACE("(%p)->(%p)\n", This, childList);
1068 return node_get_child_nodes(&This->node, childList);
1072 static HRESULT WINAPI domdoc_get_firstChild(
1073 IXMLDOMDocument3 *iface,
1074 IXMLDOMNode** firstChild )
1076 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1078 TRACE("(%p)->(%p)\n", This, firstChild);
1080 return node_get_first_child(&This->node, firstChild);
1084 static HRESULT WINAPI domdoc_get_lastChild(
1085 IXMLDOMDocument3 *iface,
1086 IXMLDOMNode** lastChild )
1088 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1090 TRACE("(%p)->(%p)\n", This, lastChild);
1092 return node_get_last_child(&This->node, lastChild);
1096 static HRESULT WINAPI domdoc_get_previousSibling(
1097 IXMLDOMDocument3 *iface,
1098 IXMLDOMNode** previousSibling )
1100 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1102 TRACE("(%p)->(%p)\n", This, previousSibling);
1104 return return_null_node(previousSibling);
1108 static HRESULT WINAPI domdoc_get_nextSibling(
1109 IXMLDOMDocument3 *iface,
1110 IXMLDOMNode** nextSibling )
1112 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1114 TRACE("(%p)->(%p)\n", This, nextSibling);
1116 return return_null_node(nextSibling);
1120 static HRESULT WINAPI domdoc_get_attributes(
1121 IXMLDOMDocument3 *iface,
1122 IXMLDOMNamedNodeMap** attributeMap )
1124 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1126 TRACE("(%p)->(%p)\n", This, attributeMap);
1128 return return_null_ptr((void**)attributeMap);
1132 static HRESULT WINAPI domdoc_insertBefore(
1133 IXMLDOMDocument3 *iface,
1134 IXMLDOMNode* newChild,
1135 VARIANT refChild,
1136 IXMLDOMNode** outNewChild )
1138 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1140 TRACE("(%p)->(%p x%d %p)\n", This, newChild, V_VT(&refChild), outNewChild);
1142 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1146 static HRESULT WINAPI domdoc_replaceChild(
1147 IXMLDOMDocument3 *iface,
1148 IXMLDOMNode* newChild,
1149 IXMLDOMNode* oldChild,
1150 IXMLDOMNode** outOldChild)
1152 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1154 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1156 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1160 static HRESULT WINAPI domdoc_removeChild(
1161 IXMLDOMDocument3 *iface,
1162 IXMLDOMNode* childNode,
1163 IXMLDOMNode** oldChild)
1165 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1166 return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), childNode, oldChild );
1170 static HRESULT WINAPI domdoc_appendChild(
1171 IXMLDOMDocument3 *iface,
1172 IXMLDOMNode* newChild,
1173 IXMLDOMNode** outNewChild)
1175 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1176 return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newChild, outNewChild );
1180 static HRESULT WINAPI domdoc_hasChildNodes(
1181 IXMLDOMDocument3 *iface,
1182 VARIANT_BOOL* hasChild)
1184 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1185 return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), hasChild );
1189 static HRESULT WINAPI domdoc_get_ownerDocument(
1190 IXMLDOMDocument3 *iface,
1191 IXMLDOMDocument** DOMDocument)
1193 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1194 return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), DOMDocument );
1198 static HRESULT WINAPI domdoc_cloneNode(
1199 IXMLDOMDocument3 *iface,
1200 VARIANT_BOOL deep,
1201 IXMLDOMNode** outNode)
1203 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1204 TRACE("(%p)->(%d %p)\n", This, deep, outNode);
1205 return node_clone( &This->node, deep, outNode );
1209 static HRESULT WINAPI domdoc_get_nodeTypeString(
1210 IXMLDOMDocument3 *iface,
1211 BSTR *p)
1213 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1214 static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
1216 TRACE("(%p)->(%p)\n", This, p);
1218 return return_bstr(documentW, p);
1222 static HRESULT WINAPI domdoc_get_text(
1223 IXMLDOMDocument3 *iface,
1224 BSTR* text )
1226 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1227 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), text );
1231 static HRESULT WINAPI domdoc_put_text(
1232 IXMLDOMDocument3 *iface,
1233 BSTR text )
1235 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1236 TRACE("(%p)->(%s)\n", This, debugstr_w(text));
1237 return E_FAIL;
1241 static HRESULT WINAPI domdoc_get_specified(
1242 IXMLDOMDocument3 *iface,
1243 VARIANT_BOOL* isSpecified )
1245 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1246 FIXME("(%p)->(%p) stub!\n", This, isSpecified);
1247 *isSpecified = VARIANT_TRUE;
1248 return S_OK;
1252 static HRESULT WINAPI domdoc_get_definition(
1253 IXMLDOMDocument3 *iface,
1254 IXMLDOMNode** definitionNode )
1256 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1257 FIXME("(%p)->(%p)\n", This, definitionNode);
1258 return E_NOTIMPL;
1262 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1263 IXMLDOMDocument3 *iface,
1264 VARIANT* typedValue )
1266 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1267 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
1270 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1271 IXMLDOMDocument3 *iface,
1272 VARIANT typedValue )
1274 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1275 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
1279 static HRESULT WINAPI domdoc_get_dataType(
1280 IXMLDOMDocument3 *iface,
1281 VARIANT* typename )
1283 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1284 TRACE("(%p)->(%p)\n", This, typename);
1285 return return_null_var( typename );
1289 static HRESULT WINAPI domdoc_put_dataType(
1290 IXMLDOMDocument3 *iface,
1291 BSTR dataTypeName )
1293 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1294 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
1297 static int XMLCALL domdoc_get_xml_writecallback(void *ctx, const char *data, int len)
1299 return xmlBufferAdd((xmlBufferPtr)ctx, (xmlChar*)data, len) == 0 ? len : 0;
1302 static HRESULT WINAPI domdoc_get_xml(
1303 IXMLDOMDocument3 *iface,
1304 BSTR* p)
1306 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1307 xmlSaveCtxtPtr ctxt;
1308 xmlBufferPtr buf;
1309 int options;
1310 long ret;
1312 TRACE("(%p)->(%p)\n", This, p);
1314 if(!p)
1315 return E_INVALIDARG;
1317 *p = NULL;
1319 buf = xmlBufferCreate();
1320 if(!buf)
1321 return E_OUTOFMEMORY;
1323 options = xmldoc_has_decl(get_doc(This)) ? XML_SAVE_NO_DECL : 0;
1324 options |= XML_SAVE_FORMAT;
1325 ctxt = xmlSaveToIO(domdoc_get_xml_writecallback, NULL, buf, "UTF-8", options);
1327 if(!ctxt)
1329 xmlBufferFree(buf);
1330 return E_OUTOFMEMORY;
1333 ret = xmlSaveDoc(ctxt, get_doc(This));
1334 /* flushes on close */
1335 xmlSaveClose(ctxt);
1337 TRACE("%ld, len=%d\n", ret, xmlBufferLength(buf));
1338 if(ret != -1 && xmlBufferLength(buf) > 0)
1340 BSTR content;
1342 content = bstr_from_xmlChar(xmlBufferContent(buf));
1343 content = EnsureCorrectEOL(content);
1345 *p = content;
1347 else
1349 *p = SysAllocStringLen(NULL, 0);
1352 xmlBufferFree(buf);
1354 return *p ? S_OK : E_OUTOFMEMORY;
1358 static HRESULT WINAPI domdoc_transformNode(
1359 IXMLDOMDocument3 *iface,
1360 IXMLDOMNode* styleSheet,
1361 BSTR* xmlString )
1363 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1364 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), styleSheet, xmlString );
1368 static HRESULT WINAPI domdoc_selectNodes(
1369 IXMLDOMDocument3 *iface,
1370 BSTR queryString,
1371 IXMLDOMNodeList** resultList )
1373 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1374 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), queryString, resultList );
1378 static HRESULT WINAPI domdoc_selectSingleNode(
1379 IXMLDOMDocument3 *iface,
1380 BSTR queryString,
1381 IXMLDOMNode** resultNode )
1383 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1384 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), queryString, resultNode );
1388 static HRESULT WINAPI domdoc_get_parsed(
1389 IXMLDOMDocument3 *iface,
1390 VARIANT_BOOL* isParsed )
1392 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1393 FIXME("(%p)->(%p) stub!\n", This, isParsed);
1394 *isParsed = VARIANT_TRUE;
1395 return S_OK;
1399 static HRESULT WINAPI domdoc_get_namespaceURI(
1400 IXMLDOMDocument3 *iface,
1401 BSTR* namespaceURI )
1403 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1404 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), namespaceURI );
1408 static HRESULT WINAPI domdoc_get_prefix(
1409 IXMLDOMDocument3 *iface,
1410 BSTR* prefix )
1412 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1413 TRACE("(%p)->(%p)\n", This, prefix);
1414 return return_null_bstr( prefix );
1418 static HRESULT WINAPI domdoc_get_baseName(
1419 IXMLDOMDocument3 *iface,
1420 BSTR* name )
1422 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1423 TRACE("(%p)->(%p)\n", This, name);
1424 return return_null_bstr( name );
1428 static HRESULT WINAPI domdoc_transformNodeToObject(
1429 IXMLDOMDocument3 *iface,
1430 IXMLDOMNode* stylesheet,
1431 VARIANT outputObject)
1433 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1434 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), stylesheet, outputObject );
1438 static HRESULT WINAPI domdoc_get_doctype(
1439 IXMLDOMDocument3 *iface,
1440 IXMLDOMDocumentType** documentType )
1442 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1443 FIXME("(%p)\n", This);
1444 return E_NOTIMPL;
1448 static HRESULT WINAPI domdoc_get_implementation(
1449 IXMLDOMDocument3 *iface,
1450 IXMLDOMImplementation** impl )
1452 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1454 TRACE("(%p)->(%p)\n", This, impl);
1456 if(!impl)
1457 return E_INVALIDARG;
1459 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1461 return S_OK;
1464 static HRESULT WINAPI domdoc_get_documentElement(
1465 IXMLDOMDocument3 *iface,
1466 IXMLDOMElement** DOMElement )
1468 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1469 IXMLDOMNode *element_node;
1470 xmlNodePtr root;
1471 HRESULT hr;
1473 TRACE("(%p)->(%p)\n", This, DOMElement);
1475 if(!DOMElement)
1476 return E_INVALIDARG;
1478 *DOMElement = NULL;
1480 root = xmlDocGetRootElement( get_doc(This) );
1481 if ( !root )
1482 return S_FALSE;
1484 element_node = create_node( root );
1485 if(!element_node) return S_FALSE;
1487 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1488 IXMLDOMNode_Release(element_node);
1490 return hr;
1494 static HRESULT WINAPI domdoc_put_documentElement(
1495 IXMLDOMDocument3 *iface,
1496 IXMLDOMElement* DOMElement )
1498 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1499 IXMLDOMNode *elementNode;
1500 xmlNodePtr oldRoot;
1501 xmlnode *xmlNode;
1502 HRESULT hr;
1504 TRACE("(%p)->(%p)\n", This, DOMElement);
1506 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1507 if(FAILED(hr))
1508 return hr;
1510 xmlNode = get_node_obj( elementNode );
1511 if(!xmlNode) {
1512 FIXME("elementNode is not our object\n");
1513 return E_FAIL;
1516 if(!xmlNode->node->parent)
1517 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1518 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1520 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1521 IXMLDOMNode_Release( elementNode );
1523 if(oldRoot)
1524 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1526 return S_OK;
1530 static HRESULT WINAPI domdoc_createElement(
1531 IXMLDOMDocument3 *iface,
1532 BSTR tagname,
1533 IXMLDOMElement** element )
1535 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1536 IXMLDOMNode *node;
1537 VARIANT type;
1538 HRESULT hr;
1540 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1542 if (!element || !tagname) return E_INVALIDARG;
1544 V_VT(&type) = VT_I1;
1545 V_I1(&type) = NODE_ELEMENT;
1547 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1548 if (hr == S_OK)
1550 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1551 IXMLDOMNode_Release(node);
1554 return hr;
1558 static HRESULT WINAPI domdoc_createDocumentFragment(
1559 IXMLDOMDocument3 *iface,
1560 IXMLDOMDocumentFragment** frag )
1562 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1563 IXMLDOMNode *node;
1564 VARIANT type;
1565 HRESULT hr;
1567 TRACE("(%p)->(%p)\n", This, frag);
1569 if (!frag) return E_INVALIDARG;
1571 *frag = NULL;
1573 V_VT(&type) = VT_I1;
1574 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1576 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1577 if (hr == S_OK)
1579 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1580 IXMLDOMNode_Release(node);
1583 return hr;
1587 static HRESULT WINAPI domdoc_createTextNode(
1588 IXMLDOMDocument3 *iface,
1589 BSTR data,
1590 IXMLDOMText** text )
1592 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1593 IXMLDOMNode *node;
1594 VARIANT type;
1595 HRESULT hr;
1597 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1599 if (!text) return E_INVALIDARG;
1601 *text = NULL;
1603 V_VT(&type) = VT_I1;
1604 V_I1(&type) = NODE_TEXT;
1606 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1607 if (hr == S_OK)
1609 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1610 IXMLDOMNode_Release(node);
1611 hr = IXMLDOMText_put_data(*text, data);
1614 return hr;
1618 static HRESULT WINAPI domdoc_createComment(
1619 IXMLDOMDocument3 *iface,
1620 BSTR data,
1621 IXMLDOMComment** comment )
1623 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1624 VARIANT type;
1625 HRESULT hr;
1626 IXMLDOMNode *node;
1628 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1630 if (!comment) return E_INVALIDARG;
1632 *comment = NULL;
1634 V_VT(&type) = VT_I1;
1635 V_I1(&type) = NODE_COMMENT;
1637 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1638 if (hr == S_OK)
1640 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1641 IXMLDOMNode_Release(node);
1642 hr = IXMLDOMComment_put_data(*comment, data);
1645 return hr;
1649 static HRESULT WINAPI domdoc_createCDATASection(
1650 IXMLDOMDocument3 *iface,
1651 BSTR data,
1652 IXMLDOMCDATASection** cdata )
1654 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1655 IXMLDOMNode *node;
1656 VARIANT type;
1657 HRESULT hr;
1659 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1661 if (!cdata) return E_INVALIDARG;
1663 *cdata = NULL;
1665 V_VT(&type) = VT_I1;
1666 V_I1(&type) = NODE_CDATA_SECTION;
1668 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1669 if (hr == S_OK)
1671 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1672 IXMLDOMNode_Release(node);
1673 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1676 return hr;
1680 static HRESULT WINAPI domdoc_createProcessingInstruction(
1681 IXMLDOMDocument3 *iface,
1682 BSTR target,
1683 BSTR data,
1684 IXMLDOMProcessingInstruction** pi )
1686 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1687 IXMLDOMNode *node;
1688 VARIANT type;
1689 HRESULT hr;
1691 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1693 if (!pi) return E_INVALIDARG;
1695 *pi = NULL;
1697 V_VT(&type) = VT_I1;
1698 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1700 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1701 if (hr == S_OK)
1703 xmlnode *node_obj;
1705 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1706 node_obj = get_node_obj(node);
1707 hr = node_set_content(node_obj, data);
1709 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1710 IXMLDOMNode_Release(node);
1713 return hr;
1717 static HRESULT WINAPI domdoc_createAttribute(
1718 IXMLDOMDocument3 *iface,
1719 BSTR name,
1720 IXMLDOMAttribute** attribute )
1722 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1723 IXMLDOMNode *node;
1724 VARIANT type;
1725 HRESULT hr;
1727 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1729 if (!attribute || !name) return E_INVALIDARG;
1731 V_VT(&type) = VT_I1;
1732 V_I1(&type) = NODE_ATTRIBUTE;
1734 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1735 if (hr == S_OK)
1737 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1738 IXMLDOMNode_Release(node);
1741 return hr;
1745 static HRESULT WINAPI domdoc_createEntityReference(
1746 IXMLDOMDocument3 *iface,
1747 BSTR name,
1748 IXMLDOMEntityReference** entityref )
1750 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1751 IXMLDOMNode *node;
1752 VARIANT type;
1753 HRESULT hr;
1755 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1757 if (!entityref) return E_INVALIDARG;
1759 *entityref = NULL;
1761 V_VT(&type) = VT_I1;
1762 V_I1(&type) = NODE_ENTITY_REFERENCE;
1764 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1765 if (hr == S_OK)
1767 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1768 IXMLDOMNode_Release(node);
1771 return hr;
1774 xmlChar* tagName_to_XPath(const BSTR tagName)
1776 xmlChar *query, *tmp;
1777 static const xmlChar mod_pre[] = "*[local-name()='";
1778 static const xmlChar mod_post[] = "']";
1779 static const xmlChar prefix[] = "descendant::";
1780 const WCHAR *tokBegin, *tokEnd;
1781 int len;
1783 query = xmlStrdup(prefix);
1785 tokBegin = tagName;
1786 while (tokBegin && *tokBegin)
1788 switch (*tokBegin)
1790 case '/':
1791 query = xmlStrcat(query, BAD_CAST "/");
1792 ++tokBegin;
1793 break;
1794 case '*':
1795 query = xmlStrcat(query, BAD_CAST "*");
1796 ++tokBegin;
1797 break;
1798 default:
1799 query = xmlStrcat(query, mod_pre);
1800 tokEnd = tokBegin;
1801 while (*tokEnd && *tokEnd != '/')
1802 ++tokEnd;
1803 len = WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, NULL, 0, NULL, NULL);
1804 tmp = xmlMalloc(len);
1805 WideCharToMultiByte(CP_UTF8, 0, tokBegin, tokEnd-tokBegin, (char*)tmp, len, NULL, NULL);
1806 query = xmlStrncat(query, tmp, len);
1807 xmlFree(tmp);
1808 tokBegin = tokEnd;
1809 query = xmlStrcat(query, mod_post);
1813 return query;
1816 static HRESULT WINAPI domdoc_getElementsByTagName(
1817 IXMLDOMDocument3 *iface,
1818 BSTR tagName,
1819 IXMLDOMNodeList** resultList )
1821 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1822 xmlChar *query;
1823 HRESULT hr;
1824 BOOL XPath;
1826 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1828 if (!tagName || !resultList) return E_INVALIDARG;
1830 XPath = This->properties->XPath;
1831 This->properties->XPath = TRUE;
1832 query = tagName_to_XPath(tagName);
1833 hr = queryresult_create((xmlNodePtr)get_doc(This), query, resultList);
1834 xmlFree(query);
1835 This->properties->XPath = XPath;
1837 return hr;
1840 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1842 VARIANT tmp;
1843 HRESULT hr;
1845 VariantInit(&tmp);
1846 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1847 if(FAILED(hr))
1848 return E_INVALIDARG;
1850 *type = V_I4(&tmp);
1852 return S_OK;
1855 static HRESULT WINAPI domdoc_createNode(
1856 IXMLDOMDocument3 *iface,
1857 VARIANT Type,
1858 BSTR name,
1859 BSTR namespaceURI,
1860 IXMLDOMNode** node )
1862 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1863 DOMNodeType node_type;
1864 xmlNodePtr xmlnode;
1865 xmlChar *xml_name, *href;
1866 HRESULT hr;
1868 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1870 if(!node) return E_INVALIDARG;
1872 hr = get_node_type(Type, &node_type);
1873 if(FAILED(hr)) return hr;
1875 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1876 FIXME("nodes with namespaces currently not supported.\n");
1878 TRACE("node_type %d\n", node_type);
1880 /* exit earlier for types that need name */
1881 switch(node_type)
1883 case NODE_ELEMENT:
1884 case NODE_ATTRIBUTE:
1885 case NODE_ENTITY_REFERENCE:
1886 case NODE_PROCESSING_INSTRUCTION:
1887 if (!name || *name == 0) return E_FAIL;
1888 default:
1889 break;
1892 xml_name = xmlChar_from_wchar(name);
1893 /* prevent empty href to be allocated */
1894 href = namespaceURI ? xmlChar_from_wchar(namespaceURI) : NULL;
1896 switch(node_type)
1898 case NODE_ELEMENT:
1900 xmlChar *local, *prefix;
1902 local = xmlSplitQName2(xml_name, &prefix);
1904 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
1906 /* allow to create default namespace xmlns= */
1907 if (local || (href && *href))
1909 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
1910 xmlSetNs(xmlnode, ns);
1913 xmlFree(local);
1914 xmlFree(prefix);
1916 break;
1918 case NODE_ATTRIBUTE:
1919 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1920 break;
1921 case NODE_TEXT:
1922 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1923 break;
1924 case NODE_CDATA_SECTION:
1925 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1926 break;
1927 case NODE_ENTITY_REFERENCE:
1928 xmlnode = xmlNewReference(get_doc(This), xml_name);
1929 break;
1930 case NODE_PROCESSING_INSTRUCTION:
1931 #ifdef HAVE_XMLNEWDOCPI
1932 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1933 #else
1934 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1935 xmlnode = NULL;
1936 #endif
1937 break;
1938 case NODE_COMMENT:
1939 xmlnode = xmlNewDocComment(get_doc(This), NULL);
1940 break;
1941 case NODE_DOCUMENT_FRAGMENT:
1942 xmlnode = xmlNewDocFragment(get_doc(This));
1943 break;
1944 /* unsupported types */
1945 case NODE_DOCUMENT:
1946 case NODE_DOCUMENT_TYPE:
1947 case NODE_ENTITY:
1948 case NODE_NOTATION:
1949 heap_free(xml_name);
1950 return E_INVALIDARG;
1951 default:
1952 FIXME("unhandled node type %d\n", node_type);
1953 xmlnode = NULL;
1954 break;
1957 *node = create_node(xmlnode);
1958 heap_free(xml_name);
1959 heap_free(href);
1961 if(*node)
1963 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1964 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1965 return S_OK;
1968 return E_FAIL;
1971 static HRESULT WINAPI domdoc_nodeFromID(
1972 IXMLDOMDocument3 *iface,
1973 BSTR idString,
1974 IXMLDOMNode** node )
1976 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1977 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1978 return E_NOTIMPL;
1981 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1983 domdoc *This = obj;
1984 xmlDocPtr xmldoc;
1986 xmldoc = doparse(This, ptr, len, NULL);
1987 if(xmldoc) {
1988 xmldoc->_private = create_priv();
1989 return attach_xmldoc(This, xmldoc);
1992 return S_OK;
1995 static HRESULT doread( domdoc *This, LPWSTR filename )
1997 bsc_t *bsc;
1998 HRESULT hr;
2000 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
2001 if(FAILED(hr))
2002 return hr;
2004 if(This->bsc)
2005 detach_bsc(This->bsc);
2007 This->bsc = bsc;
2008 return S_OK;
2011 static HRESULT WINAPI domdoc_load(
2012 IXMLDOMDocument3 *iface,
2013 VARIANT xmlSource,
2014 VARIANT_BOOL* isSuccessful )
2016 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2017 LPWSTR filename = NULL;
2018 HRESULT hr = S_FALSE;
2019 IXMLDOMDocument3 *pNewDoc = NULL;
2020 IStream *pStream = NULL;
2021 xmlDocPtr xmldoc;
2023 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
2025 *isSuccessful = VARIANT_FALSE;
2027 assert( &This->node );
2029 switch( V_VT(&xmlSource) )
2031 case VT_BSTR:
2032 filename = V_BSTR(&xmlSource);
2033 break;
2034 case VT_UNKNOWN:
2035 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
2036 if(hr == S_OK)
2038 if(pNewDoc)
2040 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
2041 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
2042 hr = attach_xmldoc(This, xmldoc);
2044 if(SUCCEEDED(hr))
2045 *isSuccessful = VARIANT_TRUE;
2047 return hr;
2050 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
2051 if(hr == S_OK)
2053 IPersistStream *pDocStream;
2054 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
2055 if(hr == S_OK)
2057 hr = IPersistStream_Load(pDocStream, pStream);
2058 IStream_Release(pStream);
2059 if(hr == S_OK)
2061 *isSuccessful = VARIANT_TRUE;
2063 TRACE("Using IStream to load Document\n");
2064 return S_OK;
2066 else
2068 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
2071 else
2073 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
2076 else
2078 /* ISequentialStream */
2079 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
2081 break;
2082 default:
2083 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
2086 TRACE("filename (%s)\n", debugstr_w(filename));
2088 if ( filename )
2090 hr = doread( This, filename );
2092 if ( FAILED(hr) )
2093 This->error = E_FAIL;
2094 else
2096 hr = This->error = S_OK;
2097 *isSuccessful = VARIANT_TRUE;
2101 if(!filename || FAILED(hr)) {
2102 xmldoc = xmlNewDoc(NULL);
2103 xmldoc->_private = create_priv();
2104 hr = attach_xmldoc(This, xmldoc);
2105 if(SUCCEEDED(hr))
2106 hr = S_FALSE;
2109 TRACE("ret (%d)\n", hr);
2111 return hr;
2115 static HRESULT WINAPI domdoc_get_readyState(
2116 IXMLDOMDocument3 *iface,
2117 LONG *value )
2119 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2120 FIXME("stub! (%p)->(%p)\n", This, value);
2122 if (!value)
2123 return E_INVALIDARG;
2125 *value = READYSTATE_COMPLETE;
2126 return S_OK;
2130 static HRESULT WINAPI domdoc_get_parseError(
2131 IXMLDOMDocument3 *iface,
2132 IXMLDOMParseError** errorObj )
2134 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2135 static const WCHAR err[] = {'e','r','r','o','r',0};
2136 BSTR error_string = NULL;
2138 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
2140 if(This->error)
2141 error_string = SysAllocString(err);
2143 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
2144 if(!*errorObj) return E_OUTOFMEMORY;
2145 return S_OK;
2149 static HRESULT WINAPI domdoc_get_url(
2150 IXMLDOMDocument3 *iface,
2151 BSTR* urlString )
2153 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2154 FIXME("(%p)->(%p)\n", This, urlString);
2155 return E_NOTIMPL;
2159 static HRESULT WINAPI domdoc_get_async(
2160 IXMLDOMDocument3 *iface,
2161 VARIANT_BOOL* isAsync )
2163 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2165 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
2166 *isAsync = This->async;
2167 return S_OK;
2171 static HRESULT WINAPI domdoc_put_async(
2172 IXMLDOMDocument3 *iface,
2173 VARIANT_BOOL isAsync )
2175 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2177 TRACE("(%p)->(%d)\n", This, isAsync);
2178 This->async = isAsync;
2179 return S_OK;
2183 static HRESULT WINAPI domdoc_abort(
2184 IXMLDOMDocument3 *iface )
2186 domdoc *This = impl_from_IXMLDOMDocument3(iface);
2187 FIXME("%p\n", This);
2188 return E_NOTIMPL;
2192 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
2194 UINT len;
2195 LPSTR str;
2197 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
2198 str = heap_alloc( len );
2199 if ( !str )
2200 return FALSE;
2201 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
2202 *plen = len;
2203 *pstr = str;
2204 return TRUE;
2207 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2208 static HRESULT WINAPI domdoc_loadXML(
2209 IXMLDOMDocument3 *iface,
2210 BSTR bstrXML,
2211 VARIANT_BOOL* isSuccessful )
2213 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2214 static const xmlChar encoding[] = "UTF-8";
2215 xmlDocPtr xmldoc = NULL;
2216 HRESULT hr = S_FALSE, hr2;
2217 char *str;
2218 int len;
2220 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2222 assert ( &This->node );
2224 if ( isSuccessful )
2226 *isSuccessful = VARIANT_FALSE;
2228 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
2230 xmldoc = doparse(This, str, len, encoding);
2231 heap_free( str );
2232 if ( !xmldoc )
2234 This->error = E_FAIL;
2235 TRACE("failed to parse document\n");
2237 else
2239 hr = This->error = S_OK;
2240 *isSuccessful = VARIANT_TRUE;
2241 TRACE("parsed document %p\n", xmldoc);
2245 if(!xmldoc)
2246 xmldoc = xmlNewDoc(NULL);
2248 xmldoc->_private = create_priv();
2250 hr2 = attach_xmldoc(This, xmldoc);
2251 if( FAILED(hr2) )
2252 hr = hr2;
2254 return hr;
2257 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer, int len)
2259 DWORD written = -1;
2261 if(!WriteFile(ctx, buffer, len, &written, NULL))
2263 WARN("write error\n");
2264 return -1;
2266 else
2267 return written;
2270 static int XMLCALL domdoc_save_closecallback(void *ctx)
2272 return CloseHandle(ctx) ? 0 : -1;
2275 static int XMLCALL domdoc_stream_save_writecallback(void *ctx, const char *buffer, int len)
2277 ULONG written = 0;
2278 HRESULT hr;
2280 hr = IStream_Write((IStream*)ctx, buffer, len, &written);
2281 if (hr != S_OK)
2283 WARN("stream write error: 0x%08x\n", hr);
2284 return -1;
2286 else
2287 return written;
2290 static int XMLCALL domdoc_stream_save_closecallback(void *ctx)
2292 IStream_Release((IStream*)ctx);
2293 return 0;
2296 static HRESULT WINAPI domdoc_save(
2297 IXMLDOMDocument3 *iface,
2298 VARIANT destination )
2300 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2301 xmlSaveCtxtPtr ctx = NULL;
2302 xmlNodePtr xmldecl;
2303 HRESULT ret = S_OK;
2305 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
2306 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
2308 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
2310 FIXME("Unhandled vt %d\n", V_VT(&destination));
2311 return S_FALSE;
2314 if(V_VT(&destination) == VT_UNKNOWN)
2316 IUnknown *pUnk = V_UNKNOWN(&destination);
2317 IXMLDOMDocument2 *document;
2318 IStream *stream;
2320 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&document);
2321 if(ret == S_OK)
2323 VARIANT_BOOL success;
2324 BSTR xml;
2326 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2327 if(ret == S_OK)
2329 ret = IXMLDOMDocument3_loadXML(document, xml, &success);
2330 SysFreeString(xml);
2333 IXMLDOMDocument3_Release(document);
2334 return ret;
2337 ret = IUnknown_QueryInterface(pUnk, &IID_IStream, (void**)&stream);
2338 if(ret == S_OK)
2340 ctx = xmlSaveToIO(domdoc_stream_save_writecallback,
2341 domdoc_stream_save_closecallback, stream, NULL, XML_SAVE_NO_DECL);
2343 if(!ctx)
2345 IStream_Release(stream);
2346 return E_FAIL;
2350 else
2352 /* save with file path */
2353 HANDLE handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
2354 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2355 if( handle == INVALID_HANDLE_VALUE )
2357 WARN("failed to create file\n");
2358 return E_FAIL;
2361 /* disable top XML declaration */
2362 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2363 handle, NULL, XML_SAVE_NO_DECL);
2364 if (!ctx)
2366 CloseHandle(handle);
2367 return E_FAIL;
2371 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2372 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2373 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2375 /* will release resources through close callback */
2376 xmlSaveClose(ctx);
2378 return ret;
2381 static HRESULT WINAPI domdoc_get_validateOnParse(
2382 IXMLDOMDocument3 *iface,
2383 VARIANT_BOOL* isValidating )
2385 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2386 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2387 *isValidating = This->validating;
2388 return S_OK;
2392 static HRESULT WINAPI domdoc_put_validateOnParse(
2393 IXMLDOMDocument3 *iface,
2394 VARIANT_BOOL isValidating )
2396 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2397 TRACE("(%p)->(%d)\n", This, isValidating);
2398 This->validating = isValidating;
2399 return S_OK;
2403 static HRESULT WINAPI domdoc_get_resolveExternals(
2404 IXMLDOMDocument3 *iface,
2405 VARIANT_BOOL* isResolving )
2407 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2408 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2409 *isResolving = This->resolving;
2410 return S_OK;
2414 static HRESULT WINAPI domdoc_put_resolveExternals(
2415 IXMLDOMDocument3 *iface,
2416 VARIANT_BOOL isResolving )
2418 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2419 TRACE("(%p)->(%d)\n", This, isResolving);
2420 This->resolving = isResolving;
2421 return S_OK;
2425 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2426 IXMLDOMDocument3 *iface,
2427 VARIANT_BOOL* isPreserving )
2429 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2430 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->properties->preserving);
2431 *isPreserving = This->properties->preserving;
2432 return S_OK;
2436 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2437 IXMLDOMDocument3 *iface,
2438 VARIANT_BOOL isPreserving )
2440 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2441 TRACE("(%p)->(%d)\n", This, isPreserving);
2442 This->properties->preserving = isPreserving;
2443 return S_OK;
2447 static HRESULT WINAPI domdoc_put_onReadyStateChange(
2448 IXMLDOMDocument3 *iface,
2449 VARIANT readyStateChangeSink )
2451 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2452 FIXME("%p\n", This);
2453 return E_NOTIMPL;
2457 static HRESULT WINAPI domdoc_put_onDataAvailable(
2458 IXMLDOMDocument3 *iface,
2459 VARIANT onDataAvailableSink )
2461 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2462 FIXME("%p\n", This);
2463 return E_NOTIMPL;
2466 static HRESULT WINAPI domdoc_put_onTransformNode(
2467 IXMLDOMDocument3 *iface,
2468 VARIANT onTransformNodeSink )
2470 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2471 FIXME("%p\n", This);
2472 return E_NOTIMPL;
2475 static HRESULT WINAPI domdoc_get_namespaces(
2476 IXMLDOMDocument3* iface,
2477 IXMLDOMSchemaCollection** schemaCollection )
2479 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2480 FIXME("(%p)->(%p)\n", This, schemaCollection);
2481 return E_NOTIMPL;
2484 static HRESULT WINAPI domdoc_get_schemas(
2485 IXMLDOMDocument3* iface,
2486 VARIANT* var1 )
2488 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2489 HRESULT hr = S_FALSE;
2490 IXMLDOMSchemaCollection2* cur_schema = This->properties->schemaCache;
2492 TRACE("(%p)->(%p)\n", This, var1);
2494 VariantInit(var1); /* Test shows we don't call VariantClear here */
2495 V_VT(var1) = VT_NULL;
2497 if(cur_schema)
2499 hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2500 if(SUCCEEDED(hr))
2501 V_VT(var1) = VT_DISPATCH;
2503 return hr;
2506 static HRESULT WINAPI domdoc_putref_schemas(
2507 IXMLDOMDocument3* iface,
2508 VARIANT var1)
2510 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2511 HRESULT hr = E_FAIL;
2512 IXMLDOMSchemaCollection2* new_schema = NULL;
2514 FIXME("(%p): semi-stub\n", This);
2515 switch(V_VT(&var1))
2517 case VT_UNKNOWN:
2518 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2519 break;
2521 case VT_DISPATCH:
2522 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2523 break;
2525 case VT_NULL:
2526 case VT_EMPTY:
2527 hr = S_OK;
2528 break;
2530 default:
2531 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2534 if(SUCCEEDED(hr))
2536 IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->properties->schemaCache, new_schema);
2537 if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
2540 return hr;
2543 static inline BOOL is_wellformed(xmlDocPtr doc)
2545 #ifdef HAVE_XMLDOC_PROPERTIES
2546 return doc->properties & XML_DOC_WELLFORMED;
2547 #else
2548 /* Not a full check, but catches the worst violations */
2549 xmlNodePtr child;
2550 int root = 0;
2552 for (child = doc->children; child != NULL; child = child->next)
2554 switch (child->type)
2556 case XML_ELEMENT_NODE:
2557 if (++root > 1)
2558 return FALSE;
2559 break;
2560 case XML_TEXT_NODE:
2561 case XML_CDATA_SECTION_NODE:
2562 return FALSE;
2563 break;
2564 default:
2565 break;
2569 return root == 1;
2570 #endif
2573 static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
2575 va_list ap;
2576 va_start(ap, msg);
2577 LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
2578 va_end(ap);
2581 static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
2583 va_list ap;
2584 va_start(ap, msg);
2585 LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
2586 va_end(ap);
2589 static HRESULT WINAPI domdoc_validateNode(
2590 IXMLDOMDocument3* iface,
2591 IXMLDOMNode* node,
2592 IXMLDOMParseError** err)
2594 domdoc* This = impl_from_IXMLDOMDocument3(iface);
2595 LONG state, err_code = 0;
2596 HRESULT hr = S_OK;
2597 int validated = 0;
2599 TRACE("(%p)->(%p, %p)\n", This, node, err);
2600 domdoc_get_readyState(iface, &state);
2601 if (state != READYSTATE_COMPLETE)
2603 if (err)
2604 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2605 return E_PENDING;
2608 if (!node)
2610 if (err)
2611 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2612 return E_POINTER;
2615 if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
2617 if (err)
2618 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2619 return E_FAIL;
2622 if (!is_wellformed(get_doc(This)))
2624 ERR("doc not well-formed");
2625 if (err)
2626 *err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
2627 return S_FALSE;
2630 /* DTD validation */
2631 if (get_doc(This)->intSubset || get_doc(This)->extSubset)
2633 xmlValidCtxtPtr vctx = xmlNewValidCtxt();
2634 vctx->error = validate_error;
2635 vctx->warning = validate_warning;
2636 ++validated;
2638 if (!((node == (IXMLDOMNode*)iface)?
2639 xmlValidateDocument(vctx, get_doc(This)) :
2640 xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
2642 /* TODO: get a real error code here */
2643 TRACE("DTD validation failed\n");
2644 err_code = E_XML_INVALID;
2645 hr = S_FALSE;
2647 xmlFreeValidCtxt(vctx);
2650 /* Schema validation */
2651 if (hr == S_OK && This->properties->schemaCache != NULL)
2654 hr = SchemaCache_validate_tree(This->properties->schemaCache, get_node_obj(node)->node);
2655 if (!FAILED(hr))
2657 ++validated;
2658 /* TODO: get a real error code here */
2659 if (hr == S_OK)
2661 TRACE("schema validation succeeded\n");
2663 else
2665 ERR("schema validation failed\n");
2666 err_code = E_XML_INVALID;
2669 else
2671 /* not really OK, just didn't find a schema for the ns */
2672 hr = S_OK;
2676 if (!validated)
2678 ERR("no DTD or schema found\n");
2679 err_code = E_XML_NODTD;
2680 hr = S_FALSE;
2683 if (err)
2684 *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
2686 return hr;
2689 static HRESULT WINAPI domdoc_validate(
2690 IXMLDOMDocument3* iface,
2691 IXMLDOMParseError** err)
2693 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2694 TRACE("(%p)->(%p)\n", This, err);
2695 return domdoc_validateNode(iface, (IXMLDOMNode*)iface, err);
2698 static HRESULT WINAPI domdoc_setProperty(
2699 IXMLDOMDocument3* iface,
2700 BSTR p,
2701 VARIANT var)
2703 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2705 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2707 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2709 VARIANT varStr;
2710 HRESULT hr;
2711 BSTR bstr;
2713 V_VT(&varStr) = VT_EMPTY;
2714 if (V_VT(&var) != VT_BSTR)
2716 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2717 return hr;
2718 bstr = V_BSTR(&varStr);
2720 else
2721 bstr = V_BSTR(&var);
2723 hr = S_OK;
2724 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2725 This->properties->XPath = TRUE;
2726 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2727 This->properties->XPath = FALSE;
2728 else
2729 hr = E_FAIL;
2731 VariantClear(&varStr);
2732 return hr;
2734 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2736 VARIANT varStr;
2737 HRESULT hr;
2738 BSTR bstr;
2739 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2740 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2741 xmlXPathContextPtr ctx;
2742 struct list *pNsList;
2743 select_ns_entry* pNsEntry = NULL;
2745 V_VT(&varStr) = VT_EMPTY;
2746 if (V_VT(&var) != VT_BSTR)
2748 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2749 return hr;
2750 bstr = V_BSTR(&varStr);
2752 else
2753 bstr = V_BSTR(&var);
2755 hr = S_OK;
2757 pNsList = &(This->properties->selectNsList);
2758 clear_selectNsList(pNsList);
2759 heap_free(nsStr);
2760 nsStr = xmlChar_from_wchar(bstr);
2763 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2765 This->properties->selectNsStr = nsStr;
2766 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2767 if (bstr && *bstr)
2769 ctx = xmlXPathNewContext(This->node.node->doc);
2770 pTokBegin = nsStr;
2771 pTokEnd = nsStr;
2772 for (; *pTokBegin; pTokBegin = pTokEnd)
2774 if (pNsEntry != NULL)
2775 memset(pNsEntry, 0, sizeof(select_ns_entry));
2776 else
2777 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2779 while (*pTokBegin == ' ')
2780 ++pTokBegin;
2781 pTokEnd = pTokBegin;
2782 while (*pTokEnd != ' ' && *pTokEnd != 0)
2783 ++pTokEnd;
2785 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2787 hr = E_FAIL;
2788 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2789 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2790 continue;
2793 pTokBegin += 5;
2794 if (*pTokBegin == '=')
2796 /*valid for XSLPattern?*/
2797 FIXME("Setting default xmlns not supported - skipping.\n");
2798 pTokBegin = pTokEnd;
2799 continue;
2801 else if (*pTokBegin == ':')
2803 pNsEntry->prefix = ++pTokBegin;
2804 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2807 if (pTokInner == pTokEnd)
2809 hr = E_FAIL;
2810 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2811 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2812 continue;
2815 pNsEntry->prefix_end = *pTokInner;
2816 *pTokInner = 0;
2817 ++pTokInner;
2819 if (pTokEnd-pTokInner > 1 &&
2820 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2821 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2823 pNsEntry->href = ++pTokInner;
2824 pNsEntry->href_end = *(pTokEnd-1);
2825 *(pTokEnd-1) = 0;
2826 list_add_tail(pNsList, &pNsEntry->entry);
2827 /*let libxml figure out if they're valid from here ;)*/
2828 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2830 hr = E_FAIL;
2832 pNsEntry = NULL;
2833 continue;
2835 else
2837 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2838 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2839 list_add_tail(pNsList, &pNsEntry->entry);
2841 pNsEntry = NULL;
2842 hr = E_FAIL;
2843 continue;
2846 else
2848 hr = E_FAIL;
2849 continue;
2852 heap_free(pNsEntry);
2853 xmlXPathFreeContext(ctx);
2856 VariantClear(&varStr);
2857 return hr;
2859 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2860 lstrcmpiW(p, PropertyNewParserW) == 0)
2862 /* Ignore */
2863 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2864 return S_OK;
2867 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2868 return E_FAIL;
2871 static HRESULT WINAPI domdoc_getProperty(
2872 IXMLDOMDocument3* iface,
2873 BSTR p,
2874 VARIANT* var)
2876 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2878 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2880 if (!var)
2881 return E_INVALIDARG;
2883 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2885 V_VT(var) = VT_BSTR;
2886 V_BSTR(var) = This->properties->XPath ?
2887 SysAllocString(PropValueXPathW) :
2888 SysAllocString(PropValueXSLPatternW);
2889 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2891 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2893 int lenA, lenW;
2894 BSTR rebuiltStr, cur;
2895 const xmlChar *nsStr;
2896 struct list *pNsList;
2897 select_ns_entry* pNsEntry;
2899 V_VT(var) = VT_BSTR;
2900 nsStr = This->properties->selectNsStr;
2901 pNsList = &This->properties->selectNsList;
2902 lenA = This->properties->selectNsStr_len;
2903 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
2904 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
2905 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
2906 cur = rebuiltStr;
2907 /* this is fine because all of the chars that end tokens are ASCII*/
2908 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
2910 while (*cur != 0) ++cur;
2911 if (pNsEntry->prefix_end)
2913 *cur = pNsEntry->prefix_end;
2914 while (*cur != 0) ++cur;
2917 if (pNsEntry->href_end)
2919 *cur = pNsEntry->href_end;
2922 V_BSTR(var) = SysAllocString(rebuiltStr);
2923 heap_free(rebuiltStr);
2924 return S_OK;
2927 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2928 return E_FAIL;
2931 static HRESULT WINAPI domdoc_importNode(
2932 IXMLDOMDocument3* iface,
2933 IXMLDOMNode* node,
2934 VARIANT_BOOL deep,
2935 IXMLDOMNode** clone)
2937 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2938 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
2939 return E_NOTIMPL;
2942 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
2944 domdoc_QueryInterface,
2945 domdoc_AddRef,
2946 domdoc_Release,
2947 domdoc_GetTypeInfoCount,
2948 domdoc_GetTypeInfo,
2949 domdoc_GetIDsOfNames,
2950 domdoc_Invoke,
2951 domdoc_get_nodeName,
2952 domdoc_get_nodeValue,
2953 domdoc_put_nodeValue,
2954 domdoc_get_nodeType,
2955 domdoc_get_parentNode,
2956 domdoc_get_childNodes,
2957 domdoc_get_firstChild,
2958 domdoc_get_lastChild,
2959 domdoc_get_previousSibling,
2960 domdoc_get_nextSibling,
2961 domdoc_get_attributes,
2962 domdoc_insertBefore,
2963 domdoc_replaceChild,
2964 domdoc_removeChild,
2965 domdoc_appendChild,
2966 domdoc_hasChildNodes,
2967 domdoc_get_ownerDocument,
2968 domdoc_cloneNode,
2969 domdoc_get_nodeTypeString,
2970 domdoc_get_text,
2971 domdoc_put_text,
2972 domdoc_get_specified,
2973 domdoc_get_definition,
2974 domdoc_get_nodeTypedValue,
2975 domdoc_put_nodeTypedValue,
2976 domdoc_get_dataType,
2977 domdoc_put_dataType,
2978 domdoc_get_xml,
2979 domdoc_transformNode,
2980 domdoc_selectNodes,
2981 domdoc_selectSingleNode,
2982 domdoc_get_parsed,
2983 domdoc_get_namespaceURI,
2984 domdoc_get_prefix,
2985 domdoc_get_baseName,
2986 domdoc_transformNodeToObject,
2987 domdoc_get_doctype,
2988 domdoc_get_implementation,
2989 domdoc_get_documentElement,
2990 domdoc_put_documentElement,
2991 domdoc_createElement,
2992 domdoc_createDocumentFragment,
2993 domdoc_createTextNode,
2994 domdoc_createComment,
2995 domdoc_createCDATASection,
2996 domdoc_createProcessingInstruction,
2997 domdoc_createAttribute,
2998 domdoc_createEntityReference,
2999 domdoc_getElementsByTagName,
3000 domdoc_createNode,
3001 domdoc_nodeFromID,
3002 domdoc_load,
3003 domdoc_get_readyState,
3004 domdoc_get_parseError,
3005 domdoc_get_url,
3006 domdoc_get_async,
3007 domdoc_put_async,
3008 domdoc_abort,
3009 domdoc_loadXML,
3010 domdoc_save,
3011 domdoc_get_validateOnParse,
3012 domdoc_put_validateOnParse,
3013 domdoc_get_resolveExternals,
3014 domdoc_put_resolveExternals,
3015 domdoc_get_preserveWhiteSpace,
3016 domdoc_put_preserveWhiteSpace,
3017 domdoc_put_onReadyStateChange,
3018 domdoc_put_onDataAvailable,
3019 domdoc_put_onTransformNode,
3020 domdoc_get_namespaces,
3021 domdoc_get_schemas,
3022 domdoc_putref_schemas,
3023 domdoc_validate,
3024 domdoc_setProperty,
3025 domdoc_getProperty,
3026 domdoc_validateNode,
3027 domdoc_importNode
3030 /* IConnectionPointContainer */
3031 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
3032 REFIID riid, void **ppv)
3034 domdoc *This = impl_from_IConnectionPointContainer(iface);
3035 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3*)This, riid, ppv);
3038 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
3040 domdoc *This = impl_from_IConnectionPointContainer(iface);
3041 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3*)This);
3044 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
3046 domdoc *This = impl_from_IConnectionPointContainer(iface);
3047 return IXMLDOMDocument3_Release((IXMLDOMDocument3*)This);
3050 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
3051 IEnumConnectionPoints **ppEnum)
3053 domdoc *This = impl_from_IConnectionPointContainer(iface);
3054 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3055 return E_NOTIMPL;
3058 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
3059 REFIID riid, IConnectionPoint **cp)
3061 domdoc *This = impl_from_IConnectionPointContainer(iface);
3062 ConnectionPoint *iter;
3064 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), cp);
3066 *cp = NULL;
3068 for(iter = This->cp_list; iter; iter = iter->next)
3070 if (IsEqualGUID(iter->iid, riid))
3071 *cp = (IConnectionPoint*)&iter->lpVtblConnectionPoint;
3074 if (*cp)
3076 IConnectionPoint_AddRef(*cp);
3077 return S_OK;
3080 FIXME("unsupported riid %s\n", debugstr_guid(riid));
3081 return CONNECT_E_NOCONNECTION;
3085 static const struct IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
3087 ConnectionPointContainer_QueryInterface,
3088 ConnectionPointContainer_AddRef,
3089 ConnectionPointContainer_Release,
3090 ConnectionPointContainer_EnumConnectionPoints,
3091 ConnectionPointContainer_FindConnectionPoint
3094 /* IConnectionPoint */
3095 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
3096 REFIID riid, void **ppv)
3098 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3100 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv );
3102 *ppv = NULL;
3104 if (IsEqualGUID(&IID_IUnknown, riid) ||
3105 IsEqualGUID(&IID_IConnectionPoint, riid))
3107 *ppv = iface;
3110 if (*ppv)
3112 IConnectionPoint_AddRef(iface);
3113 return S_OK;
3116 WARN("Unsupported interface %s\n", debugstr_guid(riid));
3117 return E_NOINTERFACE;
3120 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
3122 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3123 return IConnectionPointContainer_AddRef(This->container);
3126 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
3128 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3129 return IConnectionPointContainer_Release(This->container);
3132 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *iid)
3134 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3136 TRACE("(%p)->(%p)\n", This, iid);
3138 if (!iid) return E_POINTER;
3140 *iid = *This->iid;
3141 return S_OK;
3144 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
3145 IConnectionPointContainer **container)
3147 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3149 TRACE("(%p)->(%p)\n", This, container);
3151 if (!container) return E_POINTER;
3153 *container = This->container;
3154 IConnectionPointContainer_AddRef(*container);
3155 return S_OK;
3158 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
3159 DWORD *pdwCookie)
3161 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3162 FIXME("(%p)->(%p %p): stub\n", This, pUnkSink, pdwCookie);
3163 return E_NOTIMPL;
3166 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD cookie)
3168 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3170 TRACE("(%p)->(%d)\n", This, cookie);
3172 if (cookie == 0 || cookie > This->sinks_size || !This->sinks[cookie-1].unk)
3173 return CONNECT_E_NOCONNECTION;
3175 IUnknown_Release(This->sinks[cookie-1].unk);
3176 This->sinks[cookie-1].unk = NULL;
3178 return S_OK;
3181 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
3182 IEnumConnections **ppEnum)
3184 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
3185 FIXME("(%p)->(%p): stub\n", This, ppEnum);
3186 return E_NOTIMPL;
3189 static const IConnectionPointVtbl ConnectionPointVtbl =
3191 ConnectionPoint_QueryInterface,
3192 ConnectionPoint_AddRef,
3193 ConnectionPoint_Release,
3194 ConnectionPoint_GetConnectionInterface,
3195 ConnectionPoint_GetConnectionPointContainer,
3196 ConnectionPoint_Advise,
3197 ConnectionPoint_Unadvise,
3198 ConnectionPoint_EnumConnections
3201 void ConnectionPoint_Init(ConnectionPoint *cp, struct domdoc *doc, REFIID riid)
3203 cp->lpVtblConnectionPoint = &ConnectionPointVtbl;
3204 cp->doc = doc;
3205 cp->iid = riid;
3206 cp->sinks = NULL;
3207 cp->sinks_size = 0;
3209 cp->next = doc->cp_list;
3210 doc->cp_list = cp;
3212 cp->container = (IConnectionPointContainer*)&doc->lpVtblConnectionPointContainer;
3215 /* domdoc implementation of IObjectWithSite */
3216 static HRESULT WINAPI
3217 domdoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
3219 domdoc *This = impl_from_IObjectWithSite(iface);
3220 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppvObject );
3223 static ULONG WINAPI domdoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
3225 domdoc *This = impl_from_IObjectWithSite(iface);
3226 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3229 static ULONG WINAPI domdoc_ObjectWithSite_Release( IObjectWithSite* iface )
3231 domdoc *This = impl_from_IObjectWithSite(iface);
3232 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3235 static HRESULT WINAPI domdoc_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
3237 domdoc *This = impl_from_IObjectWithSite(iface);
3239 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
3241 if ( !This->site )
3242 return E_FAIL;
3244 return IUnknown_QueryInterface( This->site, iid, ppvSite );
3247 static HRESULT WINAPI domdoc_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
3249 domdoc *This = impl_from_IObjectWithSite(iface);
3251 TRACE("(%p)->(%p)\n", iface, punk);
3253 if(!punk)
3255 if(This->site)
3257 IUnknown_Release( This->site );
3258 This->site = NULL;
3261 return S_OK;
3264 IUnknown_AddRef( punk );
3266 if(This->site)
3267 IUnknown_Release( This->site );
3269 This->site = punk;
3271 return S_OK;
3274 static const IObjectWithSiteVtbl domdocObjectSite =
3276 domdoc_ObjectWithSite_QueryInterface,
3277 domdoc_ObjectWithSite_AddRef,
3278 domdoc_ObjectWithSite_Release,
3279 domdoc_ObjectWithSite_SetSite,
3280 domdoc_ObjectWithSite_GetSite
3283 static HRESULT WINAPI domdoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
3285 domdoc *This = impl_from_IObjectSafety(iface);
3286 return IXMLDOMDocument3_QueryInterface( (IXMLDOMDocument3 *)This, riid, ppv );
3289 static ULONG WINAPI domdoc_Safety_AddRef(IObjectSafety *iface)
3291 domdoc *This = impl_from_IObjectSafety(iface);
3292 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
3295 static ULONG WINAPI domdoc_Safety_Release(IObjectSafety *iface)
3297 domdoc *This = impl_from_IObjectSafety(iface);
3298 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
3301 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
3303 static HRESULT WINAPI domdoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3304 DWORD *supported, DWORD *enabled)
3306 domdoc *This = impl_from_IObjectSafety(iface);
3308 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
3310 if(!supported || !enabled) return E_POINTER;
3312 *supported = SAFETY_SUPPORTED_OPTIONS;
3313 *enabled = This->safeopt;
3315 return S_OK;
3318 static HRESULT WINAPI domdoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
3319 DWORD mask, DWORD enabled)
3321 domdoc *This = impl_from_IObjectSafety(iface);
3322 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
3324 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
3325 return E_FAIL;
3327 This->safeopt = enabled & mask & SAFETY_SUPPORTED_OPTIONS;
3328 return S_OK;
3331 #undef SAFETY_SUPPORTED_OPTIONS
3333 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
3334 domdoc_Safety_QueryInterface,
3335 domdoc_Safety_AddRef,
3336 domdoc_Safety_Release,
3337 domdoc_Safety_GetInterfaceSafetyOptions,
3338 domdoc_Safety_SetInterfaceSafetyOptions
3341 static const tid_t domdoc_iface_tids[] = {
3342 IXMLDOMNode_tid,
3343 IXMLDOMDocument_tid,
3344 IXMLDOMDocument2_tid,
3347 static dispex_static_data_t domdoc_dispex = {
3348 NULL,
3349 IXMLDOMDocument2_tid,
3350 NULL,
3351 domdoc_iface_tids
3354 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
3356 domdoc *doc;
3358 doc = heap_alloc( sizeof (*doc) );
3359 if( !doc )
3360 return E_OUTOFMEMORY;
3362 doc->lpVtbl = &domdoc_vtbl;
3363 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
3364 doc->lpvtblIObjectWithSite = &domdocObjectSite;
3365 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
3366 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
3367 doc->lpVtblConnectionPointContainer = &ConnectionPointContainerVtbl;
3368 doc->ref = 1;
3369 doc->async = VARIANT_TRUE;
3370 doc->validating = 0;
3371 doc->resolving = 0;
3372 doc->properties = properties_from_xmlDocPtr(xmldoc);
3373 doc->error = S_OK;
3374 doc->stream = NULL;
3375 doc->site = NULL;
3376 doc->safeopt = 0;
3377 doc->bsc = NULL;
3378 doc->cp_list = NULL;
3380 /* events connection points */
3381 ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
3382 ConnectionPoint_Init(&doc->cp_propnotif, doc, &IID_IPropertyNotifySink);
3383 ConnectionPoint_Init(&doc->cp_domdocevents, doc, &DIID_XMLDOMDocumentEvents);
3385 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->lpVtbl, &domdoc_dispex);
3387 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
3389 TRACE("returning iface %p\n", *document);
3390 return S_OK;
3393 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3395 xmlDocPtr xmldoc;
3396 HRESULT hr;
3398 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
3400 xmldoc = xmlNewDoc(NULL);
3401 if(!xmldoc)
3402 return E_OUTOFMEMORY;
3404 xmldoc->_private = create_priv();
3405 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
3407 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
3408 if(FAILED(hr))
3410 free_properties(properties_from_xmlDocPtr(xmldoc));
3411 heap_free(xmldoc->_private);
3412 xmlFreeDoc(xmldoc);
3413 return hr;
3416 return hr;
3419 IUnknown* create_domdoc( xmlNodePtr document )
3421 void* pObj = NULL;
3422 HRESULT hr;
3424 TRACE("(%p)\n", document);
3426 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
3427 if (FAILED(hr))
3428 return NULL;
3430 return pObj;
3433 #else
3435 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
3437 MESSAGE("This program tried to use a DOMDocument object, but\n"
3438 "libxml2 support was not present at compile time.\n");
3439 return E_NOTIMPL;
3442 #endif