push 337eb2e2d902d84a5d689451984c5832d7e04fc4
[wine/hacks.git] / dlls / msxml3 / domdoc.c
blobf71b1344ac6d2fda2ae6b9f87ce082ecb3a303ed
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 HRESULT attach_xmldoc( IXMLDOMNode *node, xmlDocPtr xml )
214 xmlnode *This = impl_from_IXMLDOMNode( node );
216 if(This->node)
217 xmldoc_release(This->node->doc);
219 This->node = (xmlNodePtr) xml;
220 if(This->node)
221 xmldoc_add_ref(This->node->doc);
223 return S_OK;
226 static inline domdoc *impl_from_IXMLDOMDocument2( IXMLDOMDocument2 *iface )
228 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
231 static inline xmlDocPtr get_doc( domdoc *This )
233 return (xmlDocPtr) xmlNodePtr_from_domnode( This->node, XML_DOCUMENT_NODE );
236 static inline domdoc *impl_from_IPersistStream(IPersistStream *iface)
238 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStream));
241 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
243 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
246 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
248 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
252 /************************************************************************
253 * xmldoc implementation of IPersistStream.
255 static HRESULT WINAPI xmldoc_IPersistStream_QueryInterface(
256 IPersistStream *iface, REFIID riid, LPVOID *ppvObj)
258 domdoc *this = impl_from_IPersistStream(iface);
259 return IXMLDocument_QueryInterface((IXMLDocument *)this, riid, ppvObj);
262 static ULONG WINAPI xmldoc_IPersistStream_AddRef(
263 IPersistStream *iface)
265 domdoc *this = impl_from_IPersistStream(iface);
266 return IXMLDocument_AddRef((IXMLDocument *)this);
269 static ULONG WINAPI xmldoc_IPersistStream_Release(
270 IPersistStream *iface)
272 domdoc *this = impl_from_IPersistStream(iface);
273 return IXMLDocument_Release((IXMLDocument *)this);
276 static HRESULT WINAPI xmldoc_IPersistStream_GetClassID(
277 IPersistStream *iface, CLSID *classid)
279 TRACE("(%p,%p): stub!\n", iface, classid);
281 if(!classid)
282 return E_POINTER;
284 *classid = CLSID_DOMDocument2;
286 return S_OK;
289 static HRESULT WINAPI xmldoc_IPersistStream_IsDirty(
290 IPersistStream *iface)
292 domdoc *This = impl_from_IPersistStream(iface);
294 FIXME("(%p->%p): stub!\n", iface, This);
296 return S_FALSE;
299 static HRESULT WINAPI xmldoc_IPersistStream_Load(
300 IPersistStream *iface, LPSTREAM pStm)
302 domdoc *This = impl_from_IPersistStream(iface);
303 HRESULT hr;
304 HGLOBAL hglobal;
305 DWORD read, written, len;
306 BYTE buf[4096];
307 char *ptr;
308 xmlDocPtr xmldoc = NULL;
310 TRACE("(%p, %p)\n", iface, pStm);
312 if (!pStm)
313 return E_INVALIDARG;
315 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
316 if (FAILED(hr))
317 return hr;
321 IStream_Read(pStm, buf, sizeof(buf), &read);
322 hr = IStream_Write(This->stream, buf, read, &written);
323 } while(SUCCEEDED(hr) && written != 0 && read != 0);
325 if (FAILED(hr))
327 ERR("Failed to copy stream\n");
328 return hr;
331 hr = GetHGlobalFromStream(This->stream, &hglobal);
332 if (FAILED(hr))
333 return hr;
335 len = GlobalSize(hglobal);
336 ptr = GlobalLock(hglobal);
337 if (len != 0)
338 xmldoc = parse_xml(ptr, len);
339 GlobalUnlock(hglobal);
341 if (!xmldoc)
343 ERR("Failed to parse xml\n");
344 return E_FAIL;
347 xmldoc->_private = create_priv();
349 return attach_xmldoc( This->node, xmldoc );
352 static HRESULT WINAPI xmldoc_IPersistStream_Save(
353 IPersistStream *iface, LPSTREAM pStm, BOOL fClearDirty)
355 FIXME("(%p, %p, %d): stub!\n", iface, pStm, fClearDirty);
356 return E_NOTIMPL;
359 static HRESULT WINAPI xmldoc_IPersistStream_GetSizeMax(
360 IPersistStream *iface, ULARGE_INTEGER *pcbSize)
362 TRACE("(%p, %p): stub!\n", iface, pcbSize);
363 return E_NOTIMPL;
366 static const IPersistStreamVtbl xmldoc_IPersistStream_VTable =
368 xmldoc_IPersistStream_QueryInterface,
369 xmldoc_IPersistStream_AddRef,
370 xmldoc_IPersistStream_Release,
371 xmldoc_IPersistStream_GetClassID,
372 xmldoc_IPersistStream_IsDirty,
373 xmldoc_IPersistStream_Load,
374 xmldoc_IPersistStream_Save,
375 xmldoc_IPersistStream_GetSizeMax,
378 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument2 *iface, REFIID riid, void** ppvObject )
380 domdoc *This = impl_from_IXMLDOMDocument2( iface );
382 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
384 *ppvObject = NULL;
386 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
387 IsEqualGUID( riid, &IID_IDispatch ) ||
388 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
389 IsEqualGUID( riid, &IID_IXMLDOMDocument2 ) )
391 *ppvObject = iface;
393 else if ( IsEqualGUID( riid, &IID_IXMLDOMNode ) )
395 return IUnknown_QueryInterface(This->node_unk, riid, ppvObject);
397 else if (IsEqualGUID(&IID_IPersistStream, riid))
399 *ppvObject = (IPersistStream*)&(This->lpvtblIPersistStream);
401 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
403 *ppvObject = (IObjectWithSite*)&(This->lpvtblIObjectWithSite);
405 else if(dispex_query_interface(&This->dispex, riid, ppvObject))
407 return *ppvObject ? S_OK : E_NOINTERFACE;
409 else if(IsEqualGUID(&IID_IRunnableObject, riid))
411 TRACE("IID_IRunnableObject not supported returning NULL\n");
412 return E_NOINTERFACE;
414 else
416 FIXME("interface %s not implemented\n", debugstr_guid(riid));
417 return E_NOINTERFACE;
420 IXMLDOMDocument_AddRef( iface );
422 return S_OK;
426 static ULONG WINAPI domdoc_AddRef(
427 IXMLDOMDocument2 *iface )
429 domdoc *This = impl_from_IXMLDOMDocument2( iface );
430 TRACE("%p\n", This );
431 return InterlockedIncrement( &This->ref );
435 static ULONG WINAPI domdoc_Release(
436 IXMLDOMDocument2 *iface )
438 domdoc *This = impl_from_IXMLDOMDocument2( iface );
439 LONG ref;
441 TRACE("%p\n", This );
443 ref = InterlockedDecrement( &This->ref );
444 if ( ref == 0 )
446 if(This->bsc)
447 detach_bsc(This->bsc);
449 if (This->site)
450 IUnknown_Release( This->site );
451 IUnknown_Release( This->node_unk );
452 if(This->schema) IXMLDOMSchemaCollection_Release( This->schema );
453 if (This->stream) IStream_Release(This->stream);
454 HeapFree( GetProcessHeap(), 0, This );
457 return ref;
460 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument2 *iface, UINT* pctinfo )
462 domdoc *This = impl_from_IXMLDOMDocument2( iface );
464 TRACE("(%p)->(%p)\n", This, pctinfo);
466 *pctinfo = 1;
468 return S_OK;
471 static HRESULT WINAPI domdoc_GetTypeInfo(
472 IXMLDOMDocument2 *iface,
473 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
475 domdoc *This = impl_from_IXMLDOMDocument2( iface );
476 HRESULT hr;
478 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
480 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
482 return hr;
485 static HRESULT WINAPI domdoc_GetIDsOfNames(
486 IXMLDOMDocument2 *iface,
487 REFIID riid,
488 LPOLESTR* rgszNames,
489 UINT cNames,
490 LCID lcid,
491 DISPID* rgDispId)
493 domdoc *This = impl_from_IXMLDOMDocument2( iface );
494 ITypeInfo *typeinfo;
495 HRESULT hr;
497 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
498 lcid, rgDispId);
500 if(!rgszNames || cNames == 0 || !rgDispId)
501 return E_INVALIDARG;
503 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
504 if(SUCCEEDED(hr))
506 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
507 ITypeInfo_Release(typeinfo);
510 return hr;
514 static HRESULT WINAPI domdoc_Invoke(
515 IXMLDOMDocument2 *iface,
516 DISPID dispIdMember,
517 REFIID riid,
518 LCID lcid,
519 WORD wFlags,
520 DISPPARAMS* pDispParams,
521 VARIANT* pVarResult,
522 EXCEPINFO* pExcepInfo,
523 UINT* puArgErr)
525 domdoc *This = impl_from_IXMLDOMDocument2( iface );
526 ITypeInfo *typeinfo;
527 HRESULT hr;
529 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
530 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
532 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
533 if(SUCCEEDED(hr))
535 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
536 pVarResult, pExcepInfo, puArgErr);
537 ITypeInfo_Release(typeinfo);
540 return hr;
544 static HRESULT WINAPI domdoc_get_nodeName(
545 IXMLDOMDocument2 *iface,
546 BSTR* name )
548 domdoc *This = impl_from_IXMLDOMDocument2( iface );
549 return IXMLDOMNode_get_nodeName( This->node, name );
553 static HRESULT WINAPI domdoc_get_nodeValue(
554 IXMLDOMDocument2 *iface,
555 VARIANT* value )
557 domdoc *This = impl_from_IXMLDOMDocument2( iface );
558 return IXMLDOMNode_get_nodeValue( This->node, value );
562 static HRESULT WINAPI domdoc_put_nodeValue(
563 IXMLDOMDocument2 *iface,
564 VARIANT value)
566 domdoc *This = impl_from_IXMLDOMDocument2( iface );
567 return IXMLDOMNode_put_nodeValue( This->node, value );
571 static HRESULT WINAPI domdoc_get_nodeType(
572 IXMLDOMDocument2 *iface,
573 DOMNodeType* type )
575 domdoc *This = impl_from_IXMLDOMDocument2( iface );
576 return IXMLDOMNode_get_nodeType( This->node, type );
580 static HRESULT WINAPI domdoc_get_parentNode(
581 IXMLDOMDocument2 *iface,
582 IXMLDOMNode** parent )
584 domdoc *This = impl_from_IXMLDOMDocument2( iface );
585 return IXMLDOMNode_get_parentNode( This->node, parent );
589 static HRESULT WINAPI domdoc_get_childNodes(
590 IXMLDOMDocument2 *iface,
591 IXMLDOMNodeList** childList )
593 domdoc *This = impl_from_IXMLDOMDocument2( iface );
594 return IXMLDOMNode_get_childNodes( This->node, childList );
598 static HRESULT WINAPI domdoc_get_firstChild(
599 IXMLDOMDocument2 *iface,
600 IXMLDOMNode** firstChild )
602 domdoc *This = impl_from_IXMLDOMDocument2( iface );
603 return IXMLDOMNode_get_firstChild( This->node, firstChild );
607 static HRESULT WINAPI domdoc_get_lastChild(
608 IXMLDOMDocument2 *iface,
609 IXMLDOMNode** lastChild )
611 domdoc *This = impl_from_IXMLDOMDocument2( iface );
612 return IXMLDOMNode_get_lastChild( This->node, lastChild );
616 static HRESULT WINAPI domdoc_get_previousSibling(
617 IXMLDOMDocument2 *iface,
618 IXMLDOMNode** previousSibling )
620 domdoc *This = impl_from_IXMLDOMDocument2( iface );
621 return IXMLDOMNode_get_previousSibling( This->node, previousSibling );
625 static HRESULT WINAPI domdoc_get_nextSibling(
626 IXMLDOMDocument2 *iface,
627 IXMLDOMNode** nextSibling )
629 domdoc *This = impl_from_IXMLDOMDocument2( iface );
630 return IXMLDOMNode_get_nextSibling( This->node, nextSibling );
634 static HRESULT WINAPI domdoc_get_attributes(
635 IXMLDOMDocument2 *iface,
636 IXMLDOMNamedNodeMap** attributeMap )
638 domdoc *This = impl_from_IXMLDOMDocument2( iface );
639 return IXMLDOMNode_get_attributes( This->node, attributeMap );
643 static HRESULT WINAPI domdoc_insertBefore(
644 IXMLDOMDocument2 *iface,
645 IXMLDOMNode* newChild,
646 VARIANT refChild,
647 IXMLDOMNode** outNewChild )
649 domdoc *This = impl_from_IXMLDOMDocument2( iface );
650 return IXMLDOMNode_insertBefore( This->node, newChild, refChild, outNewChild );
654 static HRESULT WINAPI domdoc_replaceChild(
655 IXMLDOMDocument2 *iface,
656 IXMLDOMNode* newChild,
657 IXMLDOMNode* oldChild,
658 IXMLDOMNode** outOldChild)
660 domdoc *This = impl_from_IXMLDOMDocument2( iface );
661 return IXMLDOMNode_replaceChild( This->node, newChild, oldChild, outOldChild );
665 static HRESULT WINAPI domdoc_removeChild(
666 IXMLDOMDocument2 *iface,
667 IXMLDOMNode* childNode,
668 IXMLDOMNode** oldChild)
670 domdoc *This = impl_from_IXMLDOMDocument2( iface );
671 return IXMLDOMNode_removeChild( This->node, childNode, oldChild );
675 static HRESULT WINAPI domdoc_appendChild(
676 IXMLDOMDocument2 *iface,
677 IXMLDOMNode* newChild,
678 IXMLDOMNode** outNewChild)
680 domdoc *This = impl_from_IXMLDOMDocument2( iface );
681 return IXMLDOMNode_appendChild( This->node, newChild, outNewChild );
685 static HRESULT WINAPI domdoc_hasChildNodes(
686 IXMLDOMDocument2 *iface,
687 VARIANT_BOOL* hasChild)
689 domdoc *This = impl_from_IXMLDOMDocument2( iface );
690 return IXMLDOMNode_hasChildNodes( This->node, hasChild );
694 static HRESULT WINAPI domdoc_get_ownerDocument(
695 IXMLDOMDocument2 *iface,
696 IXMLDOMDocument** DOMDocument)
698 domdoc *This = impl_from_IXMLDOMDocument2( iface );
699 return IXMLDOMNode_get_ownerDocument( This->node, DOMDocument );
703 static HRESULT WINAPI domdoc_cloneNode(
704 IXMLDOMDocument2 *iface,
705 VARIANT_BOOL deep,
706 IXMLDOMNode** cloneRoot)
708 domdoc *This = impl_from_IXMLDOMDocument2( iface );
709 return IXMLDOMNode_cloneNode( This->node, deep, cloneRoot );
713 static HRESULT WINAPI domdoc_get_nodeTypeString(
714 IXMLDOMDocument2 *iface,
715 BSTR* nodeType )
717 domdoc *This = impl_from_IXMLDOMDocument2( iface );
718 return IXMLDOMNode_get_nodeTypeString( This->node, nodeType );
722 static HRESULT WINAPI domdoc_get_text(
723 IXMLDOMDocument2 *iface,
724 BSTR* text )
726 domdoc *This = impl_from_IXMLDOMDocument2( iface );
727 return IXMLDOMNode_get_text( This->node, text );
731 static HRESULT WINAPI domdoc_put_text(
732 IXMLDOMDocument2 *iface,
733 BSTR text )
735 domdoc *This = impl_from_IXMLDOMDocument2( iface );
736 return IXMLDOMNode_put_text( This->node, text );
740 static HRESULT WINAPI domdoc_get_specified(
741 IXMLDOMDocument2 *iface,
742 VARIANT_BOOL* isSpecified )
744 domdoc *This = impl_from_IXMLDOMDocument2( iface );
745 return IXMLDOMNode_get_specified( This->node, isSpecified );
749 static HRESULT WINAPI domdoc_get_definition(
750 IXMLDOMDocument2 *iface,
751 IXMLDOMNode** definitionNode )
753 domdoc *This = impl_from_IXMLDOMDocument2( iface );
754 return IXMLDOMNode_get_definition( This->node, definitionNode );
758 static HRESULT WINAPI domdoc_get_nodeTypedValue(
759 IXMLDOMDocument2 *iface,
760 VARIANT* typedValue )
762 domdoc *This = impl_from_IXMLDOMDocument2( iface );
763 return IXMLDOMNode_get_nodeTypedValue( This->node, typedValue );
766 static HRESULT WINAPI domdoc_put_nodeTypedValue(
767 IXMLDOMDocument2 *iface,
768 VARIANT typedValue )
770 domdoc *This = impl_from_IXMLDOMDocument2( iface );
771 return IXMLDOMNode_put_nodeTypedValue( This->node, typedValue );
775 static HRESULT WINAPI domdoc_get_dataType(
776 IXMLDOMDocument2 *iface,
777 VARIANT* dataTypeName )
779 domdoc *This = impl_from_IXMLDOMDocument2( iface );
780 return IXMLDOMNode_get_dataType( This->node, dataTypeName );
784 static HRESULT WINAPI domdoc_put_dataType(
785 IXMLDOMDocument2 *iface,
786 BSTR dataTypeName )
788 domdoc *This = impl_from_IXMLDOMDocument2( iface );
789 return IXMLDOMNode_put_dataType( This->node, dataTypeName );
793 static HRESULT WINAPI domdoc_get_xml(
794 IXMLDOMDocument2 *iface,
795 BSTR* xmlString )
797 domdoc *This = impl_from_IXMLDOMDocument2( iface );
798 return IXMLDOMNode_get_xml( This->node, xmlString );
802 static HRESULT WINAPI domdoc_transformNode(
803 IXMLDOMDocument2 *iface,
804 IXMLDOMNode* styleSheet,
805 BSTR* xmlString )
807 domdoc *This = impl_from_IXMLDOMDocument2( iface );
808 return IXMLDOMNode_transformNode( This->node, styleSheet, xmlString );
812 static HRESULT WINAPI domdoc_selectNodes(
813 IXMLDOMDocument2 *iface,
814 BSTR queryString,
815 IXMLDOMNodeList** resultList )
817 domdoc *This = impl_from_IXMLDOMDocument2( iface );
818 return IXMLDOMNode_selectNodes( This->node, queryString, resultList );
822 static HRESULT WINAPI domdoc_selectSingleNode(
823 IXMLDOMDocument2 *iface,
824 BSTR queryString,
825 IXMLDOMNode** resultNode )
827 domdoc *This = impl_from_IXMLDOMDocument2( iface );
828 return IXMLDOMNode_selectSingleNode( This->node, queryString, resultNode );
832 static HRESULT WINAPI domdoc_get_parsed(
833 IXMLDOMDocument2 *iface,
834 VARIANT_BOOL* isParsed )
836 domdoc *This = impl_from_IXMLDOMDocument2( iface );
837 return IXMLDOMNode_get_parsed( This->node, isParsed );
841 static HRESULT WINAPI domdoc_get_namespaceURI(
842 IXMLDOMDocument2 *iface,
843 BSTR* namespaceURI )
845 domdoc *This = impl_from_IXMLDOMDocument2( iface );
846 return IXMLDOMNode_get_namespaceURI( This->node, namespaceURI );
850 static HRESULT WINAPI domdoc_get_prefix(
851 IXMLDOMDocument2 *iface,
852 BSTR* prefixString )
854 domdoc *This = impl_from_IXMLDOMDocument2( iface );
855 return IXMLDOMNode_get_prefix( This->node, prefixString );
859 static HRESULT WINAPI domdoc_get_baseName(
860 IXMLDOMDocument2 *iface,
861 BSTR* nameString )
863 domdoc *This = impl_from_IXMLDOMDocument2( iface );
864 return IXMLDOMNode_get_baseName( This->node, nameString );
868 static HRESULT WINAPI domdoc_transformNodeToObject(
869 IXMLDOMDocument2 *iface,
870 IXMLDOMNode* stylesheet,
871 VARIANT outputObject)
873 domdoc *This = impl_from_IXMLDOMDocument2( iface );
874 return IXMLDOMNode_transformNodeToObject( This->node, stylesheet, outputObject );
878 static HRESULT WINAPI domdoc_get_doctype(
879 IXMLDOMDocument2 *iface,
880 IXMLDOMDocumentType** documentType )
882 FIXME("\n");
883 return E_NOTIMPL;
887 static HRESULT WINAPI domdoc_get_implementation(
888 IXMLDOMDocument2 *iface,
889 IXMLDOMImplementation** impl )
891 if(!impl)
892 return E_INVALIDARG;
894 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
896 return S_OK;
899 static HRESULT WINAPI domdoc_get_documentElement(
900 IXMLDOMDocument2 *iface,
901 IXMLDOMElement** DOMElement )
903 domdoc *This = impl_from_IXMLDOMDocument2( iface );
904 xmlDocPtr xmldoc = NULL;
905 xmlNodePtr root = NULL;
906 IXMLDOMNode *element_node;
907 HRESULT hr;
909 TRACE("%p %p\n", This, This->node);
911 if(!DOMElement)
912 return E_INVALIDARG;
914 *DOMElement = NULL;
916 xmldoc = get_doc( This );
918 root = xmlDocGetRootElement( xmldoc );
919 if ( !root )
920 return S_FALSE;
922 element_node = create_node( root );
923 if(!element_node) return S_FALSE;
925 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (LPVOID*)DOMElement);
926 IXMLDOMNode_Release(element_node);
928 return hr;
932 static HRESULT WINAPI domdoc_put_documentElement(
933 IXMLDOMDocument2 *iface,
934 IXMLDOMElement* DOMElement )
936 domdoc *This = impl_from_IXMLDOMDocument2( iface );
937 IXMLDOMNode *elementNode;
938 xmlNodePtr oldRoot;
939 xmlnode *xmlNode;
940 HRESULT hr;
942 TRACE("(%p)->(%p)\n", This, DOMElement);
944 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
945 if(FAILED(hr))
946 return hr;
948 xmlNode = impl_from_IXMLDOMNode( elementNode );
950 if(!xmlNode->node->parent)
951 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
952 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
954 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
955 IXMLDOMNode_Release( elementNode );
957 if(oldRoot)
958 xmldoc_add_orphan(oldRoot->doc, oldRoot);
960 return S_OK;
964 static HRESULT WINAPI domdoc_createElement(
965 IXMLDOMDocument2 *iface,
966 BSTR tagname,
967 IXMLDOMElement** element )
969 xmlNodePtr xmlnode;
970 domdoc *This = impl_from_IXMLDOMDocument2( iface );
971 xmlChar *xml_name;
972 IUnknown *elem_unk;
973 HRESULT hr;
975 TRACE("%p->(%s,%p)\n", iface, debugstr_w(tagname), element);
977 xml_name = xmlChar_from_wchar((WCHAR*)tagname);
978 xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
979 xmldoc_add_orphan(xmlnode->doc, xmlnode);
981 TRACE("created xmlptr %p\n", xmlnode);
982 elem_unk = create_element(xmlnode, NULL);
983 HeapFree(GetProcessHeap(), 0, xml_name);
985 hr = IUnknown_QueryInterface(elem_unk, &IID_IXMLDOMElement, (void **)element);
986 IUnknown_Release(elem_unk);
987 TRACE("returning %p\n", *element);
988 return hr;
992 static HRESULT WINAPI domdoc_createDocumentFragment(
993 IXMLDOMDocument2 *iface,
994 IXMLDOMDocumentFragment** docFrag )
996 domdoc *This = impl_from_IXMLDOMDocument2( iface );
997 xmlNodePtr xmlnode;
999 TRACE("%p\n", iface);
1001 if(!docFrag)
1002 return E_INVALIDARG;
1004 *docFrag = NULL;
1006 xmlnode = xmlNewDocFragment(get_doc( This ) );
1008 if(!xmlnode)
1009 return E_FAIL;
1011 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1012 *docFrag = (IXMLDOMDocumentFragment*)create_doc_fragment(xmlnode);
1014 return S_OK;
1018 static HRESULT WINAPI domdoc_createTextNode(
1019 IXMLDOMDocument2 *iface,
1020 BSTR data,
1021 IXMLDOMText** text )
1023 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1024 xmlNodePtr xmlnode;
1025 xmlChar *xml_content;
1027 TRACE("%p->(%s %p)\n", iface, debugstr_w(data), text);
1029 if(!text)
1030 return E_INVALIDARG;
1032 *text = NULL;
1034 xml_content = xmlChar_from_wchar((WCHAR*)data);
1035 xmlnode = xmlNewText(xml_content);
1036 HeapFree(GetProcessHeap(), 0, xml_content);
1038 if(!xmlnode)
1039 return E_FAIL;
1041 xmlnode->doc = get_doc( This );
1042 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1044 *text = (IXMLDOMText*)create_text(xmlnode);
1046 return S_OK;
1050 static HRESULT WINAPI domdoc_createComment(
1051 IXMLDOMDocument2 *iface,
1052 BSTR data,
1053 IXMLDOMComment** comment )
1055 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1056 xmlNodePtr xmlnode;
1057 xmlChar *xml_content;
1059 TRACE("%p->(%s %p)\n", iface, debugstr_w(data), comment);
1061 if(!comment)
1062 return E_INVALIDARG;
1064 *comment = NULL;
1066 xml_content = xmlChar_from_wchar((WCHAR*)data);
1067 xmlnode = xmlNewComment(xml_content);
1068 HeapFree(GetProcessHeap(), 0, xml_content);
1070 if(!xmlnode)
1071 return E_FAIL;
1073 xmlnode->doc = get_doc( This );
1074 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1076 *comment = (IXMLDOMComment*)create_comment(xmlnode);
1078 return S_OK;
1082 static HRESULT WINAPI domdoc_createCDATASection(
1083 IXMLDOMDocument2 *iface,
1084 BSTR data,
1085 IXMLDOMCDATASection** cdata )
1087 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1088 xmlNodePtr xmlnode;
1089 xmlChar *xml_content;
1091 TRACE("%p->(%s %p)\n", iface, debugstr_w(data), cdata);
1093 if(!cdata)
1094 return E_INVALIDARG;
1096 *cdata = NULL;
1098 xml_content = xmlChar_from_wchar((WCHAR*)data);
1099 xmlnode = xmlNewCDataBlock(get_doc( This ), xml_content, strlen( (char*)xml_content) );
1100 HeapFree(GetProcessHeap(), 0, xml_content);
1102 if(!xmlnode)
1103 return E_FAIL;
1105 xmlnode->doc = get_doc( This );
1106 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1108 *cdata = (IXMLDOMCDATASection*)create_cdata(xmlnode);
1110 return S_OK;
1114 static HRESULT WINAPI domdoc_createProcessingInstruction(
1115 IXMLDOMDocument2 *iface,
1116 BSTR target,
1117 BSTR data,
1118 IXMLDOMProcessingInstruction** pi )
1120 #ifdef HAVE_XMLNEWDOCPI
1121 xmlNodePtr xmlnode;
1122 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1123 xmlChar *xml_target, *xml_content;
1125 TRACE("%p->(%s %s %p)\n", iface, debugstr_w(target), debugstr_w(data), pi);
1127 if(!pi)
1128 return E_INVALIDARG;
1130 if(!target || lstrlenW(target) == 0)
1131 return E_FAIL;
1133 xml_target = xmlChar_from_wchar((WCHAR*)target);
1134 xml_content = xmlChar_from_wchar((WCHAR*)data);
1136 xmlnode = xmlNewDocPI(get_doc(This), xml_target, xml_content);
1137 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1138 TRACE("created xmlptr %p\n", xmlnode);
1139 *pi = (IXMLDOMProcessingInstruction*)create_pi(xmlnode);
1141 HeapFree(GetProcessHeap(), 0, xml_content);
1142 HeapFree(GetProcessHeap(), 0, xml_target);
1144 return S_OK;
1145 #else
1146 FIXME("Libxml 2.6.15 or greater required.\n");
1147 return E_NOTIMPL;
1148 #endif
1152 static HRESULT WINAPI domdoc_createAttribute(
1153 IXMLDOMDocument2 *iface,
1154 BSTR name,
1155 IXMLDOMAttribute** attribute )
1157 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1158 xmlNodePtr xmlnode;
1159 xmlChar *xml_name;
1161 TRACE("%p->(%s %p)\n", iface, debugstr_w(name), attribute);
1163 if(!attribute)
1164 return E_INVALIDARG;
1166 *attribute = NULL;
1168 xml_name = xmlChar_from_wchar((WCHAR*)name);
1169 xmlnode = (xmlNode *)xmlNewProp(NULL, xml_name, NULL);
1170 HeapFree(GetProcessHeap(), 0, xml_name);
1172 if(!xmlnode)
1173 return E_FAIL;
1175 xmlnode->doc = get_doc( This );
1176 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1178 *attribute = (IXMLDOMAttribute*)create_attribute(xmlnode);
1180 return S_OK;
1184 static HRESULT WINAPI domdoc_createEntityReference(
1185 IXMLDOMDocument2 *iface,
1186 BSTR name,
1187 IXMLDOMEntityReference** entityRef )
1189 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1190 xmlNodePtr xmlnode;
1191 xmlChar *xml_name;
1193 TRACE("%p\n", iface);
1195 if(!entityRef)
1196 return E_INVALIDARG;
1198 *entityRef = NULL;
1200 xml_name = xmlChar_from_wchar((WCHAR*)name);
1201 xmlnode = xmlNewReference(get_doc( This ), xml_name );
1202 HeapFree(GetProcessHeap(), 0, xml_name);
1204 if(!xmlnode)
1205 return E_FAIL;
1207 xmlnode->doc = get_doc( This );
1208 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1210 *entityRef = (IXMLDOMEntityReference*)create_doc_entity_ref(xmlnode);
1212 return S_OK;
1216 static HRESULT WINAPI domdoc_getElementsByTagName(
1217 IXMLDOMDocument2 *iface,
1218 BSTR tagName,
1219 IXMLDOMNodeList** resultList )
1221 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1222 LPWSTR szPattern;
1223 HRESULT hr;
1224 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
1226 szPattern = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(2+lstrlenW(tagName)+1));
1227 szPattern[0] = szPattern[1] = '/';
1228 lstrcpyW(szPattern + 2, tagName);
1230 hr = queryresult_create((xmlNodePtr)get_doc(This), szPattern, resultList);
1231 HeapFree(GetProcessHeap(), 0, szPattern);
1233 return hr;
1236 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1238 VARIANT tmp;
1239 HRESULT hr;
1241 VariantInit(&tmp);
1242 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1243 if(FAILED(hr))
1244 return E_INVALIDARG;
1246 *type = V_I4(&tmp);
1248 return S_OK;
1251 static HRESULT WINAPI domdoc_createNode(
1252 IXMLDOMDocument2 *iface,
1253 VARIANT Type,
1254 BSTR name,
1255 BSTR namespaceURI,
1256 IXMLDOMNode** node )
1258 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1259 DOMNodeType node_type;
1260 xmlNodePtr xmlnode = NULL;
1261 xmlChar *xml_name;
1262 HRESULT hr;
1264 TRACE("(%p)->(type,%s,%s,%p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1266 hr = get_node_type(Type, &node_type);
1267 if(FAILED(hr))
1268 return hr;
1270 TRACE("node_type %d\n", node_type);
1272 xml_name = xmlChar_from_wchar((WCHAR*)name);
1274 switch(node_type)
1276 case NODE_ELEMENT:
1277 xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
1278 *node = create_node(xmlnode);
1279 TRACE("created %p\n", xmlnode);
1280 break;
1281 case NODE_ATTRIBUTE:
1282 xmlnode = (xmlNode *)xmlNewProp(NULL, xml_name, NULL);
1283 if(xmlnode)
1285 xmlnode->doc = get_doc( This );
1287 *node = (IXMLDOMNode*)create_attribute(xmlnode);
1290 TRACE("created %p\n", xmlnode);
1291 break;
1293 default:
1294 FIXME("unhandled node type %d\n", node_type);
1295 break;
1298 HeapFree(GetProcessHeap(), 0, xml_name);
1300 if(xmlnode && *node)
1302 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1303 return S_OK;
1306 return E_FAIL;
1309 static HRESULT WINAPI domdoc_nodeFromID(
1310 IXMLDOMDocument2 *iface,
1311 BSTR idString,
1312 IXMLDOMNode** node )
1314 FIXME("\n");
1315 return E_NOTIMPL;
1318 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1320 domdoc *This = obj;
1321 xmlDocPtr xmldoc;
1323 xmldoc = doparse( ptr, len );
1324 if(xmldoc) {
1325 xmldoc->_private = create_priv();
1326 return attach_xmldoc(This->node, xmldoc);
1329 return S_OK;
1332 static HRESULT doread( domdoc *This, LPWSTR filename )
1334 bsc_t *bsc;
1335 HRESULT hr;
1337 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1338 if(FAILED(hr))
1339 return hr;
1341 if(This->bsc)
1342 detach_bsc(This->bsc);
1344 This->bsc = bsc;
1345 return S_OK;
1348 static HRESULT WINAPI domdoc_load(
1349 IXMLDOMDocument2 *iface,
1350 VARIANT xmlSource,
1351 VARIANT_BOOL* isSuccessful )
1353 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1354 LPWSTR filename = NULL;
1355 HRESULT hr = S_FALSE;
1356 IXMLDOMDocument2 *pNewDoc = NULL;
1357 IStream *pStream = NULL;
1358 xmlDocPtr xmldoc;
1360 TRACE("type %d\n", V_VT(&xmlSource) );
1362 *isSuccessful = VARIANT_FALSE;
1364 assert( This->node );
1366 switch( V_VT(&xmlSource) )
1368 case VT_BSTR:
1369 filename = V_BSTR(&xmlSource);
1370 break;
1371 case VT_UNKNOWN:
1372 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument2, (void**)&pNewDoc);
1373 if(hr == S_OK)
1375 if(pNewDoc)
1377 domdoc *newDoc = impl_from_IXMLDOMDocument2( pNewDoc );
1378 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1379 hr = attach_xmldoc(This->node, xmldoc);
1381 if(SUCCEEDED(hr))
1382 *isSuccessful = VARIANT_TRUE;
1384 return hr;
1387 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1388 if(hr == S_OK)
1390 IPersistStream *pDocStream;
1391 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1392 if(hr == S_OK)
1394 hr = xmldoc_IPersistStream_Load(pDocStream, pStream);
1395 IStream_Release(pStream);
1396 if(hr == S_OK)
1398 *isSuccessful = VARIANT_TRUE;
1400 TRACE("Using ID_IStream to load Document\n");
1401 return S_OK;
1403 else
1405 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1408 else
1410 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1413 else
1415 /* ISequentialStream */
1416 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1418 break;
1419 default:
1420 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1423 TRACE("filename (%s)\n", debugstr_w(filename));
1425 if ( filename )
1427 hr = doread( This, filename );
1429 if ( FAILED(hr) )
1430 This->error = E_FAIL;
1431 else
1433 hr = This->error = S_OK;
1434 *isSuccessful = VARIANT_TRUE;
1438 if(!filename || FAILED(hr)) {
1439 xmldoc = xmlNewDoc(NULL);
1440 xmldoc->_private = create_priv();
1441 hr = attach_xmldoc(This->node, xmldoc);
1442 if(SUCCEEDED(hr))
1443 hr = S_FALSE;
1446 TRACE("ret (%d)\n", hr);
1448 return hr;
1452 static HRESULT WINAPI domdoc_get_readyState(
1453 IXMLDOMDocument2 *iface,
1454 long* value )
1456 FIXME("\n");
1457 return E_NOTIMPL;
1461 static HRESULT WINAPI domdoc_get_parseError(
1462 IXMLDOMDocument2 *iface,
1463 IXMLDOMParseError** errorObj )
1465 BSTR error_string = NULL;
1466 static const WCHAR err[] = {'e','r','r','o','r',0};
1467 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1469 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
1471 if(This->error)
1472 error_string = SysAllocString(err);
1474 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
1475 if(!*errorObj) return E_OUTOFMEMORY;
1476 return S_OK;
1480 static HRESULT WINAPI domdoc_get_url(
1481 IXMLDOMDocument2 *iface,
1482 BSTR* urlString )
1484 FIXME("\n");
1485 return E_NOTIMPL;
1489 static HRESULT WINAPI domdoc_get_async(
1490 IXMLDOMDocument2 *iface,
1491 VARIANT_BOOL* isAsync )
1493 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1495 TRACE("%p <- %d\n", isAsync, This->async);
1496 *isAsync = This->async;
1497 return S_OK;
1501 static HRESULT WINAPI domdoc_put_async(
1502 IXMLDOMDocument2 *iface,
1503 VARIANT_BOOL isAsync )
1505 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1507 TRACE("%d\n", isAsync);
1508 This->async = isAsync;
1509 return S_OK;
1513 static HRESULT WINAPI domdoc_abort(
1514 IXMLDOMDocument2 *iface )
1516 FIXME("\n");
1517 return E_NOTIMPL;
1521 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
1523 UINT len, blen = SysStringLen( bstr );
1524 LPSTR str;
1526 len = WideCharToMultiByte( CP_UTF8, 0, bstr, blen, NULL, 0, NULL, NULL );
1527 str = HeapAlloc( GetProcessHeap(), 0, len );
1528 if ( !str )
1529 return FALSE;
1530 WideCharToMultiByte( CP_UTF8, 0, bstr, blen, str, len, NULL, NULL );
1531 *plen = len;
1532 *pstr = str;
1533 return TRUE;
1536 static HRESULT WINAPI domdoc_loadXML(
1537 IXMLDOMDocument2 *iface,
1538 BSTR bstrXML,
1539 VARIANT_BOOL* isSuccessful )
1541 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1542 xmlDocPtr xmldoc = NULL;
1543 char *str;
1544 int len;
1545 HRESULT hr = S_FALSE, hr2;
1547 TRACE("%p %s %p\n", This, debugstr_w( bstrXML ), isSuccessful );
1549 assert ( This->node );
1551 if ( isSuccessful )
1553 *isSuccessful = VARIANT_FALSE;
1555 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
1557 xmldoc = doparse( str, len );
1558 HeapFree( GetProcessHeap(), 0, str );
1559 if ( !xmldoc )
1560 This->error = E_FAIL;
1561 else
1563 hr = This->error = S_OK;
1564 *isSuccessful = VARIANT_TRUE;
1568 if(!xmldoc)
1569 xmldoc = xmlNewDoc(NULL);
1571 xmldoc->_private = create_priv();
1572 hr2 = attach_xmldoc( This->node, xmldoc );
1573 if( FAILED(hr2) )
1574 hr = hr2;
1576 return hr;
1580 static HRESULT WINAPI domdoc_save(
1581 IXMLDOMDocument2 *iface,
1582 VARIANT destination )
1584 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1585 HANDLE handle;
1586 xmlChar *mem, *p;
1587 int size;
1588 HRESULT ret = S_OK;
1589 DWORD written;
1591 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
1592 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
1594 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
1596 FIXME("Unhandled vt %d\n", V_VT(&destination));
1597 return S_FALSE;
1600 if(V_VT(&destination) == VT_UNKNOWN)
1602 IUnknown *pUnk = V_UNKNOWN(&destination);
1603 IXMLDOMDocument *pDocument;
1605 ret = IXMLDOMDocument_QueryInterface(pUnk, &IID_IXMLDOMDocument2, (void**)&pDocument);
1606 if(ret == S_OK)
1608 BSTR bXML;
1609 VARIANT_BOOL bSuccessful;
1611 ret = IXMLDOMDocument_get_xml(iface, &bXML);
1612 if(ret == S_OK)
1614 ret = IXMLDOMDocument_loadXML(pDocument, bXML, &bSuccessful);
1616 SysFreeString(bXML);
1619 IXMLDOMDocument_Release(pDocument);
1622 TRACE("ret %d\n", ret);
1624 return ret;
1627 handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
1628 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1629 if( handle == INVALID_HANDLE_VALUE )
1631 WARN("failed to create file\n");
1632 return S_FALSE;
1635 xmlDocDumpMemory(get_doc(This), &mem, &size);
1638 * libxml2 always adds XML declaration on top of the file and one for each processing instruction node in DOM tree.
1639 * MSXML adds XML declaration only for processing instruction nodes.
1640 * We skip the first XML declaration generated by libxml2 to get exactly what we need.
1642 p = mem;
1643 if(size > 2 && p[0] == '<' && p[1] == '?') {
1644 while(p < mem+size && (p[0] != '?' || p[1] != '>'))
1645 p++;
1646 p += 2;
1647 while(p < mem+size && isspace(*p))
1648 p++;
1649 size -= p-mem;
1652 if(!WriteFile(handle, p, (DWORD)size, &written, NULL) || written != (DWORD)size)
1654 WARN("write error\n");
1655 ret = S_FALSE;
1658 xmlFree(mem);
1659 CloseHandle(handle);
1660 return ret;
1663 static HRESULT WINAPI domdoc_get_validateOnParse(
1664 IXMLDOMDocument2 *iface,
1665 VARIANT_BOOL* isValidating )
1667 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1669 TRACE("%p <- %d\n", isValidating, This->validating);
1670 *isValidating = This->validating;
1671 return S_OK;
1675 static HRESULT WINAPI domdoc_put_validateOnParse(
1676 IXMLDOMDocument2 *iface,
1677 VARIANT_BOOL isValidating )
1679 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1681 TRACE("%d\n", isValidating);
1682 This->validating = isValidating;
1683 return S_OK;
1687 static HRESULT WINAPI domdoc_get_resolveExternals(
1688 IXMLDOMDocument2 *iface,
1689 VARIANT_BOOL* isResolving )
1691 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1693 TRACE("%p <- %d\n", isResolving, This->resolving);
1694 *isResolving = This->resolving;
1695 return S_OK;
1699 static HRESULT WINAPI domdoc_put_resolveExternals(
1700 IXMLDOMDocument2 *iface,
1701 VARIANT_BOOL isResolving )
1703 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1705 TRACE("%d\n", isResolving);
1706 This->resolving = isResolving;
1707 return S_OK;
1711 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
1712 IXMLDOMDocument2 *iface,
1713 VARIANT_BOOL* isPreserving )
1715 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1717 TRACE("%p <- %d\n", isPreserving, This->preserving);
1718 *isPreserving = This->preserving;
1719 return S_OK;
1723 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
1724 IXMLDOMDocument2 *iface,
1725 VARIANT_BOOL isPreserving )
1727 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1729 TRACE("%d\n", isPreserving);
1730 This->preserving = isPreserving;
1731 return S_OK;
1735 static HRESULT WINAPI domdoc_put_onReadyStateChange(
1736 IXMLDOMDocument2 *iface,
1737 VARIANT readyStateChangeSink )
1739 FIXME("\n");
1740 return E_NOTIMPL;
1744 static HRESULT WINAPI domdoc_put_onDataAvailable(
1745 IXMLDOMDocument2 *iface,
1746 VARIANT onDataAvailableSink )
1748 FIXME("\n");
1749 return E_NOTIMPL;
1752 static HRESULT WINAPI domdoc_put_onTransformNode(
1753 IXMLDOMDocument2 *iface,
1754 VARIANT onTransformNodeSink )
1756 FIXME("\n");
1757 return E_NOTIMPL;
1760 static HRESULT WINAPI domdoc_get_namespaces(
1761 IXMLDOMDocument2* iface,
1762 IXMLDOMSchemaCollection** schemaCollection )
1764 FIXME("\n");
1765 return E_NOTIMPL;
1768 static HRESULT WINAPI domdoc_get_schemas(
1769 IXMLDOMDocument2* iface,
1770 VARIANT* var1 )
1772 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1773 HRESULT hr = S_FALSE;
1774 IXMLDOMSchemaCollection *cur_schema = This->schema;
1776 TRACE("(%p)->(%p)\n", This, var1);
1778 VariantInit(var1); /* Test shows we don't call VariantClear here */
1779 V_VT(var1) = VT_NULL;
1781 if(cur_schema)
1783 hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
1784 if(SUCCEEDED(hr))
1785 V_VT(var1) = VT_DISPATCH;
1787 return hr;
1790 static HRESULT WINAPI domdoc_putref_schemas(
1791 IXMLDOMDocument2* iface,
1792 VARIANT var1)
1794 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1795 HRESULT hr = E_FAIL;
1796 IXMLDOMSchemaCollection *new_schema = NULL;
1798 FIXME("(%p): semi-stub\n", This);
1799 switch(V_VT(&var1))
1801 case VT_UNKNOWN:
1802 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1803 break;
1805 case VT_DISPATCH:
1806 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
1807 break;
1809 case VT_NULL:
1810 case VT_EMPTY:
1811 hr = S_OK;
1812 break;
1814 default:
1815 WARN("Can't get schema from vt %x\n", V_VT(&var1));
1818 if(SUCCEEDED(hr))
1820 IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
1821 if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
1824 return hr;
1827 static HRESULT WINAPI domdoc_validate(
1828 IXMLDOMDocument2* iface,
1829 IXMLDOMParseError** err)
1831 FIXME("\n");
1832 return E_NOTIMPL;
1835 static HRESULT WINAPI domdoc_setProperty(
1836 IXMLDOMDocument2* iface,
1837 BSTR p,
1838 VARIANT var)
1840 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1842 if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
1844 VARIANT varStr;
1845 HRESULT hr;
1846 BSTR bstr;
1848 V_VT(&varStr) = VT_EMPTY;
1849 if (V_VT(&var) != VT_BSTR)
1851 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
1852 return hr;
1853 bstr = V_BSTR(&varStr);
1855 else
1856 bstr = V_BSTR(&var);
1858 hr = S_OK;
1859 if (lstrcmpiW(bstr, SZ_VALUE_XPATH) == 0)
1860 This->bUseXPath = TRUE;
1861 else if (lstrcmpiW(bstr, SZ_VALUE_XSLPATTERN) == 0)
1862 This->bUseXPath = FALSE;
1863 else
1864 hr = E_FAIL;
1866 VariantClear(&varStr);
1867 return hr;
1870 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
1871 return E_FAIL;
1874 static HRESULT WINAPI domdoc_getProperty(
1875 IXMLDOMDocument2* iface,
1876 BSTR p,
1877 VARIANT* var)
1879 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1881 if (var == NULL)
1882 return E_INVALIDARG;
1883 if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
1885 V_VT(var) = VT_BSTR;
1886 if (This->bUseXPath)
1887 V_BSTR(var) = SysAllocString(SZ_VALUE_XPATH);
1888 else
1889 V_BSTR(var) = SysAllocString(SZ_VALUE_XSLPATTERN);
1890 return S_OK;
1893 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
1894 return E_FAIL;
1897 static const struct IXMLDOMDocument2Vtbl domdoc_vtbl =
1899 domdoc_QueryInterface,
1900 domdoc_AddRef,
1901 domdoc_Release,
1902 domdoc_GetTypeInfoCount,
1903 domdoc_GetTypeInfo,
1904 domdoc_GetIDsOfNames,
1905 domdoc_Invoke,
1906 domdoc_get_nodeName,
1907 domdoc_get_nodeValue,
1908 domdoc_put_nodeValue,
1909 domdoc_get_nodeType,
1910 domdoc_get_parentNode,
1911 domdoc_get_childNodes,
1912 domdoc_get_firstChild,
1913 domdoc_get_lastChild,
1914 domdoc_get_previousSibling,
1915 domdoc_get_nextSibling,
1916 domdoc_get_attributes,
1917 domdoc_insertBefore,
1918 domdoc_replaceChild,
1919 domdoc_removeChild,
1920 domdoc_appendChild,
1921 domdoc_hasChildNodes,
1922 domdoc_get_ownerDocument,
1923 domdoc_cloneNode,
1924 domdoc_get_nodeTypeString,
1925 domdoc_get_text,
1926 domdoc_put_text,
1927 domdoc_get_specified,
1928 domdoc_get_definition,
1929 domdoc_get_nodeTypedValue,
1930 domdoc_put_nodeTypedValue,
1931 domdoc_get_dataType,
1932 domdoc_put_dataType,
1933 domdoc_get_xml,
1934 domdoc_transformNode,
1935 domdoc_selectNodes,
1936 domdoc_selectSingleNode,
1937 domdoc_get_parsed,
1938 domdoc_get_namespaceURI,
1939 domdoc_get_prefix,
1940 domdoc_get_baseName,
1941 domdoc_transformNodeToObject,
1942 domdoc_get_doctype,
1943 domdoc_get_implementation,
1944 domdoc_get_documentElement,
1945 domdoc_put_documentElement,
1946 domdoc_createElement,
1947 domdoc_createDocumentFragment,
1948 domdoc_createTextNode,
1949 domdoc_createComment,
1950 domdoc_createCDATASection,
1951 domdoc_createProcessingInstruction,
1952 domdoc_createAttribute,
1953 domdoc_createEntityReference,
1954 domdoc_getElementsByTagName,
1955 domdoc_createNode,
1956 domdoc_nodeFromID,
1957 domdoc_load,
1958 domdoc_get_readyState,
1959 domdoc_get_parseError,
1960 domdoc_get_url,
1961 domdoc_get_async,
1962 domdoc_put_async,
1963 domdoc_abort,
1964 domdoc_loadXML,
1965 domdoc_save,
1966 domdoc_get_validateOnParse,
1967 domdoc_put_validateOnParse,
1968 domdoc_get_resolveExternals,
1969 domdoc_put_resolveExternals,
1970 domdoc_get_preserveWhiteSpace,
1971 domdoc_put_preserveWhiteSpace,
1972 domdoc_put_onReadyStateChange,
1973 domdoc_put_onDataAvailable,
1974 domdoc_put_onTransformNode,
1975 domdoc_get_namespaces,
1976 domdoc_get_schemas,
1977 domdoc_putref_schemas,
1978 domdoc_validate,
1979 domdoc_setProperty,
1980 domdoc_getProperty
1983 /* xmldoc implementation of IObjectWithSite */
1984 static HRESULT WINAPI
1985 xmldoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
1987 domdoc *This = impl_from_IObjectWithSite(iface);
1988 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppvObject );
1991 static ULONG WINAPI
1992 xmldoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
1994 domdoc *This = impl_from_IObjectWithSite(iface);
1995 return IXMLDocument_AddRef((IXMLDocument *)This);
1998 static ULONG WINAPI
1999 xmldoc_ObjectWithSite_Release( IObjectWithSite* iface )
2001 domdoc *This = impl_from_IObjectWithSite(iface);
2002 return IXMLDocument_Release((IXMLDocument *)This);
2005 static HRESULT WINAPI
2006 xmldoc_GetSite( IObjectWithSite *iface, REFIID iid, void ** ppvSite )
2008 domdoc *This = impl_from_IObjectWithSite(iface);
2010 TRACE("%p %s %p\n", This, debugstr_guid( iid ), ppvSite );
2012 if ( !This->site )
2013 return E_FAIL;
2015 return IUnknown_QueryInterface( This->site, iid, ppvSite );
2018 static HRESULT WINAPI
2019 xmldoc_SetSite( IObjectWithSite *iface, IUnknown *punk )
2021 domdoc *This = impl_from_IObjectWithSite(iface);
2023 TRACE("%p %p\n", iface, punk);
2025 if(!punk)
2027 if(This->site)
2029 IUnknown_Release( This->site );
2030 This->site = NULL;
2033 return S_OK;
2036 if ( punk )
2037 IUnknown_AddRef( punk );
2039 if(This->site)
2040 IUnknown_Release( This->site );
2042 This->site = punk;
2044 return S_OK;
2047 static const IObjectWithSiteVtbl domdocObjectSite =
2049 xmldoc_ObjectWithSite_QueryInterface,
2050 xmldoc_ObjectWithSite_AddRef,
2051 xmldoc_ObjectWithSite_Release,
2052 xmldoc_SetSite,
2053 xmldoc_GetSite,
2056 static HRESULT WINAPI xmldoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
2058 domdoc *This = impl_from_IObjectSafety(iface);
2059 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppv );
2062 static ULONG WINAPI xmldoc_Safety_AddRef(IObjectSafety *iface)
2064 domdoc *This = impl_from_IObjectSafety(iface);
2065 return IXMLDocument_AddRef((IXMLDocument *)This);
2068 static ULONG WINAPI xmldoc_Safety_Release(IObjectSafety *iface)
2070 domdoc *This = impl_from_IObjectSafety(iface);
2071 return IXMLDocument_Release((IXMLDocument *)This);
2074 #define SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
2076 static HRESULT WINAPI xmldoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2077 DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
2079 domdoc *This = impl_from_IObjectSafety(iface);
2081 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
2083 if(!pdwSupportedOptions || !pdwEnabledOptions)
2084 return E_POINTER;
2086 *pdwSupportedOptions = SUPPORTED_OPTIONS;
2087 *pdwEnabledOptions = This->safeopt;
2089 return S_OK;
2092 static HRESULT WINAPI xmldoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2093 DWORD dwOptionSetMask, DWORD dwEnabledOptions)
2095 domdoc *This = impl_from_IObjectSafety(iface);
2097 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
2099 if(dwOptionSetMask & ~SUPPORTED_OPTIONS)
2100 return E_FAIL;
2102 This->safeopt = dwEnabledOptions & dwEnabledOptions;
2103 return S_OK;
2106 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
2107 xmldoc_Safety_QueryInterface,
2108 xmldoc_Safety_AddRef,
2109 xmldoc_Safety_Release,
2110 xmldoc_Safety_GetInterfaceSafetyOptions,
2111 xmldoc_Safety_SetInterfaceSafetyOptions
2115 static const tid_t domdoc_iface_tids[] = {
2116 IXMLDOMNode_tid,
2117 IXMLDOMDocument_tid,
2118 IXMLDOMDocument2_tid,
2121 static dispex_static_data_t domdoc_dispex = {
2122 NULL,
2123 IXMLDOMDocument2_tid,
2124 NULL,
2125 domdoc_iface_tids
2128 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument2 **document)
2130 domdoc *doc;
2131 HRESULT hr;
2133 doc = HeapAlloc( GetProcessHeap(), 0, sizeof (*doc) );
2134 if( !doc )
2135 return E_OUTOFMEMORY;
2137 doc->lpVtbl = &domdoc_vtbl;
2138 doc->lpvtblIPersistStream = &xmldoc_IPersistStream_VTable;
2139 doc->lpvtblIObjectWithSite = &domdocObjectSite;
2140 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
2141 doc->ref = 1;
2142 doc->async = 0;
2143 doc->validating = 0;
2144 doc->resolving = 0;
2145 doc->preserving = 0;
2146 doc->bUseXPath = FALSE;
2147 doc->error = S_OK;
2148 doc->schema = NULL;
2149 doc->stream = NULL;
2150 doc->site = NULL;
2151 doc->safeopt = 0;
2152 doc->bsc = NULL;
2154 doc->node_unk = create_basic_node( (xmlNodePtr)xmldoc, (IUnknown*)&doc->lpVtbl );
2155 if(!doc->node_unk)
2157 HeapFree(GetProcessHeap(), 0, doc);
2158 return E_FAIL;
2161 hr = IUnknown_QueryInterface(doc->node_unk, &IID_IXMLDOMNode, (LPVOID*)&doc->node);
2162 if(FAILED(hr))
2164 IUnknown_Release(doc->node_unk);
2165 HeapFree( GetProcessHeap(), 0, doc );
2166 return E_FAIL;
2169 init_dispex(&doc->dispex, (IUnknown*)&doc->lpVtbl, &domdoc_dispex);
2171 /* The ref on doc->node is actually looped back into this object, so release it */
2172 IXMLDOMNode_Release(doc->node);
2174 *document = (IXMLDOMDocument2*)&doc->lpVtbl;
2176 TRACE("returning iface %p\n", *document);
2177 return S_OK;
2180 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2182 xmlDocPtr xmldoc;
2183 HRESULT hr;
2185 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
2187 xmldoc = xmlNewDoc(NULL);
2188 if(!xmldoc)
2189 return E_OUTOFMEMORY;
2191 xmldoc->_private = create_priv();
2193 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument2**)ppObj);
2194 if(FAILED(hr))
2195 xmlFreeDoc(xmldoc);
2197 return hr;
2200 IUnknown* create_domdoc( xmlNodePtr document )
2202 HRESULT hr;
2203 LPVOID pObj = NULL;
2205 TRACE("(%p)\n", document);
2207 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument2**)&pObj);
2208 if (FAILED(hr))
2209 return NULL;
2211 return (IUnknown*)pObj;
2214 #else
2216 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2218 MESSAGE("This program tried to use a DOMDocument object, but\n"
2219 "libxml2 support was not present at compile time.\n");
2220 return E_NOTIMPL;
2223 #endif