push 8742e928a3d078c1d2cecb5ceee0ffde3118cbb7
[wine/hacks.git] / dlls / msxml3 / domdoc.c
blobc685889a953dff7ea549f3f8eb4dd46f92108c43
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 xmldoc->_private = create_priv();
334 attach_xmlnode( This->node, (xmlNodePtr)xmldoc );
336 return S_OK;
339 static HRESULT WINAPI xmldoc_IPersistStream_Save(
340 IPersistStream *iface, LPSTREAM pStm, BOOL fClearDirty)
342 FIXME("(%p, %p, %d): stub!\n", iface, pStm, fClearDirty);
343 return E_NOTIMPL;
346 static HRESULT WINAPI xmldoc_IPersistStream_GetSizeMax(
347 IPersistStream *iface, ULARGE_INTEGER *pcbSize)
349 TRACE("(%p, %p): stub!\n", iface, pcbSize);
350 return E_NOTIMPL;
353 static const IPersistStreamVtbl xmldoc_IPersistStream_VTable =
355 xmldoc_IPersistStream_QueryInterface,
356 xmldoc_IPersistStream_AddRef,
357 xmldoc_IPersistStream_Release,
358 xmldoc_IPersistStream_GetClassID,
359 xmldoc_IPersistStream_IsDirty,
360 xmldoc_IPersistStream_Load,
361 xmldoc_IPersistStream_Save,
362 xmldoc_IPersistStream_GetSizeMax,
365 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument2 *iface, REFIID riid, void** ppvObject )
367 domdoc *This = impl_from_IXMLDOMDocument2( iface );
369 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
371 *ppvObject = NULL;
373 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
374 IsEqualGUID( riid, &IID_IDispatch ) ||
375 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
376 IsEqualGUID( riid, &IID_IXMLDOMDocument2 ) )
378 *ppvObject = iface;
380 else if ( IsEqualGUID( riid, &IID_IXMLDOMNode ) )
382 return IUnknown_QueryInterface(This->node_unk, riid, ppvObject);
384 else if (IsEqualGUID(&IID_IPersistStream, riid))
386 *ppvObject = (IPersistStream*)&(This->lpvtblIPersistStream);
388 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
390 *ppvObject = (IObjectWithSite*)&(This->lpvtblIObjectWithSite);
392 else if(dispex_query_interface(&This->dispex, riid, ppvObject))
394 return *ppvObject ? S_OK : E_NOINTERFACE;
396 else if(IsEqualGUID(&IID_IRunnableObject, riid))
398 TRACE("IID_IRunnableObject not supported returning NULL\n");
399 return E_NOINTERFACE;
401 else
403 FIXME("interface %s not implemented\n", debugstr_guid(riid));
404 return E_NOINTERFACE;
407 IXMLDOMDocument_AddRef( iface );
409 return S_OK;
413 static ULONG WINAPI domdoc_AddRef(
414 IXMLDOMDocument2 *iface )
416 domdoc *This = impl_from_IXMLDOMDocument2( iface );
417 TRACE("%p\n", This );
418 return InterlockedIncrement( &This->ref );
422 static ULONG WINAPI domdoc_Release(
423 IXMLDOMDocument2 *iface )
425 domdoc *This = impl_from_IXMLDOMDocument2( iface );
426 LONG ref;
428 TRACE("%p\n", This );
430 ref = InterlockedDecrement( &This->ref );
431 if ( ref == 0 )
433 if(This->bsc)
434 detach_bsc(This->bsc);
436 if (This->site)
437 IUnknown_Release( This->site );
438 IUnknown_Release( This->node_unk );
439 if(This->schema) IXMLDOMSchemaCollection_Release( This->schema );
440 if (This->stream) IStream_Release(This->stream);
441 HeapFree( GetProcessHeap(), 0, This );
444 return ref;
447 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument2 *iface, UINT* pctinfo )
449 domdoc *This = impl_from_IXMLDOMDocument2( iface );
451 TRACE("(%p)->(%p)\n", This, pctinfo);
453 *pctinfo = 1;
455 return S_OK;
458 static HRESULT WINAPI domdoc_GetTypeInfo(
459 IXMLDOMDocument2 *iface,
460 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
462 domdoc *This = impl_from_IXMLDOMDocument2( iface );
463 HRESULT hr;
465 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
467 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
469 return hr;
472 static HRESULT WINAPI domdoc_GetIDsOfNames(
473 IXMLDOMDocument2 *iface,
474 REFIID riid,
475 LPOLESTR* rgszNames,
476 UINT cNames,
477 LCID lcid,
478 DISPID* rgDispId)
480 domdoc *This = impl_from_IXMLDOMDocument2( iface );
481 ITypeInfo *typeinfo;
482 HRESULT hr;
484 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
485 lcid, rgDispId);
487 if(!rgszNames || cNames == 0 || !rgDispId)
488 return E_INVALIDARG;
490 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
491 if(SUCCEEDED(hr))
493 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
494 ITypeInfo_Release(typeinfo);
497 return hr;
501 static HRESULT WINAPI domdoc_Invoke(
502 IXMLDOMDocument2 *iface,
503 DISPID dispIdMember,
504 REFIID riid,
505 LCID lcid,
506 WORD wFlags,
507 DISPPARAMS* pDispParams,
508 VARIANT* pVarResult,
509 EXCEPINFO* pExcepInfo,
510 UINT* puArgErr)
512 domdoc *This = impl_from_IXMLDOMDocument2( iface );
513 ITypeInfo *typeinfo;
514 HRESULT hr;
516 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
517 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
519 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
520 if(SUCCEEDED(hr))
522 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
523 pVarResult, pExcepInfo, puArgErr);
524 ITypeInfo_Release(typeinfo);
527 return hr;
531 static HRESULT WINAPI domdoc_get_nodeName(
532 IXMLDOMDocument2 *iface,
533 BSTR* name )
535 domdoc *This = impl_from_IXMLDOMDocument2( iface );
536 return IXMLDOMNode_get_nodeName( This->node, name );
540 static HRESULT WINAPI domdoc_get_nodeValue(
541 IXMLDOMDocument2 *iface,
542 VARIANT* value )
544 domdoc *This = impl_from_IXMLDOMDocument2( iface );
545 return IXMLDOMNode_get_nodeValue( This->node, value );
549 static HRESULT WINAPI domdoc_put_nodeValue(
550 IXMLDOMDocument2 *iface,
551 VARIANT value)
553 domdoc *This = impl_from_IXMLDOMDocument2( iface );
554 return IXMLDOMNode_put_nodeValue( This->node, value );
558 static HRESULT WINAPI domdoc_get_nodeType(
559 IXMLDOMDocument2 *iface,
560 DOMNodeType* type )
562 domdoc *This = impl_from_IXMLDOMDocument2( iface );
563 return IXMLDOMNode_get_nodeType( This->node, type );
567 static HRESULT WINAPI domdoc_get_parentNode(
568 IXMLDOMDocument2 *iface,
569 IXMLDOMNode** parent )
571 domdoc *This = impl_from_IXMLDOMDocument2( iface );
572 return IXMLDOMNode_get_parentNode( This->node, parent );
576 static HRESULT WINAPI domdoc_get_childNodes(
577 IXMLDOMDocument2 *iface,
578 IXMLDOMNodeList** childList )
580 domdoc *This = impl_from_IXMLDOMDocument2( iface );
581 return IXMLDOMNode_get_childNodes( This->node, childList );
585 static HRESULT WINAPI domdoc_get_firstChild(
586 IXMLDOMDocument2 *iface,
587 IXMLDOMNode** firstChild )
589 domdoc *This = impl_from_IXMLDOMDocument2( iface );
590 return IXMLDOMNode_get_firstChild( This->node, firstChild );
594 static HRESULT WINAPI domdoc_get_lastChild(
595 IXMLDOMDocument2 *iface,
596 IXMLDOMNode** lastChild )
598 domdoc *This = impl_from_IXMLDOMDocument2( iface );
599 return IXMLDOMNode_get_lastChild( This->node, lastChild );
603 static HRESULT WINAPI domdoc_get_previousSibling(
604 IXMLDOMDocument2 *iface,
605 IXMLDOMNode** previousSibling )
607 domdoc *This = impl_from_IXMLDOMDocument2( iface );
608 return IXMLDOMNode_get_previousSibling( This->node, previousSibling );
612 static HRESULT WINAPI domdoc_get_nextSibling(
613 IXMLDOMDocument2 *iface,
614 IXMLDOMNode** nextSibling )
616 domdoc *This = impl_from_IXMLDOMDocument2( iface );
617 return IXMLDOMNode_get_nextSibling( This->node, nextSibling );
621 static HRESULT WINAPI domdoc_get_attributes(
622 IXMLDOMDocument2 *iface,
623 IXMLDOMNamedNodeMap** attributeMap )
625 domdoc *This = impl_from_IXMLDOMDocument2( iface );
626 return IXMLDOMNode_get_attributes( This->node, attributeMap );
630 static HRESULT WINAPI domdoc_insertBefore(
631 IXMLDOMDocument2 *iface,
632 IXMLDOMNode* newChild,
633 VARIANT refChild,
634 IXMLDOMNode** outNewChild )
636 domdoc *This = impl_from_IXMLDOMDocument2( iface );
637 return IXMLDOMNode_insertBefore( This->node, newChild, refChild, outNewChild );
641 static HRESULT WINAPI domdoc_replaceChild(
642 IXMLDOMDocument2 *iface,
643 IXMLDOMNode* newChild,
644 IXMLDOMNode* oldChild,
645 IXMLDOMNode** outOldChild)
647 domdoc *This = impl_from_IXMLDOMDocument2( iface );
648 return IXMLDOMNode_replaceChild( This->node, newChild, oldChild, outOldChild );
652 static HRESULT WINAPI domdoc_removeChild(
653 IXMLDOMDocument2 *iface,
654 IXMLDOMNode* childNode,
655 IXMLDOMNode** oldChild)
657 domdoc *This = impl_from_IXMLDOMDocument2( iface );
658 return IXMLDOMNode_removeChild( This->node, childNode, oldChild );
662 static HRESULT WINAPI domdoc_appendChild(
663 IXMLDOMDocument2 *iface,
664 IXMLDOMNode* newChild,
665 IXMLDOMNode** outNewChild)
667 domdoc *This = impl_from_IXMLDOMDocument2( iface );
668 return IXMLDOMNode_appendChild( This->node, newChild, outNewChild );
672 static HRESULT WINAPI domdoc_hasChildNodes(
673 IXMLDOMDocument2 *iface,
674 VARIANT_BOOL* hasChild)
676 domdoc *This = impl_from_IXMLDOMDocument2( iface );
677 return IXMLDOMNode_hasChildNodes( This->node, hasChild );
681 static HRESULT WINAPI domdoc_get_ownerDocument(
682 IXMLDOMDocument2 *iface,
683 IXMLDOMDocument** DOMDocument)
685 domdoc *This = impl_from_IXMLDOMDocument2( iface );
686 return IXMLDOMNode_get_ownerDocument( This->node, DOMDocument );
690 static HRESULT WINAPI domdoc_cloneNode(
691 IXMLDOMDocument2 *iface,
692 VARIANT_BOOL deep,
693 IXMLDOMNode** cloneRoot)
695 domdoc *This = impl_from_IXMLDOMDocument2( iface );
696 return IXMLDOMNode_cloneNode( This->node, deep, cloneRoot );
700 static HRESULT WINAPI domdoc_get_nodeTypeString(
701 IXMLDOMDocument2 *iface,
702 BSTR* nodeType )
704 domdoc *This = impl_from_IXMLDOMDocument2( iface );
705 return IXMLDOMNode_get_nodeTypeString( This->node, nodeType );
709 static HRESULT WINAPI domdoc_get_text(
710 IXMLDOMDocument2 *iface,
711 BSTR* text )
713 domdoc *This = impl_from_IXMLDOMDocument2( iface );
714 return IXMLDOMNode_get_text( This->node, text );
718 static HRESULT WINAPI domdoc_put_text(
719 IXMLDOMDocument2 *iface,
720 BSTR text )
722 domdoc *This = impl_from_IXMLDOMDocument2( iface );
723 return IXMLDOMNode_put_text( This->node, text );
727 static HRESULT WINAPI domdoc_get_specified(
728 IXMLDOMDocument2 *iface,
729 VARIANT_BOOL* isSpecified )
731 domdoc *This = impl_from_IXMLDOMDocument2( iface );
732 return IXMLDOMNode_get_specified( This->node, isSpecified );
736 static HRESULT WINAPI domdoc_get_definition(
737 IXMLDOMDocument2 *iface,
738 IXMLDOMNode** definitionNode )
740 domdoc *This = impl_from_IXMLDOMDocument2( iface );
741 return IXMLDOMNode_get_definition( This->node, definitionNode );
745 static HRESULT WINAPI domdoc_get_nodeTypedValue(
746 IXMLDOMDocument2 *iface,
747 VARIANT* typedValue )
749 domdoc *This = impl_from_IXMLDOMDocument2( iface );
750 return IXMLDOMNode_get_nodeTypedValue( This->node, typedValue );
753 static HRESULT WINAPI domdoc_put_nodeTypedValue(
754 IXMLDOMDocument2 *iface,
755 VARIANT typedValue )
757 domdoc *This = impl_from_IXMLDOMDocument2( iface );
758 return IXMLDOMNode_put_nodeTypedValue( This->node, typedValue );
762 static HRESULT WINAPI domdoc_get_dataType(
763 IXMLDOMDocument2 *iface,
764 VARIANT* dataTypeName )
766 domdoc *This = impl_from_IXMLDOMDocument2( iface );
767 return IXMLDOMNode_get_dataType( This->node, dataTypeName );
771 static HRESULT WINAPI domdoc_put_dataType(
772 IXMLDOMDocument2 *iface,
773 BSTR dataTypeName )
775 domdoc *This = impl_from_IXMLDOMDocument2( iface );
776 return IXMLDOMNode_put_dataType( This->node, dataTypeName );
780 static HRESULT WINAPI domdoc_get_xml(
781 IXMLDOMDocument2 *iface,
782 BSTR* xmlString )
784 domdoc *This = impl_from_IXMLDOMDocument2( iface );
785 return IXMLDOMNode_get_xml( This->node, xmlString );
789 static HRESULT WINAPI domdoc_transformNode(
790 IXMLDOMDocument2 *iface,
791 IXMLDOMNode* styleSheet,
792 BSTR* xmlString )
794 domdoc *This = impl_from_IXMLDOMDocument2( iface );
795 return IXMLDOMNode_transformNode( This->node, styleSheet, xmlString );
799 static HRESULT WINAPI domdoc_selectNodes(
800 IXMLDOMDocument2 *iface,
801 BSTR queryString,
802 IXMLDOMNodeList** resultList )
804 domdoc *This = impl_from_IXMLDOMDocument2( iface );
805 return IXMLDOMNode_selectNodes( This->node, queryString, resultList );
809 static HRESULT WINAPI domdoc_selectSingleNode(
810 IXMLDOMDocument2 *iface,
811 BSTR queryString,
812 IXMLDOMNode** resultNode )
814 domdoc *This = impl_from_IXMLDOMDocument2( iface );
815 return IXMLDOMNode_selectSingleNode( This->node, queryString, resultNode );
819 static HRESULT WINAPI domdoc_get_parsed(
820 IXMLDOMDocument2 *iface,
821 VARIANT_BOOL* isParsed )
823 domdoc *This = impl_from_IXMLDOMDocument2( iface );
824 return IXMLDOMNode_get_parsed( This->node, isParsed );
828 static HRESULT WINAPI domdoc_get_namespaceURI(
829 IXMLDOMDocument2 *iface,
830 BSTR* namespaceURI )
832 domdoc *This = impl_from_IXMLDOMDocument2( iface );
833 return IXMLDOMNode_get_namespaceURI( This->node, namespaceURI );
837 static HRESULT WINAPI domdoc_get_prefix(
838 IXMLDOMDocument2 *iface,
839 BSTR* prefixString )
841 domdoc *This = impl_from_IXMLDOMDocument2( iface );
842 return IXMLDOMNode_get_prefix( This->node, prefixString );
846 static HRESULT WINAPI domdoc_get_baseName(
847 IXMLDOMDocument2 *iface,
848 BSTR* nameString )
850 domdoc *This = impl_from_IXMLDOMDocument2( iface );
851 return IXMLDOMNode_get_baseName( This->node, nameString );
855 static HRESULT WINAPI domdoc_transformNodeToObject(
856 IXMLDOMDocument2 *iface,
857 IXMLDOMNode* stylesheet,
858 VARIANT outputObject)
860 domdoc *This = impl_from_IXMLDOMDocument2( iface );
861 return IXMLDOMNode_transformNodeToObject( This->node, stylesheet, outputObject );
865 static HRESULT WINAPI domdoc_get_doctype(
866 IXMLDOMDocument2 *iface,
867 IXMLDOMDocumentType** documentType )
869 FIXME("\n");
870 return E_NOTIMPL;
874 static HRESULT WINAPI domdoc_get_implementation(
875 IXMLDOMDocument2 *iface,
876 IXMLDOMImplementation** impl )
878 if(!impl)
879 return E_INVALIDARG;
881 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
883 return S_OK;
886 static HRESULT WINAPI domdoc_get_documentElement(
887 IXMLDOMDocument2 *iface,
888 IXMLDOMElement** DOMElement )
890 domdoc *This = impl_from_IXMLDOMDocument2( iface );
891 xmlDocPtr xmldoc = NULL;
892 xmlNodePtr root = NULL;
893 IXMLDOMNode *element_node;
894 HRESULT hr;
896 TRACE("%p %p\n", This, This->node);
898 if(!DOMElement)
899 return E_INVALIDARG;
901 *DOMElement = NULL;
903 xmldoc = get_doc( This );
905 root = xmlDocGetRootElement( xmldoc );
906 if ( !root )
907 return S_FALSE;
909 element_node = create_node( root );
910 if(!element_node) return S_FALSE;
912 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (LPVOID*)DOMElement);
913 IXMLDOMNode_Release(element_node);
915 return hr;
919 static HRESULT WINAPI domdoc_put_documentElement(
920 IXMLDOMDocument2 *iface,
921 IXMLDOMElement* DOMElement )
923 domdoc *This = impl_from_IXMLDOMDocument2( iface );
924 IXMLDOMNode *elementNode;
925 xmlNodePtr oldRoot;
926 xmlnode *xmlNode;
927 HRESULT hr;
929 TRACE("(%p)->(%p)\n", This, DOMElement);
931 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
932 if(FAILED(hr))
933 return hr;
935 xmlNode = impl_from_IXMLDOMNode( elementNode );
937 if(!xmlNode->node->parent)
938 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
939 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
941 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
942 IXMLDOMNode_Release( elementNode );
944 if(oldRoot)
945 xmldoc_add_orphan(oldRoot->doc, oldRoot);
947 return S_OK;
951 static HRESULT WINAPI domdoc_createElement(
952 IXMLDOMDocument2 *iface,
953 BSTR tagname,
954 IXMLDOMElement** element )
956 xmlNodePtr xmlnode;
957 domdoc *This = impl_from_IXMLDOMDocument2( iface );
958 xmlChar *xml_name;
959 IUnknown *elem_unk;
960 HRESULT hr;
962 TRACE("%p->(%s,%p)\n", iface, debugstr_w(tagname), element);
964 xml_name = xmlChar_from_wchar((WCHAR*)tagname);
965 xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
966 xmldoc_add_orphan(xmlnode->doc, xmlnode);
968 TRACE("created xmlptr %p\n", xmlnode);
969 elem_unk = create_element(xmlnode, NULL);
970 HeapFree(GetProcessHeap(), 0, xml_name);
972 hr = IUnknown_QueryInterface(elem_unk, &IID_IXMLDOMElement, (void **)element);
973 IUnknown_Release(elem_unk);
974 TRACE("returning %p\n", *element);
975 return hr;
979 static HRESULT WINAPI domdoc_createDocumentFragment(
980 IXMLDOMDocument2 *iface,
981 IXMLDOMDocumentFragment** docFrag )
983 domdoc *This = impl_from_IXMLDOMDocument2( iface );
984 xmlNodePtr xmlnode;
986 TRACE("%p\n", iface);
988 if(!docFrag)
989 return E_INVALIDARG;
991 *docFrag = NULL;
993 xmlnode = xmlNewDocFragment(get_doc( This ) );
995 if(!xmlnode)
996 return E_FAIL;
998 xmldoc_add_orphan(xmlnode->doc, xmlnode);
999 *docFrag = (IXMLDOMDocumentFragment*)create_doc_fragment(xmlnode);
1001 return S_OK;
1005 static HRESULT WINAPI domdoc_createTextNode(
1006 IXMLDOMDocument2 *iface,
1007 BSTR data,
1008 IXMLDOMText** text )
1010 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1011 xmlNodePtr xmlnode;
1012 xmlChar *xml_content;
1014 TRACE("%p->(%s %p)\n", iface, debugstr_w(data), text);
1016 if(!text)
1017 return E_INVALIDARG;
1019 *text = NULL;
1021 xml_content = xmlChar_from_wchar((WCHAR*)data);
1022 xmlnode = xmlNewText(xml_content);
1023 HeapFree(GetProcessHeap(), 0, xml_content);
1025 if(!xmlnode)
1026 return E_FAIL;
1028 xmlnode->doc = get_doc( This );
1029 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1031 *text = (IXMLDOMText*)create_text(xmlnode);
1033 return S_OK;
1037 static HRESULT WINAPI domdoc_createComment(
1038 IXMLDOMDocument2 *iface,
1039 BSTR data,
1040 IXMLDOMComment** comment )
1042 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1043 xmlNodePtr xmlnode;
1044 xmlChar *xml_content;
1046 TRACE("%p->(%s %p)\n", iface, debugstr_w(data), comment);
1048 if(!comment)
1049 return E_INVALIDARG;
1051 *comment = NULL;
1053 xml_content = xmlChar_from_wchar((WCHAR*)data);
1054 xmlnode = xmlNewComment(xml_content);
1055 HeapFree(GetProcessHeap(), 0, xml_content);
1057 if(!xmlnode)
1058 return E_FAIL;
1060 xmlnode->doc = get_doc( This );
1061 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1063 *comment = (IXMLDOMComment*)create_comment(xmlnode);
1065 return S_OK;
1069 static HRESULT WINAPI domdoc_createCDATASection(
1070 IXMLDOMDocument2 *iface,
1071 BSTR data,
1072 IXMLDOMCDATASection** cdata )
1074 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1075 xmlNodePtr xmlnode;
1076 xmlChar *xml_content;
1078 TRACE("%p->(%s %p)\n", iface, debugstr_w(data), cdata);
1080 if(!cdata)
1081 return E_INVALIDARG;
1083 *cdata = NULL;
1085 xml_content = xmlChar_from_wchar((WCHAR*)data);
1086 xmlnode = xmlNewCDataBlock(get_doc( This ), xml_content, strlen( (char*)xml_content) );
1087 HeapFree(GetProcessHeap(), 0, xml_content);
1089 if(!xmlnode)
1090 return E_FAIL;
1092 xmlnode->doc = get_doc( This );
1093 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1095 *cdata = (IXMLDOMCDATASection*)create_cdata(xmlnode);
1097 return S_OK;
1101 static HRESULT WINAPI domdoc_createProcessingInstruction(
1102 IXMLDOMDocument2 *iface,
1103 BSTR target,
1104 BSTR data,
1105 IXMLDOMProcessingInstruction** pi )
1107 #ifdef HAVE_XMLNEWDOCPI
1108 xmlNodePtr xmlnode;
1109 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1110 xmlChar *xml_target, *xml_content;
1112 TRACE("%p->(%s %s %p)\n", iface, debugstr_w(target), debugstr_w(data), pi);
1114 if(!pi)
1115 return E_INVALIDARG;
1117 if(!target || lstrlenW(target) == 0)
1118 return E_FAIL;
1120 xml_target = xmlChar_from_wchar((WCHAR*)target);
1121 xml_content = xmlChar_from_wchar((WCHAR*)data);
1123 xmlnode = xmlNewDocPI(get_doc(This), xml_target, xml_content);
1124 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1125 TRACE("created xmlptr %p\n", xmlnode);
1126 *pi = (IXMLDOMProcessingInstruction*)create_pi(xmlnode);
1128 HeapFree(GetProcessHeap(), 0, xml_content);
1129 HeapFree(GetProcessHeap(), 0, xml_target);
1131 return S_OK;
1132 #else
1133 FIXME("Libxml 2.6.15 or greater required.\n");
1134 return E_NOTIMPL;
1135 #endif
1139 static HRESULT WINAPI domdoc_createAttribute(
1140 IXMLDOMDocument2 *iface,
1141 BSTR name,
1142 IXMLDOMAttribute** attribute )
1144 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1145 xmlNodePtr xmlnode;
1146 xmlChar *xml_name;
1148 TRACE("%p->(%s %p)\n", iface, debugstr_w(name), attribute);
1150 if(!attribute)
1151 return E_INVALIDARG;
1153 *attribute = NULL;
1155 xml_name = xmlChar_from_wchar((WCHAR*)name);
1156 xmlnode = (xmlNode *)xmlNewProp(NULL, xml_name, NULL);
1157 HeapFree(GetProcessHeap(), 0, xml_name);
1159 if(!xmlnode)
1160 return E_FAIL;
1162 xmlnode->doc = get_doc( This );
1163 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1165 *attribute = (IXMLDOMAttribute*)create_attribute(xmlnode);
1167 return S_OK;
1171 static HRESULT WINAPI domdoc_createEntityReference(
1172 IXMLDOMDocument2 *iface,
1173 BSTR name,
1174 IXMLDOMEntityReference** entityRef )
1176 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1177 xmlNodePtr xmlnode;
1178 xmlChar *xml_name;
1180 TRACE("%p\n", iface);
1182 if(!entityRef)
1183 return E_INVALIDARG;
1185 *entityRef = NULL;
1187 xml_name = xmlChar_from_wchar((WCHAR*)name);
1188 xmlnode = xmlNewReference(get_doc( This ), xml_name );
1189 HeapFree(GetProcessHeap(), 0, xml_name);
1191 if(!xmlnode)
1192 return E_FAIL;
1194 xmlnode->doc = get_doc( This );
1195 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1197 *entityRef = (IXMLDOMEntityReference*)create_doc_entity_ref(xmlnode);
1199 return S_OK;
1203 static HRESULT WINAPI domdoc_getElementsByTagName(
1204 IXMLDOMDocument2 *iface,
1205 BSTR tagName,
1206 IXMLDOMNodeList** resultList )
1208 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1209 LPWSTR szPattern;
1210 HRESULT hr;
1211 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1213 szPattern = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(2+lstrlenW(tagName)+1));
1214 szPattern[0] = szPattern[1] = '/';
1215 lstrcpyW(szPattern + 2, tagName);
1217 hr = queryresult_create((xmlNodePtr)get_doc(This), szPattern, resultList);
1218 HeapFree(GetProcessHeap(), 0, szPattern);
1220 return hr;
1223 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1225 VARIANT tmp;
1226 HRESULT hr;
1228 VariantInit(&tmp);
1229 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1230 if(FAILED(hr))
1231 return E_INVALIDARG;
1233 *type = V_I4(&tmp);
1235 return S_OK;
1238 static HRESULT WINAPI domdoc_createNode(
1239 IXMLDOMDocument2 *iface,
1240 VARIANT Type,
1241 BSTR name,
1242 BSTR namespaceURI,
1243 IXMLDOMNode** node )
1245 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1246 DOMNodeType node_type;
1247 xmlNodePtr xmlnode = NULL;
1248 xmlChar *xml_name;
1249 HRESULT hr;
1251 TRACE("(%p)->(type,%s,%s,%p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1253 hr = get_node_type(Type, &node_type);
1254 if(FAILED(hr))
1255 return hr;
1257 TRACE("node_type %d\n", node_type);
1259 xml_name = xmlChar_from_wchar((WCHAR*)name);
1261 switch(node_type)
1263 case NODE_ELEMENT:
1264 xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
1265 *node = create_node(xmlnode);
1266 TRACE("created %p\n", xmlnode);
1267 break;
1268 case NODE_ATTRIBUTE:
1269 xmlnode = (xmlNode *)xmlNewProp(NULL, xml_name, NULL);
1270 if(xmlnode)
1272 xmlnode->doc = get_doc( This );
1274 *node = (IXMLDOMNode*)create_attribute(xmlnode);
1277 TRACE("created %p\n", xmlnode);
1278 break;
1280 default:
1281 FIXME("unhandled node type %d\n", node_type);
1282 break;
1285 HeapFree(GetProcessHeap(), 0, xml_name);
1287 if(xmlnode && *node)
1289 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1290 return S_OK;
1293 return E_FAIL;
1296 static HRESULT WINAPI domdoc_nodeFromID(
1297 IXMLDOMDocument2 *iface,
1298 BSTR idString,
1299 IXMLDOMNode** node )
1301 FIXME("\n");
1302 return E_NOTIMPL;
1305 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1307 domdoc *This = obj;
1308 xmlDocPtr xmldoc;
1310 xmldoc = doparse( ptr, len );
1311 if(xmldoc) {
1312 xmldoc->_private = create_priv();
1313 attach_xmlnode(This->node, (xmlNodePtr) xmldoc);
1316 return S_OK;
1319 static HRESULT doread( domdoc *This, LPWSTR filename )
1321 bsc_t *bsc;
1322 HRESULT hr;
1324 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1325 if(FAILED(hr))
1326 return hr;
1328 if(This->bsc)
1329 detach_bsc(This->bsc);
1331 This->bsc = bsc;
1332 return S_OK;
1335 static HRESULT WINAPI domdoc_load(
1336 IXMLDOMDocument2 *iface,
1337 VARIANT xmlSource,
1338 VARIANT_BOOL* isSuccessful )
1340 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1341 LPWSTR filename = NULL;
1342 HRESULT hr = S_FALSE;
1343 IXMLDOMDocument2 *pNewDoc = NULL;
1344 IStream *pStream = NULL;
1345 xmlDocPtr xmldoc;
1347 TRACE("type %d\n", V_VT(&xmlSource) );
1349 *isSuccessful = VARIANT_FALSE;
1351 assert( This->node );
1353 attach_xmlnode(This->node, NULL);
1355 switch( V_VT(&xmlSource) )
1357 case VT_BSTR:
1358 filename = V_BSTR(&xmlSource);
1359 break;
1360 case VT_UNKNOWN:
1361 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument2, (void**)&pNewDoc);
1362 if(hr == S_OK)
1364 if(pNewDoc)
1366 domdoc *newDoc = impl_from_IXMLDOMDocument2( pNewDoc );
1367 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1368 attach_xmlnode(This->node, (xmlNodePtr) xmldoc);
1370 *isSuccessful = VARIANT_TRUE;
1372 return S_OK;
1375 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1376 if(hr == S_OK)
1378 IPersistStream *pDocStream;
1379 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1380 if(hr == S_OK)
1382 hr = xmldoc_IPersistStream_Load(pDocStream, pStream);
1383 IStream_Release(pStream);
1384 if(hr == S_OK)
1386 *isSuccessful = VARIANT_TRUE;
1388 TRACE("Using ID_IStream to load Document\n");
1389 return S_OK;
1391 else
1393 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1396 else
1398 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1401 else
1403 /* ISequentialStream */
1404 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1406 break;
1407 default:
1408 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1411 TRACE("filename (%s)\n", debugstr_w(filename));
1413 if ( filename )
1415 hr = doread( This, filename );
1417 if ( FAILED(hr) )
1418 This->error = E_FAIL;
1419 else
1421 hr = This->error = S_OK;
1422 *isSuccessful = VARIANT_TRUE;
1426 if(!filename || FAILED(hr)) {
1427 xmldoc = xmlNewDoc(NULL);
1428 xmldoc->_private = create_priv();
1429 attach_xmlnode(This->node, (xmlNodePtr) xmldoc);
1430 hr = S_FALSE;
1433 TRACE("ret (%d)\n", hr);
1435 return hr;
1439 static HRESULT WINAPI domdoc_get_readyState(
1440 IXMLDOMDocument2 *iface,
1441 long* value )
1443 FIXME("\n");
1444 return E_NOTIMPL;
1448 static HRESULT WINAPI domdoc_get_parseError(
1449 IXMLDOMDocument2 *iface,
1450 IXMLDOMParseError** errorObj )
1452 BSTR error_string = NULL;
1453 static const WCHAR err[] = {'e','r','r','o','r',0};
1454 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1456 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
1458 if(This->error)
1459 error_string = SysAllocString(err);
1461 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
1462 if(!*errorObj) return E_OUTOFMEMORY;
1463 return S_OK;
1467 static HRESULT WINAPI domdoc_get_url(
1468 IXMLDOMDocument2 *iface,
1469 BSTR* urlString )
1471 FIXME("\n");
1472 return E_NOTIMPL;
1476 static HRESULT WINAPI domdoc_get_async(
1477 IXMLDOMDocument2 *iface,
1478 VARIANT_BOOL* isAsync )
1480 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1482 TRACE("%p <- %d\n", isAsync, This->async);
1483 *isAsync = This->async;
1484 return S_OK;
1488 static HRESULT WINAPI domdoc_put_async(
1489 IXMLDOMDocument2 *iface,
1490 VARIANT_BOOL isAsync )
1492 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1494 TRACE("%d\n", isAsync);
1495 This->async = isAsync;
1496 return S_OK;
1500 static HRESULT WINAPI domdoc_abort(
1501 IXMLDOMDocument2 *iface )
1503 FIXME("\n");
1504 return E_NOTIMPL;
1508 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
1510 UINT len, blen = SysStringLen( bstr );
1511 LPSTR str;
1513 len = WideCharToMultiByte( CP_UTF8, 0, bstr, blen, NULL, 0, NULL, NULL );
1514 str = HeapAlloc( GetProcessHeap(), 0, len );
1515 if ( !str )
1516 return FALSE;
1517 WideCharToMultiByte( CP_UTF8, 0, bstr, blen, str, len, NULL, NULL );
1518 *plen = len;
1519 *pstr = str;
1520 return TRUE;
1523 static HRESULT WINAPI domdoc_loadXML(
1524 IXMLDOMDocument2 *iface,
1525 BSTR bstrXML,
1526 VARIANT_BOOL* isSuccessful )
1528 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1529 xmlDocPtr xmldoc = NULL;
1530 char *str;
1531 int len;
1532 HRESULT hr = S_FALSE;
1534 TRACE("%p %s %p\n", This, debugstr_w( bstrXML ), isSuccessful );
1536 assert ( This->node );
1538 attach_xmlnode( This->node, NULL );
1540 if ( isSuccessful )
1542 *isSuccessful = VARIANT_FALSE;
1544 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
1546 xmldoc = doparse( str, len );
1547 HeapFree( GetProcessHeap(), 0, str );
1548 if ( !xmldoc )
1549 This->error = E_FAIL;
1550 else
1552 hr = This->error = S_OK;
1553 *isSuccessful = VARIANT_TRUE;
1557 if(!xmldoc)
1558 xmldoc = xmlNewDoc(NULL);
1560 xmldoc->_private = create_priv();
1561 attach_xmlnode( This->node, (xmlNodePtr) xmldoc );
1563 return hr;
1567 static HRESULT WINAPI domdoc_save(
1568 IXMLDOMDocument2 *iface,
1569 VARIANT destination )
1571 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1572 HANDLE handle;
1573 xmlChar *mem, *p;
1574 int size;
1575 HRESULT ret = S_OK;
1576 DWORD written;
1578 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
1579 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
1581 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
1583 FIXME("Unhandled vt %d\n", V_VT(&destination));
1584 return S_FALSE;
1587 if(V_VT(&destination) == VT_UNKNOWN)
1589 IUnknown *pUnk = V_UNKNOWN(&destination);
1590 IXMLDOMDocument *pDocument;
1592 ret = IXMLDOMDocument_QueryInterface(pUnk, &IID_IXMLDOMDocument2, (void**)&pDocument);
1593 if(ret == S_OK)
1595 BSTR bXML;
1596 VARIANT_BOOL bSuccessful;
1598 ret = IXMLDOMDocument_get_xml(iface, &bXML);
1599 if(ret == S_OK)
1601 ret = IXMLDOMDocument_loadXML(pDocument, bXML, &bSuccessful);
1603 SysFreeString(bXML);
1606 IXMLDOMDocument_Release(pDocument);
1609 TRACE("ret %d\n", ret);
1611 return ret;
1614 handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
1615 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1616 if( handle == INVALID_HANDLE_VALUE )
1618 WARN("failed to create file\n");
1619 return S_FALSE;
1622 xmlDocDumpMemory(get_doc(This), &mem, &size);
1625 * libxml2 always adds XML declaration on top of the file and one for each processing instruction node in DOM tree.
1626 * MSXML adds XML declaration only for processing instruction nodes.
1627 * We skip the first XML declaration generated by libxml2 to get exactly what we need.
1629 p = mem;
1630 if(size > 2 && p[0] == '<' && p[1] == '?') {
1631 while(p < mem+size && (p[0] != '?' || p[1] != '>'))
1632 p++;
1633 p += 2;
1634 while(p < mem+size && isspace(*p))
1635 p++;
1636 size -= p-mem;
1639 if(!WriteFile(handle, p, (DWORD)size, &written, NULL) || written != (DWORD)size)
1641 WARN("write error\n");
1642 ret = S_FALSE;
1645 xmlFree(mem);
1646 CloseHandle(handle);
1647 return ret;
1650 static HRESULT WINAPI domdoc_get_validateOnParse(
1651 IXMLDOMDocument2 *iface,
1652 VARIANT_BOOL* isValidating )
1654 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1656 TRACE("%p <- %d\n", isValidating, This->validating);
1657 *isValidating = This->validating;
1658 return S_OK;
1662 static HRESULT WINAPI domdoc_put_validateOnParse(
1663 IXMLDOMDocument2 *iface,
1664 VARIANT_BOOL isValidating )
1666 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1668 TRACE("%d\n", isValidating);
1669 This->validating = isValidating;
1670 return S_OK;
1674 static HRESULT WINAPI domdoc_get_resolveExternals(
1675 IXMLDOMDocument2 *iface,
1676 VARIANT_BOOL* isResolving )
1678 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1680 TRACE("%p <- %d\n", isResolving, This->resolving);
1681 *isResolving = This->resolving;
1682 return S_OK;
1686 static HRESULT WINAPI domdoc_put_resolveExternals(
1687 IXMLDOMDocument2 *iface,
1688 VARIANT_BOOL isResolving )
1690 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1692 TRACE("%d\n", isResolving);
1693 This->resolving = isResolving;
1694 return S_OK;
1698 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
1699 IXMLDOMDocument2 *iface,
1700 VARIANT_BOOL* isPreserving )
1702 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1704 TRACE("%p <- %d\n", isPreserving, This->preserving);
1705 *isPreserving = This->preserving;
1706 return S_OK;
1710 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
1711 IXMLDOMDocument2 *iface,
1712 VARIANT_BOOL isPreserving )
1714 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1716 TRACE("%d\n", isPreserving);
1717 This->preserving = isPreserving;
1718 return S_OK;
1722 static HRESULT WINAPI domdoc_put_onReadyStateChange(
1723 IXMLDOMDocument2 *iface,
1724 VARIANT readyStateChangeSink )
1726 FIXME("\n");
1727 return E_NOTIMPL;
1731 static HRESULT WINAPI domdoc_put_onDataAvailable(
1732 IXMLDOMDocument2 *iface,
1733 VARIANT onDataAvailableSink )
1735 FIXME("\n");
1736 return E_NOTIMPL;
1739 static HRESULT WINAPI domdoc_put_onTransformNode(
1740 IXMLDOMDocument2 *iface,
1741 VARIANT onTransformNodeSink )
1743 FIXME("\n");
1744 return E_NOTIMPL;
1747 static HRESULT WINAPI domdoc_get_namespaces(
1748 IXMLDOMDocument2* iface,
1749 IXMLDOMSchemaCollection** schemaCollection )
1751 FIXME("\n");
1752 return E_NOTIMPL;
1755 static HRESULT WINAPI domdoc_get_schemas(
1756 IXMLDOMDocument2* iface,
1757 VARIANT* var1 )
1759 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1760 HRESULT hr = S_FALSE;
1761 IXMLDOMSchemaCollection *cur_schema = This->schema;
1763 TRACE("(%p)->(%p)\n", This, var1);
1765 VariantInit(var1); /* Test shows we don't call VariantClear here */
1766 V_VT(var1) = VT_NULL;
1768 if(cur_schema)
1770 hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
1771 if(SUCCEEDED(hr))
1772 V_VT(var1) = VT_DISPATCH;
1774 return hr;
1777 static HRESULT WINAPI domdoc_putref_schemas(
1778 IXMLDOMDocument2* iface,
1779 VARIANT var1)
1781 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1782 HRESULT hr = E_FAIL;
1783 IXMLDOMSchemaCollection *new_schema = NULL;
1785 FIXME("(%p): semi-stub\n", This);
1786 switch(V_VT(&var1))
1788 case VT_UNKNOWN:
1789 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1790 break;
1792 case VT_DISPATCH:
1793 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1794 break;
1796 case VT_NULL:
1797 case VT_EMPTY:
1798 hr = S_OK;
1799 break;
1801 default:
1802 WARN("Can't get schema from vt %x\n", V_VT(&var1));
1805 if(SUCCEEDED(hr))
1807 IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
1808 if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
1811 return hr;
1814 static HRESULT WINAPI domdoc_validate(
1815 IXMLDOMDocument2* iface,
1816 IXMLDOMParseError** err)
1818 FIXME("\n");
1819 return E_NOTIMPL;
1822 static HRESULT WINAPI domdoc_setProperty(
1823 IXMLDOMDocument2* iface,
1824 BSTR p,
1825 VARIANT var)
1827 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1829 if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
1831 VARIANT varStr;
1832 HRESULT hr;
1833 BSTR bstr;
1835 V_VT(&varStr) = VT_EMPTY;
1836 if (V_VT(&var) != VT_BSTR)
1838 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
1839 return hr;
1840 bstr = V_BSTR(&varStr);
1842 else
1843 bstr = V_BSTR(&var);
1845 hr = S_OK;
1846 if (lstrcmpiW(bstr, SZ_VALUE_XPATH) == 0)
1847 This->bUseXPath = TRUE;
1848 else if (lstrcmpiW(bstr, SZ_VALUE_XSLPATTERN) == 0)
1849 This->bUseXPath = FALSE;
1850 else
1851 hr = E_FAIL;
1853 VariantClear(&varStr);
1854 return hr;
1857 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
1858 return E_FAIL;
1861 static HRESULT WINAPI domdoc_getProperty(
1862 IXMLDOMDocument2* iface,
1863 BSTR p,
1864 VARIANT* var)
1866 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1868 if (var == NULL)
1869 return E_INVALIDARG;
1870 if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
1872 V_VT(var) = VT_BSTR;
1873 if (This->bUseXPath)
1874 V_BSTR(var) = SysAllocString(SZ_VALUE_XPATH);
1875 else
1876 V_BSTR(var) = SysAllocString(SZ_VALUE_XSLPATTERN);
1877 return S_OK;
1880 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
1881 return E_FAIL;
1884 static const struct IXMLDOMDocument2Vtbl domdoc_vtbl =
1886 domdoc_QueryInterface,
1887 domdoc_AddRef,
1888 domdoc_Release,
1889 domdoc_GetTypeInfoCount,
1890 domdoc_GetTypeInfo,
1891 domdoc_GetIDsOfNames,
1892 domdoc_Invoke,
1893 domdoc_get_nodeName,
1894 domdoc_get_nodeValue,
1895 domdoc_put_nodeValue,
1896 domdoc_get_nodeType,
1897 domdoc_get_parentNode,
1898 domdoc_get_childNodes,
1899 domdoc_get_firstChild,
1900 domdoc_get_lastChild,
1901 domdoc_get_previousSibling,
1902 domdoc_get_nextSibling,
1903 domdoc_get_attributes,
1904 domdoc_insertBefore,
1905 domdoc_replaceChild,
1906 domdoc_removeChild,
1907 domdoc_appendChild,
1908 domdoc_hasChildNodes,
1909 domdoc_get_ownerDocument,
1910 domdoc_cloneNode,
1911 domdoc_get_nodeTypeString,
1912 domdoc_get_text,
1913 domdoc_put_text,
1914 domdoc_get_specified,
1915 domdoc_get_definition,
1916 domdoc_get_nodeTypedValue,
1917 domdoc_put_nodeTypedValue,
1918 domdoc_get_dataType,
1919 domdoc_put_dataType,
1920 domdoc_get_xml,
1921 domdoc_transformNode,
1922 domdoc_selectNodes,
1923 domdoc_selectSingleNode,
1924 domdoc_get_parsed,
1925 domdoc_get_namespaceURI,
1926 domdoc_get_prefix,
1927 domdoc_get_baseName,
1928 domdoc_transformNodeToObject,
1929 domdoc_get_doctype,
1930 domdoc_get_implementation,
1931 domdoc_get_documentElement,
1932 domdoc_put_documentElement,
1933 domdoc_createElement,
1934 domdoc_createDocumentFragment,
1935 domdoc_createTextNode,
1936 domdoc_createComment,
1937 domdoc_createCDATASection,
1938 domdoc_createProcessingInstruction,
1939 domdoc_createAttribute,
1940 domdoc_createEntityReference,
1941 domdoc_getElementsByTagName,
1942 domdoc_createNode,
1943 domdoc_nodeFromID,
1944 domdoc_load,
1945 domdoc_get_readyState,
1946 domdoc_get_parseError,
1947 domdoc_get_url,
1948 domdoc_get_async,
1949 domdoc_put_async,
1950 domdoc_abort,
1951 domdoc_loadXML,
1952 domdoc_save,
1953 domdoc_get_validateOnParse,
1954 domdoc_put_validateOnParse,
1955 domdoc_get_resolveExternals,
1956 domdoc_put_resolveExternals,
1957 domdoc_get_preserveWhiteSpace,
1958 domdoc_put_preserveWhiteSpace,
1959 domdoc_put_onReadyStateChange,
1960 domdoc_put_onDataAvailable,
1961 domdoc_put_onTransformNode,
1962 domdoc_get_namespaces,
1963 domdoc_get_schemas,
1964 domdoc_putref_schemas,
1965 domdoc_validate,
1966 domdoc_setProperty,
1967 domdoc_getProperty
1970 /* xmldoc implementation of IObjectWithSite */
1971 static HRESULT WINAPI
1972 xmldoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
1974 domdoc *This = impl_from_IObjectWithSite(iface);
1975 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppvObject );
1978 static ULONG WINAPI
1979 xmldoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
1981 domdoc *This = impl_from_IObjectWithSite(iface);
1982 return IXMLDocument_AddRef((IXMLDocument *)This);
1985 static ULONG WINAPI
1986 xmldoc_ObjectWithSite_Release( IObjectWithSite* iface )
1988 domdoc *This = impl_from_IObjectWithSite(iface);
1989 return IXMLDocument_Release((IXMLDocument *)This);
1992 static HRESULT WINAPI
1993 xmldoc_GetSite( IObjectWithSite *iface, REFIID iid, void ** ppvSite )
1995 domdoc *This = impl_from_IObjectWithSite(iface);
1997 TRACE("%p %s %p\n", This, debugstr_guid( iid ), ppvSite );
1999 if ( !This->site )
2000 return E_FAIL;
2002 return IUnknown_QueryInterface( This->site, iid, ppvSite );
2005 static HRESULT WINAPI
2006 xmldoc_SetSite( IObjectWithSite *iface, IUnknown *punk )
2008 domdoc *This = impl_from_IObjectWithSite(iface);
2010 TRACE("%p %p\n", iface, punk);
2012 if(!punk)
2014 if(This->site)
2016 IUnknown_Release( This->site );
2017 This->site = NULL;
2020 return S_OK;
2023 if ( punk )
2024 IUnknown_AddRef( punk );
2026 if(This->site)
2027 IUnknown_Release( This->site );
2029 This->site = punk;
2031 return S_OK;
2034 static const IObjectWithSiteVtbl domdocObjectSite =
2036 xmldoc_ObjectWithSite_QueryInterface,
2037 xmldoc_ObjectWithSite_AddRef,
2038 xmldoc_ObjectWithSite_Release,
2039 xmldoc_SetSite,
2040 xmldoc_GetSite,
2043 static HRESULT WINAPI xmldoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
2045 domdoc *This = impl_from_IObjectSafety(iface);
2046 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppv );
2049 static ULONG WINAPI xmldoc_Safety_AddRef(IObjectSafety *iface)
2051 domdoc *This = impl_from_IObjectSafety(iface);
2052 return IXMLDocument_AddRef((IXMLDocument *)This);
2055 static ULONG WINAPI xmldoc_Safety_Release(IObjectSafety *iface)
2057 domdoc *This = impl_from_IObjectSafety(iface);
2058 return IXMLDocument_Release((IXMLDocument *)This);
2061 #define SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
2063 static HRESULT WINAPI xmldoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2064 DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
2066 domdoc *This = impl_from_IObjectSafety(iface);
2068 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
2070 if(!pdwSupportedOptions || !pdwEnabledOptions)
2071 return E_POINTER;
2073 *pdwSupportedOptions = SUPPORTED_OPTIONS;
2074 *pdwEnabledOptions = This->safeopt;
2076 return S_OK;
2079 static HRESULT WINAPI xmldoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2080 DWORD dwOptionSetMask, DWORD dwEnabledOptions)
2082 domdoc *This = impl_from_IObjectSafety(iface);
2084 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
2086 if(dwOptionSetMask & ~SUPPORTED_OPTIONS)
2087 return E_FAIL;
2089 This->safeopt = dwEnabledOptions & dwEnabledOptions;
2090 return S_OK;
2093 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
2094 xmldoc_Safety_QueryInterface,
2095 xmldoc_Safety_AddRef,
2096 xmldoc_Safety_Release,
2097 xmldoc_Safety_GetInterfaceSafetyOptions,
2098 xmldoc_Safety_SetInterfaceSafetyOptions
2102 static const tid_t domdoc_iface_tids[] = {
2103 IXMLDOMNode_tid,
2104 IXMLDOMDocument_tid,
2105 IXMLDOMDocument2_tid,
2108 static dispex_static_data_t domdoc_dispex = {
2109 NULL,
2110 IXMLDOMDocument2_tid,
2111 NULL,
2112 domdoc_iface_tids
2115 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument2 **document)
2117 domdoc *doc;
2118 HRESULT hr;
2120 doc = HeapAlloc( GetProcessHeap(), 0, sizeof (*doc) );
2121 if( !doc )
2122 return E_OUTOFMEMORY;
2124 doc->lpVtbl = &domdoc_vtbl;
2125 doc->lpvtblIPersistStream = &xmldoc_IPersistStream_VTable;
2126 doc->lpvtblIObjectWithSite = &domdocObjectSite;
2127 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
2128 doc->ref = 1;
2129 doc->async = 0;
2130 doc->validating = 0;
2131 doc->resolving = 0;
2132 doc->preserving = 0;
2133 doc->bUseXPath = FALSE;
2134 doc->error = S_OK;
2135 doc->schema = NULL;
2136 doc->stream = NULL;
2137 doc->site = NULL;
2138 doc->safeopt = 0;
2139 doc->bsc = NULL;
2141 doc->node_unk = create_basic_node( (xmlNodePtr)xmldoc, (IUnknown*)&doc->lpVtbl );
2142 if(!doc->node_unk)
2144 HeapFree(GetProcessHeap(), 0, doc);
2145 return E_FAIL;
2148 hr = IUnknown_QueryInterface(doc->node_unk, &IID_IXMLDOMNode, (LPVOID*)&doc->node);
2149 if(FAILED(hr))
2151 IUnknown_Release(doc->node_unk);
2152 HeapFree( GetProcessHeap(), 0, doc );
2153 return E_FAIL;
2156 init_dispex(&doc->dispex, (IUnknown*)&doc->lpVtbl, &domdoc_dispex);
2158 /* The ref on doc->node is actually looped back into this object, so release it */
2159 IXMLDOMNode_Release(doc->node);
2161 *document = (IXMLDOMDocument2*)&doc->lpVtbl;
2163 TRACE("returning iface %p\n", *document);
2164 return S_OK;
2167 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2169 xmlDocPtr xmldoc;
2170 HRESULT hr;
2172 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
2174 xmldoc = xmlNewDoc(NULL);
2175 if(!xmldoc)
2176 return E_OUTOFMEMORY;
2178 xmldoc->_private = create_priv();
2180 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument2**)ppObj);
2181 if(FAILED(hr))
2182 xmlFreeDoc(xmldoc);
2184 return hr;
2187 IUnknown* create_domdoc( xmlNodePtr document )
2189 HRESULT hr;
2190 LPVOID pObj = NULL;
2192 TRACE("(%p)\n", document);
2194 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument2**)&pObj);
2195 if (FAILED(hr))
2196 return NULL;
2198 return (IUnknown*)pObj;
2201 #else
2203 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2205 MESSAGE("This program tried to use a DOMDocument object, but\n"
2206 "libxml2 support was not present at compile time.\n");
2207 return E_NOTIMPL;
2210 #endif