d3dcompiler: Add D3D_BLOB_LEGACY_SHADER to D3DGetBlobPart().
[wine.git] / dlls / msxml3 / domdoc.c
blob9d3f61f42c7811a5c9e7eee7fb4b7f68f08d8169
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 "msxml6.h"
35 #include "wininet.h"
36 #include "winreg.h"
37 #include "shlwapi.h"
38 #include "ocidl.h"
39 #include "objsafe.h"
40 #include "dispex.h"
42 #include "wine/debug.h"
43 #include "wine/list.h"
45 #include "msxml_private.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
49 #ifdef HAVE_LIBXML2
51 #include <libxml/xpathInternals.h>
52 #include <libxml/xmlsave.h>
53 #include <libxml/SAX2.h>
55 /* not defined in older versions */
56 #define XML_SAVE_FORMAT 1
57 #define XML_SAVE_NO_DECL 2
58 #define XML_SAVE_NO_EMPTY 4
59 #define XML_SAVE_NO_XHTML 8
60 #define XML_SAVE_XHTML 16
61 #define XML_SAVE_AS_XML 32
62 #define XML_SAVE_AS_HTML 64
64 static const WCHAR PropertySelectionLanguageW[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
65 static const WCHAR PropertySelectionNamespacesW[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
66 static const WCHAR PropertyProhibitDTDW[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
67 static const WCHAR PropertyNewParserW[] = {'N','e','w','P','a','r','s','e','r',0};
68 static const WCHAR PropValueXPathW[] = {'X','P','a','t','h',0};
69 static const WCHAR PropValueXSLPatternW[] = {'X','S','L','P','a','t','t','e','r','n',0};
71 /* Data used by domdoc_getProperty()/domdoc_setProperty().
72 * We need to preserve this when reloading a document,
73 * and also need access to it from the libxml backend. */
74 typedef struct _domdoc_properties {
75 struct list selectNsList;
76 xmlChar const* selectNsStr;
77 LONG selectNsStr_len;
78 BOOL XPath;
79 } domdoc_properties;
81 typedef struct _domdoc
83 xmlnode node;
84 const struct IXMLDOMDocument3Vtbl *lpVtbl;
85 const struct IPersistStreamInitVtbl *lpvtblIPersistStreamInit;
86 const struct IObjectWithSiteVtbl *lpvtblIObjectWithSite;
87 const struct IObjectSafetyVtbl *lpvtblIObjectSafety;
88 const struct ISupportErrorInfoVtbl *lpvtblISupportErrorInfo;
89 LONG ref;
90 VARIANT_BOOL async;
91 VARIANT_BOOL validating;
92 VARIANT_BOOL resolving;
93 VARIANT_BOOL preserving;
94 domdoc_properties* properties;
95 IXMLDOMSchemaCollection *schema;
96 bsc_t *bsc;
97 HRESULT error;
99 /* IPersistStream */
100 IStream *stream;
102 /* IObjectWithSite*/
103 IUnknown *site;
105 /* IObjectSafety */
106 DWORD safeopt;
107 } domdoc;
110 In native windows, the whole lifetime management of XMLDOMNodes is
111 managed automatically using reference counts. Wine emulates that by
112 maintaining a reference count to the document that is increased for
113 each IXMLDOMNode pointer passed out for this document. If all these
114 pointers are gone, the document is unreachable and gets freed, that
115 is, all nodes in the tree of the document get freed.
117 You are able to create nodes that are associated to a document (in
118 fact, in msxml's XMLDOM model, all nodes are associated to a document),
119 but not in the tree of that document, for example using the createFoo
120 functions from IXMLDOMDocument. These nodes do not get cleaned up
121 by libxml, so we have to do it ourselves.
123 To catch these nodes, a list of "orphan nodes" is introduced.
124 It contains pointers to all roots of node trees that are
125 associated with the document without being part of the document
126 tree. All nodes with parent==NULL (except for the document root nodes)
127 should be in the orphan node list of their document. All orphan nodes
128 get freed together with the document itself.
131 typedef struct _xmldoc_priv {
132 LONG refs;
133 struct list orphans;
134 domdoc_properties* properties;
135 } xmldoc_priv;
137 typedef struct _orphan_entry {
138 struct list entry;
139 xmlNode * node;
140 } orphan_entry;
142 typedef struct _select_ns_entry {
143 struct list entry;
144 xmlChar const* prefix;
145 xmlChar prefix_end;
146 xmlChar const* href;
147 xmlChar href_end;
148 } select_ns_entry;
150 static inline xmldoc_priv * priv_from_xmlDocPtr(const xmlDocPtr doc)
152 return doc->_private;
155 static inline domdoc_properties * properties_from_xmlDocPtr(xmlDocPtr doc)
157 return priv_from_xmlDocPtr(doc)->properties;
160 BOOL is_xpathmode(const xmlDocPtr doc)
162 return properties_from_xmlDocPtr(doc)->XPath;
165 int registerNamespaces(xmlXPathContextPtr ctxt)
167 int n = 0;
168 const select_ns_entry* ns = NULL;
169 const struct list* pNsList = &properties_from_xmlDocPtr(ctxt->doc)->selectNsList;
171 TRACE("(%p)\n", ctxt);
173 LIST_FOR_EACH_ENTRY( ns, pNsList, select_ns_entry, entry )
175 xmlXPathRegisterNs(ctxt, ns->prefix, ns->href);
176 ++n;
179 return n;
182 static inline void clear_selectNsList(struct list* pNsList)
184 select_ns_entry *ns, *ns2;
185 LIST_FOR_EACH_ENTRY_SAFE( ns, ns2, pNsList, select_ns_entry, entry )
187 heap_free( ns );
189 list_init(pNsList);
192 static xmldoc_priv * create_priv(void)
194 xmldoc_priv *priv;
195 priv = heap_alloc( sizeof (*priv) );
197 if (priv)
199 priv->refs = 0;
200 list_init( &priv->orphans );
201 priv->properties = NULL;
204 return priv;
207 static domdoc_properties * create_properties(const GUID *clsid)
209 domdoc_properties *properties = heap_alloc(sizeof(domdoc_properties));
211 list_init( &properties->selectNsList );
212 properties->selectNsStr = heap_alloc_zero(sizeof(xmlChar));
213 properties->selectNsStr_len = 0;
214 properties->XPath = FALSE;
216 /* properties that are dependent on object versions */
217 if (IsEqualCLSID( clsid, &CLSID_DOMDocument40 ) ||
218 IsEqualCLSID( clsid, &CLSID_DOMDocument60 ))
220 properties->XPath = TRUE;
223 return properties;
226 static domdoc_properties* copy_properties(domdoc_properties const* properties)
228 domdoc_properties* pcopy = heap_alloc(sizeof(domdoc_properties));
229 select_ns_entry const* ns = NULL;
230 select_ns_entry* new_ns = NULL;
231 int len = (properties->selectNsStr_len+1)*sizeof(xmlChar);
232 ptrdiff_t offset;
234 if (pcopy)
236 pcopy->XPath = properties->XPath;
237 pcopy->selectNsStr_len = properties->selectNsStr_len;
238 list_init( &pcopy->selectNsList );
239 pcopy->selectNsStr = heap_alloc(len);
240 memcpy((xmlChar*)pcopy->selectNsStr, properties->selectNsStr, len);
241 offset = pcopy->selectNsStr - properties->selectNsStr;
243 LIST_FOR_EACH_ENTRY( ns, (&properties->selectNsList), select_ns_entry, entry )
245 new_ns = heap_alloc(sizeof(select_ns_entry));
246 memcpy(new_ns, ns, sizeof(select_ns_entry));
247 new_ns->href += offset;
248 new_ns->prefix += offset;
249 list_add_tail(&pcopy->selectNsList, &new_ns->entry);
254 return pcopy;
257 static void free_properties(domdoc_properties* properties)
259 if (properties)
261 clear_selectNsList(&properties->selectNsList);
262 heap_free((xmlChar*)properties->selectNsStr);
263 heap_free(properties);
267 /* links a "<?xml" node as a first child */
268 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
270 assert(doc != NULL);
271 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
274 /* unlinks a first "<?xml" child if it was created */
275 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
277 xmlNodePtr node;
279 assert(doc != NULL);
281 if (doc->standalone != -1)
283 node = doc->children;
284 xmlUnlinkNode( node );
286 else
287 node = NULL;
289 return node;
292 static inline BOOL strn_isspace(xmlChar const* str, int len)
294 for (; str && len > 0 && *str; ++str, --len)
295 if (!isspace(*str))
296 break;
298 return len == 0;
301 static void sax_characters(void *ctx, const xmlChar *ch, int len)
303 xmlParserCtxtPtr pctx;
304 domdoc const* This;
306 pctx = (xmlParserCtxtPtr) ctx;
307 This = (domdoc const*) pctx->_private;
309 if (!This->preserving)
311 xmlChar* ws = xmlGetNsProp(pctx->node, BAD_CAST "space", XML_XML_NAMESPACE);
312 if ((!ws || xmlStrcmp(ws, BAD_CAST "preserve") != 0) &&
313 strn_isspace(ch, len))
315 xmlFree(ws);
316 return;
318 xmlFree(ws);
321 xmlSAX2Characters(ctx, ch, len);
324 static xmlDocPtr doparse(domdoc* This, char *ptr, int len)
326 xmlDocPtr doc;
327 static xmlSAXHandler sax_handler = {
328 xmlSAX2InternalSubset, /* internalSubset */
329 xmlSAX2IsStandalone, /* isStandalone */
330 xmlSAX2HasInternalSubset, /* hasInternalSubset */
331 xmlSAX2HasExternalSubset, /* hasExternalSubset */
332 xmlSAX2ResolveEntity, /* resolveEntity */
333 xmlSAX2GetEntity, /* getEntity */
334 xmlSAX2EntityDecl, /* entityDecl */
335 xmlSAX2NotationDecl, /* notationDecl */
336 xmlSAX2AttributeDecl, /* attributeDecl */
337 xmlSAX2ElementDecl, /* elementDecl */
338 xmlSAX2UnparsedEntityDecl, /* unparsedEntityDecl */
339 xmlSAX2SetDocumentLocator, /* setDocumentLocator */
340 xmlSAX2StartDocument, /* startDocument */
341 xmlSAX2EndDocument, /* endDocument */
342 xmlSAX2StartElement, /* startElement */
343 xmlSAX2EndElement, /* endElement */
344 xmlSAX2Reference, /* reference */
345 sax_characters, /* characters */
346 sax_characters, /* ignorableWhitespace */
347 xmlSAX2ProcessingInstruction, /* processingInstruction */
348 xmlSAX2Comment, /* comment */
349 NULL, /* TODO: warning */
350 NULL, /* TODO: error */
351 NULL, /* TODO: fatalError */
352 xmlSAX2GetParameterEntity, /* getParameterEntity */
353 xmlSAX2CDataBlock, /* cdataBlock */
354 xmlSAX2ExternalSubset, /* externalSubset */
355 0, /* initialized */
356 NULL, /* _private */
357 xmlSAX2StartElementNs, /* startElementNs */
358 xmlSAX2EndElementNs, /* endElementNs */
359 NULL /* TODO: serror */
362 doc = xmlSAXParseMemoryWithData(&sax_handler, ptr, len, 0, This);
364 /* TODO: put this in one of the SAX callbacks */
365 /* create first child as a <?xml...?> */
366 if (doc && doc->standalone != -1)
368 xmlNodePtr node;
369 char buff[30];
370 xmlChar *xmlbuff = (xmlChar*)buff;
372 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
374 /* version attribute can't be omitted */
375 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
376 xmlNodeAddContent( node, xmlbuff );
378 if (doc->encoding)
380 sprintf(buff, " encoding=\"%s\"", doc->encoding);
381 xmlNodeAddContent( node, xmlbuff );
384 if (doc->standalone != -2)
386 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
387 xmlNodeAddContent( node, xmlbuff );
390 xmldoc_link_xmldecl( doc, node );
393 return doc;
396 LONG xmldoc_add_ref(xmlDocPtr doc)
398 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
399 TRACE("(%p)->(%d)\n", doc, ref);
400 return ref;
403 LONG xmldoc_release(xmlDocPtr doc)
405 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
406 LONG ref = InterlockedDecrement(&priv->refs);
407 TRACE("(%p)->(%d)\n", doc, ref);
408 if(ref == 0)
410 orphan_entry *orphan, *orphan2;
411 TRACE("freeing docptr %p\n", doc);
413 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
415 xmlFreeNode( orphan->node );
416 heap_free( orphan );
418 free_properties(priv->properties);
419 heap_free(doc->_private);
421 xmlFreeDoc(doc);
424 return ref;
427 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
429 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
430 orphan_entry *entry;
432 entry = heap_alloc( sizeof (*entry) );
433 if(!entry)
434 return E_OUTOFMEMORY;
436 entry->node = node;
437 list_add_head( &priv->orphans, &entry->entry );
438 return S_OK;
441 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
443 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
444 orphan_entry *entry, *entry2;
446 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
448 if( entry->node == node )
450 list_remove( &entry->entry );
451 heap_free( entry );
452 return S_OK;
456 return S_FALSE;
459 static inline xmlDocPtr get_doc( domdoc *This )
461 return (xmlDocPtr)This->node.node;
464 static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
466 if(This->node.node)
468 priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
469 if (xmldoc_release(get_doc(This)) != 0)
470 priv_from_xmlDocPtr(get_doc(This))->properties =
471 copy_properties(This->properties);
474 This->node.node = (xmlNodePtr) xml;
476 if(This->node.node)
478 xmldoc_add_ref(get_doc(This));
479 priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
482 return S_OK;
485 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
487 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
490 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
492 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStreamInit));
495 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
497 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
500 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
502 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
505 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
507 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblISupportErrorInfo));
510 /************************************************************************
511 * domdoc implementation of IPersistStream.
513 static HRESULT WINAPI domdoc_IPersistStreamInit_QueryInterface(
514 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
516 domdoc *this = impl_from_IPersistStreamInit(iface);
517 return IXMLDOMDocument2_QueryInterface((IXMLDOMDocument2 *)this, riid, ppvObj);
520 static ULONG WINAPI domdoc_IPersistStreamInit_AddRef(
521 IPersistStreamInit *iface)
523 domdoc *this = impl_from_IPersistStreamInit(iface);
524 return IXMLDOMDocument2_AddRef((IXMLDOMDocument2 *)this);
527 static ULONG WINAPI domdoc_IPersistStreamInit_Release(
528 IPersistStreamInit *iface)
530 domdoc *this = impl_from_IPersistStreamInit(iface);
531 return IXMLDOMDocument2_Release((IXMLDOMDocument2 *)this);
534 static HRESULT WINAPI domdoc_IPersistStreamInit_GetClassID(
535 IPersistStreamInit *iface, CLSID *classid)
537 TRACE("(%p,%p): stub!\n", iface, classid);
539 if(!classid)
540 return E_POINTER;
542 *classid = CLSID_DOMDocument2;
544 return S_OK;
547 static HRESULT WINAPI domdoc_IPersistStreamInit_IsDirty(
548 IPersistStreamInit *iface)
550 domdoc *This = impl_from_IPersistStreamInit(iface);
551 FIXME("(%p): stub!\n", This);
552 return S_FALSE;
555 static HRESULT WINAPI domdoc_IPersistStreamInit_Load(
556 IPersistStreamInit *iface, LPSTREAM pStm)
558 domdoc *This = impl_from_IPersistStreamInit(iface);
559 HRESULT hr;
560 HGLOBAL hglobal;
561 DWORD read, written, len;
562 BYTE buf[4096];
563 char *ptr;
564 xmlDocPtr xmldoc = NULL;
566 TRACE("(%p)->(%p)\n", This, pStm);
568 if (!pStm)
569 return E_INVALIDARG;
571 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
572 if (FAILED(hr))
573 return hr;
577 IStream_Read(pStm, buf, sizeof(buf), &read);
578 hr = IStream_Write(This->stream, buf, read, &written);
579 } while(SUCCEEDED(hr) && written != 0 && read != 0);
581 if (FAILED(hr))
583 ERR("Failed to copy stream\n");
584 return hr;
587 hr = GetHGlobalFromStream(This->stream, &hglobal);
588 if (FAILED(hr))
589 return hr;
591 len = GlobalSize(hglobal);
592 ptr = GlobalLock(hglobal);
593 if (len != 0)
594 xmldoc = doparse(This, ptr, len);
595 GlobalUnlock(hglobal);
597 if (!xmldoc)
599 ERR("Failed to parse xml\n");
600 return E_FAIL;
603 xmldoc->_private = create_priv();
605 return attach_xmldoc(This, xmldoc);
608 static HRESULT WINAPI domdoc_IPersistStreamInit_Save(
609 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
611 domdoc *This = impl_from_IPersistStreamInit(iface);
612 BSTR xmlString;
613 HRESULT hr;
615 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
617 hr = IXMLDOMDocument3_get_xml( (IXMLDOMDocument3*)&This->lpVtbl, &xmlString );
618 if(hr == S_OK)
620 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
622 hr = IStream_Write( stream, xmlString, len, NULL );
623 SysFreeString(xmlString);
626 TRACE("ret 0x%08x\n", hr);
628 return hr;
631 static HRESULT WINAPI domdoc_IPersistStreamInit_GetSizeMax(
632 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
634 domdoc *This = impl_from_IPersistStreamInit(iface);
635 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
636 return E_NOTIMPL;
639 static HRESULT WINAPI domdoc_IPersistStreamInit_InitNew(
640 IPersistStreamInit *iface)
642 domdoc *This = impl_from_IPersistStreamInit(iface);
643 TRACE("(%p)\n", This);
644 return S_OK;
647 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
649 domdoc_IPersistStreamInit_QueryInterface,
650 domdoc_IPersistStreamInit_AddRef,
651 domdoc_IPersistStreamInit_Release,
652 domdoc_IPersistStreamInit_GetClassID,
653 domdoc_IPersistStreamInit_IsDirty,
654 domdoc_IPersistStreamInit_Load,
655 domdoc_IPersistStreamInit_Save,
656 domdoc_IPersistStreamInit_GetSizeMax,
657 domdoc_IPersistStreamInit_InitNew
660 /* ISupportErrorInfo interface */
661 static HRESULT WINAPI support_error_QueryInterface(
662 ISupportErrorInfo *iface,
663 REFIID riid, void** ppvObj )
665 domdoc *This = impl_from_ISupportErrorInfo(iface);
666 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3 *)This, riid, ppvObj);
669 static ULONG WINAPI support_error_AddRef(
670 ISupportErrorInfo *iface )
672 domdoc *This = impl_from_ISupportErrorInfo(iface);
673 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
676 static ULONG WINAPI support_error_Release(
677 ISupportErrorInfo *iface )
679 domdoc *This = impl_from_ISupportErrorInfo(iface);
680 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
683 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
684 ISupportErrorInfo *iface,
685 REFIID riid )
687 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
688 return S_FALSE;
691 static const struct ISupportErrorInfoVtbl support_error_vtbl =
693 support_error_QueryInterface,
694 support_error_AddRef,
695 support_error_Release,
696 support_error_InterfaceSupportsErrorInfo
699 /* IXMLDOMDocument2 interface */
700 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
702 domdoc *This = impl_from_IXMLDOMDocument3( iface );
704 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
706 *ppvObject = NULL;
708 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
709 IsEqualGUID( riid, &IID_IDispatch ) ||
710 IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
711 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
712 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
713 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
715 *ppvObject = iface;
717 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
718 IsEqualGUID(&IID_IPersistStreamInit, riid))
720 *ppvObject = &(This->lpvtblIPersistStreamInit);
722 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
724 *ppvObject = &(This->lpvtblIObjectWithSite);
726 else if (IsEqualGUID(&IID_IObjectSafety, riid))
728 *ppvObject = &(This->lpvtblIObjectSafety);
730 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
732 *ppvObject = &This->lpvtblISupportErrorInfo;
734 else if(node_query_interface(&This->node, riid, ppvObject))
736 return *ppvObject ? S_OK : E_NOINTERFACE;
738 else if(IsEqualGUID(&IID_IRunnableObject, riid))
740 TRACE("IID_IRunnableObject not supported returning NULL\n");
741 return E_NOINTERFACE;
743 else
745 FIXME("interface %s not implemented\n", debugstr_guid(riid));
746 return E_NOINTERFACE;
749 IUnknown_AddRef((IUnknown*)*ppvObject);
751 return S_OK;
755 static ULONG WINAPI domdoc_AddRef(
756 IXMLDOMDocument3 *iface )
758 domdoc *This = impl_from_IXMLDOMDocument3( iface );
759 TRACE("%p\n", This );
760 return InterlockedIncrement( &This->ref );
764 static ULONG WINAPI domdoc_Release(
765 IXMLDOMDocument3 *iface )
767 domdoc *This = impl_from_IXMLDOMDocument3( iface );
768 LONG ref;
770 TRACE("%p\n", This );
772 ref = InterlockedDecrement( &This->ref );
773 if ( ref == 0 )
775 if(This->bsc)
776 detach_bsc(This->bsc);
778 if (This->site)
779 IUnknown_Release( This->site );
780 destroy_xmlnode(&This->node);
781 if(This->schema) IXMLDOMSchemaCollection_Release( This->schema );
782 if (This->stream) IStream_Release(This->stream);
783 HeapFree( GetProcessHeap(), 0, This );
786 return ref;
789 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
791 domdoc *This = impl_from_IXMLDOMDocument3( iface );
793 TRACE("(%p)->(%p)\n", This, pctinfo);
795 *pctinfo = 1;
797 return S_OK;
800 static HRESULT WINAPI domdoc_GetTypeInfo(
801 IXMLDOMDocument3 *iface,
802 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
804 domdoc *This = impl_from_IXMLDOMDocument3( iface );
805 HRESULT hr;
807 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
809 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
811 return hr;
814 static HRESULT WINAPI domdoc_GetIDsOfNames(
815 IXMLDOMDocument3 *iface,
816 REFIID riid,
817 LPOLESTR* rgszNames,
818 UINT cNames,
819 LCID lcid,
820 DISPID* rgDispId)
822 domdoc *This = impl_from_IXMLDOMDocument3( iface );
823 ITypeInfo *typeinfo;
824 HRESULT hr;
826 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
827 lcid, rgDispId);
829 if(!rgszNames || cNames == 0 || !rgDispId)
830 return E_INVALIDARG;
832 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
833 if(SUCCEEDED(hr))
835 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
836 ITypeInfo_Release(typeinfo);
839 return hr;
843 static HRESULT WINAPI domdoc_Invoke(
844 IXMLDOMDocument3 *iface,
845 DISPID dispIdMember,
846 REFIID riid,
847 LCID lcid,
848 WORD wFlags,
849 DISPPARAMS* pDispParams,
850 VARIANT* pVarResult,
851 EXCEPINFO* pExcepInfo,
852 UINT* puArgErr)
854 domdoc *This = impl_from_IXMLDOMDocument3( iface );
855 ITypeInfo *typeinfo;
856 HRESULT hr;
858 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
859 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
861 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
862 if(SUCCEEDED(hr))
864 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
865 pVarResult, pExcepInfo, puArgErr);
866 ITypeInfo_Release(typeinfo);
869 return hr;
873 static HRESULT WINAPI domdoc_get_nodeName(
874 IXMLDOMDocument3 *iface,
875 BSTR* name )
877 domdoc *This = impl_from_IXMLDOMDocument3( iface );
879 static const WCHAR documentW[] = {'#','d','o','c','u','m','e','n','t',0};
881 TRACE("(%p)->(%p)\n", This, name);
883 return return_bstr(documentW, name);
887 static HRESULT WINAPI domdoc_get_nodeValue(
888 IXMLDOMDocument3 *iface,
889 VARIANT* value )
891 domdoc *This = impl_from_IXMLDOMDocument3( iface );
893 TRACE("(%p)->(%p)\n", This, value);
895 if(!value)
896 return E_INVALIDARG;
898 V_VT(value) = VT_NULL;
899 V_BSTR(value) = NULL; /* tests show that we should do this */
900 return S_FALSE;
904 static HRESULT WINAPI domdoc_put_nodeValue(
905 IXMLDOMDocument3 *iface,
906 VARIANT value)
908 domdoc *This = impl_from_IXMLDOMDocument3( iface );
909 FIXME("(%p)->(v%d)\n", This, V_VT(&value));
910 return E_FAIL;
914 static HRESULT WINAPI domdoc_get_nodeType(
915 IXMLDOMDocument3 *iface,
916 DOMNodeType* type )
918 domdoc *This = impl_from_IXMLDOMDocument3( iface );
920 TRACE("(%p)->(%p)\n", This, type);
922 *type = NODE_DOCUMENT;
923 return S_OK;
927 static HRESULT WINAPI domdoc_get_parentNode(
928 IXMLDOMDocument3 *iface,
929 IXMLDOMNode** parent )
931 domdoc *This = impl_from_IXMLDOMDocument3( iface );
933 TRACE("(%p)->(%p)\n", This, parent);
935 return node_get_parent(&This->node, parent);
939 static HRESULT WINAPI domdoc_get_childNodes(
940 IXMLDOMDocument3 *iface,
941 IXMLDOMNodeList** childList )
943 domdoc *This = impl_from_IXMLDOMDocument3( iface );
945 TRACE("(%p)->(%p)\n", This, childList);
947 return node_get_child_nodes(&This->node, childList);
951 static HRESULT WINAPI domdoc_get_firstChild(
952 IXMLDOMDocument3 *iface,
953 IXMLDOMNode** firstChild )
955 domdoc *This = impl_from_IXMLDOMDocument3( iface );
957 TRACE("(%p)->(%p)\n", This, firstChild);
959 return node_get_first_child(&This->node, firstChild);
963 static HRESULT WINAPI domdoc_get_lastChild(
964 IXMLDOMDocument3 *iface,
965 IXMLDOMNode** lastChild )
967 domdoc *This = impl_from_IXMLDOMDocument3( iface );
969 TRACE("(%p)->(%p)\n", This, lastChild);
971 return node_get_last_child(&This->node, lastChild);
975 static HRESULT WINAPI domdoc_get_previousSibling(
976 IXMLDOMDocument3 *iface,
977 IXMLDOMNode** previousSibling )
979 domdoc *This = impl_from_IXMLDOMDocument3( iface );
981 TRACE("(%p)->(%p)\n", This, previousSibling);
983 return return_null_node(previousSibling);
987 static HRESULT WINAPI domdoc_get_nextSibling(
988 IXMLDOMDocument3 *iface,
989 IXMLDOMNode** nextSibling )
991 domdoc *This = impl_from_IXMLDOMDocument3( iface );
993 TRACE("(%p)->(%p)\n", This, nextSibling);
995 return return_null_node(nextSibling);
999 static HRESULT WINAPI domdoc_get_attributes(
1000 IXMLDOMDocument3 *iface,
1001 IXMLDOMNamedNodeMap** attributeMap )
1003 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1005 TRACE("(%p)->(%p)\n", This, attributeMap);
1007 return return_null_ptr((void**)attributeMap);
1011 static HRESULT WINAPI domdoc_insertBefore(
1012 IXMLDOMDocument3 *iface,
1013 IXMLDOMNode* newChild,
1014 VARIANT refChild,
1015 IXMLDOMNode** outNewChild )
1017 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1019 TRACE("(%p)->(%p x%d %p)\n", This, newChild, V_VT(&refChild), outNewChild);
1021 return node_insert_before(&This->node, newChild, &refChild, outNewChild);
1025 static HRESULT WINAPI domdoc_replaceChild(
1026 IXMLDOMDocument3 *iface,
1027 IXMLDOMNode* newChild,
1028 IXMLDOMNode* oldChild,
1029 IXMLDOMNode** outOldChild)
1031 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1033 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, outOldChild);
1035 return node_replace_child(&This->node, newChild, oldChild, outOldChild);
1039 static HRESULT WINAPI domdoc_removeChild(
1040 IXMLDOMDocument3 *iface,
1041 IXMLDOMNode* childNode,
1042 IXMLDOMNode** oldChild)
1044 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1045 return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), childNode, oldChild );
1049 static HRESULT WINAPI domdoc_appendChild(
1050 IXMLDOMDocument3 *iface,
1051 IXMLDOMNode* newChild,
1052 IXMLDOMNode** outNewChild)
1054 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1055 return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newChild, outNewChild );
1059 static HRESULT WINAPI domdoc_hasChildNodes(
1060 IXMLDOMDocument3 *iface,
1061 VARIANT_BOOL* hasChild)
1063 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1064 return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), hasChild );
1068 static HRESULT WINAPI domdoc_get_ownerDocument(
1069 IXMLDOMDocument3 *iface,
1070 IXMLDOMDocument** DOMDocument)
1072 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1073 return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), DOMDocument );
1077 static HRESULT WINAPI domdoc_cloneNode(
1078 IXMLDOMDocument3 *iface,
1079 VARIANT_BOOL deep,
1080 IXMLDOMNode** cloneRoot)
1082 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1083 return IXMLDOMNode_cloneNode( IXMLDOMNode_from_impl(&This->node), deep, cloneRoot );
1087 static HRESULT WINAPI domdoc_get_nodeTypeString(
1088 IXMLDOMDocument3 *iface,
1089 BSTR* nodeType )
1091 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1092 return IXMLDOMNode_get_nodeTypeString( IXMLDOMNode_from_impl(&This->node), nodeType );
1096 static HRESULT WINAPI domdoc_get_text(
1097 IXMLDOMDocument3 *iface,
1098 BSTR* text )
1100 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1101 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), text );
1105 static HRESULT WINAPI domdoc_put_text(
1106 IXMLDOMDocument3 *iface,
1107 BSTR text )
1109 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1110 return IXMLDOMNode_put_text( IXMLDOMNode_from_impl(&This->node), text );
1114 static HRESULT WINAPI domdoc_get_specified(
1115 IXMLDOMDocument3 *iface,
1116 VARIANT_BOOL* isSpecified )
1118 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1119 return IXMLDOMNode_get_specified( IXMLDOMNode_from_impl(&This->node), isSpecified );
1123 static HRESULT WINAPI domdoc_get_definition(
1124 IXMLDOMDocument3 *iface,
1125 IXMLDOMNode** definitionNode )
1127 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1128 return IXMLDOMNode_get_definition( IXMLDOMNode_from_impl(&This->node), definitionNode );
1132 static HRESULT WINAPI domdoc_get_nodeTypedValue(
1133 IXMLDOMDocument3 *iface,
1134 VARIANT* typedValue )
1136 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1137 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
1140 static HRESULT WINAPI domdoc_put_nodeTypedValue(
1141 IXMLDOMDocument3 *iface,
1142 VARIANT typedValue )
1144 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1145 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
1149 static HRESULT WINAPI domdoc_get_dataType(
1150 IXMLDOMDocument3 *iface,
1151 VARIANT* dataTypeName )
1153 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1154 return IXMLDOMNode_get_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
1158 static HRESULT WINAPI domdoc_put_dataType(
1159 IXMLDOMDocument3 *iface,
1160 BSTR dataTypeName )
1162 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1163 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
1167 static HRESULT WINAPI domdoc_get_xml(
1168 IXMLDOMDocument3 *iface,
1169 BSTR* xmlString )
1171 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1172 return IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), xmlString );
1176 static HRESULT WINAPI domdoc_transformNode(
1177 IXMLDOMDocument3 *iface,
1178 IXMLDOMNode* styleSheet,
1179 BSTR* xmlString )
1181 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1182 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), styleSheet, xmlString );
1186 static HRESULT WINAPI domdoc_selectNodes(
1187 IXMLDOMDocument3 *iface,
1188 BSTR queryString,
1189 IXMLDOMNodeList** resultList )
1191 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1192 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), queryString, resultList );
1196 static HRESULT WINAPI domdoc_selectSingleNode(
1197 IXMLDOMDocument3 *iface,
1198 BSTR queryString,
1199 IXMLDOMNode** resultNode )
1201 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1202 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), queryString, resultNode );
1206 static HRESULT WINAPI domdoc_get_parsed(
1207 IXMLDOMDocument3 *iface,
1208 VARIANT_BOOL* isParsed )
1210 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1211 return IXMLDOMNode_get_parsed( IXMLDOMNode_from_impl(&This->node), isParsed );
1215 static HRESULT WINAPI domdoc_get_namespaceURI(
1216 IXMLDOMDocument3 *iface,
1217 BSTR* namespaceURI )
1219 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1220 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), namespaceURI );
1224 static HRESULT WINAPI domdoc_get_prefix(
1225 IXMLDOMDocument3 *iface,
1226 BSTR* prefixString )
1228 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1229 return IXMLDOMNode_get_prefix( IXMLDOMNode_from_impl(&This->node), prefixString );
1233 static HRESULT WINAPI domdoc_get_baseName(
1234 IXMLDOMDocument3 *iface,
1235 BSTR* nameString )
1237 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1238 return IXMLDOMNode_get_baseName( IXMLDOMNode_from_impl(&This->node), nameString );
1242 static HRESULT WINAPI domdoc_transformNodeToObject(
1243 IXMLDOMDocument3 *iface,
1244 IXMLDOMNode* stylesheet,
1245 VARIANT outputObject)
1247 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1248 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), stylesheet, outputObject );
1252 static HRESULT WINAPI domdoc_get_doctype(
1253 IXMLDOMDocument3 *iface,
1254 IXMLDOMDocumentType** documentType )
1256 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1257 FIXME("(%p)\n", This);
1258 return E_NOTIMPL;
1262 static HRESULT WINAPI domdoc_get_implementation(
1263 IXMLDOMDocument3 *iface,
1264 IXMLDOMImplementation** impl )
1266 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1268 TRACE("(%p)->(%p)\n", This, impl);
1270 if(!impl)
1271 return E_INVALIDARG;
1273 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1275 return S_OK;
1278 static HRESULT WINAPI domdoc_get_documentElement(
1279 IXMLDOMDocument3 *iface,
1280 IXMLDOMElement** DOMElement )
1282 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1283 IXMLDOMNode *element_node;
1284 xmlNodePtr root;
1285 HRESULT hr;
1287 TRACE("(%p)->(%p)\n", This, DOMElement);
1289 if(!DOMElement)
1290 return E_INVALIDARG;
1292 *DOMElement = NULL;
1294 root = xmlDocGetRootElement( get_doc(This) );
1295 if ( !root )
1296 return S_FALSE;
1298 element_node = create_node( root );
1299 if(!element_node) return S_FALSE;
1301 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (void**)DOMElement);
1302 IXMLDOMNode_Release(element_node);
1304 return hr;
1308 static HRESULT WINAPI domdoc_put_documentElement(
1309 IXMLDOMDocument3 *iface,
1310 IXMLDOMElement* DOMElement )
1312 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1313 IXMLDOMNode *elementNode;
1314 xmlNodePtr oldRoot;
1315 xmlnode *xmlNode;
1316 HRESULT hr;
1318 TRACE("(%p)->(%p)\n", This, DOMElement);
1320 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1321 if(FAILED(hr))
1322 return hr;
1324 xmlNode = get_node_obj( elementNode );
1325 if(!xmlNode) {
1326 FIXME("elementNode is not our object\n");
1327 return E_FAIL;
1330 if(!xmlNode->node->parent)
1331 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1332 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1334 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1335 IXMLDOMNode_Release( elementNode );
1337 if(oldRoot)
1338 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1340 return S_OK;
1344 static HRESULT WINAPI domdoc_createElement(
1345 IXMLDOMDocument3 *iface,
1346 BSTR tagname,
1347 IXMLDOMElement** element )
1349 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1350 IXMLDOMNode *node;
1351 VARIANT type;
1352 HRESULT hr;
1354 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1356 if (!element || !tagname) return E_INVALIDARG;
1358 V_VT(&type) = VT_I1;
1359 V_I1(&type) = NODE_ELEMENT;
1361 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1362 if (hr == S_OK)
1364 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1365 IXMLDOMNode_Release(node);
1368 return hr;
1372 static HRESULT WINAPI domdoc_createDocumentFragment(
1373 IXMLDOMDocument3 *iface,
1374 IXMLDOMDocumentFragment** frag )
1376 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1377 IXMLDOMNode *node;
1378 VARIANT type;
1379 HRESULT hr;
1381 TRACE("(%p)->(%p)\n", This, frag);
1383 if (!frag) return E_INVALIDARG;
1385 *frag = NULL;
1387 V_VT(&type) = VT_I1;
1388 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1390 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1391 if (hr == S_OK)
1393 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1394 IXMLDOMNode_Release(node);
1397 return hr;
1401 static HRESULT WINAPI domdoc_createTextNode(
1402 IXMLDOMDocument3 *iface,
1403 BSTR data,
1404 IXMLDOMText** text )
1406 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1407 IXMLDOMNode *node;
1408 VARIANT type;
1409 HRESULT hr;
1411 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1413 if (!text) return E_INVALIDARG;
1415 *text = NULL;
1417 V_VT(&type) = VT_I1;
1418 V_I1(&type) = NODE_TEXT;
1420 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1421 if (hr == S_OK)
1423 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1424 IXMLDOMNode_Release(node);
1425 hr = IXMLDOMText_put_data(*text, data);
1428 return hr;
1432 static HRESULT WINAPI domdoc_createComment(
1433 IXMLDOMDocument3 *iface,
1434 BSTR data,
1435 IXMLDOMComment** comment )
1437 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1438 VARIANT type;
1439 HRESULT hr;
1440 IXMLDOMNode *node;
1442 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1444 if (!comment) return E_INVALIDARG;
1446 *comment = NULL;
1448 V_VT(&type) = VT_I1;
1449 V_I1(&type) = NODE_COMMENT;
1451 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1452 if (hr == S_OK)
1454 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1455 IXMLDOMNode_Release(node);
1456 hr = IXMLDOMComment_put_data(*comment, data);
1459 return hr;
1463 static HRESULT WINAPI domdoc_createCDATASection(
1464 IXMLDOMDocument3 *iface,
1465 BSTR data,
1466 IXMLDOMCDATASection** cdata )
1468 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1469 IXMLDOMNode *node;
1470 VARIANT type;
1471 HRESULT hr;
1473 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1475 if (!cdata) return E_INVALIDARG;
1477 *cdata = NULL;
1479 V_VT(&type) = VT_I1;
1480 V_I1(&type) = NODE_CDATA_SECTION;
1482 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1483 if (hr == S_OK)
1485 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1486 IXMLDOMNode_Release(node);
1487 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1490 return hr;
1494 static HRESULT WINAPI domdoc_createProcessingInstruction(
1495 IXMLDOMDocument3 *iface,
1496 BSTR target,
1497 BSTR data,
1498 IXMLDOMProcessingInstruction** pi )
1500 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1501 IXMLDOMNode *node;
1502 VARIANT type;
1503 HRESULT hr;
1505 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1507 if (!pi) return E_INVALIDARG;
1509 *pi = NULL;
1511 V_VT(&type) = VT_I1;
1512 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1514 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1515 if (hr == S_OK)
1517 VARIANT v_data;
1518 xmlnode *node_obj;
1520 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1521 node_obj = get_node_obj(node);
1522 V_VT(&v_data) = VT_BSTR;
1523 V_BSTR(&v_data) = data;
1525 hr = node_put_value(node_obj, &v_data);
1527 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1528 IXMLDOMNode_Release(node);
1531 return hr;
1535 static HRESULT WINAPI domdoc_createAttribute(
1536 IXMLDOMDocument3 *iface,
1537 BSTR name,
1538 IXMLDOMAttribute** attribute )
1540 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1541 IXMLDOMNode *node;
1542 VARIANT type;
1543 HRESULT hr;
1545 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1547 if (!attribute || !name) return E_INVALIDARG;
1549 V_VT(&type) = VT_I1;
1550 V_I1(&type) = NODE_ATTRIBUTE;
1552 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1553 if (hr == S_OK)
1555 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1556 IXMLDOMNode_Release(node);
1559 return hr;
1563 static HRESULT WINAPI domdoc_createEntityReference(
1564 IXMLDOMDocument3 *iface,
1565 BSTR name,
1566 IXMLDOMEntityReference** entityref )
1568 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1569 IXMLDOMNode *node;
1570 VARIANT type;
1571 HRESULT hr;
1573 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1575 if (!entityref) return E_INVALIDARG;
1577 *entityref = NULL;
1579 V_VT(&type) = VT_I1;
1580 V_I1(&type) = NODE_ENTITY_REFERENCE;
1582 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1583 if (hr == S_OK)
1585 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1586 IXMLDOMNode_Release(node);
1589 return hr;
1593 static HRESULT WINAPI domdoc_getElementsByTagName(
1594 IXMLDOMDocument3 *iface,
1595 BSTR tagName,
1596 IXMLDOMNodeList** resultList )
1598 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1599 HRESULT hr;
1601 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagName), resultList);
1603 if (!tagName || !resultList) return E_INVALIDARG;
1605 if (tagName[0] == '*' && tagName[1] == 0)
1607 static const WCHAR formatallW[] = {'/','/','*',0};
1608 hr = queryresult_create((xmlNodePtr)get_doc(This), formatallW, resultList);
1610 else
1612 static const WCHAR xpathformat[] =
1613 { '/','/','*','[','l','o','c','a','l','-','n','a','m','e','(',')','=','\'' };
1614 static const WCHAR closeW[] = { '\'',']',0 };
1616 LPWSTR pattern;
1617 WCHAR *ptr;
1618 INT length;
1620 length = lstrlenW(tagName);
1622 /* without two WCHARs from format specifier */
1623 ptr = pattern = heap_alloc(sizeof(xpathformat) + length*sizeof(WCHAR) + sizeof(closeW));
1625 memcpy(ptr, xpathformat, sizeof(xpathformat));
1626 ptr += sizeof(xpathformat)/sizeof(WCHAR);
1627 memcpy(ptr, tagName, length*sizeof(WCHAR));
1628 ptr += length;
1629 memcpy(ptr, closeW, sizeof(closeW));
1631 hr = queryresult_create((xmlNodePtr)get_doc(This), pattern, resultList);
1632 heap_free(pattern);
1635 return hr;
1638 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1640 VARIANT tmp;
1641 HRESULT hr;
1643 VariantInit(&tmp);
1644 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1645 if(FAILED(hr))
1646 return E_INVALIDARG;
1648 *type = V_I4(&tmp);
1650 return S_OK;
1653 static HRESULT WINAPI domdoc_createNode(
1654 IXMLDOMDocument3 *iface,
1655 VARIANT Type,
1656 BSTR name,
1657 BSTR namespaceURI,
1658 IXMLDOMNode** node )
1660 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1661 DOMNodeType node_type;
1662 xmlNodePtr xmlnode;
1663 xmlChar *xml_name, *href;
1664 HRESULT hr;
1666 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1668 if(!node) return E_INVALIDARG;
1670 hr = get_node_type(Type, &node_type);
1671 if(FAILED(hr)) return hr;
1673 if(namespaceURI && namespaceURI[0] && node_type != NODE_ELEMENT)
1674 FIXME("nodes with namespaces currently not supported.\n");
1676 TRACE("node_type %d\n", node_type);
1678 /* exit earlier for types that need name */
1679 switch(node_type)
1681 case NODE_ELEMENT:
1682 case NODE_ATTRIBUTE:
1683 case NODE_ENTITY_REFERENCE:
1684 case NODE_PROCESSING_INSTRUCTION:
1685 if (!name || *name == 0) return E_FAIL;
1686 default:
1687 break;
1690 xml_name = xmlChar_from_wchar(name);
1691 /* prevent empty href to be allocated */
1692 href = namespaceURI ? xmlChar_from_wchar(namespaceURI) : NULL;
1694 switch(node_type)
1696 case NODE_ELEMENT:
1698 xmlChar *local, *prefix;
1700 local = xmlSplitQName2(xml_name, &prefix);
1702 xmlnode = xmlNewDocNode(get_doc(This), NULL, local ? local : xml_name, NULL);
1704 /* allow to create default namespace xmlns= */
1705 if (local || (href && *href))
1707 xmlNsPtr ns = xmlNewNs(xmlnode, href, prefix);
1708 xmlSetNs(xmlnode, ns);
1711 xmlFree(local);
1712 xmlFree(prefix);
1714 break;
1716 case NODE_ATTRIBUTE:
1717 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1718 break;
1719 case NODE_TEXT:
1720 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1721 break;
1722 case NODE_CDATA_SECTION:
1723 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1724 break;
1725 case NODE_ENTITY_REFERENCE:
1726 xmlnode = xmlNewReference(get_doc(This), xml_name);
1727 break;
1728 case NODE_PROCESSING_INSTRUCTION:
1729 #ifdef HAVE_XMLNEWDOCPI
1730 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1731 #else
1732 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1733 xmlnode = NULL;
1734 #endif
1735 break;
1736 case NODE_COMMENT:
1737 xmlnode = xmlNewDocComment(get_doc(This), NULL);
1738 break;
1739 case NODE_DOCUMENT_FRAGMENT:
1740 xmlnode = xmlNewDocFragment(get_doc(This));
1741 break;
1742 /* unsupported types */
1743 case NODE_DOCUMENT:
1744 case NODE_DOCUMENT_TYPE:
1745 case NODE_ENTITY:
1746 case NODE_NOTATION:
1747 heap_free(xml_name);
1748 return E_INVALIDARG;
1749 default:
1750 FIXME("unhandled node type %d\n", node_type);
1751 xmlnode = NULL;
1752 break;
1755 *node = create_node(xmlnode);
1756 heap_free(xml_name);
1757 heap_free(href);
1759 if(*node)
1761 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1762 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1763 return S_OK;
1766 return E_FAIL;
1769 static HRESULT WINAPI domdoc_nodeFromID(
1770 IXMLDOMDocument3 *iface,
1771 BSTR idString,
1772 IXMLDOMNode** node )
1774 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1775 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1776 return E_NOTIMPL;
1779 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1781 domdoc *This = obj;
1782 xmlDocPtr xmldoc;
1784 xmldoc = doparse(This, ptr, len);
1785 if(xmldoc) {
1786 xmldoc->_private = create_priv();
1787 return attach_xmldoc(This, xmldoc);
1790 return S_OK;
1793 static HRESULT doread( domdoc *This, LPWSTR filename )
1795 bsc_t *bsc;
1796 HRESULT hr;
1798 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1799 if(FAILED(hr))
1800 return hr;
1802 if(This->bsc)
1803 detach_bsc(This->bsc);
1805 This->bsc = bsc;
1806 return S_OK;
1809 static HRESULT WINAPI domdoc_load(
1810 IXMLDOMDocument3 *iface,
1811 VARIANT xmlSource,
1812 VARIANT_BOOL* isSuccessful )
1814 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1815 LPWSTR filename = NULL;
1816 HRESULT hr = S_FALSE;
1817 IXMLDOMDocument3 *pNewDoc = NULL;
1818 IStream *pStream = NULL;
1819 xmlDocPtr xmldoc;
1821 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
1823 *isSuccessful = VARIANT_FALSE;
1825 assert( &This->node );
1827 switch( V_VT(&xmlSource) )
1829 case VT_BSTR:
1830 filename = V_BSTR(&xmlSource);
1831 break;
1832 case VT_UNKNOWN:
1833 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
1834 if(hr == S_OK)
1836 if(pNewDoc)
1838 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
1839 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1840 hr = attach_xmldoc(This, xmldoc);
1842 if(SUCCEEDED(hr))
1843 *isSuccessful = VARIANT_TRUE;
1845 return hr;
1848 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1849 if(hr == S_OK)
1851 IPersistStream *pDocStream;
1852 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1853 if(hr == S_OK)
1855 hr = IPersistStream_Load(pDocStream, pStream);
1856 IStream_Release(pStream);
1857 if(hr == S_OK)
1859 *isSuccessful = VARIANT_TRUE;
1861 TRACE("Using IStream to load Document\n");
1862 return S_OK;
1864 else
1866 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1869 else
1871 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1874 else
1876 /* ISequentialStream */
1877 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1879 break;
1880 default:
1881 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1884 TRACE("filename (%s)\n", debugstr_w(filename));
1886 if ( filename )
1888 hr = doread( This, filename );
1890 if ( FAILED(hr) )
1891 This->error = E_FAIL;
1892 else
1894 hr = This->error = S_OK;
1895 *isSuccessful = VARIANT_TRUE;
1899 if(!filename || FAILED(hr)) {
1900 xmldoc = xmlNewDoc(NULL);
1901 xmldoc->_private = create_priv();
1902 hr = attach_xmldoc(This, xmldoc);
1903 if(SUCCEEDED(hr))
1904 hr = S_FALSE;
1907 TRACE("ret (%d)\n", hr);
1909 return hr;
1913 static HRESULT WINAPI domdoc_get_readyState(
1914 IXMLDOMDocument3 *iface,
1915 LONG *value )
1917 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1918 FIXME("stub! (%p)->(%p)\n", This, value);
1920 if (!value)
1921 return E_INVALIDARG;
1923 *value = READYSTATE_COMPLETE;
1924 return S_OK;
1928 static HRESULT WINAPI domdoc_get_parseError(
1929 IXMLDOMDocument3 *iface,
1930 IXMLDOMParseError** errorObj )
1932 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1933 static const WCHAR err[] = {'e','r','r','o','r',0};
1934 BSTR error_string = NULL;
1936 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
1938 if(This->error)
1939 error_string = SysAllocString(err);
1941 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
1942 if(!*errorObj) return E_OUTOFMEMORY;
1943 return S_OK;
1947 static HRESULT WINAPI domdoc_get_url(
1948 IXMLDOMDocument3 *iface,
1949 BSTR* urlString )
1951 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1952 FIXME("(%p)->(%p)\n", This, urlString);
1953 return E_NOTIMPL;
1957 static HRESULT WINAPI domdoc_get_async(
1958 IXMLDOMDocument3 *iface,
1959 VARIANT_BOOL* isAsync )
1961 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1963 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
1964 *isAsync = This->async;
1965 return S_OK;
1969 static HRESULT WINAPI domdoc_put_async(
1970 IXMLDOMDocument3 *iface,
1971 VARIANT_BOOL isAsync )
1973 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1975 TRACE("(%p)->(%d)\n", This, isAsync);
1976 This->async = isAsync;
1977 return S_OK;
1981 static HRESULT WINAPI domdoc_abort(
1982 IXMLDOMDocument3 *iface )
1984 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1985 FIXME("%p\n", This);
1986 return E_NOTIMPL;
1990 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
1992 UINT len;
1993 LPSTR str;
1995 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
1996 str = heap_alloc( len );
1997 if ( !str )
1998 return FALSE;
1999 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
2000 *plen = len;
2001 *pstr = str;
2002 return TRUE;
2005 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
2006 static HRESULT WINAPI domdoc_loadXML(
2007 IXMLDOMDocument3 *iface,
2008 BSTR bstrXML,
2009 VARIANT_BOOL* isSuccessful )
2011 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2012 xmlDocPtr xmldoc = NULL;
2013 HRESULT hr = S_FALSE, hr2;
2014 char *str;
2015 int len;
2017 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
2019 assert ( &This->node );
2021 if ( isSuccessful )
2023 *isSuccessful = VARIANT_FALSE;
2025 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
2027 xmldoc = doparse(This, str, len);
2028 heap_free( str );
2029 if ( !xmldoc )
2030 This->error = E_FAIL;
2031 else
2033 hr = This->error = S_OK;
2034 *isSuccessful = VARIANT_TRUE;
2035 TRACE("parsed document %p\n", xmldoc);
2039 if(!xmldoc)
2040 xmldoc = xmlNewDoc(NULL);
2042 xmldoc->_private = create_priv();
2044 hr2 = attach_xmldoc(This, xmldoc);
2045 if( FAILED(hr2) )
2046 hr = hr2;
2048 return hr;
2051 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer,
2052 int len)
2054 DWORD written = -1;
2056 if(!WriteFile(ctx, buffer, len, &written, NULL))
2058 WARN("write error\n");
2059 return -1;
2061 else
2062 return written;
2065 static int XMLCALL domdoc_save_closecallback(void *ctx)
2067 return CloseHandle(ctx) ? 0 : -1;
2070 static HRESULT WINAPI domdoc_save(
2071 IXMLDOMDocument3 *iface,
2072 VARIANT destination )
2074 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2075 HANDLE handle;
2076 xmlSaveCtxtPtr ctx;
2077 xmlNodePtr xmldecl;
2078 HRESULT ret = S_OK;
2080 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
2081 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
2083 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
2085 FIXME("Unhandled vt %d\n", V_VT(&destination));
2086 return S_FALSE;
2089 if(V_VT(&destination) == VT_UNKNOWN)
2091 IUnknown *pUnk = V_UNKNOWN(&destination);
2092 IXMLDOMDocument2 *pDocument;
2094 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&pDocument);
2095 if(ret == S_OK)
2097 VARIANT_BOOL success;
2098 BSTR xml;
2100 ret = IXMLDOMDocument3_get_xml(iface, &xml);
2101 if(ret == S_OK)
2103 ret = IXMLDOMDocument3_loadXML(pDocument, xml, &success);
2104 SysFreeString(xml);
2107 IXMLDOMDocument3_Release(pDocument);
2110 TRACE("ret %d\n", ret);
2112 return ret;
2115 handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
2116 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
2117 if( handle == INVALID_HANDLE_VALUE )
2119 WARN("failed to create file\n");
2120 return S_FALSE;
2123 /* disable top XML declaration */
2124 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
2125 handle, NULL, XML_SAVE_NO_DECL);
2126 if (!ctx)
2128 CloseHandle(handle);
2129 return S_FALSE;
2132 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
2133 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
2134 xmldoc_link_xmldecl(get_doc(This), xmldecl);
2136 /* will close file through close callback */
2137 xmlSaveClose(ctx);
2139 return ret;
2142 static HRESULT WINAPI domdoc_get_validateOnParse(
2143 IXMLDOMDocument3 *iface,
2144 VARIANT_BOOL* isValidating )
2146 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2147 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
2148 *isValidating = This->validating;
2149 return S_OK;
2153 static HRESULT WINAPI domdoc_put_validateOnParse(
2154 IXMLDOMDocument3 *iface,
2155 VARIANT_BOOL isValidating )
2157 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2158 TRACE("(%p)->(%d)\n", This, isValidating);
2159 This->validating = isValidating;
2160 return S_OK;
2164 static HRESULT WINAPI domdoc_get_resolveExternals(
2165 IXMLDOMDocument3 *iface,
2166 VARIANT_BOOL* isResolving )
2168 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2169 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
2170 *isResolving = This->resolving;
2171 return S_OK;
2175 static HRESULT WINAPI domdoc_put_resolveExternals(
2176 IXMLDOMDocument3 *iface,
2177 VARIANT_BOOL isResolving )
2179 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2180 TRACE("(%p)->(%d)\n", This, isResolving);
2181 This->resolving = isResolving;
2182 return S_OK;
2186 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
2187 IXMLDOMDocument3 *iface,
2188 VARIANT_BOOL* isPreserving )
2190 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2191 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->preserving);
2192 *isPreserving = This->preserving;
2193 return S_OK;
2197 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
2198 IXMLDOMDocument3 *iface,
2199 VARIANT_BOOL isPreserving )
2201 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2202 TRACE("(%p)->(%d)\n", This, isPreserving);
2203 This->preserving = isPreserving;
2204 return S_OK;
2208 static HRESULT WINAPI domdoc_put_onReadyStateChange(
2209 IXMLDOMDocument3 *iface,
2210 VARIANT readyStateChangeSink )
2212 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2213 FIXME("%p\n", This);
2214 return E_NOTIMPL;
2218 static HRESULT WINAPI domdoc_put_onDataAvailable(
2219 IXMLDOMDocument3 *iface,
2220 VARIANT onDataAvailableSink )
2222 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2223 FIXME("%p\n", This);
2224 return E_NOTIMPL;
2227 static HRESULT WINAPI domdoc_put_onTransformNode(
2228 IXMLDOMDocument3 *iface,
2229 VARIANT onTransformNodeSink )
2231 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2232 FIXME("%p\n", This);
2233 return E_NOTIMPL;
2236 static HRESULT WINAPI domdoc_get_namespaces(
2237 IXMLDOMDocument3* iface,
2238 IXMLDOMSchemaCollection** schemaCollection )
2240 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2241 FIXME("(%p)->(%p)\n", This, schemaCollection);
2242 return E_NOTIMPL;
2245 static HRESULT WINAPI domdoc_get_schemas(
2246 IXMLDOMDocument3* iface,
2247 VARIANT* var1 )
2249 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2250 HRESULT hr = S_FALSE;
2251 IXMLDOMSchemaCollection *cur_schema = This->schema;
2253 TRACE("(%p)->(%p)\n", This, var1);
2255 VariantInit(var1); /* Test shows we don't call VariantClear here */
2256 V_VT(var1) = VT_NULL;
2258 if(cur_schema)
2260 hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
2261 if(SUCCEEDED(hr))
2262 V_VT(var1) = VT_DISPATCH;
2264 return hr;
2267 static HRESULT WINAPI domdoc_putref_schemas(
2268 IXMLDOMDocument3* iface,
2269 VARIANT var1)
2271 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2272 HRESULT hr = E_FAIL;
2273 IXMLDOMSchemaCollection *new_schema = NULL;
2275 FIXME("(%p): semi-stub\n", This);
2276 switch(V_VT(&var1))
2278 case VT_UNKNOWN:
2279 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2280 break;
2282 case VT_DISPATCH:
2283 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2284 break;
2286 case VT_NULL:
2287 case VT_EMPTY:
2288 hr = S_OK;
2289 break;
2291 default:
2292 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2295 if(SUCCEEDED(hr))
2297 IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
2298 if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
2301 return hr;
2304 static HRESULT WINAPI domdoc_validate(
2305 IXMLDOMDocument3* iface,
2306 IXMLDOMParseError** err)
2308 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2309 LONG state;
2310 xmlValidCtxtPtr vctx;
2312 TRACE("(%p)->(%p)\n", This, err);
2313 domdoc_get_readyState(iface, &state);
2314 if (state != READYSTATE_COMPLETE)
2316 if (err)
2317 *err = create_parseError(0, NULL, NULL, NULL, 0, 0, 0);
2318 return E_PENDING;
2321 vctx = xmlNewValidCtxt();
2322 vctx->error = NULL; /* TODO: error callback */
2323 vctx->warning = NULL; /* TODO: warning callback */
2325 if (xmlValidateDocument(vctx, get_doc(This)))
2327 if (err)
2328 *err = create_parseError(0, NULL, NULL, NULL, 0, 0, 0);
2329 xmlFreeValidCtxt(vctx);
2330 return S_OK;
2333 FIXME("partial stub!\n");
2334 if (err)
2335 *err = create_parseError(0xC00CE223, NULL, NULL, NULL, 0, 0, 0);
2336 xmlFreeValidCtxt(vctx);
2337 return S_FALSE;
2340 static HRESULT WINAPI domdoc_setProperty(
2341 IXMLDOMDocument3* iface,
2342 BSTR p,
2343 VARIANT var)
2345 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2347 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2349 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2351 VARIANT varStr;
2352 HRESULT hr;
2353 BSTR bstr;
2355 V_VT(&varStr) = VT_EMPTY;
2356 if (V_VT(&var) != VT_BSTR)
2358 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2359 return hr;
2360 bstr = V_BSTR(&varStr);
2362 else
2363 bstr = V_BSTR(&var);
2365 hr = S_OK;
2366 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2367 This->properties->XPath = TRUE;
2368 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2369 This->properties->XPath = FALSE;
2370 else
2371 hr = E_FAIL;
2373 VariantClear(&varStr);
2374 return hr;
2376 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2378 VARIANT varStr;
2379 HRESULT hr;
2380 BSTR bstr;
2381 xmlChar *pTokBegin, *pTokEnd, *pTokInner;
2382 xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr;
2383 xmlXPathContextPtr ctx;
2384 struct list *pNsList;
2385 select_ns_entry* pNsEntry = NULL;
2387 V_VT(&varStr) = VT_EMPTY;
2388 if (V_VT(&var) != VT_BSTR)
2390 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2391 return hr;
2392 bstr = V_BSTR(&varStr);
2394 else
2395 bstr = V_BSTR(&var);
2397 hr = S_OK;
2399 pNsList = &(This->properties->selectNsList);
2400 clear_selectNsList(pNsList);
2401 heap_free(nsStr);
2402 nsStr = xmlChar_from_wchar(bstr);
2405 TRACE("Setting SelectionNamespaces property to: %s\n", nsStr);
2407 This->properties->selectNsStr = nsStr;
2408 This->properties->selectNsStr_len = xmlStrlen(nsStr);
2409 if (bstr && *bstr)
2411 ctx = xmlXPathNewContext(This->node.node->doc);
2412 pTokBegin = nsStr;
2413 pTokEnd = nsStr;
2414 for (; *pTokBegin; pTokBegin = pTokEnd)
2416 if (pNsEntry != NULL)
2417 memset(pNsEntry, 0, sizeof(select_ns_entry));
2418 else
2419 pNsEntry = heap_alloc_zero(sizeof(select_ns_entry));
2421 while (*pTokBegin == ' ')
2422 ++pTokBegin;
2423 pTokEnd = pTokBegin;
2424 while (*pTokEnd != ' ' && *pTokEnd != 0)
2425 ++pTokEnd;
2427 if (xmlStrncmp(pTokBegin, (xmlChar const*)"xmlns", 5) != 0)
2429 hr = E_FAIL;
2430 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2431 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2432 continue;
2435 pTokBegin += 5;
2436 if (*pTokBegin == '=')
2438 /*valid for XSLPattern?*/
2439 FIXME("Setting default xmlns not supported - skipping.\n");
2440 pTokBegin = pTokEnd;
2441 continue;
2443 else if (*pTokBegin == ':')
2445 pNsEntry->prefix = ++pTokBegin;
2446 for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner)
2449 if (pTokInner == pTokEnd)
2451 hr = E_FAIL;
2452 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2453 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokBegin, pTokEnd-pTokBegin));
2454 continue;
2457 pNsEntry->prefix_end = *pTokInner;
2458 *pTokInner = 0;
2459 ++pTokInner;
2461 if (pTokEnd-pTokInner > 1 &&
2462 ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') ||
2463 (*pTokInner == '"' && *(pTokEnd-1) == '"')))
2465 pNsEntry->href = ++pTokInner;
2466 pNsEntry->href_end = *(pTokEnd-1);
2467 *(pTokEnd-1) = 0;
2468 list_add_tail(pNsList, &pNsEntry->entry);
2469 /*let libxml figure out if they're valid from here ;)*/
2470 if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0)
2472 hr = E_FAIL;
2474 pNsEntry = NULL;
2475 continue;
2477 else
2479 WARN("Syntax error in xmlns string: %s\n\tat token: %s\n",
2480 wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner));
2481 list_add_tail(pNsList, &pNsEntry->entry);
2483 pNsEntry = NULL;
2484 hr = E_FAIL;
2485 continue;
2488 else
2490 hr = E_FAIL;
2491 continue;
2494 heap_free(pNsEntry);
2495 xmlXPathFreeContext(ctx);
2498 VariantClear(&varStr);
2499 return hr;
2501 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0 ||
2502 lstrcmpiW(p, PropertyNewParserW) == 0)
2504 /* Ignore */
2505 FIXME("Ignoring property %s, value %d\n", debugstr_w(p), V_BOOL(&var));
2506 return S_OK;
2509 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2510 return E_FAIL;
2513 static HRESULT WINAPI domdoc_getProperty(
2514 IXMLDOMDocument3* iface,
2515 BSTR p,
2516 VARIANT* var)
2518 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2520 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2522 if (!var)
2523 return E_INVALIDARG;
2525 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2527 V_VT(var) = VT_BSTR;
2528 V_BSTR(var) = This->properties->XPath ?
2529 SysAllocString(PropValueXPathW) :
2530 SysAllocString(PropValueXSLPatternW);
2531 return V_BSTR(var) ? S_OK : E_OUTOFMEMORY;
2533 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2535 int lenA, lenW;
2536 BSTR rebuiltStr, cur;
2537 const xmlChar *nsStr;
2538 struct list *pNsList;
2539 select_ns_entry* pNsEntry;
2541 V_VT(var) = VT_BSTR;
2542 nsStr = This->properties->selectNsStr;
2543 pNsList = &This->properties->selectNsList;
2544 lenA = This->properties->selectNsStr_len;
2545 lenW = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, NULL, 0);
2546 rebuiltStr = heap_alloc(lenW*sizeof(WCHAR));
2547 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)nsStr, lenA+1, rebuiltStr, lenW);
2548 cur = rebuiltStr;
2549 /* this is fine because all of the chars that end tokens are ASCII*/
2550 LIST_FOR_EACH_ENTRY(pNsEntry, pNsList, select_ns_entry, entry)
2552 while (*cur != 0) ++cur;
2553 if (pNsEntry->prefix_end)
2555 *cur = pNsEntry->prefix_end;
2556 while (*cur != 0) ++cur;
2559 if (pNsEntry->href_end)
2561 *cur = pNsEntry->href_end;
2564 V_BSTR(var) = SysAllocString(rebuiltStr);
2565 heap_free(rebuiltStr);
2566 return S_OK;
2569 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2570 return E_FAIL;
2573 static HRESULT WINAPI domdoc_validateNode(
2574 IXMLDOMDocument3* iface,
2575 IXMLDOMNode* node,
2576 IXMLDOMParseError** error)
2578 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2579 FIXME("(%p)->(%p %p): stub\n", This, node, error);
2580 return E_NOTIMPL;
2583 static HRESULT WINAPI domdoc_importNode(
2584 IXMLDOMDocument3* iface,
2585 IXMLDOMNode* node,
2586 VARIANT_BOOL deep,
2587 IXMLDOMNode** clone)
2589 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2590 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
2591 return E_NOTIMPL;
2594 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
2596 domdoc_QueryInterface,
2597 domdoc_AddRef,
2598 domdoc_Release,
2599 domdoc_GetTypeInfoCount,
2600 domdoc_GetTypeInfo,
2601 domdoc_GetIDsOfNames,
2602 domdoc_Invoke,
2603 domdoc_get_nodeName,
2604 domdoc_get_nodeValue,
2605 domdoc_put_nodeValue,
2606 domdoc_get_nodeType,
2607 domdoc_get_parentNode,
2608 domdoc_get_childNodes,
2609 domdoc_get_firstChild,
2610 domdoc_get_lastChild,
2611 domdoc_get_previousSibling,
2612 domdoc_get_nextSibling,
2613 domdoc_get_attributes,
2614 domdoc_insertBefore,
2615 domdoc_replaceChild,
2616 domdoc_removeChild,
2617 domdoc_appendChild,
2618 domdoc_hasChildNodes,
2619 domdoc_get_ownerDocument,
2620 domdoc_cloneNode,
2621 domdoc_get_nodeTypeString,
2622 domdoc_get_text,
2623 domdoc_put_text,
2624 domdoc_get_specified,
2625 domdoc_get_definition,
2626 domdoc_get_nodeTypedValue,
2627 domdoc_put_nodeTypedValue,
2628 domdoc_get_dataType,
2629 domdoc_put_dataType,
2630 domdoc_get_xml,
2631 domdoc_transformNode,
2632 domdoc_selectNodes,
2633 domdoc_selectSingleNode,
2634 domdoc_get_parsed,
2635 domdoc_get_namespaceURI,
2636 domdoc_get_prefix,
2637 domdoc_get_baseName,
2638 domdoc_transformNodeToObject,
2639 domdoc_get_doctype,
2640 domdoc_get_implementation,
2641 domdoc_get_documentElement,
2642 domdoc_put_documentElement,
2643 domdoc_createElement,
2644 domdoc_createDocumentFragment,
2645 domdoc_createTextNode,
2646 domdoc_createComment,
2647 domdoc_createCDATASection,
2648 domdoc_createProcessingInstruction,
2649 domdoc_createAttribute,
2650 domdoc_createEntityReference,
2651 domdoc_getElementsByTagName,
2652 domdoc_createNode,
2653 domdoc_nodeFromID,
2654 domdoc_load,
2655 domdoc_get_readyState,
2656 domdoc_get_parseError,
2657 domdoc_get_url,
2658 domdoc_get_async,
2659 domdoc_put_async,
2660 domdoc_abort,
2661 domdoc_loadXML,
2662 domdoc_save,
2663 domdoc_get_validateOnParse,
2664 domdoc_put_validateOnParse,
2665 domdoc_get_resolveExternals,
2666 domdoc_put_resolveExternals,
2667 domdoc_get_preserveWhiteSpace,
2668 domdoc_put_preserveWhiteSpace,
2669 domdoc_put_onReadyStateChange,
2670 domdoc_put_onDataAvailable,
2671 domdoc_put_onTransformNode,
2672 domdoc_get_namespaces,
2673 domdoc_get_schemas,
2674 domdoc_putref_schemas,
2675 domdoc_validate,
2676 domdoc_setProperty,
2677 domdoc_getProperty,
2678 domdoc_validateNode,
2679 domdoc_importNode
2682 /* xmldoc implementation of IObjectWithSite */
2683 static HRESULT WINAPI
2684 xmldoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
2686 domdoc *This = impl_from_IObjectWithSite(iface);
2687 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppvObject );
2690 static ULONG WINAPI
2691 xmldoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
2693 domdoc *This = impl_from_IObjectWithSite(iface);
2694 return IXMLDocument_AddRef((IXMLDocument *)This);
2697 static ULONG WINAPI
2698 xmldoc_ObjectWithSite_Release( IObjectWithSite* iface )
2700 domdoc *This = impl_from_IObjectWithSite(iface);
2701 return IXMLDocument_Release((IXMLDocument *)This);
2704 static HRESULT WINAPI
2705 xmldoc_GetSite( IObjectWithSite *iface, REFIID iid, void ** ppvSite )
2707 domdoc *This = impl_from_IObjectWithSite(iface);
2709 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
2711 if ( !This->site )
2712 return E_FAIL;
2714 return IUnknown_QueryInterface( This->site, iid, ppvSite );
2717 static HRESULT WINAPI
2718 xmldoc_SetSite( IObjectWithSite *iface, IUnknown *punk )
2720 domdoc *This = impl_from_IObjectWithSite(iface);
2722 TRACE("(%p)->(%p)\n", iface, punk);
2724 if(!punk)
2726 if(This->site)
2728 IUnknown_Release( This->site );
2729 This->site = NULL;
2732 return S_OK;
2735 IUnknown_AddRef( punk );
2737 if(This->site)
2738 IUnknown_Release( This->site );
2740 This->site = punk;
2742 return S_OK;
2745 static const IObjectWithSiteVtbl domdocObjectSite =
2747 xmldoc_ObjectWithSite_QueryInterface,
2748 xmldoc_ObjectWithSite_AddRef,
2749 xmldoc_ObjectWithSite_Release,
2750 xmldoc_SetSite,
2751 xmldoc_GetSite,
2754 static HRESULT WINAPI xmldoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
2756 domdoc *This = impl_from_IObjectSafety(iface);
2757 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppv );
2760 static ULONG WINAPI xmldoc_Safety_AddRef(IObjectSafety *iface)
2762 domdoc *This = impl_from_IObjectSafety(iface);
2763 return IXMLDocument_AddRef((IXMLDocument *)This);
2766 static ULONG WINAPI xmldoc_Safety_Release(IObjectSafety *iface)
2768 domdoc *This = impl_from_IObjectSafety(iface);
2769 return IXMLDocument_Release((IXMLDocument *)This);
2772 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
2774 static HRESULT WINAPI xmldoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2775 DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
2777 domdoc *This = impl_from_IObjectSafety(iface);
2779 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
2781 if(!pdwSupportedOptions || !pdwEnabledOptions)
2782 return E_POINTER;
2784 *pdwSupportedOptions = SAFETY_SUPPORTED_OPTIONS;
2785 *pdwEnabledOptions = This->safeopt;
2787 return S_OK;
2790 static HRESULT WINAPI xmldoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2791 DWORD dwOptionSetMask, DWORD dwEnabledOptions)
2793 domdoc *This = impl_from_IObjectSafety(iface);
2794 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
2796 if ((dwOptionSetMask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
2797 return E_FAIL;
2799 This->safeopt = dwEnabledOptions & dwOptionSetMask & SAFETY_SUPPORTED_OPTIONS;
2800 return S_OK;
2803 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
2804 xmldoc_Safety_QueryInterface,
2805 xmldoc_Safety_AddRef,
2806 xmldoc_Safety_Release,
2807 xmldoc_Safety_GetInterfaceSafetyOptions,
2808 xmldoc_Safety_SetInterfaceSafetyOptions
2812 static const tid_t domdoc_iface_tids[] = {
2813 IXMLDOMNode_tid,
2814 IXMLDOMDocument_tid,
2815 IXMLDOMDocument2_tid,
2818 static dispex_static_data_t domdoc_dispex = {
2819 NULL,
2820 IXMLDOMDocument2_tid,
2821 NULL,
2822 domdoc_iface_tids
2825 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
2827 domdoc *doc;
2829 doc = heap_alloc( sizeof (*doc) );
2830 if( !doc )
2831 return E_OUTOFMEMORY;
2833 doc->lpVtbl = &domdoc_vtbl;
2834 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
2835 doc->lpvtblIObjectWithSite = &domdocObjectSite;
2836 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
2837 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
2838 doc->ref = 1;
2839 doc->async = VARIANT_TRUE;
2840 doc->validating = 0;
2841 doc->resolving = 0;
2842 doc->preserving = 0;
2843 doc->properties = properties_from_xmlDocPtr(xmldoc);
2844 doc->error = S_OK;
2845 doc->schema = NULL;
2846 doc->stream = NULL;
2847 doc->site = NULL;
2848 doc->safeopt = 0;
2849 doc->bsc = NULL;
2851 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IXMLDOMNode*)&doc->lpVtbl, &domdoc_dispex);
2853 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
2855 TRACE("returning iface %p\n", *document);
2856 return S_OK;
2859 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
2861 xmlDocPtr xmldoc;
2862 HRESULT hr;
2864 TRACE("(%s, %p, %p)\n", debugstr_guid(clsid), pUnkOuter, ppObj);
2866 xmldoc = xmlNewDoc(NULL);
2867 if(!xmldoc)
2868 return E_OUTOFMEMORY;
2870 xmldoc->_private = create_priv();
2871 priv_from_xmlDocPtr(xmldoc)->properties = create_properties(clsid);
2873 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
2874 if(FAILED(hr))
2876 xmlFreeDoc(xmldoc);
2877 return hr;
2880 return hr;
2883 IUnknown* create_domdoc( xmlNodePtr document )
2885 void* pObj = NULL;
2886 HRESULT hr;
2888 TRACE("(%p)\n", document);
2890 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
2891 if (FAILED(hr))
2892 return NULL;
2894 return pObj;
2897 #else
2899 HRESULT DOMDocument_create(const GUID *clsid, IUnknown *pUnkOuter, void **ppObj)
2901 MESSAGE("This program tried to use a DOMDocument object, but\n"
2902 "libxml2 support was not present at compile time.\n");
2903 return E_NOTIMPL;
2906 #endif