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
22 #define NONAMELESSUNION
41 #include "wine/debug.h"
42 #include "wine/list.h"
44 #include "msxml_private.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
50 #include <libxml/xmlsave.h>
52 /* not defined in older versions */
53 #define XML_SAVE_FORMAT 1
54 #define XML_SAVE_NO_DECL 2
55 #define XML_SAVE_NO_EMPTY 4
56 #define XML_SAVE_NO_XHTML 8
57 #define XML_SAVE_XHTML 16
58 #define XML_SAVE_AS_XML 32
59 #define XML_SAVE_AS_HTML 64
61 static const WCHAR SZ_PROPERTY_SELECTION_LANGUAGE[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
62 static const WCHAR SZ_VALUE_XPATH[] = {'X','P','a','t','h',0};
63 static const WCHAR SZ_VALUE_XSLPATTERN[] = {'X','S','L','P','a','t','t','e','r','n',0};
65 typedef struct _domdoc
68 const struct IXMLDOMDocument2Vtbl *lpVtbl;
69 const struct IPersistStreamInitVtbl *lpvtblIPersistStreamInit;
70 const struct IObjectWithSiteVtbl *lpvtblIObjectWithSite;
71 const struct IObjectSafetyVtbl *lpvtblIObjectSafety;
72 const struct ISupportErrorInfoVtbl *lpvtblISupportErrorInfo;
75 VARIANT_BOOL validating;
76 VARIANT_BOOL resolving;
77 VARIANT_BOOL preserving;
79 IXMLDOMSchemaCollection *schema;
94 In native windows, the whole lifetime management of XMLDOMNodes is
95 managed automatically using reference counts. Wine emulates that by
96 maintaining a reference count to the document that is increased for
97 each IXMLDOMNode pointer passed out for this document. If all these
98 pointers are gone, the document is unreachable and gets freed, that
99 is, all nodes in the tree of the document get freed.
101 You are able to create nodes that are associated to a document (in
102 fact, in msxml's XMLDOM model, all nodes are associated to a document),
103 but not in the tree of that document, for example using the createFoo
104 functions from IXMLDOMDocument. These nodes do not get cleaned up
105 by libxml, so we have to do it ourselves.
107 To catch these nodes, a list of "orphan nodes" is introduced.
108 It contains pointers to all roots of node trees that are
109 associated with the document without being part of the document
110 tree. All nodes with parent==NULL (except for the document root nodes)
111 should be in the orphan node list of their document. All orphan nodes
112 get freed together with the document itself.
115 typedef struct _xmldoc_priv {
120 typedef struct _orphan_entry {
125 static inline xmldoc_priv * priv_from_xmlDocPtr(xmlDocPtr doc)
127 return doc->_private;
130 static xmldoc_priv * create_priv(void)
133 priv = heap_alloc( sizeof (*priv) );
138 list_init( &priv->orphans );
144 /* links a "<?xml" node as a first child */
145 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
148 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
151 /* unlinks a first "<?xml" child if it was created */
152 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
158 if (doc->standalone != -1)
160 node = doc->children;
161 xmlUnlinkNode( node );
169 static xmlDocPtr doparse( char *ptr, int len, const char *encoding )
173 #ifdef HAVE_XMLREADMEMORY
175 * use xmlReadMemory if possible so we can suppress
176 * writing errors to stderr
178 doc = xmlReadMemory( ptr, len, NULL, encoding,
179 XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS );
181 doc = xmlParseMemory( ptr, len );
184 /* create first child as a <?xml...?> */
185 if (doc && doc->standalone != -1)
189 xmlChar *xmlbuff = (xmlChar*)buff;
191 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
193 /* version attribute can't be omitted */
194 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
195 xmlNodeAddContent( node, xmlbuff );
199 sprintf(buff, " encoding=\"%s\"", doc->encoding);
200 xmlNodeAddContent( node, xmlbuff );
203 if (doc->standalone != -2)
205 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
206 xmlNodeAddContent( node, xmlbuff );
209 xmldoc_link_xmldecl( doc, node );
215 LONG xmldoc_add_ref(xmlDocPtr doc)
217 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
218 TRACE("(%p)->(%d)\n", doc, ref);
222 LONG xmldoc_release(xmlDocPtr doc)
224 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
225 LONG ref = InterlockedDecrement(&priv->refs);
226 TRACE("(%p)->(%d)\n", doc, ref);
229 orphan_entry *orphan, *orphan2;
230 TRACE("freeing docptr %p\n", doc);
232 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
234 xmlFreeNode( orphan->node );
237 heap_free(doc->_private);
245 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
247 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
250 entry = heap_alloc( sizeof (*entry) );
252 return E_OUTOFMEMORY;
255 list_add_head( &priv->orphans, &entry->entry );
259 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
261 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
262 orphan_entry *entry, *entry2;
264 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
266 if( entry->node == node )
268 list_remove( &entry->entry );
277 static HRESULT attach_xmldoc( xmlnode *node, xmlDocPtr xml )
280 xmldoc_release(node->node->doc);
282 node->node = (xmlNodePtr) xml;
284 xmldoc_add_ref(node->node->doc);
289 static inline domdoc *impl_from_IXMLDOMDocument2( IXMLDOMDocument2 *iface )
291 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
294 static inline xmlDocPtr get_doc( domdoc *This )
296 return (xmlDocPtr)This->node.node;
299 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
301 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStreamInit));
304 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
306 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
309 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
311 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
314 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
316 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblISupportErrorInfo));
319 /************************************************************************
320 * domdoc implementation of IPersistStream.
322 static HRESULT WINAPI domdoc_IPersistStreamInit_QueryInterface(
323 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
325 domdoc *this = impl_from_IPersistStreamInit(iface);
326 return IXMLDOMDocument2_QueryInterface((IXMLDOMDocument2 *)this, riid, ppvObj);
329 static ULONG WINAPI domdoc_IPersistStreamInit_AddRef(
330 IPersistStreamInit *iface)
332 domdoc *this = impl_from_IPersistStreamInit(iface);
333 return IXMLDOMDocument2_AddRef((IXMLDOMDocument2 *)this);
336 static ULONG WINAPI domdoc_IPersistStreamInit_Release(
337 IPersistStreamInit *iface)
339 domdoc *this = impl_from_IPersistStreamInit(iface);
340 return IXMLDOMDocument2_Release((IXMLDOMDocument2 *)this);
343 static HRESULT WINAPI domdoc_IPersistStreamInit_GetClassID(
344 IPersistStreamInit *iface, CLSID *classid)
346 TRACE("(%p,%p): stub!\n", iface, classid);
351 *classid = CLSID_DOMDocument2;
356 static HRESULT WINAPI domdoc_IPersistStreamInit_IsDirty(
357 IPersistStreamInit *iface)
359 domdoc *This = impl_from_IPersistStreamInit(iface);
360 FIXME("(%p): stub!\n", This);
364 static HRESULT WINAPI domdoc_IPersistStreamInit_Load(
365 IPersistStreamInit *iface, LPSTREAM pStm)
367 domdoc *This = impl_from_IPersistStreamInit(iface);
370 DWORD read, written, len;
373 xmlDocPtr xmldoc = NULL;
375 TRACE("(%p)->(%p)\n", This, pStm);
380 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
386 IStream_Read(pStm, buf, sizeof(buf), &read);
387 hr = IStream_Write(This->stream, buf, read, &written);
388 } while(SUCCEEDED(hr) && written != 0 && read != 0);
392 ERR("Failed to copy stream\n");
396 hr = GetHGlobalFromStream(This->stream, &hglobal);
400 len = GlobalSize(hglobal);
401 ptr = GlobalLock(hglobal);
403 xmldoc = doparse(ptr, len, NULL);
404 GlobalUnlock(hglobal);
408 ERR("Failed to parse xml\n");
412 xmldoc->_private = create_priv();
414 return attach_xmldoc( &This->node, xmldoc );
417 static HRESULT WINAPI domdoc_IPersistStreamInit_Save(
418 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
420 domdoc *This = impl_from_IPersistStreamInit(iface);
424 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
426 hr = IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), &xmlString );
429 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
431 hr = IStream_Write( stream, xmlString, len, NULL );
432 SysFreeString(xmlString);
435 TRACE("ret 0x%08x\n", hr);
440 static HRESULT WINAPI domdoc_IPersistStreamInit_GetSizeMax(
441 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
443 domdoc *This = impl_from_IPersistStreamInit(iface);
444 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
448 static HRESULT WINAPI domdoc_IPersistStreamInit_InitNew(
449 IPersistStreamInit *iface)
451 domdoc *This = impl_from_IPersistStreamInit(iface);
452 TRACE("(%p)\n", This);
456 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
458 domdoc_IPersistStreamInit_QueryInterface,
459 domdoc_IPersistStreamInit_AddRef,
460 domdoc_IPersistStreamInit_Release,
461 domdoc_IPersistStreamInit_GetClassID,
462 domdoc_IPersistStreamInit_IsDirty,
463 domdoc_IPersistStreamInit_Load,
464 domdoc_IPersistStreamInit_Save,
465 domdoc_IPersistStreamInit_GetSizeMax,
466 domdoc_IPersistStreamInit_InitNew
469 /* ISupportErrorInfo interface */
470 static HRESULT WINAPI support_error_QueryInterface(
471 ISupportErrorInfo *iface,
472 REFIID riid, void** ppvObj )
474 domdoc *This = impl_from_ISupportErrorInfo(iface);
475 return IXMLDOMDocument2_QueryInterface((IXMLDOMDocument2 *)This, riid, ppvObj);
478 static ULONG WINAPI support_error_AddRef(
479 ISupportErrorInfo *iface )
481 domdoc *This = impl_from_ISupportErrorInfo(iface);
482 return IXMLDOMDocument2_AddRef((IXMLDOMDocument2 *)This);
485 static ULONG WINAPI support_error_Release(
486 ISupportErrorInfo *iface )
488 domdoc *This = impl_from_ISupportErrorInfo(iface);
489 return IXMLDOMDocument2_Release((IXMLDOMDocument2 *)This);
492 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
493 ISupportErrorInfo *iface,
496 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
500 static const struct ISupportErrorInfoVtbl support_error_vtbl =
502 support_error_QueryInterface,
503 support_error_AddRef,
504 support_error_Release,
505 support_error_InterfaceSupportsErrorInfo
508 /* IXMLDOMDocument2 interface */
509 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument2 *iface, REFIID riid, void** ppvObject )
511 domdoc *This = impl_from_IXMLDOMDocument2( iface );
513 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
517 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
518 IsEqualGUID( riid, &IID_IDispatch ) ||
519 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
520 IsEqualGUID( riid, &IID_IXMLDOMDocument2 ) )
524 else if ( IsEqualGUID( riid, &IID_IXMLDOMNode ) )
526 *ppvObject = IXMLDOMNode_from_impl(&This->node);
528 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
529 IsEqualGUID(&IID_IPersistStreamInit, riid))
531 *ppvObject = &(This->lpvtblIPersistStreamInit);
533 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
535 *ppvObject = &(This->lpvtblIObjectWithSite);
537 else if (IsEqualGUID(&IID_IObjectSafety, riid))
539 *ppvObject = &(This->lpvtblIObjectSafety);
541 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
543 *ppvObject = &This->lpvtblISupportErrorInfo;
545 else if(dispex_query_interface(&This->node.dispex, riid, ppvObject))
547 return *ppvObject ? S_OK : E_NOINTERFACE;
549 else if(IsEqualGUID(&IID_IRunnableObject, riid))
551 TRACE("IID_IRunnableObject not supported returning NULL\n");
552 return E_NOINTERFACE;
556 FIXME("interface %s not implemented\n", debugstr_guid(riid));
557 return E_NOINTERFACE;
560 IUnknown_AddRef((IUnknown*)*ppvObject);
566 static ULONG WINAPI domdoc_AddRef(
567 IXMLDOMDocument2 *iface )
569 domdoc *This = impl_from_IXMLDOMDocument2( iface );
570 TRACE("%p\n", This );
571 return InterlockedIncrement( &This->ref );
575 static ULONG WINAPI domdoc_Release(
576 IXMLDOMDocument2 *iface )
578 domdoc *This = impl_from_IXMLDOMDocument2( iface );
581 TRACE("%p\n", This );
583 ref = InterlockedDecrement( &This->ref );
587 detach_bsc(This->bsc);
590 IUnknown_Release( This->site );
591 destroy_xmlnode(&This->node);
592 if(This->schema) IXMLDOMSchemaCollection_Release( This->schema );
593 if (This->stream) IStream_Release(This->stream);
594 HeapFree( GetProcessHeap(), 0, This );
600 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument2 *iface, UINT* pctinfo )
602 domdoc *This = impl_from_IXMLDOMDocument2( iface );
604 TRACE("(%p)->(%p)\n", This, pctinfo);
611 static HRESULT WINAPI domdoc_GetTypeInfo(
612 IXMLDOMDocument2 *iface,
613 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
615 domdoc *This = impl_from_IXMLDOMDocument2( iface );
618 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
620 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
625 static HRESULT WINAPI domdoc_GetIDsOfNames(
626 IXMLDOMDocument2 *iface,
633 domdoc *This = impl_from_IXMLDOMDocument2( iface );
637 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
640 if(!rgszNames || cNames == 0 || !rgDispId)
643 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
646 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
647 ITypeInfo_Release(typeinfo);
654 static HRESULT WINAPI domdoc_Invoke(
655 IXMLDOMDocument2 *iface,
660 DISPPARAMS* pDispParams,
662 EXCEPINFO* pExcepInfo,
665 domdoc *This = impl_from_IXMLDOMDocument2( iface );
669 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
670 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
672 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
675 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
676 pVarResult, pExcepInfo, puArgErr);
677 ITypeInfo_Release(typeinfo);
684 static HRESULT WINAPI domdoc_get_nodeName(
685 IXMLDOMDocument2 *iface,
688 domdoc *This = impl_from_IXMLDOMDocument2( iface );
689 return IXMLDOMNode_get_nodeName( IXMLDOMNode_from_impl(&This->node), name );
693 static HRESULT WINAPI domdoc_get_nodeValue(
694 IXMLDOMDocument2 *iface,
697 domdoc *This = impl_from_IXMLDOMDocument2( iface );
698 return IXMLDOMNode_get_nodeValue( IXMLDOMNode_from_impl(&This->node), value );
702 static HRESULT WINAPI domdoc_put_nodeValue(
703 IXMLDOMDocument2 *iface,
706 domdoc *This = impl_from_IXMLDOMDocument2( iface );
707 return IXMLDOMNode_put_nodeValue( IXMLDOMNode_from_impl(&This->node), value );
711 static HRESULT WINAPI domdoc_get_nodeType(
712 IXMLDOMDocument2 *iface,
715 domdoc *This = impl_from_IXMLDOMDocument2( iface );
716 return IXMLDOMNode_get_nodeType( IXMLDOMNode_from_impl(&This->node), type );
720 static HRESULT WINAPI domdoc_get_parentNode(
721 IXMLDOMDocument2 *iface,
722 IXMLDOMNode** parent )
724 domdoc *This = impl_from_IXMLDOMDocument2( iface );
725 return IXMLDOMNode_get_parentNode( IXMLDOMNode_from_impl(&This->node), parent );
729 static HRESULT WINAPI domdoc_get_childNodes(
730 IXMLDOMDocument2 *iface,
731 IXMLDOMNodeList** childList )
733 domdoc *This = impl_from_IXMLDOMDocument2( iface );
734 return IXMLDOMNode_get_childNodes( IXMLDOMNode_from_impl(&This->node), childList );
738 static HRESULT WINAPI domdoc_get_firstChild(
739 IXMLDOMDocument2 *iface,
740 IXMLDOMNode** firstChild )
742 domdoc *This = impl_from_IXMLDOMDocument2( iface );
743 return IXMLDOMNode_get_firstChild( IXMLDOMNode_from_impl(&This->node), firstChild );
747 static HRESULT WINAPI domdoc_get_lastChild(
748 IXMLDOMDocument2 *iface,
749 IXMLDOMNode** lastChild )
751 domdoc *This = impl_from_IXMLDOMDocument2( iface );
752 return IXMLDOMNode_get_lastChild( IXMLDOMNode_from_impl(&This->node), lastChild );
756 static HRESULT WINAPI domdoc_get_previousSibling(
757 IXMLDOMDocument2 *iface,
758 IXMLDOMNode** previousSibling )
760 domdoc *This = impl_from_IXMLDOMDocument2( iface );
761 return IXMLDOMNode_get_previousSibling( IXMLDOMNode_from_impl(&This->node), previousSibling );
765 static HRESULT WINAPI domdoc_get_nextSibling(
766 IXMLDOMDocument2 *iface,
767 IXMLDOMNode** nextSibling )
769 domdoc *This = impl_from_IXMLDOMDocument2( iface );
770 return IXMLDOMNode_get_nextSibling( IXMLDOMNode_from_impl(&This->node), nextSibling );
774 static HRESULT WINAPI domdoc_get_attributes(
775 IXMLDOMDocument2 *iface,
776 IXMLDOMNamedNodeMap** attributeMap )
778 domdoc *This = impl_from_IXMLDOMDocument2( iface );
779 return IXMLDOMNode_get_attributes( IXMLDOMNode_from_impl(&This->node), attributeMap );
783 static HRESULT WINAPI domdoc_insertBefore(
784 IXMLDOMDocument2 *iface,
785 IXMLDOMNode* newChild,
787 IXMLDOMNode** outNewChild )
789 domdoc *This = impl_from_IXMLDOMDocument2( iface );
790 return IXMLDOMNode_insertBefore( IXMLDOMNode_from_impl(&This->node), newChild, refChild, outNewChild );
794 static HRESULT WINAPI domdoc_replaceChild(
795 IXMLDOMDocument2 *iface,
796 IXMLDOMNode* newChild,
797 IXMLDOMNode* oldChild,
798 IXMLDOMNode** outOldChild)
800 domdoc *This = impl_from_IXMLDOMDocument2( iface );
801 return IXMLDOMNode_replaceChild( IXMLDOMNode_from_impl(&This->node), newChild, oldChild, outOldChild );
805 static HRESULT WINAPI domdoc_removeChild(
806 IXMLDOMDocument2 *iface,
807 IXMLDOMNode* childNode,
808 IXMLDOMNode** oldChild)
810 domdoc *This = impl_from_IXMLDOMDocument2( iface );
811 return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), childNode, oldChild );
815 static HRESULT WINAPI domdoc_appendChild(
816 IXMLDOMDocument2 *iface,
817 IXMLDOMNode* newChild,
818 IXMLDOMNode** outNewChild)
820 domdoc *This = impl_from_IXMLDOMDocument2( iface );
821 return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newChild, outNewChild );
825 static HRESULT WINAPI domdoc_hasChildNodes(
826 IXMLDOMDocument2 *iface,
827 VARIANT_BOOL* hasChild)
829 domdoc *This = impl_from_IXMLDOMDocument2( iface );
830 return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), hasChild );
834 static HRESULT WINAPI domdoc_get_ownerDocument(
835 IXMLDOMDocument2 *iface,
836 IXMLDOMDocument** DOMDocument)
838 domdoc *This = impl_from_IXMLDOMDocument2( iface );
839 return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), DOMDocument );
843 static HRESULT WINAPI domdoc_cloneNode(
844 IXMLDOMDocument2 *iface,
846 IXMLDOMNode** cloneRoot)
848 domdoc *This = impl_from_IXMLDOMDocument2( iface );
849 return IXMLDOMNode_cloneNode( IXMLDOMNode_from_impl(&This->node), deep, cloneRoot );
853 static HRESULT WINAPI domdoc_get_nodeTypeString(
854 IXMLDOMDocument2 *iface,
857 domdoc *This = impl_from_IXMLDOMDocument2( iface );
858 return IXMLDOMNode_get_nodeTypeString( IXMLDOMNode_from_impl(&This->node), nodeType );
862 static HRESULT WINAPI domdoc_get_text(
863 IXMLDOMDocument2 *iface,
866 domdoc *This = impl_from_IXMLDOMDocument2( iface );
867 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), text );
871 static HRESULT WINAPI domdoc_put_text(
872 IXMLDOMDocument2 *iface,
875 domdoc *This = impl_from_IXMLDOMDocument2( iface );
876 return IXMLDOMNode_put_text( IXMLDOMNode_from_impl(&This->node), text );
880 static HRESULT WINAPI domdoc_get_specified(
881 IXMLDOMDocument2 *iface,
882 VARIANT_BOOL* isSpecified )
884 domdoc *This = impl_from_IXMLDOMDocument2( iface );
885 return IXMLDOMNode_get_specified( IXMLDOMNode_from_impl(&This->node), isSpecified );
889 static HRESULT WINAPI domdoc_get_definition(
890 IXMLDOMDocument2 *iface,
891 IXMLDOMNode** definitionNode )
893 domdoc *This = impl_from_IXMLDOMDocument2( iface );
894 return IXMLDOMNode_get_definition( IXMLDOMNode_from_impl(&This->node), definitionNode );
898 static HRESULT WINAPI domdoc_get_nodeTypedValue(
899 IXMLDOMDocument2 *iface,
900 VARIANT* typedValue )
902 domdoc *This = impl_from_IXMLDOMDocument2( iface );
903 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
906 static HRESULT WINAPI domdoc_put_nodeTypedValue(
907 IXMLDOMDocument2 *iface,
910 domdoc *This = impl_from_IXMLDOMDocument2( iface );
911 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
915 static HRESULT WINAPI domdoc_get_dataType(
916 IXMLDOMDocument2 *iface,
917 VARIANT* dataTypeName )
919 domdoc *This = impl_from_IXMLDOMDocument2( iface );
920 return IXMLDOMNode_get_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
924 static HRESULT WINAPI domdoc_put_dataType(
925 IXMLDOMDocument2 *iface,
928 domdoc *This = impl_from_IXMLDOMDocument2( iface );
929 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
933 static HRESULT WINAPI domdoc_get_xml(
934 IXMLDOMDocument2 *iface,
937 domdoc *This = impl_from_IXMLDOMDocument2( iface );
938 return IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), xmlString );
942 static HRESULT WINAPI domdoc_transformNode(
943 IXMLDOMDocument2 *iface,
944 IXMLDOMNode* styleSheet,
947 domdoc *This = impl_from_IXMLDOMDocument2( iface );
948 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), styleSheet, xmlString );
952 static HRESULT WINAPI domdoc_selectNodes(
953 IXMLDOMDocument2 *iface,
955 IXMLDOMNodeList** resultList )
957 domdoc *This = impl_from_IXMLDOMDocument2( iface );
958 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), queryString, resultList );
962 static HRESULT WINAPI domdoc_selectSingleNode(
963 IXMLDOMDocument2 *iface,
965 IXMLDOMNode** resultNode )
967 domdoc *This = impl_from_IXMLDOMDocument2( iface );
968 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), queryString, resultNode );
972 static HRESULT WINAPI domdoc_get_parsed(
973 IXMLDOMDocument2 *iface,
974 VARIANT_BOOL* isParsed )
976 domdoc *This = impl_from_IXMLDOMDocument2( iface );
977 return IXMLDOMNode_get_parsed( IXMLDOMNode_from_impl(&This->node), isParsed );
981 static HRESULT WINAPI domdoc_get_namespaceURI(
982 IXMLDOMDocument2 *iface,
985 domdoc *This = impl_from_IXMLDOMDocument2( iface );
986 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), namespaceURI );
990 static HRESULT WINAPI domdoc_get_prefix(
991 IXMLDOMDocument2 *iface,
994 domdoc *This = impl_from_IXMLDOMDocument2( iface );
995 return IXMLDOMNode_get_prefix( IXMLDOMNode_from_impl(&This->node), prefixString );
999 static HRESULT WINAPI domdoc_get_baseName(
1000 IXMLDOMDocument2 *iface,
1003 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1004 return IXMLDOMNode_get_baseName( IXMLDOMNode_from_impl(&This->node), nameString );
1008 static HRESULT WINAPI domdoc_transformNodeToObject(
1009 IXMLDOMDocument2 *iface,
1010 IXMLDOMNode* stylesheet,
1011 VARIANT outputObject)
1013 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1014 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), stylesheet, outputObject );
1018 static HRESULT WINAPI domdoc_get_doctype(
1019 IXMLDOMDocument2 *iface,
1020 IXMLDOMDocumentType** documentType )
1022 domdoc *This = impl_from_IXMLDOMDocument2(iface);
1023 FIXME("(%p)\n", This);
1028 static HRESULT WINAPI domdoc_get_implementation(
1029 IXMLDOMDocument2 *iface,
1030 IXMLDOMImplementation** impl )
1032 domdoc *This = impl_from_IXMLDOMDocument2(iface);
1034 TRACE("(%p)->(%p)\n", This, impl);
1037 return E_INVALIDARG;
1039 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1044 static HRESULT WINAPI domdoc_get_documentElement(
1045 IXMLDOMDocument2 *iface,
1046 IXMLDOMElement** DOMElement )
1048 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1049 xmlDocPtr xmldoc = NULL;
1050 xmlNodePtr root = NULL;
1051 IXMLDOMNode *element_node;
1054 TRACE("(%p)->(%p)\n", This, DOMElement);
1057 return E_INVALIDARG;
1061 xmldoc = get_doc( This );
1063 root = xmlDocGetRootElement( xmldoc );
1067 element_node = create_node( root );
1068 if(!element_node) return S_FALSE;
1070 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (LPVOID*)DOMElement);
1071 IXMLDOMNode_Release(element_node);
1077 static HRESULT WINAPI domdoc_put_documentElement(
1078 IXMLDOMDocument2 *iface,
1079 IXMLDOMElement* DOMElement )
1081 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1082 IXMLDOMNode *elementNode;
1087 TRACE("(%p)->(%p)\n", This, DOMElement);
1089 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1093 xmlNode = impl_from_IXMLDOMNode( elementNode );
1095 if(!xmlNode->node->parent)
1096 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1097 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1099 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1100 IXMLDOMNode_Release( elementNode );
1103 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1109 static HRESULT WINAPI domdoc_createElement(
1110 IXMLDOMDocument2 *iface,
1112 IXMLDOMElement** element )
1114 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1119 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1121 if (!element || !tagname) return E_INVALIDARG;
1123 V_VT(&type) = VT_I1;
1124 V_I1(&type) = NODE_ELEMENT;
1126 hr = IXMLDOMDocument2_createNode(iface, type, tagname, NULL, &node);
1129 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1130 IXMLDOMNode_Release(node);
1137 static HRESULT WINAPI domdoc_createDocumentFragment(
1138 IXMLDOMDocument2 *iface,
1139 IXMLDOMDocumentFragment** frag )
1141 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1146 TRACE("(%p)->(%p)\n", This, frag);
1148 if (!frag) return E_INVALIDARG;
1152 V_VT(&type) = VT_I1;
1153 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1155 hr = IXMLDOMDocument2_createNode(iface, type, NULL, NULL, &node);
1158 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1159 IXMLDOMNode_Release(node);
1166 static HRESULT WINAPI domdoc_createTextNode(
1167 IXMLDOMDocument2 *iface,
1169 IXMLDOMText** text )
1171 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1176 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1178 if (!text) return E_INVALIDARG;
1182 V_VT(&type) = VT_I1;
1183 V_I1(&type) = NODE_TEXT;
1185 hr = IXMLDOMDocument2_createNode(iface, type, NULL, NULL, &node);
1188 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1189 IXMLDOMNode_Release(node);
1190 hr = IXMLDOMText_put_data(*text, data);
1197 static HRESULT WINAPI domdoc_createComment(
1198 IXMLDOMDocument2 *iface,
1200 IXMLDOMComment** comment )
1202 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1207 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1209 if (!comment) return E_INVALIDARG;
1213 V_VT(&type) = VT_I1;
1214 V_I1(&type) = NODE_COMMENT;
1216 hr = IXMLDOMDocument2_createNode(iface, type, NULL, NULL, &node);
1219 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1220 IXMLDOMNode_Release(node);
1221 hr = IXMLDOMComment_put_data(*comment, data);
1228 static HRESULT WINAPI domdoc_createCDATASection(
1229 IXMLDOMDocument2 *iface,
1231 IXMLDOMCDATASection** cdata )
1233 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1238 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1240 if (!cdata) return E_INVALIDARG;
1244 V_VT(&type) = VT_I1;
1245 V_I1(&type) = NODE_CDATA_SECTION;
1247 hr = IXMLDOMDocument2_createNode(iface, type, NULL, NULL, &node);
1250 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1251 IXMLDOMNode_Release(node);
1252 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1259 static HRESULT WINAPI domdoc_createProcessingInstruction(
1260 IXMLDOMDocument2 *iface,
1263 IXMLDOMProcessingInstruction** pi )
1265 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1270 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1272 if (!pi) return E_INVALIDARG;
1276 V_VT(&type) = VT_I1;
1277 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1279 hr = IXMLDOMDocument2_createNode(iface, type, target, NULL, &node);
1284 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1285 V_VT(&v_data) = VT_BSTR;
1286 V_BSTR(&v_data) = data;
1288 hr = IXMLDOMNode_put_nodeValue( node, v_data );
1290 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1291 IXMLDOMNode_Release(node);
1298 static HRESULT WINAPI domdoc_createAttribute(
1299 IXMLDOMDocument2 *iface,
1301 IXMLDOMAttribute** attribute )
1303 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1308 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1310 if (!attribute || !name) return E_INVALIDARG;
1312 V_VT(&type) = VT_I1;
1313 V_I1(&type) = NODE_ATTRIBUTE;
1315 hr = IXMLDOMDocument2_createNode(iface, type, name, NULL, &node);
1318 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1319 IXMLDOMNode_Release(node);
1326 static HRESULT WINAPI domdoc_createEntityReference(
1327 IXMLDOMDocument2 *iface,
1329 IXMLDOMEntityReference** entityref )
1331 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1336 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1338 if (!entityref) return E_INVALIDARG;
1342 V_VT(&type) = VT_I1;
1343 V_I1(&type) = NODE_ENTITY_REFERENCE;
1345 hr = IXMLDOMDocument2_createNode(iface, type, name, NULL, &node);
1348 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1349 IXMLDOMNode_Release(node);
1356 static HRESULT WINAPI domdoc_getElementsByTagName(
1357 IXMLDOMDocument2 *iface,
1359 IXMLDOMNodeList** resultList )
1361 static const WCHAR xpathformat[] =
1362 { '/','/','*','[','l','o','c','a','l','-','n','a','m','e','(',')','=','\'','%','s','\'',']',0 };
1363 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1366 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagName), resultList);
1368 if (tagName[0] == '*' && tagName[1] == 0)
1370 szPattern = heap_alloc(sizeof(WCHAR)*4);
1371 szPattern[0] = szPattern[1] = '/';
1377 szPattern = heap_alloc(sizeof(WCHAR)*(20+lstrlenW(tagName)+1));
1378 wsprintfW(szPattern, xpathformat, tagName);
1381 hr = queryresult_create((xmlNodePtr)get_doc(This), szPattern, resultList);
1382 heap_free(szPattern);
1387 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1393 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1395 return E_INVALIDARG;
1402 static HRESULT WINAPI domdoc_createNode(
1403 IXMLDOMDocument2 *iface,
1407 IXMLDOMNode** node )
1409 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1410 DOMNodeType node_type;
1415 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1417 if(!node) return E_INVALIDARG;
1419 if(namespaceURI && namespaceURI[0])
1420 FIXME("nodes with namespaces currently not supported.\n");
1422 hr = get_node_type(Type, &node_type);
1423 if(FAILED(hr)) return hr;
1425 TRACE("node_type %d\n", node_type);
1427 /* exit earlier for types that need name */
1431 case NODE_ATTRIBUTE:
1432 case NODE_ENTITY_REFERENCE:
1433 case NODE_PROCESSING_INSTRUCTION:
1434 if (!name || *name == 0) return E_FAIL;
1439 xml_name = xmlChar_from_wchar(name);
1444 xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
1446 case NODE_ATTRIBUTE:
1447 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1450 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1452 case NODE_CDATA_SECTION:
1453 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1455 case NODE_ENTITY_REFERENCE:
1456 xmlnode = xmlNewReference(get_doc(This), xml_name);
1458 case NODE_PROCESSING_INSTRUCTION:
1459 #ifdef HAVE_XMLNEWDOCPI
1460 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1462 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1467 xmlnode = xmlNewDocComment(get_doc(This), NULL);
1469 case NODE_DOCUMENT_FRAGMENT:
1470 xmlnode = xmlNewDocFragment(get_doc(This));
1472 /* unsupported types */
1474 case NODE_DOCUMENT_TYPE:
1477 heap_free(xml_name);
1478 return E_INVALIDARG;
1480 FIXME("unhandled node type %d\n", node_type);
1485 *node = create_node(xmlnode);
1486 heap_free(xml_name);
1490 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1491 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1498 static HRESULT WINAPI domdoc_nodeFromID(
1499 IXMLDOMDocument2 *iface,
1501 IXMLDOMNode** node )
1503 domdoc *This = impl_from_IXMLDOMDocument2(iface);
1504 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1508 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1513 xmldoc = doparse( ptr, len, NULL );
1515 xmldoc->_private = create_priv();
1516 return attach_xmldoc(&This->node, xmldoc);
1522 static HRESULT doread( domdoc *This, LPWSTR filename )
1527 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1532 detach_bsc(This->bsc);
1538 static HRESULT WINAPI domdoc_load(
1539 IXMLDOMDocument2 *iface,
1541 VARIANT_BOOL* isSuccessful )
1543 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1544 LPWSTR filename = NULL;
1545 HRESULT hr = S_FALSE;
1546 IXMLDOMDocument2 *pNewDoc = NULL;
1547 IStream *pStream = NULL;
1550 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
1552 *isSuccessful = VARIANT_FALSE;
1554 assert( &This->node );
1556 switch( V_VT(&xmlSource) )
1559 filename = V_BSTR(&xmlSource);
1562 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument2, (void**)&pNewDoc);
1567 domdoc *newDoc = impl_from_IXMLDOMDocument2( pNewDoc );
1568 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1569 hr = attach_xmldoc(&This->node, xmldoc);
1572 *isSuccessful = VARIANT_TRUE;
1577 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1580 IPersistStream *pDocStream;
1581 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1584 hr = IPersistStream_Load(pDocStream, pStream);
1585 IStream_Release(pStream);
1588 *isSuccessful = VARIANT_TRUE;
1590 TRACE("Using IStream to load Document\n");
1595 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1600 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1605 /* ISequentialStream */
1606 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1610 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1613 TRACE("filename (%s)\n", debugstr_w(filename));
1617 hr = doread( This, filename );
1620 This->error = E_FAIL;
1623 hr = This->error = S_OK;
1624 *isSuccessful = VARIANT_TRUE;
1628 if(!filename || FAILED(hr)) {
1629 xmldoc = xmlNewDoc(NULL);
1630 xmldoc->_private = create_priv();
1631 hr = attach_xmldoc(&This->node, xmldoc);
1636 TRACE("ret (%d)\n", hr);
1642 static HRESULT WINAPI domdoc_get_readyState(
1643 IXMLDOMDocument2 *iface,
1646 domdoc *This = impl_from_IXMLDOMDocument2(iface);
1647 FIXME("(%p)->(%p)\n", This, value);
1652 static HRESULT WINAPI domdoc_get_parseError(
1653 IXMLDOMDocument2 *iface,
1654 IXMLDOMParseError** errorObj )
1656 BSTR error_string = NULL;
1657 static const WCHAR err[] = {'e','r','r','o','r',0};
1658 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1660 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
1663 error_string = SysAllocString(err);
1665 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
1666 if(!*errorObj) return E_OUTOFMEMORY;
1671 static HRESULT WINAPI domdoc_get_url(
1672 IXMLDOMDocument2 *iface,
1675 domdoc *This = impl_from_IXMLDOMDocument2(iface);
1676 FIXME("(%p)->(%p)\n", This, urlString);
1681 static HRESULT WINAPI domdoc_get_async(
1682 IXMLDOMDocument2 *iface,
1683 VARIANT_BOOL* isAsync )
1685 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1687 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
1688 *isAsync = This->async;
1693 static HRESULT WINAPI domdoc_put_async(
1694 IXMLDOMDocument2 *iface,
1695 VARIANT_BOOL isAsync )
1697 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1699 TRACE("(%p)->(%d)\n", This, isAsync);
1700 This->async = isAsync;
1705 static HRESULT WINAPI domdoc_abort(
1706 IXMLDOMDocument2 *iface )
1708 domdoc *This = impl_from_IXMLDOMDocument2(iface);
1709 FIXME("%p\n", This);
1714 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
1719 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
1720 str = heap_alloc( len );
1723 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
1729 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
1730 static HRESULT WINAPI domdoc_loadXML(
1731 IXMLDOMDocument2 *iface,
1733 VARIANT_BOOL* isSuccessful )
1735 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1736 xmlDocPtr xmldoc = NULL;
1739 HRESULT hr = S_FALSE, hr2;
1741 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
1743 assert ( &This->node );
1747 *isSuccessful = VARIANT_FALSE;
1749 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
1751 xmldoc = doparse( str, len, "UTF-8" );
1754 This->error = E_FAIL;
1757 hr = This->error = S_OK;
1758 *isSuccessful = VARIANT_TRUE;
1763 xmldoc = xmlNewDoc(NULL);
1765 xmldoc->_private = create_priv();
1766 hr2 = attach_xmldoc( &This->node, xmldoc );
1773 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer,
1778 if(!WriteFile(ctx, buffer, len, &written, NULL))
1780 WARN("write error\n");
1787 static int XMLCALL domdoc_save_closecallback(void *ctx)
1789 return CloseHandle(ctx) ? 0 : -1;
1792 static HRESULT WINAPI domdoc_save(
1793 IXMLDOMDocument2 *iface,
1794 VARIANT destination )
1796 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1802 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
1803 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
1805 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
1807 FIXME("Unhandled vt %d\n", V_VT(&destination));
1811 if(V_VT(&destination) == VT_UNKNOWN)
1813 IUnknown *pUnk = V_UNKNOWN(&destination);
1814 IXMLDOMDocument2 *pDocument;
1816 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument2, (void**)&pDocument);
1820 VARIANT_BOOL bSuccessful;
1822 ret = IXMLDOMDocument2_get_xml(iface, &bXML);
1825 ret = IXMLDOMDocument2_loadXML(pDocument, bXML, &bSuccessful);
1827 SysFreeString(bXML);
1830 IXMLDOMDocument2_Release(pDocument);
1833 TRACE("ret %d\n", ret);
1838 handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
1839 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1840 if( handle == INVALID_HANDLE_VALUE )
1842 WARN("failed to create file\n");
1846 /* disable top XML declaration */
1847 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
1848 handle, NULL, XML_SAVE_NO_DECL);
1851 CloseHandle(handle);
1855 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
1856 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
1857 xmldoc_link_xmldecl(get_doc(This), xmldecl);
1859 /* will close file through close callback */
1865 static HRESULT WINAPI domdoc_get_validateOnParse(
1866 IXMLDOMDocument2 *iface,
1867 VARIANT_BOOL* isValidating )
1869 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1871 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
1872 *isValidating = This->validating;
1877 static HRESULT WINAPI domdoc_put_validateOnParse(
1878 IXMLDOMDocument2 *iface,
1879 VARIANT_BOOL isValidating )
1881 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1883 TRACE("(%p)->(%d)\n", This, isValidating);
1884 This->validating = isValidating;
1889 static HRESULT WINAPI domdoc_get_resolveExternals(
1890 IXMLDOMDocument2 *iface,
1891 VARIANT_BOOL* isResolving )
1893 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1895 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
1896 *isResolving = This->resolving;
1901 static HRESULT WINAPI domdoc_put_resolveExternals(
1902 IXMLDOMDocument2 *iface,
1903 VARIANT_BOOL isResolving )
1905 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1907 TRACE("(%p)->(%d)\n", This, isResolving);
1908 This->resolving = isResolving;
1913 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
1914 IXMLDOMDocument2 *iface,
1915 VARIANT_BOOL* isPreserving )
1917 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1919 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->preserving);
1920 *isPreserving = This->preserving;
1925 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
1926 IXMLDOMDocument2 *iface,
1927 VARIANT_BOOL isPreserving )
1929 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1931 TRACE("(%p)->(%d)\n", This, isPreserving);
1932 This->preserving = isPreserving;
1937 static HRESULT WINAPI domdoc_put_onReadyStateChange(
1938 IXMLDOMDocument2 *iface,
1939 VARIANT readyStateChangeSink )
1941 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1942 FIXME("%p\n", This);
1947 static HRESULT WINAPI domdoc_put_onDataAvailable(
1948 IXMLDOMDocument2 *iface,
1949 VARIANT onDataAvailableSink )
1951 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1952 FIXME("%p\n", This);
1956 static HRESULT WINAPI domdoc_put_onTransformNode(
1957 IXMLDOMDocument2 *iface,
1958 VARIANT onTransformNodeSink )
1960 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1961 FIXME("%p\n", This);
1965 static HRESULT WINAPI domdoc_get_namespaces(
1966 IXMLDOMDocument2* iface,
1967 IXMLDOMSchemaCollection** schemaCollection )
1969 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1970 FIXME("(%p)->(%p)\n", This, schemaCollection);
1974 static HRESULT WINAPI domdoc_get_schemas(
1975 IXMLDOMDocument2* iface,
1978 domdoc *This = impl_from_IXMLDOMDocument2( iface );
1979 HRESULT hr = S_FALSE;
1980 IXMLDOMSchemaCollection *cur_schema = This->schema;
1982 TRACE("(%p)->(%p)\n", This, var1);
1984 VariantInit(var1); /* Test shows we don't call VariantClear here */
1985 V_VT(var1) = VT_NULL;
1989 hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
1991 V_VT(var1) = VT_DISPATCH;
1996 static HRESULT WINAPI domdoc_putref_schemas(
1997 IXMLDOMDocument2* iface,
2000 domdoc *This = impl_from_IXMLDOMDocument2( iface );
2001 HRESULT hr = E_FAIL;
2002 IXMLDOMSchemaCollection *new_schema = NULL;
2004 FIXME("(%p): semi-stub\n", This);
2008 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2012 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2021 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2026 IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
2027 if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
2033 static HRESULT WINAPI domdoc_validate(
2034 IXMLDOMDocument2* iface,
2035 IXMLDOMParseError** err)
2037 domdoc *This = impl_from_IXMLDOMDocument2( iface );
2038 FIXME("(%p)->(%p)\n", This, err);
2042 static HRESULT WINAPI domdoc_setProperty(
2043 IXMLDOMDocument2* iface,
2047 domdoc *This = impl_from_IXMLDOMDocument2( iface );
2049 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2051 if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
2057 V_VT(&varStr) = VT_EMPTY;
2058 if (V_VT(&var) != VT_BSTR)
2060 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2062 bstr = V_BSTR(&varStr);
2065 bstr = V_BSTR(&var);
2068 if (lstrcmpiW(bstr, SZ_VALUE_XPATH) == 0)
2069 This->bUseXPath = TRUE;
2070 else if (lstrcmpiW(bstr, SZ_VALUE_XSLPATTERN) == 0)
2071 This->bUseXPath = FALSE;
2075 VariantClear(&varStr);
2079 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2083 static HRESULT WINAPI domdoc_getProperty(
2084 IXMLDOMDocument2* iface,
2088 domdoc *This = impl_from_IXMLDOMDocument2( iface );
2090 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2093 return E_INVALIDARG;
2094 if (lstrcmpiW(p, SZ_PROPERTY_SELECTION_LANGUAGE) == 0)
2096 V_VT(var) = VT_BSTR;
2097 if (This->bUseXPath)
2098 V_BSTR(var) = SysAllocString(SZ_VALUE_XPATH);
2100 V_BSTR(var) = SysAllocString(SZ_VALUE_XSLPATTERN);
2104 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2108 static const struct IXMLDOMDocument2Vtbl domdoc_vtbl =
2110 domdoc_QueryInterface,
2113 domdoc_GetTypeInfoCount,
2115 domdoc_GetIDsOfNames,
2117 domdoc_get_nodeName,
2118 domdoc_get_nodeValue,
2119 domdoc_put_nodeValue,
2120 domdoc_get_nodeType,
2121 domdoc_get_parentNode,
2122 domdoc_get_childNodes,
2123 domdoc_get_firstChild,
2124 domdoc_get_lastChild,
2125 domdoc_get_previousSibling,
2126 domdoc_get_nextSibling,
2127 domdoc_get_attributes,
2128 domdoc_insertBefore,
2129 domdoc_replaceChild,
2132 domdoc_hasChildNodes,
2133 domdoc_get_ownerDocument,
2135 domdoc_get_nodeTypeString,
2138 domdoc_get_specified,
2139 domdoc_get_definition,
2140 domdoc_get_nodeTypedValue,
2141 domdoc_put_nodeTypedValue,
2142 domdoc_get_dataType,
2143 domdoc_put_dataType,
2145 domdoc_transformNode,
2147 domdoc_selectSingleNode,
2149 domdoc_get_namespaceURI,
2151 domdoc_get_baseName,
2152 domdoc_transformNodeToObject,
2154 domdoc_get_implementation,
2155 domdoc_get_documentElement,
2156 domdoc_put_documentElement,
2157 domdoc_createElement,
2158 domdoc_createDocumentFragment,
2159 domdoc_createTextNode,
2160 domdoc_createComment,
2161 domdoc_createCDATASection,
2162 domdoc_createProcessingInstruction,
2163 domdoc_createAttribute,
2164 domdoc_createEntityReference,
2165 domdoc_getElementsByTagName,
2169 domdoc_get_readyState,
2170 domdoc_get_parseError,
2177 domdoc_get_validateOnParse,
2178 domdoc_put_validateOnParse,
2179 domdoc_get_resolveExternals,
2180 domdoc_put_resolveExternals,
2181 domdoc_get_preserveWhiteSpace,
2182 domdoc_put_preserveWhiteSpace,
2183 domdoc_put_onReadyStateChange,
2184 domdoc_put_onDataAvailable,
2185 domdoc_put_onTransformNode,
2186 domdoc_get_namespaces,
2188 domdoc_putref_schemas,
2194 /* xmldoc implementation of IObjectWithSite */
2195 static HRESULT WINAPI
2196 xmldoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
2198 domdoc *This = impl_from_IObjectWithSite(iface);
2199 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppvObject );
2203 xmldoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
2205 domdoc *This = impl_from_IObjectWithSite(iface);
2206 return IXMLDocument_AddRef((IXMLDocument *)This);
2210 xmldoc_ObjectWithSite_Release( IObjectWithSite* iface )
2212 domdoc *This = impl_from_IObjectWithSite(iface);
2213 return IXMLDocument_Release((IXMLDocument *)This);
2216 static HRESULT WINAPI
2217 xmldoc_GetSite( IObjectWithSite *iface, REFIID iid, void ** ppvSite )
2219 domdoc *This = impl_from_IObjectWithSite(iface);
2221 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
2226 return IUnknown_QueryInterface( This->site, iid, ppvSite );
2229 static HRESULT WINAPI
2230 xmldoc_SetSite( IObjectWithSite *iface, IUnknown *punk )
2232 domdoc *This = impl_from_IObjectWithSite(iface);
2234 TRACE("(%p)->(%p)\n", iface, punk);
2240 IUnknown_Release( This->site );
2247 IUnknown_AddRef( punk );
2250 IUnknown_Release( This->site );
2257 static const IObjectWithSiteVtbl domdocObjectSite =
2259 xmldoc_ObjectWithSite_QueryInterface,
2260 xmldoc_ObjectWithSite_AddRef,
2261 xmldoc_ObjectWithSite_Release,
2266 static HRESULT WINAPI xmldoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
2268 domdoc *This = impl_from_IObjectSafety(iface);
2269 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppv );
2272 static ULONG WINAPI xmldoc_Safety_AddRef(IObjectSafety *iface)
2274 domdoc *This = impl_from_IObjectSafety(iface);
2275 return IXMLDocument_AddRef((IXMLDocument *)This);
2278 static ULONG WINAPI xmldoc_Safety_Release(IObjectSafety *iface)
2280 domdoc *This = impl_from_IObjectSafety(iface);
2281 return IXMLDocument_Release((IXMLDocument *)This);
2284 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
2286 static HRESULT WINAPI xmldoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2287 DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
2289 domdoc *This = impl_from_IObjectSafety(iface);
2291 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
2293 if(!pdwSupportedOptions || !pdwEnabledOptions)
2296 *pdwSupportedOptions = SAFETY_SUPPORTED_OPTIONS;
2297 *pdwEnabledOptions = This->safeopt;
2302 static HRESULT WINAPI xmldoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2303 DWORD dwOptionSetMask, DWORD dwEnabledOptions)
2305 domdoc *This = impl_from_IObjectSafety(iface);
2306 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
2308 if ((dwOptionSetMask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
2311 This->safeopt = dwEnabledOptions & dwOptionSetMask & SAFETY_SUPPORTED_OPTIONS;
2315 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
2316 xmldoc_Safety_QueryInterface,
2317 xmldoc_Safety_AddRef,
2318 xmldoc_Safety_Release,
2319 xmldoc_Safety_GetInterfaceSafetyOptions,
2320 xmldoc_Safety_SetInterfaceSafetyOptions
2324 static const tid_t domdoc_iface_tids[] = {
2326 IXMLDOMDocument_tid,
2327 IXMLDOMDocument2_tid,
2330 static dispex_static_data_t domdoc_dispex = {
2332 IXMLDOMDocument2_tid,
2337 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument2 **document)
2341 doc = heap_alloc( sizeof (*doc) );
2343 return E_OUTOFMEMORY;
2345 doc->lpVtbl = &domdoc_vtbl;
2346 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
2347 doc->lpvtblIObjectWithSite = &domdocObjectSite;
2348 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
2349 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
2351 doc->async = VARIANT_TRUE;
2352 doc->validating = 0;
2354 doc->preserving = 0;
2355 doc->bUseXPath = FALSE;
2363 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IUnknown*)&doc->lpVtbl, &domdoc_dispex);
2365 *document = (IXMLDOMDocument2*)&doc->lpVtbl;
2367 TRACE("returning iface %p\n", *document);
2371 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2376 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
2378 xmldoc = xmlNewDoc(NULL);
2380 return E_OUTOFMEMORY;
2382 xmldoc->_private = create_priv();
2384 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument2**)ppObj);
2391 IUnknown* create_domdoc( xmlNodePtr document )
2396 TRACE("(%p)\n", document);
2398 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument2**)&pObj);
2407 HRESULT DOMDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2409 MESSAGE("This program tried to use a DOMDocument object, but\n"
2410 "libxml2 support was not present at compile time.\n");