msxml3: Don't crash on null pointer when doing ::Next() on a last child.
[wine/testsucceed.git] / dlls / msxml3 / domdoc.c
blob4808e4e00c959eb8024d84f1d501c998052c8e15
1 /*
2 * DOM Document implementation
4 * Copyright 2005 Mike McCormack
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
22 #define NONAMELESSUNION
24 #include "config.h"
26 #include <stdarg.h>
27 #include <assert.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "winnls.h"
32 #include "ole2.h"
33 #include "msxml2.h"
34 #include "wininet.h"
35 #include "winreg.h"
36 #include "shlwapi.h"
37 #include "ocidl.h"
38 #include "objsafe.h"
39 #include "dispex.h"
41 #include "wine/debug.h"
42 #include "wine/list.h"
44 #include "msxml_private.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
48 #ifdef HAVE_LIBXML2
50 #include <libxml/xmlsave.h>
52 /* not defined in older versions */
53 #define XML_SAVE_FORMAT 1
54 #define XML_SAVE_NO_DECL 2
55 #define XML_SAVE_NO_EMPTY 4
56 #define XML_SAVE_NO_XHTML 8
57 #define XML_SAVE_XHTML 16
58 #define XML_SAVE_AS_XML 32
59 #define XML_SAVE_AS_HTML 64
61 static const WCHAR SZ_PROPERTY_SELECTION_LANGUAGE[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
62 static const WCHAR SZ_VALUE_XPATH[] = {'X','P','a','t','h',0};
63 static const WCHAR SZ_VALUE_XSLPATTERN[] = {'X','S','L','P','a','t','t','e','r','n',0};
65 typedef struct _domdoc
67 xmlnode node;
68 const struct IXMLDOMDocument2Vtbl *lpVtbl;
69 const struct IPersistStreamVtbl *lpvtblIPersistStream;
70 const struct IObjectWithSiteVtbl *lpvtblIObjectWithSite;
71 const struct IObjectSafetyVtbl *lpvtblIObjectSafety;
72 const struct ISupportErrorInfoVtbl *lpvtblISupportErrorInfo;
73 LONG ref;
74 VARIANT_BOOL async;
75 VARIANT_BOOL validating;
76 VARIANT_BOOL resolving;
77 VARIANT_BOOL preserving;
78 BOOL bUseXPath;
79 IXMLDOMSchemaCollection *schema;
80 bsc_t *bsc;
81 HRESULT error;
83 /* IPersistStream */
84 IStream *stream;
86 /* IObjectWithSite*/
87 IUnknown *site;
89 /* IObjectSafety */
90 DWORD safeopt;
91 } domdoc;
94 In native windows, the whole lifetime management of XMLDOMNodes is
95 managed automatically using reference counts. Wine emulates that by
96 maintaining a reference count to the document that is increased for
97 each IXMLDOMNode pointer passed out for this document. If all these
98 pointers are gone, the document is unreachable and gets freed, that
99 is, all nodes in the tree of the document get freed.
101 You are able to create nodes that are associated to a document (in
102 fact, in msxml's XMLDOM model, all nodes are associated to a document),
103 but not in the tree of that document, for example using the createFoo
104 functions from IXMLDOMDocument. These nodes do not get cleaned up
105 by libxml, so we have to do it ourselves.
107 To catch these nodes, a list of "orphan nodes" is introduced.
108 It contains pointers to all roots of node trees that are
109 associated with the document without being part of the document
110 tree. All nodes with parent==NULL (except for the document root nodes)
111 should be in the orphan node list of their document. All orphan nodes
112 get freed together with the document itself.
115 typedef struct _xmldoc_priv {
116 LONG refs;
117 struct list orphans;
118 } xmldoc_priv;
120 typedef struct _orphan_entry {
121 struct list entry;
122 xmlNode * node;
123 } orphan_entry;
125 static inline xmldoc_priv * priv_from_xmlDocPtr(xmlDocPtr doc)
127 return doc->_private;
130 static xmldoc_priv * create_priv(void)
132 xmldoc_priv *priv;
133 priv = heap_alloc( sizeof (*priv) );
135 if(priv)
137 priv->refs = 0;
138 list_init( &priv->orphans );
141 return priv;
144 static xmlDocPtr doparse( char *ptr, int len, const char *encoding )
146 #ifdef HAVE_XMLREADMEMORY
148 * use xmlReadMemory if possible so we can suppress
149 * writing errors to stderr
151 return xmlReadMemory( ptr, len, NULL, encoding,
152 XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS );
153 #else
154 return xmlParseMemory( ptr, len );
155 #endif
158 LONG xmldoc_add_ref(xmlDocPtr doc)
160 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
161 TRACE("%d\n", ref);
162 return ref;
165 LONG xmldoc_release(xmlDocPtr doc)
167 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
168 LONG ref = InterlockedDecrement(&priv->refs);
169 TRACE("%d\n", ref);
170 if(ref == 0)
172 orphan_entry *orphan, *orphan2;
173 TRACE("freeing docptr %p\n", doc);
175 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
177 xmlFreeNode( orphan->node );
178 heap_free( orphan );
180 heap_free(doc->_private);
182 xmlFreeDoc(doc);
185 return ref;
188 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
190 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
191 orphan_entry *entry;
193 entry = heap_alloc( sizeof (*entry) );
194 if(!entry)
195 return E_OUTOFMEMORY;
197 entry->node = node;
198 list_add_head( &priv->orphans, &entry->entry );
199 return S_OK;
202 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
204 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
205 orphan_entry *entry, *entry2;
207 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
209 if( entry->node == node )
211 list_remove( &entry->entry );
212 heap_free( entry );
213 return S_OK;
217 return S_FALSE;
220 static HRESULT attach_xmldoc( xmlnode *node, xmlDocPtr xml )
222 if(node->node)
223 xmldoc_release(node->node->doc);
225 node->node = (xmlNodePtr) xml;
226 if(node->node)
227 xmldoc_add_ref(node->node->doc);
229 return S_OK;
232 static inline domdoc *impl_from_IXMLDOMDocument2( IXMLDOMDocument2 *iface )
234 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
237 static inline xmlDocPtr get_doc( domdoc *This )
239 return (xmlDocPtr)This->node.node;
242 static inline domdoc *impl_from_IPersistStream(IPersistStream *iface)
244 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStream));
247 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
249 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
252 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
254 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
257 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
259 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblISupportErrorInfo));
262 /************************************************************************
263 * xmldoc implementation of IPersistStream.
265 static HRESULT WINAPI xmldoc_IPersistStream_QueryInterface(
266 IPersistStream *iface, REFIID riid, LPVOID *ppvObj)
268 domdoc *this = impl_from_IPersistStream(iface);
269 return IXMLDocument_QueryInterface((IXMLDocument *)this, riid, ppvObj);
272 static ULONG WINAPI xmldoc_IPersistStream_AddRef(
273 IPersistStream *iface)
275 domdoc *this = impl_from_IPersistStream(iface);
276 return IXMLDocument_AddRef((IXMLDocument *)this);
279 static ULONG WINAPI xmldoc_IPersistStream_Release(
280 IPersistStream *iface)
282 domdoc *this = impl_from_IPersistStream(iface);
283 return IXMLDocument_Release((IXMLDocument *)this);
286 static HRESULT WINAPI xmldoc_IPersistStream_GetClassID(
287 IPersistStream *iface, CLSID *classid)
289 TRACE("(%p,%p): stub!\n", iface, classid);
291 if(!classid)
292 return E_POINTER;
294 *classid = CLSID_DOMDocument2;
296 return S_OK;
299 static HRESULT WINAPI xmldoc_IPersistStream_IsDirty(
300 IPersistStream *iface)
302 domdoc *This = impl_from_IPersistStream(iface);
304 FIXME("(%p): stub!\n", This);
306 return S_FALSE;
309 static HRESULT WINAPI xmldoc_IPersistStream_Load(
310 IPersistStream *iface, LPSTREAM pStm)
312 domdoc *This = impl_from_IPersistStream(iface);
313 HRESULT hr;
314 HGLOBAL hglobal;
315 DWORD read, written, len;
316 BYTE buf[4096];
317 char *ptr;
318 xmlDocPtr xmldoc = NULL;
320 TRACE("(%p)->(%p)\n", This, pStm);
322 if (!pStm)
323 return E_INVALIDARG;
325 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
326 if (FAILED(hr))
327 return hr;
331 IStream_Read(pStm, buf, sizeof(buf), &read);
332 hr = IStream_Write(This->stream, buf, read, &written);
333 } while(SUCCEEDED(hr) && written != 0 && read != 0);
335 if (FAILED(hr))
337 ERR("Failed to copy stream\n");
338 return hr;
341 hr = GetHGlobalFromStream(This->stream, &hglobal);
342 if (FAILED(hr))
343 return hr;
345 len = GlobalSize(hglobal);
346 ptr = GlobalLock(hglobal);
347 if (len != 0)
348 xmldoc = parse_xml(ptr, len);
349 GlobalUnlock(hglobal);
351 if (!xmldoc)
353 ERR("Failed to parse xml\n");
354 return E_FAIL;
357 xmldoc->_private = create_priv();
359 return attach_xmldoc( &This->node, xmldoc );
362 static HRESULT WINAPI xmldoc_IPersistStream_Save(
363 IPersistStream *iface, LPSTREAM pStm, BOOL fClearDirty)
365 domdoc *This = impl_from_IPersistStream(iface);
366 HRESULT hr;
367 BSTR xmlString;
369 TRACE("(%p)->(%p %d)\n", This, pStm, fClearDirty);
371 hr = IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), &xmlString );
372 if(hr == S_OK)
374 DWORD count;
375 DWORD len = strlenW(xmlString) * sizeof(WCHAR);
377 hr = IStream_Write( pStm, xmlString, len, &count );
379 SysFreeString(xmlString);
382 TRACE("ret 0x%08x\n", hr);
384 return hr;
387 static HRESULT WINAPI xmldoc_IPersistStream_GetSizeMax(
388 IPersistStream *iface, ULARGE_INTEGER *pcbSize)
390 domdoc *This = impl_from_IPersistStream(iface);
391 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
392 return E_NOTIMPL;
395 static const IPersistStreamVtbl xmldoc_IPersistStream_VTable =
397 xmldoc_IPersistStream_QueryInterface,
398 xmldoc_IPersistStream_AddRef,
399 xmldoc_IPersistStream_Release,
400 xmldoc_IPersistStream_GetClassID,
401 xmldoc_IPersistStream_IsDirty,
402 xmldoc_IPersistStream_Load,
403 xmldoc_IPersistStream_Save,
404 xmldoc_IPersistStream_GetSizeMax,
407 /* ISupportErrorInfo interface */
408 static HRESULT WINAPI support_error_QueryInterface(
409 ISupportErrorInfo *iface,
410 REFIID riid, void** ppvObj )
412 domdoc *This = impl_from_ISupportErrorInfo(iface);
413 return IXMLDocument_QueryInterface((IXMLDocument *)This, riid, ppvObj);
416 static ULONG WINAPI support_error_AddRef(
417 ISupportErrorInfo *iface )
419 domdoc *This = impl_from_ISupportErrorInfo(iface);
420 return IXMLDocument_AddRef((IXMLDocument *)This);
423 static ULONG WINAPI support_error_Release(
424 ISupportErrorInfo *iface )
426 domdoc *This = impl_from_ISupportErrorInfo(iface);
427 return IXMLDocument_Release((IXMLDocument *)This);
430 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
431 ISupportErrorInfo *iface,
432 REFIID riid )
434 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
435 return S_FALSE;
438 static const struct ISupportErrorInfoVtbl support_error_vtbl =
440 support_error_QueryInterface,
441 support_error_AddRef,
442 support_error_Release,
443 support_error_InterfaceSupportsErrorInfo
446 /* IXMLDOMDocument2 interface */
447 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument2 *iface, REFIID riid, void** ppvObject )
449 domdoc *This = impl_from_IXMLDOMDocument2( iface );
451 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
453 *ppvObject = NULL;
455 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
456 IsEqualGUID( riid, &IID_IDispatch ) ||
457 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
458 IsEqualGUID( riid, &IID_IXMLDOMDocument2 ) )
460 *ppvObject = iface;
462 else if ( IsEqualGUID( riid, &IID_IXMLDOMNode ) )
464 *ppvObject = IXMLDOMNode_from_impl(&This->node);
466 else if (IsEqualGUID(&IID_IPersistStream, riid))
468 *ppvObject = &(This->lpvtblIPersistStream);
470 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
472 *ppvObject = &(This->lpvtblIObjectWithSite);
474 else if (IsEqualGUID(&IID_IObjectSafety, riid))
476 *ppvObject = &(This->lpvtblIObjectSafety);
478 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
480 *ppvObject = &This->lpvtblISupportErrorInfo;
482 else if(dispex_query_interface(&This->node.dispex, riid, ppvObject))
484 return *ppvObject ? S_OK : E_NOINTERFACE;
486 else if(IsEqualGUID(&IID_IRunnableObject, riid))
488 TRACE("IID_IRunnableObject not supported returning NULL\n");
489 return E_NOINTERFACE;
491 else
493 FIXME("interface %s not implemented\n", debugstr_guid(riid));
494 return E_NOINTERFACE;
497 IUnknown_AddRef((IUnknown*)*ppvObject);
499 return S_OK;
503 static ULONG WINAPI domdoc_AddRef(
504 IXMLDOMDocument2 *iface )
506 domdoc *This = impl_from_IXMLDOMDocument2( iface );
507 TRACE("%p\n", This );
508 return InterlockedIncrement( &This->ref );
512 static ULONG WINAPI domdoc_Release(
513 IXMLDOMDocument2 *iface )
515 domdoc *This = impl_from_IXMLDOMDocument2( iface );
516 LONG ref;
518 TRACE("%p\n", This );
520 ref = InterlockedDecrement( &This->ref );
521 if ( ref == 0 )
523 if(This->bsc)
524 detach_bsc(This->bsc);
526 if (This->site)
527 IUnknown_Release( This->site );
528 destroy_xmlnode(&This->node);
529 if(This->schema) IXMLDOMSchemaCollection_Release( This->schema );
530 if (This->stream) IStream_Release(This->stream);
531 HeapFree( GetProcessHeap(), 0, This );
534 return ref;
537 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument2 *iface, UINT* pctinfo )
539 domdoc *This = impl_from_IXMLDOMDocument2( iface );
541 TRACE("(%p)->(%p)\n", This, pctinfo);
543 *pctinfo = 1;
545 return S_OK;
548 static HRESULT WINAPI domdoc_GetTypeInfo(
549 IXMLDOMDocument2 *iface,
550 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
552 domdoc *This = impl_from_IXMLDOMDocument2( iface );
553 HRESULT hr;
555 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
557 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
559 return hr;
562 static HRESULT WINAPI domdoc_GetIDsOfNames(
563 IXMLDOMDocument2 *iface,
564 REFIID riid,
565 LPOLESTR* rgszNames,
566 UINT cNames,
567 LCID lcid,
568 DISPID* rgDispId)
570 domdoc *This = impl_from_IXMLDOMDocument2( iface );
571 ITypeInfo *typeinfo;
572 HRESULT hr;
574 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
575 lcid, rgDispId);
577 if(!rgszNames || cNames == 0 || !rgDispId)
578 return E_INVALIDARG;
580 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
581 if(SUCCEEDED(hr))
583 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
584 ITypeInfo_Release(typeinfo);
587 return hr;
591 static HRESULT WINAPI domdoc_Invoke(
592 IXMLDOMDocument2 *iface,
593 DISPID dispIdMember,
594 REFIID riid,
595 LCID lcid,
596 WORD wFlags,
597 DISPPARAMS* pDispParams,
598 VARIANT* pVarResult,
599 EXCEPINFO* pExcepInfo,
600 UINT* puArgErr)
602 domdoc *This = impl_from_IXMLDOMDocument2( iface );
603 ITypeInfo *typeinfo;
604 HRESULT hr;
606 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
607 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
609 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
610 if(SUCCEEDED(hr))
612 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
613 pVarResult, pExcepInfo, puArgErr);
614 ITypeInfo_Release(typeinfo);
617 return hr;
621 static HRESULT WINAPI domdoc_get_nodeName(
622 IXMLDOMDocument2 *iface,
623 BSTR* name )
625 domdoc *This = impl_from_IXMLDOMDocument2( iface );
626 return IXMLDOMNode_get_nodeName( IXMLDOMNode_from_impl(&This->node), name );
630 static HRESULT WINAPI domdoc_get_nodeValue(
631 IXMLDOMDocument2 *iface,
632 VARIANT* value )
634 domdoc *This = impl_from_IXMLDOMDocument2( iface );
635 return IXMLDOMNode_get_nodeValue( IXMLDOMNode_from_impl(&This->node), value );
639 static HRESULT WINAPI domdoc_put_nodeValue(
640 IXMLDOMDocument2 *iface,
641 VARIANT value)
643 domdoc *This = impl_from_IXMLDOMDocument2( iface );
644 return IXMLDOMNode_put_nodeValue( IXMLDOMNode_from_impl(&This->node), value );
648 static HRESULT WINAPI domdoc_get_nodeType(
649 IXMLDOMDocument2 *iface,
650 DOMNodeType* type )
652 domdoc *This = impl_from_IXMLDOMDocument2( iface );
653 return IXMLDOMNode_get_nodeType( IXMLDOMNode_from_impl(&This->node), type );
657 static HRESULT WINAPI domdoc_get_parentNode(
658 IXMLDOMDocument2 *iface,
659 IXMLDOMNode** parent )
661 domdoc *This = impl_from_IXMLDOMDocument2( iface );
662 return IXMLDOMNode_get_parentNode( IXMLDOMNode_from_impl(&This->node), parent );
666 static HRESULT WINAPI domdoc_get_childNodes(
667 IXMLDOMDocument2 *iface,
668 IXMLDOMNodeList** childList )
670 domdoc *This = impl_from_IXMLDOMDocument2( iface );
671 return IXMLDOMNode_get_childNodes( IXMLDOMNode_from_impl(&This->node), childList );
675 static HRESULT WINAPI domdoc_get_firstChild(
676 IXMLDOMDocument2 *iface,
677 IXMLDOMNode** firstChild )
679 domdoc *This = impl_from_IXMLDOMDocument2( iface );
680 return IXMLDOMNode_get_firstChild( IXMLDOMNode_from_impl(&This->node), firstChild );
684 static HRESULT WINAPI domdoc_get_lastChild(
685 IXMLDOMDocument2 *iface,
686 IXMLDOMNode** lastChild )
688 domdoc *This = impl_from_IXMLDOMDocument2( iface );
689 return IXMLDOMNode_get_lastChild( IXMLDOMNode_from_impl(&This->node), lastChild );
693 static HRESULT WINAPI domdoc_get_previousSibling(
694 IXMLDOMDocument2 *iface,
695 IXMLDOMNode** previousSibling )
697 domdoc *This = impl_from_IXMLDOMDocument2( iface );
698 return IXMLDOMNode_get_previousSibling( IXMLDOMNode_from_impl(&This->node), previousSibling );
702 static HRESULT WINAPI domdoc_get_nextSibling(
703 IXMLDOMDocument2 *iface,
704 IXMLDOMNode** nextSibling )
706 domdoc *This = impl_from_IXMLDOMDocument2( iface );
707 return IXMLDOMNode_get_nextSibling( IXMLDOMNode_from_impl(&This->node), nextSibling );
711 static HRESULT WINAPI domdoc_get_attributes(
712 IXMLDOMDocument2 *iface,
713 IXMLDOMNamedNodeMap** attributeMap )
715 domdoc *This = impl_from_IXMLDOMDocument2( iface );
716 return IXMLDOMNode_get_attributes( IXMLDOMNode_from_impl(&This->node), attributeMap );
720 static HRESULT WINAPI domdoc_insertBefore(
721 IXMLDOMDocument2 *iface,
722 IXMLDOMNode* newChild,
723 VARIANT refChild,
724 IXMLDOMNode** outNewChild )
726 domdoc *This = impl_from_IXMLDOMDocument2( iface );
727 return IXMLDOMNode_insertBefore( IXMLDOMNode_from_impl(&This->node), newChild, refChild, outNewChild );
731 static HRESULT WINAPI domdoc_replaceChild(
732 IXMLDOMDocument2 *iface,
733 IXMLDOMNode* newChild,
734 IXMLDOMNode* oldChild,
735 IXMLDOMNode** outOldChild)
737 domdoc *This = impl_from_IXMLDOMDocument2( iface );
738 return IXMLDOMNode_replaceChild( IXMLDOMNode_from_impl(&This->node), newChild, oldChild, outOldChild );
742 static HRESULT WINAPI domdoc_removeChild(
743 IXMLDOMDocument2 *iface,
744 IXMLDOMNode* childNode,
745 IXMLDOMNode** oldChild)
747 domdoc *This = impl_from_IXMLDOMDocument2( iface );
748 return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), childNode, oldChild );
752 static HRESULT WINAPI domdoc_appendChild(
753 IXMLDOMDocument2 *iface,
754 IXMLDOMNode* newChild,
755 IXMLDOMNode** outNewChild)
757 domdoc *This = impl_from_IXMLDOMDocument2( iface );
758 return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newChild, outNewChild );
762 static HRESULT WINAPI domdoc_hasChildNodes(
763 IXMLDOMDocument2 *iface,
764 VARIANT_BOOL* hasChild)
766 domdoc *This = impl_from_IXMLDOMDocument2( iface );
767 return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), hasChild );
771 static HRESULT WINAPI domdoc_get_ownerDocument(
772 IXMLDOMDocument2 *iface,
773 IXMLDOMDocument** DOMDocument)
775 domdoc *This = impl_from_IXMLDOMDocument2( iface );
776 return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), DOMDocument );
780 static HRESULT WINAPI domdoc_cloneNode(
781 IXMLDOMDocument2 *iface,
782 VARIANT_BOOL deep,
783 IXMLDOMNode** cloneRoot)
785 domdoc *This = impl_from_IXMLDOMDocument2( iface );
786 return IXMLDOMNode_cloneNode( IXMLDOMNode_from_impl(&This->node), deep, cloneRoot );
790 static HRESULT WINAPI domdoc_get_nodeTypeString(
791 IXMLDOMDocument2 *iface,
792 BSTR* nodeType )
794 domdoc *This = impl_from_IXMLDOMDocument2( iface );
795 return IXMLDOMNode_get_nodeTypeString( IXMLDOMNode_from_impl(&This->node), nodeType );
799 static HRESULT WINAPI domdoc_get_text(
800 IXMLDOMDocument2 *iface,
801 BSTR* text )
803 domdoc *This = impl_from_IXMLDOMDocument2( iface );
804 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), text );
808 static HRESULT WINAPI domdoc_put_text(
809 IXMLDOMDocument2 *iface,
810 BSTR text )
812 domdoc *This = impl_from_IXMLDOMDocument2( iface );
813 return IXMLDOMNode_put_text( IXMLDOMNode_from_impl(&This->node), text );
817 static HRESULT WINAPI domdoc_get_specified(
818 IXMLDOMDocument2 *iface,
819 VARIANT_BOOL* isSpecified )
821 domdoc *This = impl_from_IXMLDOMDocument2( iface );
822 return IXMLDOMNode_get_specified( IXMLDOMNode_from_impl(&This->node), isSpecified );
826 static HRESULT WINAPI domdoc_get_definition(
827 IXMLDOMDocument2 *iface,
828 IXMLDOMNode** definitionNode )
830 domdoc *This = impl_from_IXMLDOMDocument2( iface );
831 return IXMLDOMNode_get_definition( IXMLDOMNode_from_impl(&This->node), definitionNode );
835 static HRESULT WINAPI domdoc_get_nodeTypedValue(
836 IXMLDOMDocument2 *iface,
837 VARIANT* typedValue )
839 domdoc *This = impl_from_IXMLDOMDocument2( iface );
840 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
843 static HRESULT WINAPI domdoc_put_nodeTypedValue(
844 IXMLDOMDocument2 *iface,
845 VARIANT typedValue )
847 domdoc *This = impl_from_IXMLDOMDocument2( iface );
848 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
852 static HRESULT WINAPI domdoc_get_dataType(
853 IXMLDOMDocument2 *iface,
854 VARIANT* dataTypeName )
856 domdoc *This = impl_from_IXMLDOMDocument2( iface );
857 return IXMLDOMNode_get_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
861 static HRESULT WINAPI domdoc_put_dataType(
862 IXMLDOMDocument2 *iface,
863 BSTR dataTypeName )
865 domdoc *This = impl_from_IXMLDOMDocument2( iface );
866 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
870 static HRESULT WINAPI domdoc_get_xml(
871 IXMLDOMDocument2 *iface,
872 BSTR* xmlString )
874 domdoc *This = impl_from_IXMLDOMDocument2( iface );
875 return IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), xmlString );
879 static HRESULT WINAPI domdoc_transformNode(
880 IXMLDOMDocument2 *iface,
881 IXMLDOMNode* styleSheet,
882 BSTR* xmlString )
884 domdoc *This = impl_from_IXMLDOMDocument2( iface );
885 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), styleSheet, xmlString );
889 static HRESULT WINAPI domdoc_selectNodes(
890 IXMLDOMDocument2 *iface,
891 BSTR queryString,
892 IXMLDOMNodeList** resultList )
894 domdoc *This = impl_from_IXMLDOMDocument2( iface );
895 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), queryString, resultList );
899 static HRESULT WINAPI domdoc_selectSingleNode(
900 IXMLDOMDocument2 *iface,
901 BSTR queryString,
902 IXMLDOMNode** resultNode )
904 domdoc *This = impl_from_IXMLDOMDocument2( iface );
905 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), queryString, resultNode );
909 static HRESULT WINAPI domdoc_get_parsed(
910 IXMLDOMDocument2 *iface,
911 VARIANT_BOOL* isParsed )
913 domdoc *This = impl_from_IXMLDOMDocument2( iface );
914 return IXMLDOMNode_get_parsed( IXMLDOMNode_from_impl(&This->node), isParsed );
918 static HRESULT WINAPI domdoc_get_namespaceURI(
919 IXMLDOMDocument2 *iface,
920 BSTR* namespaceURI )
922 domdoc *This = impl_from_IXMLDOMDocument2( iface );
923 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), namespaceURI );
927 static HRESULT WINAPI domdoc_get_prefix(
928 IXMLDOMDocument2 *iface,
929 BSTR* prefixString )
931 domdoc *This = impl_from_IXMLDOMDocument2( iface );
932 return IXMLDOMNode_get_prefix( IXMLDOMNode_from_impl(&This->node), prefixString );
936 static HRESULT WINAPI domdoc_get_baseName(
937 IXMLDOMDocument2 *iface,
938 BSTR* nameString )
940 domdoc *This = impl_from_IXMLDOMDocument2( iface );
941 return IXMLDOMNode_get_baseName( IXMLDOMNode_from_impl(&This->node), nameString );
945 static HRESULT WINAPI domdoc_transformNodeToObject(
946 IXMLDOMDocument2 *iface,
947 IXMLDOMNode* stylesheet,
948 VARIANT outputObject)
950 domdoc *This = impl_from_IXMLDOMDocument2( iface );
951 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), stylesheet, outputObject );
955 static HRESULT WINAPI domdoc_get_doctype(
956 IXMLDOMDocument2 *iface,
957 IXMLDOMDocumentType** documentType )
959 domdoc *This = impl_from_IXMLDOMDocument2(iface);
960 FIXME("(%p)\n", This);
961 return E_NOTIMPL;
965 static HRESULT WINAPI domdoc_get_implementation(
966 IXMLDOMDocument2 *iface,
967 IXMLDOMImplementation** impl )
969 domdoc *This = impl_from_IXMLDOMDocument2(iface);
971 TRACE("(%p)->(%p)\n", This, impl);
973 if(!impl)
974 return E_INVALIDARG;
976 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
978 return S_OK;
981 static HRESULT WINAPI domdoc_get_documentElement(
982 IXMLDOMDocument2 *iface,
983 IXMLDOMElement** DOMElement )
985 domdoc *This = impl_from_IXMLDOMDocument2( iface );
986 xmlDocPtr xmldoc = NULL;
987 xmlNodePtr root = NULL;
988 IXMLDOMNode *element_node;
989 HRESULT hr;
991 TRACE("(%p)->(%p)\n", This, DOMElement);
993 if(!DOMElement)
994 return E_INVALIDARG;
996 *DOMElement = NULL;
998 xmldoc = get_doc( This );
1000 root = xmlDocGetRootElement( xmldoc );
1001 if ( !root )
1002 return S_FALSE;
1004 element_node = create_node( root );
1005 if(!element_node) return S_FALSE;
1007 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (LPVOID*)DOMElement);
1008 IXMLDOMNode_Release(element_node);
1010 return hr;
1014 static HRESULT WINAPI domdoc_put_documentElement(
1015 IXMLDOMDocument2 *iface,
1016 IXMLDOMElement* DOMElement )
1018 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1019 IXMLDOMNode *elementNode;
1020 xmlNodePtr oldRoot;
1021 xmlnode *xmlNode;
1022 HRESULT hr;
1024 TRACE("(%p)->(%p)\n", This, DOMElement);
1026 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1027 if(FAILED(hr))
1028 return hr;
1030 xmlNode = impl_from_IXMLDOMNode( elementNode );
1032 if(!xmlNode->node->parent)
1033 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1034 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1036 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1037 IXMLDOMNode_Release( elementNode );
1039 if(oldRoot)
1040 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1042 return S_OK;
1046 static HRESULT WINAPI domdoc_createElement(
1047 IXMLDOMDocument2 *iface,
1048 BSTR tagname,
1049 IXMLDOMElement** element )
1051 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1052 IXMLDOMNode *node;
1053 VARIANT type;
1054 HRESULT hr;
1056 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1058 if (!element || !tagname) return E_INVALIDARG;
1060 V_VT(&type) = VT_I1;
1061 V_I1(&type) = NODE_ELEMENT;
1063 hr = IXMLDOMDocument_createNode(iface, type, tagname, NULL, &node);
1064 if (hr == S_OK)
1066 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1067 IXMLDOMNode_Release(node);
1070 return hr;
1074 static HRESULT WINAPI domdoc_createDocumentFragment(
1075 IXMLDOMDocument2 *iface,
1076 IXMLDOMDocumentFragment** frag )
1078 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1079 IXMLDOMNode *node;
1080 VARIANT type;
1081 HRESULT hr;
1083 TRACE("(%p)->(%p)\n", This, frag);
1085 if (!frag) return E_INVALIDARG;
1087 *frag = NULL;
1089 V_VT(&type) = VT_I1;
1090 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1092 hr = IXMLDOMDocument_createNode(iface, type, NULL, NULL, &node);
1093 if (hr == S_OK)
1095 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1096 IXMLDOMNode_Release(node);
1099 return hr;
1103 static HRESULT WINAPI domdoc_createTextNode(
1104 IXMLDOMDocument2 *iface,
1105 BSTR data,
1106 IXMLDOMText** text )
1108 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1109 IXMLDOMNode *node;
1110 VARIANT type;
1111 HRESULT hr;
1113 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1115 if (!text) return E_INVALIDARG;
1117 *text = NULL;
1119 V_VT(&type) = VT_I1;
1120 V_I1(&type) = NODE_TEXT;
1122 hr = IXMLDOMDocument2_createNode(iface, type, NULL, NULL, &node);
1123 if (hr == S_OK)
1125 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1126 IXMLDOMNode_Release(node);
1127 hr = IXMLDOMText_put_data(*text, data);
1130 return hr;
1134 static HRESULT WINAPI domdoc_createComment(
1135 IXMLDOMDocument2 *iface,
1136 BSTR data,
1137 IXMLDOMComment** comment )
1139 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1140 VARIANT type;
1141 HRESULT hr;
1142 IXMLDOMNode *node;
1144 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1146 if (!comment) return E_INVALIDARG;
1148 *comment = NULL;
1150 V_VT(&type) = VT_I1;
1151 V_I1(&type) = NODE_COMMENT;
1153 hr = IXMLDOMDocument2_createNode(iface, type, NULL, NULL, &node);
1154 if (hr == S_OK)
1156 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1157 IXMLDOMNode_Release(node);
1158 hr = IXMLDOMComment_put_data(*comment, data);
1161 return hr;
1165 static HRESULT WINAPI domdoc_createCDATASection(
1166 IXMLDOMDocument2 *iface,
1167 BSTR data,
1168 IXMLDOMCDATASection** cdata )
1170 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1171 IXMLDOMNode *node;
1172 VARIANT type;
1173 HRESULT hr;
1175 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1177 if (!cdata) return E_INVALIDARG;
1179 *cdata = NULL;
1181 V_VT(&type) = VT_I1;
1182 V_I1(&type) = NODE_CDATA_SECTION;
1184 hr = IXMLDOMDocument2_createNode(iface, type, NULL, NULL, &node);
1185 if (hr == S_OK)
1187 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1188 IXMLDOMNode_Release(node);
1189 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1192 return hr;
1196 static HRESULT WINAPI domdoc_createProcessingInstruction(
1197 IXMLDOMDocument2 *iface,
1198 BSTR target,
1199 BSTR data,
1200 IXMLDOMProcessingInstruction** pi )
1202 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1203 IXMLDOMNode *node;
1204 VARIANT type;
1205 HRESULT hr;
1207 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1209 if (!pi) return E_INVALIDARG;
1211 *pi = NULL;
1213 V_VT(&type) = VT_I1;
1214 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1216 hr = IXMLDOMDocument2_createNode(iface, type, target, NULL, &node);
1217 if (hr == S_OK)
1219 VARIANT v_data;
1221 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1222 V_VT(&v_data) = VT_BSTR;
1223 V_BSTR(&v_data) = data;
1225 hr = IXMLDOMNode_put_nodeValue( node, v_data );
1227 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1228 IXMLDOMNode_Release(node);
1231 return hr;
1235 static HRESULT WINAPI domdoc_createAttribute(
1236 IXMLDOMDocument2 *iface,
1237 BSTR name,
1238 IXMLDOMAttribute** attribute )
1240 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1241 IXMLDOMNode *node;
1242 VARIANT type;
1243 HRESULT hr;
1245 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1247 if (!attribute || !name) return E_INVALIDARG;
1249 V_VT(&type) = VT_I1;
1250 V_I1(&type) = NODE_ATTRIBUTE;
1252 hr = IXMLDOMDocument_createNode(iface, type, name, NULL, &node);
1253 if (hr == S_OK)
1255 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1256 IXMLDOMNode_Release(node);
1259 return hr;
1263 static HRESULT WINAPI domdoc_createEntityReference(
1264 IXMLDOMDocument2 *iface,
1265 BSTR name,
1266 IXMLDOMEntityReference** entityref )
1268 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1269 IXMLDOMNode *node;
1270 VARIANT type;
1271 HRESULT hr;
1273 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1275 if (!entityref) return E_INVALIDARG;
1277 *entityref = NULL;
1279 V_VT(&type) = VT_I1;
1280 V_I1(&type) = NODE_ENTITY_REFERENCE;
1282 hr = IXMLDOMDocument2_createNode(iface, type, name, NULL, &node);
1283 if (hr == S_OK)
1285 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1286 IXMLDOMNode_Release(node);
1289 return hr;
1293 static HRESULT WINAPI domdoc_getElementsByTagName(
1294 IXMLDOMDocument2 *iface,
1295 BSTR tagName,
1296 IXMLDOMNodeList** resultList )
1298 static const WCHAR xpathformat[] =
1299 { '/','/','*','[','l','o','c','a','l','-','n','a','m','e','(',')','=','\'','%','s','\'',']',0 };
1300 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1301 LPWSTR szPattern;
1302 HRESULT hr;
1303 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagName), resultList);
1305 if (tagName[0] == '*' && tagName[1] == 0)
1307 szPattern = heap_alloc(sizeof(WCHAR)*4);
1308 szPattern[0] = szPattern[1] = '/';
1309 szPattern[2] = '*';
1310 szPattern[3] = 0;
1312 else
1314 szPattern = heap_alloc(sizeof(WCHAR)*(20+lstrlenW(tagName)+1));
1315 wsprintfW(szPattern, xpathformat, tagName);
1318 hr = queryresult_create((xmlNodePtr)get_doc(This), szPattern, resultList);
1319 heap_free(szPattern);
1321 return hr;
1324 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1326 VARIANT tmp;
1327 HRESULT hr;
1329 VariantInit(&tmp);
1330 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1331 if(FAILED(hr))
1332 return E_INVALIDARG;
1334 *type = V_I4(&tmp);
1336 return S_OK;
1339 static HRESULT WINAPI domdoc_createNode(
1340 IXMLDOMDocument2 *iface,
1341 VARIANT Type,
1342 BSTR name,
1343 BSTR namespaceURI,
1344 IXMLDOMNode** node )
1346 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1347 DOMNodeType node_type;
1348 xmlNodePtr xmlnode;
1349 xmlChar *xml_name;
1350 HRESULT hr;
1352 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1354 if(!node) return E_INVALIDARG;
1356 if(namespaceURI && namespaceURI[0])
1357 FIXME("nodes with namespaces currently not supported.\n");
1359 hr = get_node_type(Type, &node_type);
1360 if(FAILED(hr)) return hr;
1362 TRACE("node_type %d\n", node_type);
1364 /* exit earlier for types that need name */
1365 switch(node_type)
1367 case NODE_ELEMENT:
1368 case NODE_ATTRIBUTE:
1369 case NODE_ENTITY_REFERENCE:
1370 case NODE_PROCESSING_INSTRUCTION:
1371 if (!name || *name == 0) return E_FAIL;
1372 default:
1373 break;
1376 xml_name = xmlChar_from_wchar(name);
1378 switch(node_type)
1380 case NODE_ELEMENT:
1381 xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
1382 break;
1383 case NODE_ATTRIBUTE:
1384 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1385 break;
1386 case NODE_TEXT:
1387 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1388 break;
1389 case NODE_CDATA_SECTION:
1390 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1391 break;
1392 case NODE_ENTITY_REFERENCE:
1393 xmlnode = xmlNewReference(get_doc(This), xml_name);
1394 break;
1395 case NODE_PROCESSING_INSTRUCTION:
1396 #ifdef HAVE_XMLNEWDOCPI
1397 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1398 #else
1399 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1400 xmlnode = NULL;
1401 #endif
1402 break;
1403 case NODE_COMMENT:
1404 xmlnode = xmlNewDocComment(get_doc(This), NULL);
1405 break;
1406 case NODE_DOCUMENT_FRAGMENT:
1407 xmlnode = xmlNewDocFragment(get_doc(This));
1408 break;
1409 /* unsupported types */
1410 case NODE_DOCUMENT:
1411 case NODE_DOCUMENT_TYPE:
1412 case NODE_ENTITY:
1413 case NODE_NOTATION:
1414 heap_free(xml_name);
1415 return E_INVALIDARG;
1416 default:
1417 FIXME("unhandled node type %d\n", node_type);
1418 xmlnode = NULL;
1419 break;
1422 *node = create_node(xmlnode);
1423 heap_free(xml_name);
1425 if(*node)
1427 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1428 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1429 return S_OK;
1432 return E_FAIL;
1435 static HRESULT WINAPI domdoc_nodeFromID(
1436 IXMLDOMDocument2 *iface,
1437 BSTR idString,
1438 IXMLDOMNode** node )
1440 domdoc *This = impl_from_IXMLDOMDocument2(iface);
1441 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1442 return E_NOTIMPL;
1445 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1447 domdoc *This = obj;
1448 xmlDocPtr xmldoc;
1450 xmldoc = doparse( ptr, len, NULL );
1451 if(xmldoc) {
1452 xmldoc->_private = create_priv();
1453 return attach_xmldoc(&This->node, xmldoc);
1456 return S_OK;
1459 static HRESULT doread( domdoc *This, LPWSTR filename )
1461 bsc_t *bsc;
1462 HRESULT hr;
1464 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1465 if(FAILED(hr))
1466 return hr;
1468 if(This->bsc)
1469 detach_bsc(This->bsc);
1471 This->bsc = bsc;
1472 return S_OK;
1475 static HRESULT WINAPI domdoc_load(
1476 IXMLDOMDocument2 *iface,
1477 VARIANT xmlSource,
1478 VARIANT_BOOL* isSuccessful )
1480 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1481 LPWSTR filename = NULL;
1482 HRESULT hr = S_FALSE;
1483 IXMLDOMDocument2 *pNewDoc = NULL;
1484 IStream *pStream = NULL;
1485 xmlDocPtr xmldoc;
1487 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
1489 *isSuccessful = VARIANT_FALSE;
1491 assert( &This->node );
1493 switch( V_VT(&xmlSource) )
1495 case VT_BSTR:
1496 filename = V_BSTR(&xmlSource);
1497 break;
1498 case VT_UNKNOWN:
1499 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument2, (void**)&pNewDoc);
1500 if(hr == S_OK)
1502 if(pNewDoc)
1504 domdoc *newDoc = impl_from_IXMLDOMDocument2( pNewDoc );
1505 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1506 hr = attach_xmldoc(&This->node, xmldoc);
1508 if(SUCCEEDED(hr))
1509 *isSuccessful = VARIANT_TRUE;
1511 return hr;
1514 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1515 if(hr == S_OK)
1517 IPersistStream *pDocStream;
1518 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1519 if(hr == S_OK)
1521 hr = xmldoc_IPersistStream_Load(pDocStream, pStream);
1522 IStream_Release(pStream);
1523 if(hr == S_OK)
1525 *isSuccessful = VARIANT_TRUE;
1527 TRACE("Using ID_IStream to load Document\n");
1528 return S_OK;
1530 else
1532 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1535 else
1537 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1540 else
1542 /* ISequentialStream */
1543 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1545 break;
1546 default:
1547 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1550 TRACE("filename (%s)\n", debugstr_w(filename));
1552 if ( filename )
1554 hr = doread( This, filename );
1556 if ( FAILED(hr) )
1557 This->error = E_FAIL;
1558 else
1560 hr = This->error = S_OK;
1561 *isSuccessful = VARIANT_TRUE;
1565 if(!filename || FAILED(hr)) {
1566 xmldoc = xmlNewDoc(NULL);
1567 xmldoc->_private = create_priv();
1568 hr = attach_xmldoc(&This->node, xmldoc);
1569 if(SUCCEEDED(hr))
1570 hr = S_FALSE;
1573 TRACE("ret (%d)\n", hr);
1575 return hr;
1579 static HRESULT WINAPI domdoc_get_readyState(
1580 IXMLDOMDocument2 *iface,
1581 LONG *value )
1583 domdoc *This = impl_from_IXMLDOMDocument2(iface);
1584 FIXME("(%p)->(%p)\n", This, value);
1585 return E_NOTIMPL;
1589 static HRESULT WINAPI domdoc_get_parseError(
1590 IXMLDOMDocument2 *iface,
1591 IXMLDOMParseError** errorObj )
1593 BSTR error_string = NULL;
1594 static const WCHAR err[] = {'e','r','r','o','r',0};
1595 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1597 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
1599 if(This->error)
1600 error_string = SysAllocString(err);
1602 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
1603 if(!*errorObj) return E_OUTOFMEMORY;
1604 return S_OK;
1608 static HRESULT WINAPI domdoc_get_url(
1609 IXMLDOMDocument2 *iface,
1610 BSTR* urlString )
1612 domdoc *This = impl_from_IXMLDOMDocument2(iface);
1613 FIXME("(%p)->(%p)\n", This, urlString);
1614 return E_NOTIMPL;
1618 static HRESULT WINAPI domdoc_get_async(
1619 IXMLDOMDocument2 *iface,
1620 VARIANT_BOOL* isAsync )
1622 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1624 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
1625 *isAsync = This->async;
1626 return S_OK;
1630 static HRESULT WINAPI domdoc_put_async(
1631 IXMLDOMDocument2 *iface,
1632 VARIANT_BOOL isAsync )
1634 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1636 TRACE("(%p)->(%d)\n", This, isAsync);
1637 This->async = isAsync;
1638 return S_OK;
1642 static HRESULT WINAPI domdoc_abort(
1643 IXMLDOMDocument2 *iface )
1645 domdoc *This = impl_from_IXMLDOMDocument2(iface);
1646 FIXME("%p\n", This);
1647 return E_NOTIMPL;
1651 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
1653 UINT len;
1654 LPSTR str;
1656 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
1657 str = heap_alloc( len );
1658 if ( !str )
1659 return FALSE;
1660 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
1661 *plen = len;
1662 *pstr = str;
1663 return TRUE;
1666 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
1667 static HRESULT WINAPI domdoc_loadXML(
1668 IXMLDOMDocument2 *iface,
1669 BSTR bstrXML,
1670 VARIANT_BOOL* isSuccessful )
1672 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1673 xmlDocPtr xmldoc = NULL;
1674 char *str;
1675 int len;
1676 HRESULT hr = S_FALSE, hr2;
1678 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
1680 assert ( &This->node );
1682 if ( isSuccessful )
1684 *isSuccessful = VARIANT_FALSE;
1686 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
1688 xmldoc = doparse( str, len, "UTF-8" );
1689 heap_free( str );
1690 if ( !xmldoc )
1691 This->error = E_FAIL;
1692 else
1694 hr = This->error = S_OK;
1695 *isSuccessful = VARIANT_TRUE;
1699 if(!xmldoc)
1700 xmldoc = xmlNewDoc(NULL);
1702 xmldoc->_private = create_priv();
1703 hr2 = attach_xmldoc( &This->node, xmldoc );
1704 if( FAILED(hr2) )
1705 hr = hr2;
1707 return hr;
1710 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer,
1711 int len)
1713 DWORD written = -1;
1715 if(!WriteFile(ctx, buffer, len, &written, NULL))
1717 WARN("write error\n");
1718 return -1;
1720 else
1721 return written;
1724 static int XMLCALL domdoc_save_closecallback(void *ctx)
1726 return CloseHandle(ctx) ? 0 : -1;
1729 static HRESULT WINAPI domdoc_save(
1730 IXMLDOMDocument2 *iface,
1731 VARIANT destination )
1733 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1734 HANDLE handle;
1735 xmlSaveCtxtPtr ctx;
1736 HRESULT ret = S_OK;
1738 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
1739 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
1741 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
1743 FIXME("Unhandled vt %d\n", V_VT(&destination));
1744 return S_FALSE;
1747 if(V_VT(&destination) == VT_UNKNOWN)
1749 IUnknown *pUnk = V_UNKNOWN(&destination);
1750 IXMLDOMDocument *pDocument;
1752 ret = IXMLDOMDocument_QueryInterface(pUnk, &IID_IXMLDOMDocument2, (void**)&pDocument);
1753 if(ret == S_OK)
1755 BSTR bXML;
1756 VARIANT_BOOL bSuccessful;
1758 ret = IXMLDOMDocument_get_xml(iface, &bXML);
1759 if(ret == S_OK)
1761 ret = IXMLDOMDocument_loadXML(pDocument, bXML, &bSuccessful);
1763 SysFreeString(bXML);
1766 IXMLDOMDocument_Release(pDocument);
1769 TRACE("ret %d\n", ret);
1771 return ret;
1774 handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
1775 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1776 if( handle == INVALID_HANDLE_VALUE )
1778 WARN("failed to create file\n");
1779 return S_FALSE;
1782 /* disable top XML declaration */
1783 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
1784 handle, NULL, XML_SAVE_NO_DECL);
1785 if (!ctx)
1787 CloseHandle(handle);
1788 return S_FALSE;
1791 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
1792 /* will close file through close callback */
1793 xmlSaveClose(ctx);
1795 return ret;
1798 static HRESULT WINAPI domdoc_get_validateOnParse(
1799 IXMLDOMDocument2 *iface,
1800 VARIANT_BOOL* isValidating )
1802 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1804 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
1805 *isValidating = This->validating;
1806 return S_OK;
1810 static HRESULT WINAPI domdoc_put_validateOnParse(
1811 IXMLDOMDocument2 *iface,
1812 VARIANT_BOOL isValidating )
1814 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1816 TRACE("(%p)->(%d)\n", This, isValidating);
1817 This->validating = isValidating;
1818 return S_OK;
1822 static HRESULT WINAPI domdoc_get_resolveExternals(
1823 IXMLDOMDocument2 *iface,
1824 VARIANT_BOOL* isResolving )
1826 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1828 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
1829 *isResolving = This->resolving;
1830 return S_OK;
1834 static HRESULT WINAPI domdoc_put_resolveExternals(
1835 IXMLDOMDocument2 *iface,
1836 VARIANT_BOOL isResolving )
1838 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1840 TRACE("(%p)->(%d)\n", This, isResolving);
1841 This->resolving = isResolving;
1842 return S_OK;
1846 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
1847 IXMLDOMDocument2 *iface,
1848 VARIANT_BOOL* isPreserving )
1850 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1852 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->preserving);
1853 *isPreserving = This->preserving;
1854 return S_OK;
1858 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
1859 IXMLDOMDocument2 *iface,
1860 VARIANT_BOOL isPreserving )
1862 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1864 TRACE("(%p)->(%d)\n", This, isPreserving);
1865 This->preserving = isPreserving;
1866 return S_OK;
1870 static HRESULT WINAPI domdoc_put_onReadyStateChange(
1871 IXMLDOMDocument2 *iface,
1872 VARIANT readyStateChangeSink )
1874 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1875 FIXME("%p\n", This);
1876 return E_NOTIMPL;
1880 static HRESULT WINAPI domdoc_put_onDataAvailable(
1881 IXMLDOMDocument2 *iface,
1882 VARIANT onDataAvailableSink )
1884 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1885 FIXME("%p\n", This);
1886 return E_NOTIMPL;
1889 static HRESULT WINAPI domdoc_put_onTransformNode(
1890 IXMLDOMDocument2 *iface,
1891 VARIANT onTransformNodeSink )
1893 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1894 FIXME("%p\n", This);
1895 return E_NOTIMPL;
1898 static HRESULT WINAPI domdoc_get_namespaces(
1899 IXMLDOMDocument2* iface,
1900 IXMLDOMSchemaCollection** schemaCollection )
1902 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1903 FIXME("(%p)->(%p)\n", This, schemaCollection);
1904 return E_NOTIMPL;
1907 static HRESULT WINAPI domdoc_get_schemas(
1908 IXMLDOMDocument2* iface,
1909 VARIANT* var1 )
1911 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1912 HRESULT hr = S_FALSE;
1913 IXMLDOMSchemaCollection *cur_schema = This->schema;
1915 TRACE("(%p)->(%p)\n", This, var1);
1917 VariantInit(var1); /* Test shows we don't call VariantClear here */
1918 V_VT(var1) = VT_NULL;
1920 if(cur_schema)
1922 hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
1923 if(SUCCEEDED(hr))
1924 V_VT(var1) = VT_DISPATCH;
1926 return hr;
1929 static HRESULT WINAPI domdoc_putref_schemas(
1930 IXMLDOMDocument2* iface,
1931 VARIANT var1)
1933 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1934 HRESULT hr = E_FAIL;
1935 IXMLDOMSchemaCollection *new_schema = NULL;
1937 FIXME("(%p): semi-stub\n", This);
1938 switch(V_VT(&var1))
1940 case VT_UNKNOWN:
1941 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1942 break;
1944 case VT_DISPATCH:
1945 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1946 break;
1948 case VT_NULL:
1949 case VT_EMPTY:
1950 hr = S_OK;
1951 break;
1953 default:
1954 WARN("Can't get schema from vt %x\n", V_VT(&var1));
1957 if(SUCCEEDED(hr))
1959 IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
1960 if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
1963 return hr;
1966 static HRESULT WINAPI domdoc_validate(
1967 IXMLDOMDocument2* iface,
1968 IXMLDOMParseError** err)
1970 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1971 FIXME("(%p)->(%p)\n", This, err);
1972 return E_NOTIMPL;
1975 static HRESULT WINAPI domdoc_setProperty(
1976 IXMLDOMDocument2* iface,
1977 BSTR p,
1978 VARIANT var)
1980 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1982 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
1984 if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
1986 VARIANT varStr;
1987 HRESULT hr;
1988 BSTR bstr;
1990 V_VT(&varStr) = VT_EMPTY;
1991 if (V_VT(&var) != VT_BSTR)
1993 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
1994 return hr;
1995 bstr = V_BSTR(&varStr);
1997 else
1998 bstr = V_BSTR(&var);
2000 hr = S_OK;
2001 if (lstrcmpiW(bstr, SZ_VALUE_XPATH) == 0)
2002 This->bUseXPath = TRUE;
2003 else if (lstrcmpiW(bstr, SZ_VALUE_XSLPATTERN) == 0)
2004 This->bUseXPath = FALSE;
2005 else
2006 hr = E_FAIL;
2008 VariantClear(&varStr);
2009 return hr;
2012 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2013 return E_FAIL;
2016 static HRESULT WINAPI domdoc_getProperty(
2017 IXMLDOMDocument2* iface,
2018 BSTR p,
2019 VARIANT* var)
2021 domdoc *This = impl_from_IXMLDOMDocument2( iface );
2023 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2025 if (var == NULL)
2026 return E_INVALIDARG;
2027 if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
2029 V_VT(var) = VT_BSTR;
2030 if (This->bUseXPath)
2031 V_BSTR(var) = SysAllocString(SZ_VALUE_XPATH);
2032 else
2033 V_BSTR(var) = SysAllocString(SZ_VALUE_XSLPATTERN);
2034 return S_OK;
2037 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2038 return E_FAIL;
2041 static const struct IXMLDOMDocument2Vtbl domdoc_vtbl =
2043 domdoc_QueryInterface,
2044 domdoc_AddRef,
2045 domdoc_Release,
2046 domdoc_GetTypeInfoCount,
2047 domdoc_GetTypeInfo,
2048 domdoc_GetIDsOfNames,
2049 domdoc_Invoke,
2050 domdoc_get_nodeName,
2051 domdoc_get_nodeValue,
2052 domdoc_put_nodeValue,
2053 domdoc_get_nodeType,
2054 domdoc_get_parentNode,
2055 domdoc_get_childNodes,
2056 domdoc_get_firstChild,
2057 domdoc_get_lastChild,
2058 domdoc_get_previousSibling,
2059 domdoc_get_nextSibling,
2060 domdoc_get_attributes,
2061 domdoc_insertBefore,
2062 domdoc_replaceChild,
2063 domdoc_removeChild,
2064 domdoc_appendChild,
2065 domdoc_hasChildNodes,
2066 domdoc_get_ownerDocument,
2067 domdoc_cloneNode,
2068 domdoc_get_nodeTypeString,
2069 domdoc_get_text,
2070 domdoc_put_text,
2071 domdoc_get_specified,
2072 domdoc_get_definition,
2073 domdoc_get_nodeTypedValue,
2074 domdoc_put_nodeTypedValue,
2075 domdoc_get_dataType,
2076 domdoc_put_dataType,
2077 domdoc_get_xml,
2078 domdoc_transformNode,
2079 domdoc_selectNodes,
2080 domdoc_selectSingleNode,
2081 domdoc_get_parsed,
2082 domdoc_get_namespaceURI,
2083 domdoc_get_prefix,
2084 domdoc_get_baseName,
2085 domdoc_transformNodeToObject,
2086 domdoc_get_doctype,
2087 domdoc_get_implementation,
2088 domdoc_get_documentElement,
2089 domdoc_put_documentElement,
2090 domdoc_createElement,
2091 domdoc_createDocumentFragment,
2092 domdoc_createTextNode,
2093 domdoc_createComment,
2094 domdoc_createCDATASection,
2095 domdoc_createProcessingInstruction,
2096 domdoc_createAttribute,
2097 domdoc_createEntityReference,
2098 domdoc_getElementsByTagName,
2099 domdoc_createNode,
2100 domdoc_nodeFromID,
2101 domdoc_load,
2102 domdoc_get_readyState,
2103 domdoc_get_parseError,
2104 domdoc_get_url,
2105 domdoc_get_async,
2106 domdoc_put_async,
2107 domdoc_abort,
2108 domdoc_loadXML,
2109 domdoc_save,
2110 domdoc_get_validateOnParse,
2111 domdoc_put_validateOnParse,
2112 domdoc_get_resolveExternals,
2113 domdoc_put_resolveExternals,
2114 domdoc_get_preserveWhiteSpace,
2115 domdoc_put_preserveWhiteSpace,
2116 domdoc_put_onReadyStateChange,
2117 domdoc_put_onDataAvailable,
2118 domdoc_put_onTransformNode,
2119 domdoc_get_namespaces,
2120 domdoc_get_schemas,
2121 domdoc_putref_schemas,
2122 domdoc_validate,
2123 domdoc_setProperty,
2124 domdoc_getProperty
2127 /* xmldoc implementation of IObjectWithSite */
2128 static HRESULT WINAPI
2129 xmldoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
2131 domdoc *This = impl_from_IObjectWithSite(iface);
2132 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppvObject );
2135 static ULONG WINAPI
2136 xmldoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
2138 domdoc *This = impl_from_IObjectWithSite(iface);
2139 return IXMLDocument_AddRef((IXMLDocument *)This);
2142 static ULONG WINAPI
2143 xmldoc_ObjectWithSite_Release( IObjectWithSite* iface )
2145 domdoc *This = impl_from_IObjectWithSite(iface);
2146 return IXMLDocument_Release((IXMLDocument *)This);
2149 static HRESULT WINAPI
2150 xmldoc_GetSite( IObjectWithSite *iface, REFIID iid, void ** ppvSite )
2152 domdoc *This = impl_from_IObjectWithSite(iface);
2154 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
2156 if ( !This->site )
2157 return E_FAIL;
2159 return IUnknown_QueryInterface( This->site, iid, ppvSite );
2162 static HRESULT WINAPI
2163 xmldoc_SetSite( IObjectWithSite *iface, IUnknown *punk )
2165 domdoc *This = impl_from_IObjectWithSite(iface);
2167 TRACE("(%p)->(%p)\n", iface, punk);
2169 if(!punk)
2171 if(This->site)
2173 IUnknown_Release( This->site );
2174 This->site = NULL;
2177 return S_OK;
2180 IUnknown_AddRef( punk );
2182 if(This->site)
2183 IUnknown_Release( This->site );
2185 This->site = punk;
2187 return S_OK;
2190 static const IObjectWithSiteVtbl domdocObjectSite =
2192 xmldoc_ObjectWithSite_QueryInterface,
2193 xmldoc_ObjectWithSite_AddRef,
2194 xmldoc_ObjectWithSite_Release,
2195 xmldoc_SetSite,
2196 xmldoc_GetSite,
2199 static HRESULT WINAPI xmldoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
2201 domdoc *This = impl_from_IObjectSafety(iface);
2202 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppv );
2205 static ULONG WINAPI xmldoc_Safety_AddRef(IObjectSafety *iface)
2207 domdoc *This = impl_from_IObjectSafety(iface);
2208 return IXMLDocument_AddRef((IXMLDocument *)This);
2211 static ULONG WINAPI xmldoc_Safety_Release(IObjectSafety *iface)
2213 domdoc *This = impl_from_IObjectSafety(iface);
2214 return IXMLDocument_Release((IXMLDocument *)This);
2217 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
2219 static HRESULT WINAPI xmldoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2220 DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
2222 domdoc *This = impl_from_IObjectSafety(iface);
2224 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
2226 if(!pdwSupportedOptions || !pdwEnabledOptions)
2227 return E_POINTER;
2229 *pdwSupportedOptions = SAFETY_SUPPORTED_OPTIONS;
2230 *pdwEnabledOptions = This->safeopt;
2232 return S_OK;
2235 static HRESULT WINAPI xmldoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2236 DWORD dwOptionSetMask, DWORD dwEnabledOptions)
2238 domdoc *This = impl_from_IObjectSafety(iface);
2239 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
2241 if ((dwOptionSetMask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
2242 return E_FAIL;
2244 This->safeopt = dwEnabledOptions & dwOptionSetMask & SAFETY_SUPPORTED_OPTIONS;
2245 return S_OK;
2248 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
2249 xmldoc_Safety_QueryInterface,
2250 xmldoc_Safety_AddRef,
2251 xmldoc_Safety_Release,
2252 xmldoc_Safety_GetInterfaceSafetyOptions,
2253 xmldoc_Safety_SetInterfaceSafetyOptions
2257 static const tid_t domdoc_iface_tids[] = {
2258 IXMLDOMNode_tid,
2259 IXMLDOMDocument_tid,
2260 IXMLDOMDocument2_tid,
2263 static dispex_static_data_t domdoc_dispex = {
2264 NULL,
2265 IXMLDOMDocument2_tid,
2266 NULL,
2267 domdoc_iface_tids
2270 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument2 **document)
2272 domdoc *doc;
2274 doc = heap_alloc( sizeof (*doc) );
2275 if( !doc )
2276 return E_OUTOFMEMORY;
2278 doc->lpVtbl = &domdoc_vtbl;
2279 doc->lpvtblIPersistStream = &xmldoc_IPersistStream_VTable;
2280 doc->lpvtblIObjectWithSite = &domdocObjectSite;
2281 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
2282 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
2283 doc->ref = 1;
2284 doc->async = VARIANT_TRUE;
2285 doc->validating = 0;
2286 doc->resolving = 0;
2287 doc->preserving = 0;
2288 doc->bUseXPath = FALSE;
2289 doc->error = S_OK;
2290 doc->schema = NULL;
2291 doc->stream = NULL;
2292 doc->site = NULL;
2293 doc->safeopt = 0;
2294 doc->bsc = NULL;
2296 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IUnknown*)&doc->lpVtbl, &domdoc_dispex);
2298 *document = (IXMLDOMDocument2*)&doc->lpVtbl;
2300 TRACE("returning iface %p\n", *document);
2301 return S_OK;
2304 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2306 xmlDocPtr xmldoc;
2307 HRESULT hr;
2309 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
2311 xmldoc = xmlNewDoc(NULL);
2312 if(!xmldoc)
2313 return E_OUTOFMEMORY;
2315 xmldoc->_private = create_priv();
2317 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument2**)ppObj);
2318 if(FAILED(hr))
2319 xmlFreeDoc(xmldoc);
2321 return hr;
2324 IUnknown* create_domdoc( xmlNodePtr document )
2326 HRESULT hr;
2327 LPVOID pObj = NULL;
2329 TRACE("(%p)\n", document);
2331 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument2**)&pObj);
2332 if (FAILED(hr))
2333 return NULL;
2335 return pObj;
2338 #else
2340 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2342 MESSAGE("This program tried to use a DOMDocument object, but\n"
2343 "libxml2 support was not present at compile time.\n");
2344 return E_NOTIMPL;
2347 #endif