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 PropertySelectionLanguageW[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0};
62 static const WCHAR PropertySelectionNamespacesW[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0};
63 static const WCHAR PropertyProhibitDTDW[] = {'P','r','o','h','i','b','i','t','D','T','D',0};
64 static const WCHAR PropValueXPathW[] = {'X','P','a','t','h',0};
65 static const WCHAR PropValueXSLPatternW[] = {'X','S','L','P','a','t','t','e','r','n',0};
67 typedef struct _domdoc
70 const struct IXMLDOMDocument3Vtbl *lpVtbl;
71 const struct IPersistStreamInitVtbl *lpvtblIPersistStreamInit;
72 const struct IObjectWithSiteVtbl *lpvtblIObjectWithSite;
73 const struct IObjectSafetyVtbl *lpvtblIObjectSafety;
74 const struct ISupportErrorInfoVtbl *lpvtblISupportErrorInfo;
77 VARIANT_BOOL validating;
78 VARIANT_BOOL resolving;
79 VARIANT_BOOL preserving;
81 IXMLDOMSchemaCollection *schema;
96 In native windows, the whole lifetime management of XMLDOMNodes is
97 managed automatically using reference counts. Wine emulates that by
98 maintaining a reference count to the document that is increased for
99 each IXMLDOMNode pointer passed out for this document. If all these
100 pointers are gone, the document is unreachable and gets freed, that
101 is, all nodes in the tree of the document get freed.
103 You are able to create nodes that are associated to a document (in
104 fact, in msxml's XMLDOM model, all nodes are associated to a document),
105 but not in the tree of that document, for example using the createFoo
106 functions from IXMLDOMDocument. These nodes do not get cleaned up
107 by libxml, so we have to do it ourselves.
109 To catch these nodes, a list of "orphan nodes" is introduced.
110 It contains pointers to all roots of node trees that are
111 associated with the document without being part of the document
112 tree. All nodes with parent==NULL (except for the document root nodes)
113 should be in the orphan node list of their document. All orphan nodes
114 get freed together with the document itself.
117 typedef struct _xmldoc_priv {
122 typedef struct _orphan_entry {
127 static inline xmldoc_priv * priv_from_xmlDocPtr(xmlDocPtr doc)
129 return doc->_private;
132 static xmldoc_priv * create_priv(void)
135 priv = heap_alloc( sizeof (*priv) );
140 list_init( &priv->orphans );
146 /* links a "<?xml" node as a first child */
147 void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
150 if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
153 /* unlinks a first "<?xml" child if it was created */
154 xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
160 if (doc->standalone != -1)
162 node = doc->children;
163 xmlUnlinkNode( node );
171 static xmlDocPtr doparse( char *ptr, int len, const char *encoding )
175 #ifdef HAVE_XMLREADMEMORY
177 * use xmlReadMemory if possible so we can suppress
178 * writing errors to stderr
180 doc = xmlReadMemory( ptr, len, NULL, encoding,
181 XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS );
183 doc = xmlParseMemory( ptr, len );
186 /* create first child as a <?xml...?> */
187 if (doc && doc->standalone != -1)
191 xmlChar *xmlbuff = (xmlChar*)buff;
193 node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
195 /* version attribute can't be omitted */
196 sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
197 xmlNodeAddContent( node, xmlbuff );
201 sprintf(buff, " encoding=\"%s\"", doc->encoding);
202 xmlNodeAddContent( node, xmlbuff );
205 if (doc->standalone != -2)
207 sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
208 xmlNodeAddContent( node, xmlbuff );
211 xmldoc_link_xmldecl( doc, node );
217 LONG xmldoc_add_ref(xmlDocPtr doc)
219 LONG ref = InterlockedIncrement(&priv_from_xmlDocPtr(doc)->refs);
220 TRACE("(%p)->(%d)\n", doc, ref);
224 LONG xmldoc_release(xmlDocPtr doc)
226 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
227 LONG ref = InterlockedDecrement(&priv->refs);
228 TRACE("(%p)->(%d)\n", doc, ref);
231 orphan_entry *orphan, *orphan2;
232 TRACE("freeing docptr %p\n", doc);
234 LIST_FOR_EACH_ENTRY_SAFE( orphan, orphan2, &priv->orphans, orphan_entry, entry )
236 xmlFreeNode( orphan->node );
239 heap_free(doc->_private);
247 HRESULT xmldoc_add_orphan(xmlDocPtr doc, xmlNodePtr node)
249 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
252 entry = heap_alloc( sizeof (*entry) );
254 return E_OUTOFMEMORY;
257 list_add_head( &priv->orphans, &entry->entry );
261 HRESULT xmldoc_remove_orphan(xmlDocPtr doc, xmlNodePtr node)
263 xmldoc_priv *priv = priv_from_xmlDocPtr(doc);
264 orphan_entry *entry, *entry2;
266 LIST_FOR_EACH_ENTRY_SAFE( entry, entry2, &priv->orphans, orphan_entry, entry )
268 if( entry->node == node )
270 list_remove( &entry->entry );
279 static HRESULT attach_xmldoc( xmlnode *node, xmlDocPtr xml )
282 xmldoc_release(node->node->doc);
284 node->node = (xmlNodePtr) xml;
286 xmldoc_add_ref(node->node->doc);
291 static inline domdoc *impl_from_IXMLDOMDocument3( IXMLDOMDocument3 *iface )
293 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
296 static inline xmlDocPtr get_doc( domdoc *This )
298 return (xmlDocPtr)This->node.node;
301 static inline domdoc *impl_from_IPersistStreamInit(IPersistStreamInit *iface)
303 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIPersistStreamInit));
306 static inline domdoc *impl_from_IObjectWithSite(IObjectWithSite *iface)
308 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectWithSite));
311 static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
313 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblIObjectSafety));
316 static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
318 return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpvtblISupportErrorInfo));
321 /************************************************************************
322 * domdoc implementation of IPersistStream.
324 static HRESULT WINAPI domdoc_IPersistStreamInit_QueryInterface(
325 IPersistStreamInit *iface, REFIID riid, void **ppvObj)
327 domdoc *this = impl_from_IPersistStreamInit(iface);
328 return IXMLDOMDocument2_QueryInterface((IXMLDOMDocument2 *)this, riid, ppvObj);
331 static ULONG WINAPI domdoc_IPersistStreamInit_AddRef(
332 IPersistStreamInit *iface)
334 domdoc *this = impl_from_IPersistStreamInit(iface);
335 return IXMLDOMDocument2_AddRef((IXMLDOMDocument2 *)this);
338 static ULONG WINAPI domdoc_IPersistStreamInit_Release(
339 IPersistStreamInit *iface)
341 domdoc *this = impl_from_IPersistStreamInit(iface);
342 return IXMLDOMDocument2_Release((IXMLDOMDocument2 *)this);
345 static HRESULT WINAPI domdoc_IPersistStreamInit_GetClassID(
346 IPersistStreamInit *iface, CLSID *classid)
348 TRACE("(%p,%p): stub!\n", iface, classid);
353 *classid = CLSID_DOMDocument2;
358 static HRESULT WINAPI domdoc_IPersistStreamInit_IsDirty(
359 IPersistStreamInit *iface)
361 domdoc *This = impl_from_IPersistStreamInit(iface);
362 FIXME("(%p): stub!\n", This);
366 static HRESULT WINAPI domdoc_IPersistStreamInit_Load(
367 IPersistStreamInit *iface, LPSTREAM pStm)
369 domdoc *This = impl_from_IPersistStreamInit(iface);
372 DWORD read, written, len;
375 xmlDocPtr xmldoc = NULL;
377 TRACE("(%p)->(%p)\n", This, pStm);
382 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
388 IStream_Read(pStm, buf, sizeof(buf), &read);
389 hr = IStream_Write(This->stream, buf, read, &written);
390 } while(SUCCEEDED(hr) && written != 0 && read != 0);
394 ERR("Failed to copy stream\n");
398 hr = GetHGlobalFromStream(This->stream, &hglobal);
402 len = GlobalSize(hglobal);
403 ptr = GlobalLock(hglobal);
405 xmldoc = doparse(ptr, len, NULL);
406 GlobalUnlock(hglobal);
410 ERR("Failed to parse xml\n");
414 xmldoc->_private = create_priv();
416 return attach_xmldoc( &This->node, xmldoc );
419 static HRESULT WINAPI domdoc_IPersistStreamInit_Save(
420 IPersistStreamInit *iface, IStream *stream, BOOL clr_dirty)
422 domdoc *This = impl_from_IPersistStreamInit(iface);
426 TRACE("(%p)->(%p %d)\n", This, stream, clr_dirty);
428 hr = IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), &xmlString );
431 DWORD len = SysStringLen(xmlString) * sizeof(WCHAR);
433 hr = IStream_Write( stream, xmlString, len, NULL );
434 SysFreeString(xmlString);
437 TRACE("ret 0x%08x\n", hr);
442 static HRESULT WINAPI domdoc_IPersistStreamInit_GetSizeMax(
443 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize)
445 domdoc *This = impl_from_IPersistStreamInit(iface);
446 TRACE("(%p)->(%p): stub!\n", This, pcbSize);
450 static HRESULT WINAPI domdoc_IPersistStreamInit_InitNew(
451 IPersistStreamInit *iface)
453 domdoc *This = impl_from_IPersistStreamInit(iface);
454 TRACE("(%p)\n", This);
458 static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
460 domdoc_IPersistStreamInit_QueryInterface,
461 domdoc_IPersistStreamInit_AddRef,
462 domdoc_IPersistStreamInit_Release,
463 domdoc_IPersistStreamInit_GetClassID,
464 domdoc_IPersistStreamInit_IsDirty,
465 domdoc_IPersistStreamInit_Load,
466 domdoc_IPersistStreamInit_Save,
467 domdoc_IPersistStreamInit_GetSizeMax,
468 domdoc_IPersistStreamInit_InitNew
471 /* ISupportErrorInfo interface */
472 static HRESULT WINAPI support_error_QueryInterface(
473 ISupportErrorInfo *iface,
474 REFIID riid, void** ppvObj )
476 domdoc *This = impl_from_ISupportErrorInfo(iface);
477 return IXMLDOMDocument3_QueryInterface((IXMLDOMDocument3 *)This, riid, ppvObj);
480 static ULONG WINAPI support_error_AddRef(
481 ISupportErrorInfo *iface )
483 domdoc *This = impl_from_ISupportErrorInfo(iface);
484 return IXMLDOMDocument3_AddRef((IXMLDOMDocument3 *)This);
487 static ULONG WINAPI support_error_Release(
488 ISupportErrorInfo *iface )
490 domdoc *This = impl_from_ISupportErrorInfo(iface);
491 return IXMLDOMDocument3_Release((IXMLDOMDocument3 *)This);
494 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
495 ISupportErrorInfo *iface,
498 FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
502 static const struct ISupportErrorInfoVtbl support_error_vtbl =
504 support_error_QueryInterface,
505 support_error_AddRef,
506 support_error_Release,
507 support_error_InterfaceSupportsErrorInfo
510 /* IXMLDOMDocument2 interface */
511 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
513 domdoc *This = impl_from_IXMLDOMDocument3( iface );
515 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppvObject );
519 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
520 IsEqualGUID( riid, &IID_IDispatch ) ||
521 IsEqualGUID( riid, &IID_IXMLDOMDocument ) ||
522 IsEqualGUID( riid, &IID_IXMLDOMDocument2 )||
523 IsEqualGUID( riid, &IID_IXMLDOMDocument3 ))
527 else if ( IsEqualGUID( riid, &IID_IXMLDOMNode ) )
529 *ppvObject = IXMLDOMNode_from_impl(&This->node);
531 else if (IsEqualGUID(&IID_IPersistStream, riid) ||
532 IsEqualGUID(&IID_IPersistStreamInit, riid))
534 *ppvObject = &(This->lpvtblIPersistStreamInit);
536 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
538 *ppvObject = &(This->lpvtblIObjectWithSite);
540 else if (IsEqualGUID(&IID_IObjectSafety, riid))
542 *ppvObject = &(This->lpvtblIObjectSafety);
544 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
546 *ppvObject = &This->lpvtblISupportErrorInfo;
548 else if(dispex_query_interface(&This->node.dispex, riid, ppvObject))
550 return *ppvObject ? S_OK : E_NOINTERFACE;
552 else if(IsEqualGUID(&IID_IRunnableObject, riid))
554 TRACE("IID_IRunnableObject not supported returning NULL\n");
555 return E_NOINTERFACE;
559 FIXME("interface %s not implemented\n", debugstr_guid(riid));
560 return E_NOINTERFACE;
563 IUnknown_AddRef((IUnknown*)*ppvObject);
569 static ULONG WINAPI domdoc_AddRef(
570 IXMLDOMDocument3 *iface )
572 domdoc *This = impl_from_IXMLDOMDocument3( iface );
573 TRACE("%p\n", This );
574 return InterlockedIncrement( &This->ref );
578 static ULONG WINAPI domdoc_Release(
579 IXMLDOMDocument3 *iface )
581 domdoc *This = impl_from_IXMLDOMDocument3( iface );
584 TRACE("%p\n", This );
586 ref = InterlockedDecrement( &This->ref );
590 detach_bsc(This->bsc);
593 IUnknown_Release( This->site );
594 destroy_xmlnode(&This->node);
595 if(This->schema) IXMLDOMSchemaCollection_Release( This->schema );
596 if (This->stream) IStream_Release(This->stream);
597 HeapFree( GetProcessHeap(), 0, This );
603 static HRESULT WINAPI domdoc_GetTypeInfoCount( IXMLDOMDocument3 *iface, UINT* pctinfo )
605 domdoc *This = impl_from_IXMLDOMDocument3( iface );
607 TRACE("(%p)->(%p)\n", This, pctinfo);
614 static HRESULT WINAPI domdoc_GetTypeInfo(
615 IXMLDOMDocument3 *iface,
616 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
618 domdoc *This = impl_from_IXMLDOMDocument3( iface );
621 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
623 hr = get_typeinfo(IXMLDOMDocument2_tid, ppTInfo);
628 static HRESULT WINAPI domdoc_GetIDsOfNames(
629 IXMLDOMDocument3 *iface,
636 domdoc *This = impl_from_IXMLDOMDocument3( iface );
640 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
643 if(!rgszNames || cNames == 0 || !rgDispId)
646 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
649 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
650 ITypeInfo_Release(typeinfo);
657 static HRESULT WINAPI domdoc_Invoke(
658 IXMLDOMDocument3 *iface,
663 DISPPARAMS* pDispParams,
665 EXCEPINFO* pExcepInfo,
668 domdoc *This = impl_from_IXMLDOMDocument3( iface );
672 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
673 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
675 hr = get_typeinfo(IXMLDOMDocument2_tid, &typeinfo);
678 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
679 pVarResult, pExcepInfo, puArgErr);
680 ITypeInfo_Release(typeinfo);
687 static HRESULT WINAPI domdoc_get_nodeName(
688 IXMLDOMDocument3 *iface,
691 domdoc *This = impl_from_IXMLDOMDocument3( iface );
692 return IXMLDOMNode_get_nodeName( IXMLDOMNode_from_impl(&This->node), name );
696 static HRESULT WINAPI domdoc_get_nodeValue(
697 IXMLDOMDocument3 *iface,
700 domdoc *This = impl_from_IXMLDOMDocument3( iface );
701 return IXMLDOMNode_get_nodeValue( IXMLDOMNode_from_impl(&This->node), value );
705 static HRESULT WINAPI domdoc_put_nodeValue(
706 IXMLDOMDocument3 *iface,
709 domdoc *This = impl_from_IXMLDOMDocument3( iface );
710 return IXMLDOMNode_put_nodeValue( IXMLDOMNode_from_impl(&This->node), value );
714 static HRESULT WINAPI domdoc_get_nodeType(
715 IXMLDOMDocument3 *iface,
718 domdoc *This = impl_from_IXMLDOMDocument3( iface );
719 return IXMLDOMNode_get_nodeType( IXMLDOMNode_from_impl(&This->node), type );
723 static HRESULT WINAPI domdoc_get_parentNode(
724 IXMLDOMDocument3 *iface,
725 IXMLDOMNode** parent )
727 domdoc *This = impl_from_IXMLDOMDocument3( iface );
728 return IXMLDOMNode_get_parentNode( IXMLDOMNode_from_impl(&This->node), parent );
732 static HRESULT WINAPI domdoc_get_childNodes(
733 IXMLDOMDocument3 *iface,
734 IXMLDOMNodeList** childList )
736 domdoc *This = impl_from_IXMLDOMDocument3( iface );
737 return IXMLDOMNode_get_childNodes( IXMLDOMNode_from_impl(&This->node), childList );
741 static HRESULT WINAPI domdoc_get_firstChild(
742 IXMLDOMDocument3 *iface,
743 IXMLDOMNode** firstChild )
745 domdoc *This = impl_from_IXMLDOMDocument3( iface );
746 return IXMLDOMNode_get_firstChild( IXMLDOMNode_from_impl(&This->node), firstChild );
750 static HRESULT WINAPI domdoc_get_lastChild(
751 IXMLDOMDocument3 *iface,
752 IXMLDOMNode** lastChild )
754 domdoc *This = impl_from_IXMLDOMDocument3( iface );
755 return IXMLDOMNode_get_lastChild( IXMLDOMNode_from_impl(&This->node), lastChild );
759 static HRESULT WINAPI domdoc_get_previousSibling(
760 IXMLDOMDocument3 *iface,
761 IXMLDOMNode** previousSibling )
763 domdoc *This = impl_from_IXMLDOMDocument3( iface );
764 return IXMLDOMNode_get_previousSibling( IXMLDOMNode_from_impl(&This->node), previousSibling );
768 static HRESULT WINAPI domdoc_get_nextSibling(
769 IXMLDOMDocument3 *iface,
770 IXMLDOMNode** nextSibling )
772 domdoc *This = impl_from_IXMLDOMDocument3( iface );
773 return IXMLDOMNode_get_nextSibling( IXMLDOMNode_from_impl(&This->node), nextSibling );
777 static HRESULT WINAPI domdoc_get_attributes(
778 IXMLDOMDocument3 *iface,
779 IXMLDOMNamedNodeMap** attributeMap )
781 domdoc *This = impl_from_IXMLDOMDocument3( iface );
782 return IXMLDOMNode_get_attributes( IXMLDOMNode_from_impl(&This->node), attributeMap );
786 static HRESULT WINAPI domdoc_insertBefore(
787 IXMLDOMDocument3 *iface,
788 IXMLDOMNode* newChild,
790 IXMLDOMNode** outNewChild )
792 domdoc *This = impl_from_IXMLDOMDocument3( iface );
793 return IXMLDOMNode_insertBefore( IXMLDOMNode_from_impl(&This->node), newChild, refChild, outNewChild );
797 static HRESULT WINAPI domdoc_replaceChild(
798 IXMLDOMDocument3 *iface,
799 IXMLDOMNode* newChild,
800 IXMLDOMNode* oldChild,
801 IXMLDOMNode** outOldChild)
803 domdoc *This = impl_from_IXMLDOMDocument3( iface );
804 return IXMLDOMNode_replaceChild( IXMLDOMNode_from_impl(&This->node), newChild, oldChild, outOldChild );
808 static HRESULT WINAPI domdoc_removeChild(
809 IXMLDOMDocument3 *iface,
810 IXMLDOMNode* childNode,
811 IXMLDOMNode** oldChild)
813 domdoc *This = impl_from_IXMLDOMDocument3( iface );
814 return IXMLDOMNode_removeChild( IXMLDOMNode_from_impl(&This->node), childNode, oldChild );
818 static HRESULT WINAPI domdoc_appendChild(
819 IXMLDOMDocument3 *iface,
820 IXMLDOMNode* newChild,
821 IXMLDOMNode** outNewChild)
823 domdoc *This = impl_from_IXMLDOMDocument3( iface );
824 return IXMLDOMNode_appendChild( IXMLDOMNode_from_impl(&This->node), newChild, outNewChild );
828 static HRESULT WINAPI domdoc_hasChildNodes(
829 IXMLDOMDocument3 *iface,
830 VARIANT_BOOL* hasChild)
832 domdoc *This = impl_from_IXMLDOMDocument3( iface );
833 return IXMLDOMNode_hasChildNodes( IXMLDOMNode_from_impl(&This->node), hasChild );
837 static HRESULT WINAPI domdoc_get_ownerDocument(
838 IXMLDOMDocument3 *iface,
839 IXMLDOMDocument** DOMDocument)
841 domdoc *This = impl_from_IXMLDOMDocument3( iface );
842 return IXMLDOMNode_get_ownerDocument( IXMLDOMNode_from_impl(&This->node), DOMDocument );
846 static HRESULT WINAPI domdoc_cloneNode(
847 IXMLDOMDocument3 *iface,
849 IXMLDOMNode** cloneRoot)
851 domdoc *This = impl_from_IXMLDOMDocument3( iface );
852 return IXMLDOMNode_cloneNode( IXMLDOMNode_from_impl(&This->node), deep, cloneRoot );
856 static HRESULT WINAPI domdoc_get_nodeTypeString(
857 IXMLDOMDocument3 *iface,
860 domdoc *This = impl_from_IXMLDOMDocument3( iface );
861 return IXMLDOMNode_get_nodeTypeString( IXMLDOMNode_from_impl(&This->node), nodeType );
865 static HRESULT WINAPI domdoc_get_text(
866 IXMLDOMDocument3 *iface,
869 domdoc *This = impl_from_IXMLDOMDocument3( iface );
870 return IXMLDOMNode_get_text( IXMLDOMNode_from_impl(&This->node), text );
874 static HRESULT WINAPI domdoc_put_text(
875 IXMLDOMDocument3 *iface,
878 domdoc *This = impl_from_IXMLDOMDocument3( iface );
879 return IXMLDOMNode_put_text( IXMLDOMNode_from_impl(&This->node), text );
883 static HRESULT WINAPI domdoc_get_specified(
884 IXMLDOMDocument3 *iface,
885 VARIANT_BOOL* isSpecified )
887 domdoc *This = impl_from_IXMLDOMDocument3( iface );
888 return IXMLDOMNode_get_specified( IXMLDOMNode_from_impl(&This->node), isSpecified );
892 static HRESULT WINAPI domdoc_get_definition(
893 IXMLDOMDocument3 *iface,
894 IXMLDOMNode** definitionNode )
896 domdoc *This = impl_from_IXMLDOMDocument3( iface );
897 return IXMLDOMNode_get_definition( IXMLDOMNode_from_impl(&This->node), definitionNode );
901 static HRESULT WINAPI domdoc_get_nodeTypedValue(
902 IXMLDOMDocument3 *iface,
903 VARIANT* typedValue )
905 domdoc *This = impl_from_IXMLDOMDocument3( iface );
906 return IXMLDOMNode_get_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
909 static HRESULT WINAPI domdoc_put_nodeTypedValue(
910 IXMLDOMDocument3 *iface,
913 domdoc *This = impl_from_IXMLDOMDocument3( iface );
914 return IXMLDOMNode_put_nodeTypedValue( IXMLDOMNode_from_impl(&This->node), typedValue );
918 static HRESULT WINAPI domdoc_get_dataType(
919 IXMLDOMDocument3 *iface,
920 VARIANT* dataTypeName )
922 domdoc *This = impl_from_IXMLDOMDocument3( iface );
923 return IXMLDOMNode_get_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
927 static HRESULT WINAPI domdoc_put_dataType(
928 IXMLDOMDocument3 *iface,
931 domdoc *This = impl_from_IXMLDOMDocument3( iface );
932 return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), dataTypeName );
936 static HRESULT WINAPI domdoc_get_xml(
937 IXMLDOMDocument3 *iface,
940 domdoc *This = impl_from_IXMLDOMDocument3( iface );
941 return IXMLDOMNode_get_xml( IXMLDOMNode_from_impl(&This->node), xmlString );
945 static HRESULT WINAPI domdoc_transformNode(
946 IXMLDOMDocument3 *iface,
947 IXMLDOMNode* styleSheet,
950 domdoc *This = impl_from_IXMLDOMDocument3( iface );
951 return IXMLDOMNode_transformNode( IXMLDOMNode_from_impl(&This->node), styleSheet, xmlString );
955 static HRESULT WINAPI domdoc_selectNodes(
956 IXMLDOMDocument3 *iface,
958 IXMLDOMNodeList** resultList )
960 domdoc *This = impl_from_IXMLDOMDocument3( iface );
961 return IXMLDOMNode_selectNodes( IXMLDOMNode_from_impl(&This->node), queryString, resultList );
965 static HRESULT WINAPI domdoc_selectSingleNode(
966 IXMLDOMDocument3 *iface,
968 IXMLDOMNode** resultNode )
970 domdoc *This = impl_from_IXMLDOMDocument3( iface );
971 return IXMLDOMNode_selectSingleNode( IXMLDOMNode_from_impl(&This->node), queryString, resultNode );
975 static HRESULT WINAPI domdoc_get_parsed(
976 IXMLDOMDocument3 *iface,
977 VARIANT_BOOL* isParsed )
979 domdoc *This = impl_from_IXMLDOMDocument3( iface );
980 return IXMLDOMNode_get_parsed( IXMLDOMNode_from_impl(&This->node), isParsed );
984 static HRESULT WINAPI domdoc_get_namespaceURI(
985 IXMLDOMDocument3 *iface,
988 domdoc *This = impl_from_IXMLDOMDocument3( iface );
989 return IXMLDOMNode_get_namespaceURI( IXMLDOMNode_from_impl(&This->node), namespaceURI );
993 static HRESULT WINAPI domdoc_get_prefix(
994 IXMLDOMDocument3 *iface,
997 domdoc *This = impl_from_IXMLDOMDocument3( iface );
998 return IXMLDOMNode_get_prefix( IXMLDOMNode_from_impl(&This->node), prefixString );
1002 static HRESULT WINAPI domdoc_get_baseName(
1003 IXMLDOMDocument3 *iface,
1006 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1007 return IXMLDOMNode_get_baseName( IXMLDOMNode_from_impl(&This->node), nameString );
1011 static HRESULT WINAPI domdoc_transformNodeToObject(
1012 IXMLDOMDocument3 *iface,
1013 IXMLDOMNode* stylesheet,
1014 VARIANT outputObject)
1016 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1017 return IXMLDOMNode_transformNodeToObject( IXMLDOMNode_from_impl(&This->node), stylesheet, outputObject );
1021 static HRESULT WINAPI domdoc_get_doctype(
1022 IXMLDOMDocument3 *iface,
1023 IXMLDOMDocumentType** documentType )
1025 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1026 FIXME("(%p)\n", This);
1031 static HRESULT WINAPI domdoc_get_implementation(
1032 IXMLDOMDocument3 *iface,
1033 IXMLDOMImplementation** impl )
1035 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1037 TRACE("(%p)->(%p)\n", This, impl);
1040 return E_INVALIDARG;
1042 *impl = (IXMLDOMImplementation*)create_doc_Implementation();
1047 static HRESULT WINAPI domdoc_get_documentElement(
1048 IXMLDOMDocument3 *iface,
1049 IXMLDOMElement** DOMElement )
1051 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1052 xmlDocPtr xmldoc = NULL;
1053 xmlNodePtr root = NULL;
1054 IXMLDOMNode *element_node;
1057 TRACE("(%p)->(%p)\n", This, DOMElement);
1060 return E_INVALIDARG;
1064 xmldoc = get_doc( This );
1066 root = xmlDocGetRootElement( xmldoc );
1070 element_node = create_node( root );
1071 if(!element_node) return S_FALSE;
1073 hr = IXMLDOMNode_QueryInterface(element_node, &IID_IXMLDOMElement, (LPVOID*)DOMElement);
1074 IXMLDOMNode_Release(element_node);
1080 static HRESULT WINAPI domdoc_put_documentElement(
1081 IXMLDOMDocument3 *iface,
1082 IXMLDOMElement* DOMElement )
1084 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1085 IXMLDOMNode *elementNode;
1090 TRACE("(%p)->(%p)\n", This, DOMElement);
1092 hr = IXMLDOMElement_QueryInterface( DOMElement, &IID_IXMLDOMNode, (void**)&elementNode );
1096 xmlNode = impl_from_IXMLDOMNode( elementNode );
1098 if(!xmlNode->node->parent)
1099 if(xmldoc_remove_orphan(xmlNode->node->doc, xmlNode->node) != S_OK)
1100 WARN("%p is not an orphan of %p\n", xmlNode->node->doc, xmlNode->node);
1102 oldRoot = xmlDocSetRootElement( get_doc(This), xmlNode->node);
1103 IXMLDOMNode_Release( elementNode );
1106 xmldoc_add_orphan(oldRoot->doc, oldRoot);
1112 static HRESULT WINAPI domdoc_createElement(
1113 IXMLDOMDocument3 *iface,
1115 IXMLDOMElement** element )
1117 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1122 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagname), element);
1124 if (!element || !tagname) return E_INVALIDARG;
1126 V_VT(&type) = VT_I1;
1127 V_I1(&type) = NODE_ELEMENT;
1129 hr = IXMLDOMDocument3_createNode(iface, type, tagname, NULL, &node);
1132 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)element);
1133 IXMLDOMNode_Release(node);
1140 static HRESULT WINAPI domdoc_createDocumentFragment(
1141 IXMLDOMDocument3 *iface,
1142 IXMLDOMDocumentFragment** frag )
1144 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1149 TRACE("(%p)->(%p)\n", This, frag);
1151 if (!frag) return E_INVALIDARG;
1155 V_VT(&type) = VT_I1;
1156 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
1158 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1161 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocumentFragment, (void**)frag);
1162 IXMLDOMNode_Release(node);
1169 static HRESULT WINAPI domdoc_createTextNode(
1170 IXMLDOMDocument3 *iface,
1172 IXMLDOMText** text )
1174 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1179 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), text);
1181 if (!text) return E_INVALIDARG;
1185 V_VT(&type) = VT_I1;
1186 V_I1(&type) = NODE_TEXT;
1188 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1191 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)text);
1192 IXMLDOMNode_Release(node);
1193 hr = IXMLDOMText_put_data(*text, data);
1200 static HRESULT WINAPI domdoc_createComment(
1201 IXMLDOMDocument3 *iface,
1203 IXMLDOMComment** comment )
1205 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1210 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), comment);
1212 if (!comment) return E_INVALIDARG;
1216 V_VT(&type) = VT_I1;
1217 V_I1(&type) = NODE_COMMENT;
1219 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1222 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)comment);
1223 IXMLDOMNode_Release(node);
1224 hr = IXMLDOMComment_put_data(*comment, data);
1231 static HRESULT WINAPI domdoc_createCDATASection(
1232 IXMLDOMDocument3 *iface,
1234 IXMLDOMCDATASection** cdata )
1236 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1241 TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), cdata);
1243 if (!cdata) return E_INVALIDARG;
1247 V_VT(&type) = VT_I1;
1248 V_I1(&type) = NODE_CDATA_SECTION;
1250 hr = IXMLDOMDocument3_createNode(iface, type, NULL, NULL, &node);
1253 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)cdata);
1254 IXMLDOMNode_Release(node);
1255 hr = IXMLDOMCDATASection_put_data(*cdata, data);
1262 static HRESULT WINAPI domdoc_createProcessingInstruction(
1263 IXMLDOMDocument3 *iface,
1266 IXMLDOMProcessingInstruction** pi )
1268 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1273 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(target), debugstr_w(data), pi);
1275 if (!pi) return E_INVALIDARG;
1279 V_VT(&type) = VT_I1;
1280 V_I1(&type) = NODE_PROCESSING_INSTRUCTION;
1282 hr = IXMLDOMDocument3_createNode(iface, type, target, NULL, &node);
1287 /* this is to bypass check in ::put_data() that blocks "<?xml" PIs */
1288 V_VT(&v_data) = VT_BSTR;
1289 V_BSTR(&v_data) = data;
1291 hr = IXMLDOMNode_put_nodeValue( node, v_data );
1293 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)pi);
1294 IXMLDOMNode_Release(node);
1301 static HRESULT WINAPI domdoc_createAttribute(
1302 IXMLDOMDocument3 *iface,
1304 IXMLDOMAttribute** attribute )
1306 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1311 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), attribute);
1313 if (!attribute || !name) return E_INVALIDARG;
1315 V_VT(&type) = VT_I1;
1316 V_I1(&type) = NODE_ATTRIBUTE;
1318 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1321 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMAttribute, (void**)attribute);
1322 IXMLDOMNode_Release(node);
1329 static HRESULT WINAPI domdoc_createEntityReference(
1330 IXMLDOMDocument3 *iface,
1332 IXMLDOMEntityReference** entityref )
1334 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1339 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), entityref);
1341 if (!entityref) return E_INVALIDARG;
1345 V_VT(&type) = VT_I1;
1346 V_I1(&type) = NODE_ENTITY_REFERENCE;
1348 hr = IXMLDOMDocument3_createNode(iface, type, name, NULL, &node);
1351 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMEntityReference, (void**)entityref);
1352 IXMLDOMNode_Release(node);
1359 static HRESULT WINAPI domdoc_getElementsByTagName(
1360 IXMLDOMDocument3 *iface,
1362 IXMLDOMNodeList** resultList )
1364 static const WCHAR xpathformat[] =
1365 { '/','/','*','[','l','o','c','a','l','-','n','a','m','e','(',')','=','\'','%','s','\'',']',0 };
1366 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1369 TRACE("(%p)->(%s %p)\n", This, debugstr_w(tagName), resultList);
1371 if (tagName[0] == '*' && tagName[1] == 0)
1373 szPattern = heap_alloc(sizeof(WCHAR)*4);
1374 szPattern[0] = szPattern[1] = '/';
1380 szPattern = heap_alloc(sizeof(WCHAR)*(20+lstrlenW(tagName)+1));
1381 wsprintfW(szPattern, xpathformat, tagName);
1384 hr = queryresult_create((xmlNodePtr)get_doc(This), szPattern, resultList);
1385 heap_free(szPattern);
1390 static HRESULT get_node_type(VARIANT Type, DOMNodeType * type)
1396 hr = VariantChangeType(&tmp, &Type, 0, VT_I4);
1398 return E_INVALIDARG;
1405 static HRESULT WINAPI domdoc_createNode(
1406 IXMLDOMDocument3 *iface,
1410 IXMLDOMNode** node )
1412 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1413 DOMNodeType node_type;
1418 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(namespaceURI), node);
1420 if(!node) return E_INVALIDARG;
1422 if(namespaceURI && namespaceURI[0])
1423 FIXME("nodes with namespaces currently not supported.\n");
1425 hr = get_node_type(Type, &node_type);
1426 if(FAILED(hr)) return hr;
1428 TRACE("node_type %d\n", node_type);
1430 /* exit earlier for types that need name */
1434 case NODE_ATTRIBUTE:
1435 case NODE_ENTITY_REFERENCE:
1436 case NODE_PROCESSING_INSTRUCTION:
1437 if (!name || *name == 0) return E_FAIL;
1442 xml_name = xmlChar_from_wchar(name);
1447 xmlnode = xmlNewDocNode(get_doc(This), NULL, xml_name, NULL);
1449 case NODE_ATTRIBUTE:
1450 xmlnode = (xmlNodePtr)xmlNewDocProp(get_doc(This), xml_name, NULL);
1453 xmlnode = (xmlNodePtr)xmlNewDocText(get_doc(This), NULL);
1455 case NODE_CDATA_SECTION:
1456 xmlnode = xmlNewCDataBlock(get_doc(This), NULL, 0);
1458 case NODE_ENTITY_REFERENCE:
1459 xmlnode = xmlNewReference(get_doc(This), xml_name);
1461 case NODE_PROCESSING_INSTRUCTION:
1462 #ifdef HAVE_XMLNEWDOCPI
1463 xmlnode = xmlNewDocPI(get_doc(This), xml_name, NULL);
1465 FIXME("xmlNewDocPI() not supported, use libxml2 2.6.15 or greater\n");
1470 xmlnode = xmlNewDocComment(get_doc(This), NULL);
1472 case NODE_DOCUMENT_FRAGMENT:
1473 xmlnode = xmlNewDocFragment(get_doc(This));
1475 /* unsupported types */
1477 case NODE_DOCUMENT_TYPE:
1480 heap_free(xml_name);
1481 return E_INVALIDARG;
1483 FIXME("unhandled node type %d\n", node_type);
1488 *node = create_node(xmlnode);
1489 heap_free(xml_name);
1493 TRACE("created node (%d, %p, %p)\n", node_type, *node, xmlnode);
1494 xmldoc_add_orphan(xmlnode->doc, xmlnode);
1501 static HRESULT WINAPI domdoc_nodeFromID(
1502 IXMLDOMDocument3 *iface,
1504 IXMLDOMNode** node )
1506 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1507 FIXME("(%p)->(%s %p)\n", This, debugstr_w(idString), node);
1511 static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len)
1516 xmldoc = doparse( ptr, len, NULL );
1518 xmldoc->_private = create_priv();
1519 return attach_xmldoc(&This->node, xmldoc);
1525 static HRESULT doread( domdoc *This, LPWSTR filename )
1530 hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc);
1535 detach_bsc(This->bsc);
1541 static HRESULT WINAPI domdoc_load(
1542 IXMLDOMDocument3 *iface,
1544 VARIANT_BOOL* isSuccessful )
1546 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1547 LPWSTR filename = NULL;
1548 HRESULT hr = S_FALSE;
1549 IXMLDOMDocument3 *pNewDoc = NULL;
1550 IStream *pStream = NULL;
1553 TRACE("(%p)->type %d\n", This, V_VT(&xmlSource) );
1555 *isSuccessful = VARIANT_FALSE;
1557 assert( &This->node );
1559 switch( V_VT(&xmlSource) )
1562 filename = V_BSTR(&xmlSource);
1565 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IXMLDOMDocument3, (void**)&pNewDoc);
1570 domdoc *newDoc = impl_from_IXMLDOMDocument3( pNewDoc );
1571 xmldoc = xmlCopyDoc(get_doc(newDoc), 1);
1572 hr = attach_xmldoc(&This->node, xmldoc);
1575 *isSuccessful = VARIANT_TRUE;
1580 hr = IUnknown_QueryInterface(V_UNKNOWN(&xmlSource), &IID_IStream, (void**)&pStream);
1583 IPersistStream *pDocStream;
1584 hr = IUnknown_QueryInterface(iface, &IID_IPersistStream, (void**)&pDocStream);
1587 hr = IPersistStream_Load(pDocStream, pStream);
1588 IStream_Release(pStream);
1591 *isSuccessful = VARIANT_TRUE;
1593 TRACE("Using IStream to load Document\n");
1598 ERR("xmldoc_IPersistStream_Load failed (%d)\n", hr);
1603 ERR("QueryInterface IID_IPersistStream failed (%d)\n", hr);
1608 /* ISequentialStream */
1609 FIXME("Unknown type not supported (%d) (%p)(%p)\n", hr, pNewDoc, V_UNKNOWN(&xmlSource)->lpVtbl);
1613 FIXME("VT type not supported (%d)\n", V_VT(&xmlSource));
1616 TRACE("filename (%s)\n", debugstr_w(filename));
1620 hr = doread( This, filename );
1623 This->error = E_FAIL;
1626 hr = This->error = S_OK;
1627 *isSuccessful = VARIANT_TRUE;
1631 if(!filename || FAILED(hr)) {
1632 xmldoc = xmlNewDoc(NULL);
1633 xmldoc->_private = create_priv();
1634 hr = attach_xmldoc(&This->node, xmldoc);
1639 TRACE("ret (%d)\n", hr);
1645 static HRESULT WINAPI domdoc_get_readyState(
1646 IXMLDOMDocument3 *iface,
1649 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1650 FIXME("(%p)->(%p)\n", This, value);
1655 static HRESULT WINAPI domdoc_get_parseError(
1656 IXMLDOMDocument3 *iface,
1657 IXMLDOMParseError** errorObj )
1659 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1660 static const WCHAR err[] = {'e','r','r','o','r',0};
1661 BSTR error_string = NULL;
1663 FIXME("(%p)->(%p): creating a dummy parseError\n", iface, errorObj);
1666 error_string = SysAllocString(err);
1668 *errorObj = create_parseError(This->error, NULL, error_string, NULL, 0, 0, 0);
1669 if(!*errorObj) return E_OUTOFMEMORY;
1674 static HRESULT WINAPI domdoc_get_url(
1675 IXMLDOMDocument3 *iface,
1678 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1679 FIXME("(%p)->(%p)\n", This, urlString);
1684 static HRESULT WINAPI domdoc_get_async(
1685 IXMLDOMDocument3 *iface,
1686 VARIANT_BOOL* isAsync )
1688 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1690 TRACE("(%p)->(%p: %d)\n", This, isAsync, This->async);
1691 *isAsync = This->async;
1696 static HRESULT WINAPI domdoc_put_async(
1697 IXMLDOMDocument3 *iface,
1698 VARIANT_BOOL isAsync )
1700 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1702 TRACE("(%p)->(%d)\n", This, isAsync);
1703 This->async = isAsync;
1708 static HRESULT WINAPI domdoc_abort(
1709 IXMLDOMDocument3 *iface )
1711 domdoc *This = impl_from_IXMLDOMDocument3(iface);
1712 FIXME("%p\n", This);
1717 static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen )
1722 len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL );
1723 str = heap_alloc( len );
1726 WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL );
1732 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
1733 static HRESULT WINAPI domdoc_loadXML(
1734 IXMLDOMDocument3 *iface,
1736 VARIANT_BOOL* isSuccessful )
1738 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1739 xmlDocPtr xmldoc = NULL;
1740 HRESULT hr = S_FALSE, hr2;
1744 TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
1746 assert ( &This->node );
1750 *isSuccessful = VARIANT_FALSE;
1752 if ( bstrXML && bstr_to_utf8( bstrXML, &str, &len ) )
1754 xmldoc = doparse( str, len, "UTF-8" );
1757 This->error = E_FAIL;
1760 hr = This->error = S_OK;
1761 *isSuccessful = VARIANT_TRUE;
1762 TRACE("parsed document %p\n", xmldoc);
1767 xmldoc = xmlNewDoc(NULL);
1769 xmldoc->_private = create_priv();
1770 hr2 = attach_xmldoc( &This->node, xmldoc );
1777 static int XMLCALL domdoc_save_writecallback(void *ctx, const char *buffer,
1782 if(!WriteFile(ctx, buffer, len, &written, NULL))
1784 WARN("write error\n");
1791 static int XMLCALL domdoc_save_closecallback(void *ctx)
1793 return CloseHandle(ctx) ? 0 : -1;
1796 static HRESULT WINAPI domdoc_save(
1797 IXMLDOMDocument3 *iface,
1798 VARIANT destination )
1800 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1806 TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
1807 V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL);
1809 if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN)
1811 FIXME("Unhandled vt %d\n", V_VT(&destination));
1815 if(V_VT(&destination) == VT_UNKNOWN)
1817 IUnknown *pUnk = V_UNKNOWN(&destination);
1818 IXMLDOMDocument2 *pDocument;
1820 ret = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMDocument3, (void**)&pDocument);
1823 VARIANT_BOOL success;
1826 ret = IXMLDOMDocument3_get_xml(iface, &xml);
1829 ret = IXMLDOMDocument3_loadXML(pDocument, xml, &success);
1833 IXMLDOMDocument3_Release(pDocument);
1836 TRACE("ret %d\n", ret);
1841 handle = CreateFileW( V_BSTR(&destination), GENERIC_WRITE, 0,
1842 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1843 if( handle == INVALID_HANDLE_VALUE )
1845 WARN("failed to create file\n");
1849 /* disable top XML declaration */
1850 ctx = xmlSaveToIO(domdoc_save_writecallback, domdoc_save_closecallback,
1851 handle, NULL, XML_SAVE_NO_DECL);
1854 CloseHandle(handle);
1858 xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
1859 if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
1860 xmldoc_link_xmldecl(get_doc(This), xmldecl);
1862 /* will close file through close callback */
1868 static HRESULT WINAPI domdoc_get_validateOnParse(
1869 IXMLDOMDocument3 *iface,
1870 VARIANT_BOOL* isValidating )
1872 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1873 TRACE("(%p)->(%p: %d)\n", This, isValidating, This->validating);
1874 *isValidating = This->validating;
1879 static HRESULT WINAPI domdoc_put_validateOnParse(
1880 IXMLDOMDocument3 *iface,
1881 VARIANT_BOOL isValidating )
1883 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1884 TRACE("(%p)->(%d)\n", This, isValidating);
1885 This->validating = isValidating;
1890 static HRESULT WINAPI domdoc_get_resolveExternals(
1891 IXMLDOMDocument3 *iface,
1892 VARIANT_BOOL* isResolving )
1894 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1895 TRACE("(%p)->(%p: %d)\n", This, isResolving, This->resolving);
1896 *isResolving = This->resolving;
1901 static HRESULT WINAPI domdoc_put_resolveExternals(
1902 IXMLDOMDocument3 *iface,
1903 VARIANT_BOOL isResolving )
1905 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1906 TRACE("(%p)->(%d)\n", This, isResolving);
1907 This->resolving = isResolving;
1912 static HRESULT WINAPI domdoc_get_preserveWhiteSpace(
1913 IXMLDOMDocument3 *iface,
1914 VARIANT_BOOL* isPreserving )
1916 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1917 TRACE("(%p)->(%p: %d)\n", This, isPreserving, This->preserving);
1918 *isPreserving = This->preserving;
1923 static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
1924 IXMLDOMDocument3 *iface,
1925 VARIANT_BOOL isPreserving )
1927 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1928 TRACE("(%p)->(%d)\n", This, isPreserving);
1929 This->preserving = isPreserving;
1934 static HRESULT WINAPI domdoc_put_onReadyStateChange(
1935 IXMLDOMDocument3 *iface,
1936 VARIANT readyStateChangeSink )
1938 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1939 FIXME("%p\n", This);
1944 static HRESULT WINAPI domdoc_put_onDataAvailable(
1945 IXMLDOMDocument3 *iface,
1946 VARIANT onDataAvailableSink )
1948 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1949 FIXME("%p\n", This);
1953 static HRESULT WINAPI domdoc_put_onTransformNode(
1954 IXMLDOMDocument3 *iface,
1955 VARIANT onTransformNodeSink )
1957 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1958 FIXME("%p\n", This);
1962 static HRESULT WINAPI domdoc_get_namespaces(
1963 IXMLDOMDocument3* iface,
1964 IXMLDOMSchemaCollection** schemaCollection )
1966 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1967 FIXME("(%p)->(%p)\n", This, schemaCollection);
1971 static HRESULT WINAPI domdoc_get_schemas(
1972 IXMLDOMDocument3* iface,
1975 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1976 HRESULT hr = S_FALSE;
1977 IXMLDOMSchemaCollection *cur_schema = This->schema;
1979 TRACE("(%p)->(%p)\n", This, var1);
1981 VariantInit(var1); /* Test shows we don't call VariantClear here */
1982 V_VT(var1) = VT_NULL;
1986 hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
1988 V_VT(var1) = VT_DISPATCH;
1993 static HRESULT WINAPI domdoc_putref_schemas(
1994 IXMLDOMDocument3* iface,
1997 domdoc *This = impl_from_IXMLDOMDocument3( iface );
1998 HRESULT hr = E_FAIL;
1999 IXMLDOMSchemaCollection *new_schema = NULL;
2001 FIXME("(%p): semi-stub\n", This);
2005 hr = IUnknown_QueryInterface(V_UNKNOWN(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2009 hr = IDispatch_QueryInterface(V_DISPATCH(&var1), &IID_IXMLDOMSchemaCollection, (void**)&new_schema);
2018 WARN("Can't get schema from vt %x\n", V_VT(&var1));
2023 IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
2024 if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
2030 static HRESULT WINAPI domdoc_validate(
2031 IXMLDOMDocument3* iface,
2032 IXMLDOMParseError** err)
2034 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2035 FIXME("(%p)->(%p)\n", This, err);
2039 static HRESULT WINAPI domdoc_setProperty(
2040 IXMLDOMDocument3* iface,
2044 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2046 TRACE("(%p)->(%s)\n", This, debugstr_w(p));
2048 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2054 V_VT(&varStr) = VT_EMPTY;
2055 if (V_VT(&var) != VT_BSTR)
2057 if (FAILED(hr = VariantChangeType(&varStr, &var, 0, VT_BSTR)))
2059 bstr = V_BSTR(&varStr);
2062 bstr = V_BSTR(&var);
2065 if (lstrcmpiW(bstr, PropValueXPathW) == 0)
2066 This->bUseXPath = TRUE;
2067 else if (lstrcmpiW(bstr, PropValueXSLPatternW) == 0)
2068 This->bUseXPath = FALSE;
2072 VariantClear(&varStr);
2075 else if (lstrcmpiW(p, PropertyProhibitDTDW) == 0)
2078 FIXME("Ignoring property ProhibitDTD, value %d\n", V_BOOL(&var));
2081 else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0)
2083 if (V_VT(&var) == VT_BSTR)
2084 FIXME("Unsupported SelectionNamespaces: %s\n", wine_dbgstr_w(V_BSTR(&var)));
2088 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2092 static HRESULT WINAPI domdoc_getProperty(
2093 IXMLDOMDocument3* iface,
2097 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2099 TRACE("(%p)->(%p)\n", This, debugstr_w(p));
2102 return E_INVALIDARG;
2104 if (lstrcmpiW(p, PropertySelectionLanguageW) == 0)
2106 V_VT(var) = VT_BSTR;
2107 if (This->bUseXPath)
2108 V_BSTR(var) = SysAllocString(PropValueXPathW);
2110 V_BSTR(var) = SysAllocString(PropValueXSLPatternW);
2114 FIXME("Unknown property %s\n", wine_dbgstr_w(p));
2118 static HRESULT WINAPI domdoc_validateNode(
2119 IXMLDOMDocument3* iface,
2121 IXMLDOMParseError** error)
2123 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2124 FIXME("(%p)->(%p %p): stub\n", This, node, error);
2128 static HRESULT WINAPI domdoc_importNode(
2129 IXMLDOMDocument3* iface,
2132 IXMLDOMNode** clone)
2134 domdoc *This = impl_from_IXMLDOMDocument3( iface );
2135 FIXME("(%p)->(%p %d %p): stub\n", This, node, deep, clone);
2139 static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
2141 domdoc_QueryInterface,
2144 domdoc_GetTypeInfoCount,
2146 domdoc_GetIDsOfNames,
2148 domdoc_get_nodeName,
2149 domdoc_get_nodeValue,
2150 domdoc_put_nodeValue,
2151 domdoc_get_nodeType,
2152 domdoc_get_parentNode,
2153 domdoc_get_childNodes,
2154 domdoc_get_firstChild,
2155 domdoc_get_lastChild,
2156 domdoc_get_previousSibling,
2157 domdoc_get_nextSibling,
2158 domdoc_get_attributes,
2159 domdoc_insertBefore,
2160 domdoc_replaceChild,
2163 domdoc_hasChildNodes,
2164 domdoc_get_ownerDocument,
2166 domdoc_get_nodeTypeString,
2169 domdoc_get_specified,
2170 domdoc_get_definition,
2171 domdoc_get_nodeTypedValue,
2172 domdoc_put_nodeTypedValue,
2173 domdoc_get_dataType,
2174 domdoc_put_dataType,
2176 domdoc_transformNode,
2178 domdoc_selectSingleNode,
2180 domdoc_get_namespaceURI,
2182 domdoc_get_baseName,
2183 domdoc_transformNodeToObject,
2185 domdoc_get_implementation,
2186 domdoc_get_documentElement,
2187 domdoc_put_documentElement,
2188 domdoc_createElement,
2189 domdoc_createDocumentFragment,
2190 domdoc_createTextNode,
2191 domdoc_createComment,
2192 domdoc_createCDATASection,
2193 domdoc_createProcessingInstruction,
2194 domdoc_createAttribute,
2195 domdoc_createEntityReference,
2196 domdoc_getElementsByTagName,
2200 domdoc_get_readyState,
2201 domdoc_get_parseError,
2208 domdoc_get_validateOnParse,
2209 domdoc_put_validateOnParse,
2210 domdoc_get_resolveExternals,
2211 domdoc_put_resolveExternals,
2212 domdoc_get_preserveWhiteSpace,
2213 domdoc_put_preserveWhiteSpace,
2214 domdoc_put_onReadyStateChange,
2215 domdoc_put_onDataAvailable,
2216 domdoc_put_onTransformNode,
2217 domdoc_get_namespaces,
2219 domdoc_putref_schemas,
2223 domdoc_validateNode,
2227 /* xmldoc implementation of IObjectWithSite */
2228 static HRESULT WINAPI
2229 xmldoc_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
2231 domdoc *This = impl_from_IObjectWithSite(iface);
2232 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppvObject );
2236 xmldoc_ObjectWithSite_AddRef( IObjectWithSite* iface )
2238 domdoc *This = impl_from_IObjectWithSite(iface);
2239 return IXMLDocument_AddRef((IXMLDocument *)This);
2243 xmldoc_ObjectWithSite_Release( IObjectWithSite* iface )
2245 domdoc *This = impl_from_IObjectWithSite(iface);
2246 return IXMLDocument_Release((IXMLDocument *)This);
2249 static HRESULT WINAPI
2250 xmldoc_GetSite( IObjectWithSite *iface, REFIID iid, void ** ppvSite )
2252 domdoc *This = impl_from_IObjectWithSite(iface);
2254 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
2259 return IUnknown_QueryInterface( This->site, iid, ppvSite );
2262 static HRESULT WINAPI
2263 xmldoc_SetSite( IObjectWithSite *iface, IUnknown *punk )
2265 domdoc *This = impl_from_IObjectWithSite(iface);
2267 TRACE("(%p)->(%p)\n", iface, punk);
2273 IUnknown_Release( This->site );
2280 IUnknown_AddRef( punk );
2283 IUnknown_Release( This->site );
2290 static const IObjectWithSiteVtbl domdocObjectSite =
2292 xmldoc_ObjectWithSite_QueryInterface,
2293 xmldoc_ObjectWithSite_AddRef,
2294 xmldoc_ObjectWithSite_Release,
2299 static HRESULT WINAPI xmldoc_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
2301 domdoc *This = impl_from_IObjectSafety(iface);
2302 return IXMLDocument_QueryInterface( (IXMLDocument *)This, riid, ppv );
2305 static ULONG WINAPI xmldoc_Safety_AddRef(IObjectSafety *iface)
2307 domdoc *This = impl_from_IObjectSafety(iface);
2308 return IXMLDocument_AddRef((IXMLDocument *)This);
2311 static ULONG WINAPI xmldoc_Safety_Release(IObjectSafety *iface)
2313 domdoc *This = impl_from_IObjectSafety(iface);
2314 return IXMLDocument_Release((IXMLDocument *)This);
2317 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
2319 static HRESULT WINAPI xmldoc_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2320 DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
2322 domdoc *This = impl_from_IObjectSafety(iface);
2324 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
2326 if(!pdwSupportedOptions || !pdwEnabledOptions)
2329 *pdwSupportedOptions = SAFETY_SUPPORTED_OPTIONS;
2330 *pdwEnabledOptions = This->safeopt;
2335 static HRESULT WINAPI xmldoc_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
2336 DWORD dwOptionSetMask, DWORD dwEnabledOptions)
2338 domdoc *This = impl_from_IObjectSafety(iface);
2339 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
2341 if ((dwOptionSetMask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
2344 This->safeopt = dwEnabledOptions & dwOptionSetMask & SAFETY_SUPPORTED_OPTIONS;
2348 static const IObjectSafetyVtbl domdocObjectSafetyVtbl = {
2349 xmldoc_Safety_QueryInterface,
2350 xmldoc_Safety_AddRef,
2351 xmldoc_Safety_Release,
2352 xmldoc_Safety_GetInterfaceSafetyOptions,
2353 xmldoc_Safety_SetInterfaceSafetyOptions
2357 static const tid_t domdoc_iface_tids[] = {
2359 IXMLDOMDocument_tid,
2360 IXMLDOMDocument2_tid,
2363 static dispex_static_data_t domdoc_dispex = {
2365 IXMLDOMDocument2_tid,
2370 HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
2374 doc = heap_alloc( sizeof (*doc) );
2376 return E_OUTOFMEMORY;
2378 doc->lpVtbl = &domdoc_vtbl;
2379 doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable;
2380 doc->lpvtblIObjectWithSite = &domdocObjectSite;
2381 doc->lpvtblIObjectSafety = &domdocObjectSafetyVtbl;
2382 doc->lpvtblISupportErrorInfo = &support_error_vtbl;
2384 doc->async = VARIANT_TRUE;
2385 doc->validating = 0;
2387 doc->preserving = 0;
2388 doc->bUseXPath = FALSE;
2396 init_xmlnode(&doc->node, (xmlNodePtr)xmldoc, (IUnknown*)&doc->lpVtbl, &domdoc_dispex);
2398 *document = (IXMLDOMDocument3*)&doc->lpVtbl;
2400 TRACE("returning iface %p\n", *document);
2404 HRESULT DOMDocument_create(IUnknown *pUnkOuter, void **ppObj)
2409 TRACE("(%p, %p)\n", pUnkOuter, ppObj);
2411 xmldoc = xmlNewDoc(NULL);
2413 return E_OUTOFMEMORY;
2415 xmldoc->_private = create_priv();
2417 hr = DOMDocument_create_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
2424 IUnknown* create_domdoc( xmlNodePtr document )
2429 TRACE("(%p)\n", document);
2431 hr = DOMDocument_create_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
2440 HRESULT DOMDocument_create(IUnknown *pUnkOuter, void **ppObj)
2442 MESSAGE("This program tried to use a DOMDocument object, but\n"
2443 "libxml2 support was not present at compile time.\n");