push e2dd5002080a3a5df525dea14b261213385de3ae
[wine/hacks.git] / dlls / msxml3 / domdoc.c
blobd03d8c7742fb1dba8da70adc3953b0b61faef48c
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 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};
51 static const WCHAR SZ_VALUE_XPATH[] = {'X','P','a','t','h',0};
52 static const WCHAR SZ_VALUE_XSLPATTERN[] = {'X','S','L','P','a','t','t','e','r','n',0};
54 typedef struct _domdoc
56 const struct IXMLDOMDocument2Vtbl *lpVtbl;
57 const struct IPersistStreamVtbl *lpvtblIPersistStream;
58 const struct IObjectWithSiteVtbl *lpvtblIObjectWithSite;
59 const struct IObjectSafetyVtbl *lpvtblIObjectSafety;
60 LONG ref;
61 VARIANT_BOOL async;
62 VARIANT_BOOL validating;
63 VARIANT_BOOL resolving;
64 VARIANT_BOOL preserving;
65 BOOL bUseXPath;
66 IUnknown *node_unk;
67 IXMLDOMNode *node;
68 IXMLDOMSchemaCollection *schema;
69 bsc_t *bsc;
70 HRESULT error;
72 /* IPersistStream */
73 IStream *stream;
75 /* IObjectWithSite*/
76 IUnknown *site;
78 /* IObjectSafety */
79 DWORD safeopt;
81 /* IDispatchEx */
82 DispatchEx dispex;
83 } domdoc;
86 In native windows, the whole lifetime management of XMLDOMNodes is
87 managed automatically using reference counts. Wine emulates that by
88 maintaining a reference count to the document that is increased for
89 each IXMLDOMNode pointer passed out for this document. If all these
90 pointers are gone, the document is unreachable and gets freed, that
91 is, all nodes in the tree of the document get freed.
93 You are able to create nodes that are associated to a document (in
94 fact, in msxml's XMLDOM model, all nodes are associated to a document),
95 but not in the tree of that document, for example using the createFoo
96 functions from IXMLDOMDocument. These nodes do not get cleaned up
97 by libxml, so we have to do it ourselves.
99 To catch these nodes, a list of "orphan nodes" is introduced.
100 It contains pointers to all roots of node trees that are
101 associated with the document without being part of the document
102 tree. All nodes with parent==NULL (except for the document root nodes)
103 should be in the orphan node list of their document. All orphan nodes
104 get freed together with the document itself.
107 typedef struct _xmldoc_priv {
108 LONG refs;
109 struct list orphans;
110 } xmldoc_priv;
112 typedef struct _orphan_entry {
113 struct list entry;
114 xmlNode * node;
115 } orphan_entry;
117 static inline xmldoc_priv * priv_from_xmlDocPtr(xmlDocPtr doc)
119 return doc->_private;
122 static xmldoc_priv * create_priv(void)
124 xmldoc_priv *priv;
125 priv = HeapAlloc( GetProcessHeap(), 0, sizeof (*priv) );
127 if(priv)
129 priv->refs = 0;
130 list_init( &priv->orphans );
133 return priv;
136 static xmlDocPtr doparse( char *ptr, int len )
138 #ifdef HAVE_XMLREADMEMORY
140 * use xmlReadMemory if possible so we can suppress
141 * writing errors to stderr
143 return xmlReadMemory( ptr, len, NULL, NULL,
144 XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS );
145 #else
146 return xmlParseMemory( ptr, len );
147 #endif
150 LONG xmldoc_add_ref(xmlDocPtr doc)
152 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
153 TRACE("%d\n", ref);
154 return ref;
157 LONG xmldoc_release(xmlDocPtr doc)
159 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
160 LONG ref = InterlockedDecrement(&priv->refs);
161 TRACE("%d\n", ref);
162 if(ref == 0)
164 orphan_entry *orphan, *orphan2;
165 TRACE("freeing docptr %p\n", doc);
167 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
169 xmlFreeNode( orphan->node );
170 HeapFree( GetProcessHeap(), 0, orphan );
172 HeapFree(GetProcessHeap(), 0, doc->_private);
174 xmlFreeDoc(doc);
177 return ref;
180 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
182 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
183 orphan_entry *entry;
185 entry = HeapAlloc( GetProcessHeap(), 0, sizeof (*entry) );
186 if(!entry)
187 return E_OUTOFMEMORY;
189 entry->node = node;
190 list_add_head( &priv->orphans, &entry->entry );
191 return S_OK;
194 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
196 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
197 orphan_entry *entry, *entry2;
199 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
201 if( entry->node == node )
203 list_remove( &entry->entry );
204 HeapFree( GetProcessHeap(), 0, entry );
205 return S_OK;
209 return S_FALSE;
212 static inline domdoc *impl_from_IXMLDOMDocument2( IXMLDOMDocument2 *iface )
214 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
217 static inline xmlDocPtr get_doc( domdoc *This )
219 return (xmlDocPtr) xmlNodePtr_from_domnode( This->node, XML_DOCUMENT_NODE );
222 static inline domdoc *impl_from_IPersistStream(IPersistStream *iface)
224 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStream));
227 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
229 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
232 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
234 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
238 /************************************************************************
239 * xmldoc implementation of IPersistStream.
241 static HRESULT WINAPI xmldoc_IPersistStream_QueryInterface(
242 IPersistStream *iface, REFIID riid, LPVOID *ppvObj)
244 domdoc *this = impl_from_IPersistStream(iface);
245 return IXMLDocument_QueryInterface((IXMLDocument *)this, riid, ppvObj);
248 static ULONG WINAPI xmldoc_IPersistStream_AddRef(
249 IPersistStream *iface)
251 domdoc *this = impl_from_IPersistStream(iface);
252 return IXMLDocument_AddRef((IXMLDocument *)this);
255 static ULONG WINAPI xmldoc_IPersistStream_Release(
256 IPersistStream *iface)
258 domdoc *this = impl_from_IPersistStream(iface);
259 return IXMLDocument_Release((IXMLDocument *)this);
262 static HRESULT WINAPI xmldoc_IPersistStream_GetClassID(
263 IPersistStream *iface, CLSID *classid)
265 TRACE("(%p,%p): stub!\n", iface, classid);
267 if(!classid)
268 return E_POINTER;
270 *classid = CLSID_DOMDocument2;
272 return S_OK;
275 static HRESULT WINAPI xmldoc_IPersistStream_IsDirty(
276 IPersistStream *iface)
278 domdoc *This = impl_from_IPersistStream(iface);
280 FIXME("(%p->%p): stub!\n", iface, This);
282 return S_FALSE;
285 static HRESULT WINAPI xmldoc_IPersistStream_Load(
286 IPersistStream *iface, LPSTREAM pStm)
288 domdoc *This = impl_from_IPersistStream(iface);
289 HRESULT hr;
290 HGLOBAL hglobal;
291 DWORD read, written, len;
292 BYTE buf[4096];
293 char *ptr;
294 xmlDocPtr xmldoc = NULL;
296 TRACE("(%p, %p)\n", iface, pStm);
298 if (!pStm)
299 return E_INVALIDARG;
301 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
302 if (FAILED(hr))
303 return hr;
307 IStream_Read(pStm, buf, sizeof(buf), &read);
308 hr = IStream_Write(This->stream, buf, read, &written);
309 } while(SUCCEEDED(hr) && written != 0 && read != 0);
311 if (FAILED(hr))
313 ERR("Failed to copy stream\n");
314 return hr;
317 hr = GetHGlobalFromStream(This->stream, &hglobal);
318 if (FAILED(hr))
319 return hr;
321 len = GlobalSize(hglobal);
322 ptr = GlobalLock(hglobal);
323 if (len != 0)
324 xmldoc = parse_xml(ptr, len);
325 GlobalUnlock(hglobal);
327 if (!xmldoc)
329 ERR("Failed to parse xml\n");
330 return E_FAIL;
333 attach_xmlnode( This->node, (xmlNodePtr)xmldoc );
335 return S_OK;
338 static HRESULT WINAPI xmldoc_IPersistStream_Save(
339 IPersistStream *iface, LPSTREAM pStm, BOOL fClearDirty)
341 FIXME("(%p, %p, %d): stub!\n", iface, pStm, fClearDirty);
342 return E_NOTIMPL;
345 static HRESULT WINAPI xmldoc_IPersistStream_GetSizeMax(
346 IPersistStream *iface, ULARGE_INTEGER *pcbSize)
348 TRACE("(%p, %p): stub!\n", iface, pcbSize);
349 return E_NOTIMPL;
352 static const IPersistStreamVtbl xmldoc_IPersistStream_VTable =
354 xmldoc_IPersistStream_QueryInterface,
355 xmldoc_IPersistStream_AddRef,
356 xmldoc_IPersistStream_Release,
357 xmldoc_IPersistStream_GetClassID,
358 xmldoc_IPersistStream_IsDirty,
359 xmldoc_IPersistStream_Load,
360 xmldoc_IPersistStream_Save,
361 xmldoc_IPersistStream_GetSizeMax,
364 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument2 *iface, REFIID riid, void** ppvObject )
366 domdoc *This = impl_from_IXMLDOMDocument2( iface );
368 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
370 *ppvObject = NULL;
372 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
373 IsEqualGUID( riid, &IID_IDispatch ) ||
374 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
375 IsEqualGUID( riid, &IID_IXMLDOMDocument2 ) )
377 *ppvObject = iface;
379 else if ( IsEqualGUID( riid, &IID_IXMLDOMNode ) )
381 return IUnknown_QueryInterface(This->node_unk, riid, ppvObject);
383 else if (IsEqualGUID(&IID_IPersistStream, riid))
385 *ppvObject = (IPersistStream*)&(This->lpvtblIPersistStream);
387 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
389 *ppvObject = (IObjectWithSite*)&(This->lpvtblIObjectWithSite);
391 else if(dispex_query_interface(&This->dispex, riid, ppvObject))
393 return *ppvObject ? S_OK : E_NOINTERFACE;
395 else if(IsEqualGUID(&IID_IRunnableObject, riid))
397 TRACE("IID_IRunnableObject not supported returning NULL\n");
398 return E_NOINTERFACE;
400 else
402 FIXME("interface %s not implemented\n", debugstr_guid(riid));
403 return E_NOINTERFACE;
406 IXMLDOMDocument_AddRef( iface );
408 return S_OK;
412 static ULONG WINAPI domdoc_AddRef(
413 IXMLDOMDocument2 *iface )
415 domdoc *This = impl_from_IXMLDOMDocument2( iface );
416 TRACE("%p\n", This );
417 return InterlockedIncrement( &This->ref );
421 static ULONG WINAPI domdoc_Release(
422 IXMLDOMDocument2 *iface )
424 domdoc *This = impl_from_IXMLDOMDocument2( iface );
425 LONG ref;
427 TRACE("%p\n", This );
429 ref = InterlockedDecrement( &This->ref );
430 if ( ref == 0 )
432 if(This->bsc)
433 detach_bsc(This->bsc);
435 if (This->site)
436 IUnknown_Release( This->site );
437 IUnknown_Release( This->node_unk );
438 if(This->schema) IXMLDOMSchemaCollection_Release( This->schema );
439 if (This->stream) IStream_Release(This->stream);
440 HeapFree( GetProcessHeap(), 0, This );
443 return ref;
446 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument2 *iface, UINT* pctinfo )
448 domdoc *This = impl_from_IXMLDOMDocument2( iface );
450 TRACE("(%p)->(%p)\n", This, pctinfo);
452 *pctinfo = 1;
454 return S_OK;
457 static HRESULT WINAPI domdoc_GetTypeInfo(
458 IXMLDOMDocument2 *iface,
459 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
461 domdoc *This = impl_from_IXMLDOMDocument2( iface );
462 HRESULT hr;
464 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
466 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
468 return hr;
471 static HRESULT WINAPI domdoc_GetIDsOfNames(
472 IXMLDOMDocument2 *iface,
473 REFIID riid,
474 LPOLESTR* rgszNames,
475 UINT cNames,
476 LCID lcid,
477 DISPID* rgDispId)
479 domdoc *This = impl_from_IXMLDOMDocument2( iface );
480 ITypeInfo *typeinfo;
481 HRESULT hr;
483 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
484 lcid, rgDispId);
486 if(!rgszNames || cNames == 0 || !rgDispId)
487 return E_INVALIDARG;
489 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
490 if(SUCCEEDED(hr))
492 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
493 ITypeInfo_Release(typeinfo);
496 return hr;
500 static HRESULT WINAPI domdoc_Invoke(
501 IXMLDOMDocument2 *iface,
502 DISPID dispIdMember,
503 REFIID riid,
504 LCID lcid,
505 WORD wFlags,
506 DISPPARAMS* pDispParams,
507 VARIANT* pVarResult,
508 EXCEPINFO* pExcepInfo,
509 UINT* puArgErr)
511 domdoc *This = impl_from_IXMLDOMDocument2( iface );
512 ITypeInfo *typeinfo;
513 HRESULT hr;
515 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
516 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
518 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
519 if(SUCCEEDED(hr))
521 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
522 pVarResult, pExcepInfo, puArgErr);
523 ITypeInfo_Release(typeinfo);
526 return hr;
530 static HRESULT WINAPI domdoc_get_nodeName(
531 IXMLDOMDocument2 *iface,
532 BSTR* name )
534 domdoc *This = impl_from_IXMLDOMDocument2( iface );
535 return IXMLDOMNode_get_nodeName( This->node, name );
539 static HRESULT WINAPI domdoc_get_nodeValue(
540 IXMLDOMDocument2 *iface,
541 VARIANT* value )
543 domdoc *This = impl_from_IXMLDOMDocument2( iface );
544 return IXMLDOMNode_get_nodeValue( This->node, value );
548 static HRESULT WINAPI domdoc_put_nodeValue(
549 IXMLDOMDocument2 *iface,
550 VARIANT value)
552 domdoc *This = impl_from_IXMLDOMDocument2( iface );
553 return IXMLDOMNode_put_nodeValue( This->node, value );
557 static HRESULT WINAPI domdoc_get_nodeType(
558 IXMLDOMDocument2 *iface,
559 DOMNodeType* type )
561 domdoc *This = impl_from_IXMLDOMDocument2( iface );
562 return IXMLDOMNode_get_nodeType( This->node, type );
566 static HRESULT WINAPI domdoc_get_parentNode(
567 IXMLDOMDocument2 *iface,
568 IXMLDOMNode** parent )
570 domdoc *This = impl_from_IXMLDOMDocument2( iface );
571 return IXMLDOMNode_get_parentNode( This->node, parent );
575 static HRESULT WINAPI domdoc_get_childNodes(
576 IXMLDOMDocument2 *iface,
577 IXMLDOMNodeList** childList )
579 domdoc *This = impl_from_IXMLDOMDocument2( iface );
580 return IXMLDOMNode_get_childNodes( This->node, childList );
584 static HRESULT WINAPI domdoc_get_firstChild(
585 IXMLDOMDocument2 *iface,
586 IXMLDOMNode** firstChild )
588 domdoc *This = impl_from_IXMLDOMDocument2( iface );
589 return IXMLDOMNode_get_firstChild( This->node, firstChild );
593 static HRESULT WINAPI domdoc_get_lastChild(
594 IXMLDOMDocument2 *iface,
595 IXMLDOMNode** lastChild )
597 domdoc *This = impl_from_IXMLDOMDocument2( iface );
598 return IXMLDOMNode_get_lastChild( This->node, lastChild );
602 static HRESULT WINAPI domdoc_get_previousSibling(
603 IXMLDOMDocument2 *iface,
604 IXMLDOMNode** previousSibling )
606 domdoc *This = impl_from_IXMLDOMDocument2( iface );
607 return IXMLDOMNode_get_previousSibling( This->node, previousSibling );
611 static HRESULT WINAPI domdoc_get_nextSibling(
612 IXMLDOMDocument2 *iface,
613 IXMLDOMNode** nextSibling )
615 domdoc *This = impl_from_IXMLDOMDocument2( iface );
616 return IXMLDOMNode_get_nextSibling( This->node, nextSibling );
620 static HRESULT WINAPI domdoc_get_attributes(
621 IXMLDOMDocument2 *iface,
622 IXMLDOMNamedNodeMap** attributeMap )
624 domdoc *This = impl_from_IXMLDOMDocument2( iface );
625 return IXMLDOMNode_get_attributes( This->node, attributeMap );
629 static HRESULT WINAPI domdoc_insertBefore(
630 IXMLDOMDocument2 *iface,
631 IXMLDOMNode* newChild,
632 VARIANT refChild,
633 IXMLDOMNode** outNewChild )
635 domdoc *This = impl_from_IXMLDOMDocument2( iface );
636 return IXMLDOMNode_insertBefore( This->node, newChild, refChild, outNewChild );
640 static HRESULT WINAPI domdoc_replaceChild(
641 IXMLDOMDocument2 *iface,
642 IXMLDOMNode* newChild,
643 IXMLDOMNode* oldChild,
644 IXMLDOMNode** outOldChild)
646 domdoc *This = impl_from_IXMLDOMDocument2( iface );
647 return IXMLDOMNode_replaceChild( This->node, newChild, oldChild, outOldChild );
651 static HRESULT WINAPI domdoc_removeChild(
652 IXMLDOMDocument2 *iface,
653 IXMLDOMNode* childNode,
654 IXMLDOMNode** oldChild)
656 domdoc *This = impl_from_IXMLDOMDocument2( iface );
657 return IXMLDOMNode_removeChild( This->node, childNode, oldChild );
661 static HRESULT WINAPI domdoc_appendChild(
662 IXMLDOMDocument2 *iface,
663 IXMLDOMNode* newChild,
664 IXMLDOMNode** outNewChild)
666 domdoc *This = impl_from_IXMLDOMDocument2( iface );
667 return IXMLDOMNode_appendChild( This->node, newChild, outNewChild );
671 static HRESULT WINAPI domdoc_hasChildNodes(
672 IXMLDOMDocument2 *iface,
673 VARIANT_BOOL* hasChild)
675 domdoc *This = impl_from_IXMLDOMDocument2( iface );
676 return IXMLDOMNode_hasChildNodes( This->node, hasChild );
680 static HRESULT WINAPI domdoc_get_ownerDocument(
681 IXMLDOMDocument2 *iface,
682 IXMLDOMDocument** DOMDocument)
684 domdoc *This = impl_from_IXMLDOMDocument2( iface );
685 return IXMLDOMNode_get_ownerDocument( This->node, DOMDocument );
689 static HRESULT WINAPI domdoc_cloneNode(
690 IXMLDOMDocument2 *iface,
691 VARIANT_BOOL deep,
692 IXMLDOMNode** cloneRoot)
694 domdoc *This = impl_from_IXMLDOMDocument2( iface );
695 return IXMLDOMNode_cloneNode( This->node, deep, cloneRoot );
699 static HRESULT WINAPI domdoc_get_nodeTypeString(
700 IXMLDOMDocument2 *iface,
701 BSTR* nodeType )
703 domdoc *This = impl_from_IXMLDOMDocument2( iface );
704 return IXMLDOMNode_get_nodeTypeString( This->node, nodeType );
708 static HRESULT WINAPI domdoc_get_text(
709 IXMLDOMDocument2 *iface,
710 BSTR* text )
712 domdoc *This = impl_from_IXMLDOMDocument2( iface );
713 return IXMLDOMNode_get_text( This->node, text );
717 static HRESULT WINAPI domdoc_put_text(
718 IXMLDOMDocument2 *iface,
719 BSTR text )
721 domdoc *This = impl_from_IXMLDOMDocument2( iface );
722 return IXMLDOMNode_put_text( This->node, text );
726 static HRESULT WINAPI domdoc_get_specified(
727 IXMLDOMDocument2 *iface,
728 VARIANT_BOOL* isSpecified )
730 domdoc *This = impl_from_IXMLDOMDocument2( iface );
731 return IXMLDOMNode_get_specified( This->node, isSpecified );
735 static HRESULT WINAPI domdoc_get_definition(
736 IXMLDOMDocument2 *iface,
737 IXMLDOMNode** definitionNode )
739 domdoc *This = impl_from_IXMLDOMDocument2( iface );
740 return IXMLDOMNode_get_definition( This->node, definitionNode );
744 static HRESULT WINAPI domdoc_get_nodeTypedValue(
745 IXMLDOMDocument2 *iface,
746 VARIANT* typedValue )
748 domdoc *This = impl_from_IXMLDOMDocument2( iface );
749 return IXMLDOMNode_get_nodeTypedValue( This->node, typedValue );
752 static HRESULT WINAPI domdoc_put_nodeTypedValue(
753 IXMLDOMDocument2 *iface,
754 VARIANT typedValue )
756 domdoc *This = impl_from_IXMLDOMDocument2( iface );
757 return IXMLDOMNode_put_nodeTypedValue( This->node, typedValue );
761 static HRESULT WINAPI domdoc_get_dataType(
762 IXMLDOMDocument2 *iface,
763 VARIANT* dataTypeName )
765 domdoc *This = impl_from_IXMLDOMDocument2( iface );
766 return IXMLDOMNode_get_dataType( This->node, dataTypeName );
770 static HRESULT WINAPI domdoc_put_dataType(
771 IXMLDOMDocument2 *iface,
772 BSTR dataTypeName )
774 domdoc *This = impl_from_IXMLDOMDocument2( iface );
775 return IXMLDOMNode_put_dataType( This->node, dataTypeName );
779 static HRESULT WINAPI domdoc_get_xml(
780 IXMLDOMDocument2 *iface,
781 BSTR* xmlString )
783 domdoc *This = impl_from_IXMLDOMDocument2( iface );
784 return IXMLDOMNode_get_xml( This->node, xmlString );
788 static HRESULT WINAPI domdoc_transformNode(
789 IXMLDOMDocument2 *iface,
790 IXMLDOMNode* styleSheet,
791 BSTR* xmlString )
793 domdoc *This = impl_from_IXMLDOMDocument2( iface );
794 return IXMLDOMNode_transformNode( This->node, styleSheet, xmlString );
798 static HRESULT WINAPI domdoc_selectNodes(
799 IXMLDOMDocument2 *iface,
800 BSTR queryString,
801 IXMLDOMNodeList** resultList )
803 domdoc *This = impl_from_IXMLDOMDocument2( iface );
804 return IXMLDOMNode_selectNodes( This->node, queryString, resultList );
808 static HRESULT WINAPI domdoc_selectSingleNode(
809 IXMLDOMDocument2 *iface,
810 BSTR queryString,
811 IXMLDOMNode** resultNode )
813 domdoc *This = impl_from_IXMLDOMDocument2( iface );
814 return IXMLDOMNode_selectSingleNode( This->node, queryString, resultNode );
818 static HRESULT WINAPI domdoc_get_parsed(
819 IXMLDOMDocument2 *iface,
820 VARIANT_BOOL* isParsed )
822 domdoc *This = impl_from_IXMLDOMDocument2( iface );
823 return IXMLDOMNode_get_parsed( This->node, isParsed );
827 static HRESULT WINAPI domdoc_get_namespaceURI(
828 IXMLDOMDocument2 *iface,
829 BSTR* namespaceURI )
831 domdoc *This = impl_from_IXMLDOMDocument2( iface );
832 return IXMLDOMNode_get_namespaceURI( This->node, namespaceURI );
836 static HRESULT WINAPI domdoc_get_prefix(
837 IXMLDOMDocument2 *iface,
838 BSTR* prefixString )
840 domdoc *This = impl_from_IXMLDOMDocument2( iface );
841 return IXMLDOMNode_get_prefix( This->node, prefixString );
845 static HRESULT WINAPI domdoc_get_baseName(
846 IXMLDOMDocument2 *iface,
847 BSTR* nameString )
849 domdoc *This = impl_from_IXMLDOMDocument2( iface );
850 return IXMLDOMNode_get_baseName( This->node, nameString );
854 static HRESULT WINAPI domdoc_transformNodeToObject(
855 IXMLDOMDocument2 *iface,
856 IXMLDOMNode* stylesheet,
857 VARIANT outputObject)
859 domdoc *This = impl_from_IXMLDOMDocument2( iface );
860 return IXMLDOMNode_transformNodeToObject( This->node, stylesheet, outputObject );
864 static HRESULT WINAPI domdoc_get_doctype(
865 IXMLDOMDocument2 *iface,
866 IXMLDOMDocumentType** documentType )
868 FIXME("\n");
869 return E_NOTIMPL;
873 static HRESULT WINAPI domdoc_get_implementation(
874 IXMLDOMDocument2 *iface,
875 IXMLDOMImplementation** impl )
877 if(!impl)
878 return E_INVALIDARG;
880 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
882 return S_OK;
885 static HRESULT WINAPI domdoc_get_documentElement(
886 IXMLDOMDocument2 *iface,
887 IXMLDOMElement** DOMElement )
889 domdoc *This = impl_from_IXMLDOMDocument2( iface );
890 xmlDocPtr xmldoc = NULL;
891 xmlNodePtr root = NULL;
892 IXMLDOMNode *element_node;
893 HRESULT hr;
895 TRACE("%p %p\n", This, This->node);
897 if(!DOMElement)
898 return E_INVALIDARG;
900 *DOMElement = NULL;
902 xmldoc = get_doc( This );
904 root = xmlDocGetRootElement( xmldoc );
905 if ( !root )
906 return S_FALSE;
908 element_node = create_node( root );
909 if(!element_node) return S_FALSE;
911 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (LPVOID*)DOMElement);
912 IXMLDOMNode_Release(element_node);
914 return hr;
918 static HRESULT WINAPI domdoc_put_documentElement(
919 IXMLDOMDocument2 *iface,
920 IXMLDOMElement* DOMElement )
922 domdoc *This = impl_from_IXMLDOMDocument2( iface );
923 IXMLDOMNode *elementNode;
924 xmlnode *xmlNode;
925 HRESULT hr;
927 TRACE("(%p)->(%p)\n", This, DOMElement);
929 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
930 if(FAILED(hr))
931 return hr;
933 xmlNode = impl_from_IXMLDOMNode( elementNode );
934 xmlDocSetRootElement( get_doc(This), xmlNode->node);
935 IXMLDOMNode_Release( elementNode );
937 return S_OK;
941 static HRESULT WINAPI domdoc_createElement(
942 IXMLDOMDocument2 *iface,
943 BSTR tagname,
944 IXMLDOMElement** element )
946 xmlNodePtr xmlnode;
947 domdoc *This = impl_from_IXMLDOMDocument2( iface );
948 xmlChar *xml_name;
949 IUnknown *elem_unk;
950 HRESULT hr;
952 TRACE("%p->(%s,%p)\n", iface, debugstr_w(tagname), element);
954 xml_name = xmlChar_from_wchar((WCHAR*)tagname);
955 xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
956 xmldoc_add_orphan(xmlnode->doc, xmlnode);
958 TRACE("created xmlptr %p\n", xmlnode);
959 elem_unk = create_element(xmlnode, NULL);
960 HeapFree(GetProcessHeap(), 0, xml_name);
962 hr = IUnknown_QueryInterface(elem_unk, &IID_IXMLDOMElement, (void **)element);
963 IUnknown_Release(elem_unk);
964 TRACE("returning %p\n", *element);
965 return hr;
969 static HRESULT WINAPI domdoc_createDocumentFragment(
970 IXMLDOMDocument2 *iface,
971 IXMLDOMDocumentFragment** docFrag )
973 domdoc *This = impl_from_IXMLDOMDocument2( iface );
974 xmlNodePtr xmlnode;
976 TRACE("%p\n", iface);
978 if(!docFrag)
979 return E_INVALIDARG;
981 *docFrag = NULL;
983 xmlnode = xmlNewDocFragment(get_doc( This ) );
985 if(!xmlnode)
986 return E_FAIL;
988 xmldoc_add_orphan(xmlnode->doc, xmlnode);
989 *docFrag = (IXMLDOMDocumentFragment*)create_doc_fragment(xmlnode);
991 return S_OK;
995 static HRESULT WINAPI domdoc_createTextNode(
996 IXMLDOMDocument2 *iface,
997 BSTR data,
998 IXMLDOMText** text )
1000 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1001 xmlNodePtr xmlnode;
1002 xmlChar *xml_content;
1004 TRACE("%p->(%s %p)\n", iface, debugstr_w(data), text);
1006 if(!text)
1007 return E_INVALIDARG;
1009 *text = NULL;
1011 xml_content = xmlChar_from_wchar((WCHAR*)data);
1012 xmlnode = xmlNewText(xml_content);
1013 HeapFree(GetProcessHeap(), 0, xml_content);
1015 if(!xmlnode)
1016 return E_FAIL;
1018 xmlnode->doc = get_doc( This );
1019 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1021 *text = (IXMLDOMText*)create_text(xmlnode);
1023 return S_OK;
1027 static HRESULT WINAPI domdoc_createComment(
1028 IXMLDOMDocument2 *iface,
1029 BSTR data,
1030 IXMLDOMComment** comment )
1032 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1033 xmlNodePtr xmlnode;
1034 xmlChar *xml_content;
1036 TRACE("%p->(%s %p)\n", iface, debugstr_w(data), comment);
1038 if(!comment)
1039 return E_INVALIDARG;
1041 *comment = NULL;
1043 xml_content = xmlChar_from_wchar((WCHAR*)data);
1044 xmlnode = xmlNewComment(xml_content);
1045 HeapFree(GetProcessHeap(), 0, xml_content);
1047 if(!xmlnode)
1048 return E_FAIL;
1050 xmlnode->doc = get_doc( This );
1051 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1053 *comment = (IXMLDOMComment*)create_comment(xmlnode);
1055 return S_OK;
1059 static HRESULT WINAPI domdoc_createCDATASection(
1060 IXMLDOMDocument2 *iface,
1061 BSTR data,
1062 IXMLDOMCDATASection** cdata )
1064 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1065 xmlNodePtr xmlnode;
1066 xmlChar *xml_content;
1068 TRACE("%p->(%s %p)\n", iface, debugstr_w(data), cdata);
1070 if(!cdata)
1071 return E_INVALIDARG;
1073 *cdata = NULL;
1075 xml_content = xmlChar_from_wchar((WCHAR*)data);
1076 xmlnode = xmlNewCDataBlock(get_doc( This ), xml_content, strlen( (char*)xml_content) );
1077 HeapFree(GetProcessHeap(), 0, xml_content);
1079 if(!xmlnode)
1080 return E_FAIL;
1082 xmlnode->doc = get_doc( This );
1083 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1085 *cdata = (IXMLDOMCDATASection*)create_cdata(xmlnode);
1087 return S_OK;
1091 static HRESULT WINAPI domdoc_createProcessingInstruction(
1092 IXMLDOMDocument2 *iface,
1093 BSTR target,
1094 BSTR data,
1095 IXMLDOMProcessingInstruction** pi )
1097 #ifdef HAVE_XMLNEWDOCPI
1098 xmlNodePtr xmlnode;
1099 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1100 xmlChar *xml_target, *xml_content;
1102 TRACE("%p->(%s %s %p)\n", iface, debugstr_w(target), debugstr_w(data), pi);
1104 if(!pi)
1105 return E_INVALIDARG;
1107 if(!target || lstrlenW(target) == 0)
1108 return E_FAIL;
1110 xml_target = xmlChar_from_wchar((WCHAR*)target);
1111 xml_content = xmlChar_from_wchar((WCHAR*)data);
1113 xmlnode = xmlNewDocPI(get_doc(This), xml_target, xml_content);
1114 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1115 TRACE("created xmlptr %p\n", xmlnode);
1116 *pi = (IXMLDOMProcessingInstruction*)create_pi(xmlnode);
1118 HeapFree(GetProcessHeap(), 0, xml_content);
1119 HeapFree(GetProcessHeap(), 0, xml_target);
1121 return S_OK;
1122 #else
1123 FIXME("Libxml 2.6.15 or greater required.\n");
1124 return E_NOTIMPL;
1125 #endif
1129 static HRESULT WINAPI domdoc_createAttribute(
1130 IXMLDOMDocument2 *iface,
1131 BSTR name,
1132 IXMLDOMAttribute** attribute )
1134 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1135 xmlNodePtr xmlnode;
1136 xmlChar *xml_name;
1138 TRACE("%p->(%s %p)\n", iface, debugstr_w(name), attribute);
1140 if(!attribute)
1141 return E_INVALIDARG;
1143 *attribute = NULL;
1145 xml_name = xmlChar_from_wchar((WCHAR*)name);
1146 xmlnode = (xmlNode *)xmlNewProp(NULL, xml_name, NULL);
1147 HeapFree(GetProcessHeap(), 0, xml_name);
1149 if(!xmlnode)
1150 return E_FAIL;
1152 xmlnode->doc = get_doc( This );
1153 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1155 *attribute = (IXMLDOMAttribute*)create_attribute(xmlnode);
1157 return S_OK;
1161 static HRESULT WINAPI domdoc_createEntityReference(
1162 IXMLDOMDocument2 *iface,
1163 BSTR name,
1164 IXMLDOMEntityReference** entityRef )
1166 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1167 xmlNodePtr xmlnode;
1168 xmlChar *xml_name;
1170 TRACE("%p\n", iface);
1172 if(!entityRef)
1173 return E_INVALIDARG;
1175 *entityRef = NULL;
1177 xml_name = xmlChar_from_wchar((WCHAR*)name);
1178 xmlnode = xmlNewReference(get_doc( This ), xml_name );
1179 HeapFree(GetProcessHeap(), 0, xml_name);
1181 if(!xmlnode)
1182 return E_FAIL;
1184 xmlnode->doc = get_doc( This );
1185 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1187 *entityRef = (IXMLDOMEntityReference*)create_doc_entity_ref(xmlnode);
1189 return S_OK;
1193 static HRESULT WINAPI domdoc_getElementsByTagName(
1194 IXMLDOMDocument2 *iface,
1195 BSTR tagName,
1196 IXMLDOMNodeList** resultList )
1198 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1199 LPWSTR szPattern;
1200 HRESULT hr;
1201 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1203 szPattern = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(2+lstrlenW(tagName)+1));
1204 szPattern[0] = szPattern[1] = '/';
1205 lstrcpyW(szPattern + 2, tagName);
1207 hr = queryresult_create((xmlNodePtr)get_doc(This), szPattern, resultList);
1208 HeapFree(GetProcessHeap(), 0, szPattern);
1210 return hr;
1213 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1215 VARIANT tmp;
1216 HRESULT hr;
1218 VariantInit(&tmp);
1219 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1220 if(FAILED(hr))
1221 return E_INVALIDARG;
1223 *type = V_I4(&tmp);
1225 return S_OK;
1228 static HRESULT WINAPI domdoc_createNode(
1229 IXMLDOMDocument2 *iface,
1230 VARIANT Type,
1231 BSTR name,
1232 BSTR namespaceURI,
1233 IXMLDOMNode** node )
1235 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1236 DOMNodeType node_type;
1237 xmlNodePtr xmlnode = NULL;
1238 xmlChar *xml_name;
1239 HRESULT hr;
1241 TRACE("(%p)->(type,%s,%s,%p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1243 hr = get_node_type(Type, &node_type);
1244 if(FAILED(hr))
1245 return hr;
1247 TRACE("node_type %d\n", node_type);
1249 xml_name = xmlChar_from_wchar((WCHAR*)name);
1251 switch(node_type)
1253 case NODE_ELEMENT:
1254 xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
1255 *node = create_node(xmlnode);
1256 TRACE("created %p\n", xmlnode);
1257 break;
1258 case NODE_ATTRIBUTE:
1259 xmlnode = (xmlNode *)xmlNewProp(NULL, xml_name, NULL);
1260 if(xmlnode)
1262 xmlnode->doc = get_doc( This );
1264 *node = (IXMLDOMNode*)create_attribute(xmlnode);
1267 TRACE("created %p\n", xmlnode);
1268 break;
1270 default:
1271 FIXME("unhandled node type %d\n", node_type);
1272 break;
1275 HeapFree(GetProcessHeap(), 0, xml_name);
1277 if(xmlnode && *node)
1279 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1280 return S_OK;
1283 return E_FAIL;
1286 static HRESULT WINAPI domdoc_nodeFromID(
1287 IXMLDOMDocument2 *iface,
1288 BSTR idString,
1289 IXMLDOMNode** node )
1291 FIXME("\n");
1292 return E_NOTIMPL;
1295 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1297 domdoc *This = obj;
1298 xmlDocPtr xmldoc;
1300 xmldoc = doparse( ptr, len );
1301 if(xmldoc) {
1302 xmldoc->_private = create_priv();
1303 attach_xmlnode(This->node, (xmlNodePtr) xmldoc);
1306 return S_OK;
1309 static HRESULT doread( domdoc *This, LPWSTR filename )
1311 bsc_t *bsc;
1312 HRESULT hr;
1314 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1315 if(FAILED(hr))
1316 return hr;
1318 if(This->bsc)
1319 detach_bsc(This->bsc);
1321 This->bsc = bsc;
1322 return S_OK;
1325 static HRESULT WINAPI domdoc_load(
1326 IXMLDOMDocument2 *iface,
1327 VARIANT xmlSource,
1328 VARIANT_BOOL* isSuccessful )
1330 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1331 LPWSTR filename = NULL;
1332 HRESULT hr = S_FALSE;
1333 IXMLDOMDocument2 *pNewDoc = NULL;
1334 IStream *pStream = NULL;
1335 xmlDocPtr xmldoc;
1337 TRACE("type %d\n", V_VT(&xmlSource) );
1339 *isSuccessful = VARIANT_FALSE;
1341 assert( This->node );
1343 attach_xmlnode(This->node, NULL);
1345 switch( V_VT(&xmlSource) )
1347 case VT_BSTR:
1348 filename = V_BSTR(&xmlSource);
1349 break;
1350 case VT_UNKNOWN:
1351 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument2, (void**)&pNewDoc);
1352 if(hr == S_OK)
1354 if(pNewDoc)
1356 domdoc *newDoc = impl_from_IXMLDOMDocument2( pNewDoc );
1357 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1358 attach_xmlnode(This->node, (xmlNodePtr) xmldoc);
1360 *isSuccessful = VARIANT_TRUE;
1362 return S_OK;
1365 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1366 if(hr == S_OK)
1368 IPersistStream *pDocStream;
1369 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1370 if(hr == S_OK)
1372 hr = xmldoc_IPersistStream_Load(pDocStream, pStream);
1373 IStream_Release(pStream);
1374 if(hr == S_OK)
1376 *isSuccessful = VARIANT_TRUE;
1378 TRACE("Using ID_IStream to load Document\n");
1379 return S_OK;
1381 else
1383 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1386 else
1388 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1391 else
1393 /* ISequentialStream */
1394 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1396 break;
1397 default:
1398 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1401 TRACE("filename (%s)\n", debugstr_w(filename));
1403 if ( filename )
1405 hr = doread( This, filename );
1407 if ( FAILED(hr) )
1408 This->error = E_FAIL;
1409 else
1411 hr = This->error = S_OK;
1412 *isSuccessful = VARIANT_TRUE;
1416 if(!filename || FAILED(hr)) {
1417 xmldoc = xmlNewDoc(NULL);
1418 xmldoc->_private = create_priv();
1419 attach_xmlnode(This->node, (xmlNodePtr) xmldoc);
1420 hr = S_FALSE;
1423 TRACE("ret (%d)\n", hr);
1425 return hr;
1429 static HRESULT WINAPI domdoc_get_readyState(
1430 IXMLDOMDocument2 *iface,
1431 long* value )
1433 FIXME("\n");
1434 return E_NOTIMPL;
1438 static HRESULT WINAPI domdoc_get_parseError(
1439 IXMLDOMDocument2 *iface,
1440 IXMLDOMParseError** errorObj )
1442 BSTR error_string = NULL;
1443 static const WCHAR err[] = {'e','r','r','o','r',0};
1444 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1446 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
1448 if(This->error)
1449 error_string = SysAllocString(err);
1451 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
1452 if(!*errorObj) return E_OUTOFMEMORY;
1453 return S_OK;
1457 static HRESULT WINAPI domdoc_get_url(
1458 IXMLDOMDocument2 *iface,
1459 BSTR* urlString )
1461 FIXME("\n");
1462 return E_NOTIMPL;
1466 static HRESULT WINAPI domdoc_get_async(
1467 IXMLDOMDocument2 *iface,
1468 VARIANT_BOOL* isAsync )
1470 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1472 TRACE("%p <- %d\n", isAsync, This->async);
1473 *isAsync = This->async;
1474 return S_OK;
1478 static HRESULT WINAPI domdoc_put_async(
1479 IXMLDOMDocument2 *iface,
1480 VARIANT_BOOL isAsync )
1482 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1484 TRACE("%d\n", isAsync);
1485 This->async = isAsync;
1486 return S_OK;
1490 static HRESULT WINAPI domdoc_abort(
1491 IXMLDOMDocument2 *iface )
1493 FIXME("\n");
1494 return E_NOTIMPL;
1498 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
1500 UINT len, blen = SysStringLen( bstr );
1501 LPSTR str;
1503 len = WideCharToMultiByte( CP_UTF8, 0, bstr, blen, NULL, 0, NULL, NULL );
1504 str = HeapAlloc( GetProcessHeap(), 0, len );
1505 if ( !str )
1506 return FALSE;
1507 WideCharToMultiByte( CP_UTF8, 0, bstr, blen, str, len, NULL, NULL );
1508 *plen = len;
1509 *pstr = str;
1510 return TRUE;
1513 static HRESULT WINAPI domdoc_loadXML(
1514 IXMLDOMDocument2 *iface,
1515 BSTR bstrXML,
1516 VARIANT_BOOL* isSuccessful )
1518 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1519 xmlDocPtr xmldoc = NULL;
1520 char *str;
1521 int len;
1522 HRESULT hr = S_FALSE;
1524 TRACE("%p %s %p\n", This, debugstr_w( bstrXML ), isSuccessful );
1526 assert ( This->node );
1528 attach_xmlnode( This->node, NULL );
1530 if ( isSuccessful )
1532 *isSuccessful = VARIANT_FALSE;
1534 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
1536 xmldoc = doparse( str, len );
1537 HeapFree( GetProcessHeap(), 0, str );
1538 if ( !xmldoc )
1539 This->error = E_FAIL;
1540 else
1542 hr = This->error = S_OK;
1543 *isSuccessful = VARIANT_TRUE;
1547 if(!xmldoc)
1548 xmldoc = xmlNewDoc(NULL);
1550 xmldoc->_private = create_priv();
1551 attach_xmlnode( This->node, (xmlNodePtr) xmldoc );
1553 return hr;
1557 static HRESULT WINAPI domdoc_save(
1558 IXMLDOMDocument2 *iface,
1559 VARIANT destination )
1561 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1562 HANDLE handle;
1563 xmlChar *mem, *p;
1564 int size;
1565 HRESULT ret = S_OK;
1566 DWORD written;
1568 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
1569 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
1571 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
1573 FIXME("Unhandled vt %d\n", V_VT(&destination));
1574 return S_FALSE;
1577 if(V_VT(&destination) == VT_UNKNOWN)
1579 IUnknown *pUnk = V_UNKNOWN(&destination);
1580 IXMLDOMDocument *pDocument;
1582 ret = IXMLDOMDocument_QueryInterface(pUnk, &IID_IXMLDOMDocument2, (void**)&pDocument);
1583 if(ret == S_OK)
1585 BSTR bXML;
1586 VARIANT_BOOL bSuccessful;
1588 ret = IXMLDOMDocument_get_xml(iface, &bXML);
1589 if(ret == S_OK)
1591 ret = IXMLDOMDocument_loadXML(pDocument, bXML, &bSuccessful);
1593 SysFreeString(bXML);
1596 IXMLDOMDocument_Release(pDocument);
1599 TRACE("ret %d\n", ret);
1601 return ret;
1604 handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
1605 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1606 if( handle == INVALID_HANDLE_VALUE )
1608 WARN("failed to create file\n");
1609 return S_FALSE;
1612 xmlDocDumpMemory(get_doc(This), &mem, &size);
1615 * libxml2 always adds XML declaration on top of the file and one for each processing instruction node in DOM tree.
1616 * MSXML adds XML declaration only for processing instruction nodes.
1617 * We skip the first XML declaration generated by libxml2 to get exactly what we need.
1619 p = mem;
1620 if(size > 2 && p[0] == '<' && p[1] == '?') {
1621 while(p < mem+size && (p[0] != '?' || p[1] != '>'))
1622 p++;
1623 p += 2;
1624 while(p < mem+size && isspace(*p))
1625 p++;
1626 size -= p-mem;
1629 if(!WriteFile(handle, p, (DWORD)size, &written, NULL) || written != (DWORD)size)
1631 WARN("write error\n");
1632 ret = S_FALSE;
1635 xmlFree(mem);
1636 CloseHandle(handle);
1637 return ret;
1640 static HRESULT WINAPI domdoc_get_validateOnParse(
1641 IXMLDOMDocument2 *iface,
1642 VARIANT_BOOL* isValidating )
1644 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1646 TRACE("%p <- %d\n", isValidating, This->validating);
1647 *isValidating = This->validating;
1648 return S_OK;
1652 static HRESULT WINAPI domdoc_put_validateOnParse(
1653 IXMLDOMDocument2 *iface,
1654 VARIANT_BOOL isValidating )
1656 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1658 TRACE("%d\n", isValidating);
1659 This->validating = isValidating;
1660 return S_OK;
1664 static HRESULT WINAPI domdoc_get_resolveExternals(
1665 IXMLDOMDocument2 *iface,
1666 VARIANT_BOOL* isResolving )
1668 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1670 TRACE("%p <- %d\n", isResolving, This->resolving);
1671 *isResolving = This->resolving;
1672 return S_OK;
1676 static HRESULT WINAPI domdoc_put_resolveExternals(
1677 IXMLDOMDocument2 *iface,
1678 VARIANT_BOOL isResolving )
1680 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1682 TRACE("%d\n", isResolving);
1683 This->resolving = isResolving;
1684 return S_OK;
1688 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
1689 IXMLDOMDocument2 *iface,
1690 VARIANT_BOOL* isPreserving )
1692 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1694 TRACE("%p <- %d\n", isPreserving, This->preserving);
1695 *isPreserving = This->preserving;
1696 return S_OK;
1700 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
1701 IXMLDOMDocument2 *iface,
1702 VARIANT_BOOL isPreserving )
1704 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1706 TRACE("%d\n", isPreserving);
1707 This->preserving = isPreserving;
1708 return S_OK;
1712 static HRESULT WINAPI domdoc_put_onReadyStateChange(
1713 IXMLDOMDocument2 *iface,
1714 VARIANT readyStateChangeSink )
1716 FIXME("\n");
1717 return E_NOTIMPL;
1721 static HRESULT WINAPI domdoc_put_onDataAvailable(
1722 IXMLDOMDocument2 *iface,
1723 VARIANT onDataAvailableSink )
1725 FIXME("\n");
1726 return E_NOTIMPL;
1729 static HRESULT WINAPI domdoc_put_onTransformNode(
1730 IXMLDOMDocument2 *iface,
1731 VARIANT onTransformNodeSink )
1733 FIXME("\n");
1734 return E_NOTIMPL;
1737 static HRESULT WINAPI domdoc_get_namespaces(
1738 IXMLDOMDocument2* iface,
1739 IXMLDOMSchemaCollection** schemaCollection )
1741 FIXME("\n");
1742 return E_NOTIMPL;
1745 static HRESULT WINAPI domdoc_get_schemas(
1746 IXMLDOMDocument2* iface,
1747 VARIANT* var1 )
1749 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1750 HRESULT hr = S_FALSE;
1751 IXMLDOMSchemaCollection *cur_schema = This->schema;
1753 TRACE("(%p)->(%p)\n", This, var1);
1755 VariantInit(var1); /* Test shows we don't call VariantClear here */
1756 V_VT(var1) = VT_NULL;
1758 if(cur_schema)
1760 hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
1761 if(SUCCEEDED(hr))
1762 V_VT(var1) = VT_DISPATCH;
1764 return hr;
1767 static HRESULT WINAPI domdoc_putref_schemas(
1768 IXMLDOMDocument2* iface,
1769 VARIANT var1)
1771 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1772 HRESULT hr = E_FAIL;
1773 IXMLDOMSchemaCollection *new_schema = NULL;
1775 FIXME("(%p): semi-stub\n", This);
1776 switch(V_VT(&var1))
1778 case VT_UNKNOWN:
1779 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1780 break;
1782 case VT_DISPATCH:
1783 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1784 break;
1786 case VT_NULL:
1787 case VT_EMPTY:
1788 hr = S_OK;
1789 break;
1791 default:
1792 WARN("Can't get schema from vt %x\n", V_VT(&var1));
1795 if(SUCCEEDED(hr))
1797 IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
1798 if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
1801 return hr;
1804 static HRESULT WINAPI domdoc_validate(
1805 IXMLDOMDocument2* iface,
1806 IXMLDOMParseError** err)
1808 FIXME("\n");
1809 return E_NOTIMPL;
1812 static HRESULT WINAPI domdoc_setProperty(
1813 IXMLDOMDocument2* iface,
1814 BSTR p,
1815 VARIANT var)
1817 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1819 if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
1821 VARIANT varStr;
1822 HRESULT hr;
1823 BSTR bstr;
1825 V_VT(&varStr) = VT_EMPTY;
1826 if (V_VT(&var) != VT_BSTR)
1828 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
1829 return hr;
1830 bstr = V_BSTR(&varStr);
1832 else
1833 bstr = V_BSTR(&var);
1835 hr = S_OK;
1836 if (lstrcmpiW(bstr, SZ_VALUE_XPATH) == 0)
1837 This->bUseXPath = TRUE;
1838 else if (lstrcmpiW(bstr, SZ_VALUE_XSLPATTERN) == 0)
1839 This->bUseXPath = FALSE;
1840 else
1841 hr = E_FAIL;
1843 VariantClear(&varStr);
1844 return hr;
1847 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
1848 return E_FAIL;
1851 static HRESULT WINAPI domdoc_getProperty(
1852 IXMLDOMDocument2* iface,
1853 BSTR p,
1854 VARIANT* var)
1856 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1858 if (var == NULL)
1859 return E_INVALIDARG;
1860 if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
1862 V_VT(var) = VT_BSTR;
1863 if (This->bUseXPath)
1864 V_BSTR(var) = SysAllocString(SZ_VALUE_XPATH);
1865 else
1866 V_BSTR(var) = SysAllocString(SZ_VALUE_XSLPATTERN);
1867 return S_OK;
1870 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
1871 return E_FAIL;
1874 static const struct IXMLDOMDocument2Vtbl domdoc_vtbl =
1876 domdoc_QueryInterface,
1877 domdoc_AddRef,
1878 domdoc_Release,
1879 domdoc_GetTypeInfoCount,
1880 domdoc_GetTypeInfo,
1881 domdoc_GetIDsOfNames,
1882 domdoc_Invoke,
1883 domdoc_get_nodeName,
1884 domdoc_get_nodeValue,
1885 domdoc_put_nodeValue,
1886 domdoc_get_nodeType,
1887 domdoc_get_parentNode,
1888 domdoc_get_childNodes,
1889 domdoc_get_firstChild,
1890 domdoc_get_lastChild,
1891 domdoc_get_previousSibling,
1892 domdoc_get_nextSibling,
1893 domdoc_get_attributes,
1894 domdoc_insertBefore,
1895 domdoc_replaceChild,
1896 domdoc_removeChild,
1897 domdoc_appendChild,
1898 domdoc_hasChildNodes,
1899 domdoc_get_ownerDocument,
1900 domdoc_cloneNode,
1901 domdoc_get_nodeTypeString,
1902 domdoc_get_text,
1903 domdoc_put_text,
1904 domdoc_get_specified,
1905 domdoc_get_definition,
1906 domdoc_get_nodeTypedValue,
1907 domdoc_put_nodeTypedValue,
1908 domdoc_get_dataType,
1909 domdoc_put_dataType,
1910 domdoc_get_xml,
1911 domdoc_transformNode,
1912 domdoc_selectNodes,
1913 domdoc_selectSingleNode,
1914 domdoc_get_parsed,
1915 domdoc_get_namespaceURI,
1916 domdoc_get_prefix,
1917 domdoc_get_baseName,
1918 domdoc_transformNodeToObject,
1919 domdoc_get_doctype,
1920 domdoc_get_implementation,
1921 domdoc_get_documentElement,
1922 domdoc_put_documentElement,
1923 domdoc_createElement,
1924 domdoc_createDocumentFragment,
1925 domdoc_createTextNode,
1926 domdoc_createComment,
1927 domdoc_createCDATASection,
1928 domdoc_createProcessingInstruction,
1929 domdoc_createAttribute,
1930 domdoc_createEntityReference,
1931 domdoc_getElementsByTagName,
1932 domdoc_createNode,
1933 domdoc_nodeFromID,
1934 domdoc_load,
1935 domdoc_get_readyState,
1936 domdoc_get_parseError,
1937 domdoc_get_url,
1938 domdoc_get_async,
1939 domdoc_put_async,
1940 domdoc_abort,
1941 domdoc_loadXML,
1942 domdoc_save,
1943 domdoc_get_validateOnParse,
1944 domdoc_put_validateOnParse,
1945 domdoc_get_resolveExternals,
1946 domdoc_put_resolveExternals,
1947 domdoc_get_preserveWhiteSpace,
1948 domdoc_put_preserveWhiteSpace,
1949 domdoc_put_onReadyStateChange,
1950 domdoc_put_onDataAvailable,
1951 domdoc_put_onTransformNode,
1952 domdoc_get_namespaces,
1953 domdoc_get_schemas,
1954 domdoc_putref_schemas,
1955 domdoc_validate,
1956 domdoc_setProperty,
1957 domdoc_getProperty
1960 /* xmldoc implementation of IObjectWithSite */
1961 static HRESULT WINAPI
1962 xmldoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
1964 domdoc *This = impl_from_IObjectWithSite(iface);
1965 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppvObject );
1968 static ULONG WINAPI
1969 xmldoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
1971 domdoc *This = impl_from_IObjectWithSite(iface);
1972 return IXMLDocument_AddRef((IXMLDocument *)This);
1975 static ULONG WINAPI
1976 xmldoc_ObjectWithSite_Release( IObjectWithSite* iface )
1978 domdoc *This = impl_from_IObjectWithSite(iface);
1979 return IXMLDocument_Release((IXMLDocument *)This);
1982 static HRESULT WINAPI
1983 xmldoc_GetSite( IObjectWithSite *iface, REFIID iid, void ** ppvSite )
1985 domdoc *This = impl_from_IObjectWithSite(iface);
1987 TRACE("%p %s %p\n", This, debugstr_guid( iid ), ppvSite );
1989 if ( !This->site )
1990 return E_FAIL;
1992 return IUnknown_QueryInterface( This->site, iid, ppvSite );
1995 static HRESULT WINAPI
1996 xmldoc_SetSite( IObjectWithSite *iface, IUnknown *punk )
1998 domdoc *This = impl_from_IObjectWithSite(iface);
2000 TRACE("%p %p\n", iface, punk);
2002 if(!punk)
2004 if(This->site)
2006 IUnknown_Release( This->site );
2007 This->site = NULL;
2010 return S_OK;
2013 if ( punk )
2014 IUnknown_AddRef( punk );
2016 if(This->site)
2017 IUnknown_Release( This->site );
2019 This->site = punk;
2021 return S_OK;
2024 static const IObjectWithSiteVtbl domdocObjectSite =
2026 xmldoc_ObjectWithSite_QueryInterface,
2027 xmldoc_ObjectWithSite_AddRef,
2028 xmldoc_ObjectWithSite_Release,
2029 xmldoc_SetSite,
2030 xmldoc_GetSite,
2033 static HRESULT WINAPI xmldoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
2035 domdoc *This = impl_from_IObjectSafety(iface);
2036 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppv );
2039 static ULONG WINAPI xmldoc_Safety_AddRef(IObjectSafety *iface)
2041 domdoc *This = impl_from_IObjectSafety(iface);
2042 return IXMLDocument_AddRef((IXMLDocument *)This);
2045 static ULONG WINAPI xmldoc_Safety_Release(IObjectSafety *iface)
2047 domdoc *This = impl_from_IObjectSafety(iface);
2048 return IXMLDocument_Release((IXMLDocument *)This);
2051 #define SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
2053 static HRESULT WINAPI xmldoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2054 DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
2056 domdoc *This = impl_from_IObjectSafety(iface);
2058 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
2060 if(!pdwSupportedOptions || !pdwEnabledOptions)
2061 return E_POINTER;
2063 *pdwSupportedOptions = SUPPORTED_OPTIONS;
2064 *pdwEnabledOptions = This->safeopt;
2066 return S_OK;
2069 static HRESULT WINAPI xmldoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2070 DWORD dwOptionSetMask, DWORD dwEnabledOptions)
2072 domdoc *This = impl_from_IObjectSafety(iface);
2074 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
2076 if(dwOptionSetMask & ~SUPPORTED_OPTIONS)
2077 return E_FAIL;
2079 This->safeopt = dwEnabledOptions & dwEnabledOptions;
2080 return S_OK;
2083 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
2084 xmldoc_Safety_QueryInterface,
2085 xmldoc_Safety_AddRef,
2086 xmldoc_Safety_Release,
2087 xmldoc_Safety_GetInterfaceSafetyOptions,
2088 xmldoc_Safety_SetInterfaceSafetyOptions
2092 static const tid_t domdoc_iface_tids[] = {
2093 IXMLDOMNode_tid,
2094 IXMLDOMDocument_tid,
2095 IXMLDOMDocument2_tid,
2098 static dispex_static_data_t domdoc_dispex = {
2099 NULL,
2100 IXMLDOMDocument2_tid,
2101 NULL,
2102 domdoc_iface_tids
2105 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument2 **document)
2107 domdoc *doc;
2108 HRESULT hr;
2110 doc = HeapAlloc( GetProcessHeap(), 0, sizeof (*doc) );
2111 if( !doc )
2112 return E_OUTOFMEMORY;
2114 doc->lpVtbl = &domdoc_vtbl;
2115 doc->lpvtblIPersistStream = &xmldoc_IPersistStream_VTable;
2116 doc->lpvtblIObjectWithSite = &domdocObjectSite;
2117 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
2118 doc->ref = 1;
2119 doc->async = 0;
2120 doc->validating = 0;
2121 doc->resolving = 0;
2122 doc->preserving = 0;
2123 doc->bUseXPath = FALSE;
2124 doc->error = S_OK;
2125 doc->schema = NULL;
2126 doc->stream = NULL;
2127 doc->site = NULL;
2128 doc->safeopt = 0;
2129 doc->bsc = NULL;
2131 doc->node_unk = create_basic_node( (xmlNodePtr)xmldoc, (IUnknown*)&doc->lpVtbl );
2132 if(!doc->node_unk)
2134 HeapFree(GetProcessHeap(), 0, doc);
2135 return E_FAIL;
2138 hr = IUnknown_QueryInterface(doc->node_unk, &IID_IXMLDOMNode, (LPVOID*)&doc->node);
2139 if(FAILED(hr))
2141 IUnknown_Release(doc->node_unk);
2142 HeapFree( GetProcessHeap(), 0, doc );
2143 return E_FAIL;
2146 init_dispex(&doc->dispex, (IUnknown*)&doc->lpVtbl, &domdoc_dispex);
2148 /* The ref on doc->node is actually looped back into this object, so release it */
2149 IXMLDOMNode_Release(doc->node);
2151 *document = (IXMLDOMDocument2*)&doc->lpVtbl;
2153 TRACE("returning iface %p\n", *document);
2154 return S_OK;
2157 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2159 xmlDocPtr xmldoc;
2160 HRESULT hr;
2162 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
2164 xmldoc = xmlNewDoc(NULL);
2165 if(!xmldoc)
2166 return E_OUTOFMEMORY;
2168 xmldoc->_private = create_priv();
2170 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument2**)ppObj);
2171 if(FAILED(hr))
2172 xmlFreeDoc(xmldoc);
2174 return hr;
2177 IUnknown* create_domdoc( xmlNodePtr document )
2179 HRESULT hr;
2180 LPVOID pObj = NULL;
2182 TRACE("(%p)\n", document);
2184 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument2**)&pObj);
2185 if (FAILED(hr))
2186 return NULL;
2188 return (IUnknown*)pObj;
2191 #else
2193 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2195 MESSAGE("This program tried to use a DOMDocument object, but\n"
2196 "libxml2 support was not present at compile time.\n");
2197 return E_NOTIMPL;
2200 #endif