diff --git a/dlls/msxml3/Makefile.in b/dlls/msxml3/Makefile.in index ce989635fb2..16a21792cb2 100644 --- a/dlls/msxml3/Makefile.in +++ b/dlls/msxml3/Makefile.in @@ -16,6 +16,7 @@ C_SRCS = \ domdoc.c \ domimpl.c \ element.c \ + entityref.c \ factory.c \ main.c \ node.c \ diff --git a/dlls/msxml3/domdoc.c b/dlls/msxml3/domdoc.c index 666e7d810de..1bfeab134e5 100644 --- a/dlls/msxml3/domdoc.c +++ b/dlls/msxml3/domdoc.c @@ -1074,8 +1074,29 @@ static HRESULT WINAPI domdoc_createEntityReference( BSTR name, IXMLDOMEntityReference** entityRef ) { - FIXME("\n"); - return E_NOTIMPL; + domdoc *This = impl_from_IXMLDOMDocument2( iface ); + xmlNodePtr xmlnode; + xmlChar *xml_name; + + TRACE("%p\n", iface); + + if(!entityRef) + return E_INVALIDARG; + + *entityRef = NULL; + + xml_name = xmlChar_from_wchar((WCHAR*)name); + xmlnode = xmlNewReference(get_doc( This ), xml_name ); + HeapFree(GetProcessHeap(), 0, xml_name); + + if(!xmlnode) + return E_FAIL; + + xmlnode->doc = get_doc( This ); + + *entityRef = (IXMLDOMEntityReference*)create_doc_entity_ref(xmlnode); + + return S_OK; } diff --git a/dlls/msxml3/entityref.c b/dlls/msxml3/entityref.c new file mode 100644 index 00000000000..9671fa13aba --- /dev/null +++ b/dlls/msxml3/entityref.c @@ -0,0 +1,511 @@ +/* + * DOM Entity Reference implementation + * + * Copyright 2007 Alistair Leslie-Hughes + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include "config.h" + +#include +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "ole2.h" +#include "msxml2.h" + +#include "msxml_private.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msxml); + +#ifdef HAVE_LIBXML2 + +typedef struct _entityref +{ + const struct IXMLDOMEntityReferenceVtbl *lpVtbl; + LONG ref; + IUnknown *node_unk; + IXMLDOMNode *node; +} entityref; + +static inline entityref *impl_from_IXMLDOMEntityReference( IXMLDOMEntityReference *iface ) +{ + return (entityref *)((char*)iface - FIELD_OFFSET(entityref, lpVtbl)); +} + +static HRESULT WINAPI entityref_QueryInterface( + IXMLDOMEntityReference *iface, + REFIID riid, + void** ppvObject ) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject); + + if ( IsEqualGUID( riid, &IID_IXMLDOMEntityReference ) || + IsEqualGUID( riid, &IID_IUnknown ) ) + { + *ppvObject = iface; + } + else if ( IsEqualGUID( riid, &IID_IDispatch ) || + IsEqualGUID( riid, &IID_IXMLDOMNode ) ) + { + return IUnknown_QueryInterface(This->node_unk, riid, ppvObject); + } + else + { + FIXME("Unsupported inteferace %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; + } + + IXMLDOMEntityReference_AddRef( iface ); + + return S_OK; +} + +static ULONG WINAPI entityref_AddRef( + IXMLDOMEntityReference *iface ) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return InterlockedIncrement( &This->ref ); +} + +static ULONG WINAPI entityref_Release( + IXMLDOMEntityReference *iface ) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + ULONG ref; + + ref = InterlockedDecrement( &This->ref ); + if ( ref == 0 ) + { + IUnknown_Release( This->node_unk ); + HeapFree( GetProcessHeap(), 0, This ); + } + + return ref; +} + +static HRESULT WINAPI entityref_GetTypeInfoCount( + IXMLDOMEntityReference *iface, + UINT* pctinfo ) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI entityref_GetTypeInfo( + IXMLDOMEntityReference *iface, + UINT iTInfo, LCID lcid, + ITypeInfo** ppTInfo ) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI entityref_GetIDsOfNames( + IXMLDOMEntityReference *iface, + REFIID riid, LPOLESTR* rgszNames, + UINT cNames, LCID lcid, DISPID* rgDispId ) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI entityref_Invoke( + IXMLDOMEntityReference *iface, + DISPID dispIdMember, REFIID riid, LCID lcid, + WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, UINT* puArgErr ) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI entityref_get_nodeName( + IXMLDOMEntityReference *iface, + BSTR* p ) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_nodeName( This->node, p ); +} + +static HRESULT WINAPI entityref_get_nodeValue( + IXMLDOMEntityReference *iface, + VARIANT* var1 ) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_nodeValue( This->node, var1 ); +} + +static HRESULT WINAPI entityref_put_nodeValue( + IXMLDOMEntityReference *iface, + VARIANT var1 ) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_put_nodeValue( This->node, var1 ); +} + +static HRESULT WINAPI entityref_get_nodeType( + IXMLDOMEntityReference *iface, + DOMNodeType* domNodeType ) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_nodeType( This->node, domNodeType ); +} + +static HRESULT WINAPI entityref_get_parentNode( + IXMLDOMEntityReference *iface, + IXMLDOMNode** parent ) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_parentNode( This->node, parent ); +} + +static HRESULT WINAPI entityref_get_childNodes( + IXMLDOMEntityReference *iface, + IXMLDOMNodeList** outList) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_childNodes( This->node, outList ); +} + +static HRESULT WINAPI entityref_get_firstChild( + IXMLDOMEntityReference *iface, + IXMLDOMNode** domNode) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_firstChild( This->node, domNode ); +} + +static HRESULT WINAPI entityref_get_lastChild( + IXMLDOMEntityReference *iface, + IXMLDOMNode** domNode) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_lastChild( This->node, domNode ); +} + +static HRESULT WINAPI entityref_get_previousSibling( + IXMLDOMEntityReference *iface, + IXMLDOMNode** domNode) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_previousSibling( This->node, domNode ); +} + +static HRESULT WINAPI entityref_get_nextSibling( + IXMLDOMEntityReference *iface, + IXMLDOMNode** domNode) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_nextSibling( This->node, domNode ); +} + +static HRESULT WINAPI entityref_get_attributes( + IXMLDOMEntityReference *iface, + IXMLDOMNamedNodeMap** attributeMap) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_attributes( This->node, attributeMap ); +} + +static HRESULT WINAPI entityref_insertBefore( + IXMLDOMEntityReference *iface, + IXMLDOMNode* newNode, VARIANT var1, + IXMLDOMNode** outOldNode) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_insertBefore( This->node, newNode, var1, outOldNode ); +} + +static HRESULT WINAPI entityref_replaceChild( + IXMLDOMEntityReference *iface, + IXMLDOMNode* newNode, + IXMLDOMNode* oldNode, + IXMLDOMNode** outOldNode) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_replaceChild( This->node, newNode, oldNode, outOldNode ); +} + +static HRESULT WINAPI entityref_removeChild( + IXMLDOMEntityReference *iface, + IXMLDOMNode* domNode, IXMLDOMNode** oldNode) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_removeChild( This->node, domNode, oldNode ); +} + +static HRESULT WINAPI entityref_appendChild( + IXMLDOMEntityReference *iface, + IXMLDOMNode* newNode, IXMLDOMNode** outNewNode) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_appendChild( This->node, newNode, outNewNode ); +} + +static HRESULT WINAPI entityref_hasChildNodes( + IXMLDOMEntityReference *iface, + VARIANT_BOOL* pbool) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_hasChildNodes( This->node, pbool ); +} + +static HRESULT WINAPI entityref_get_ownerDocument( + IXMLDOMEntityReference *iface, + IXMLDOMDocument** domDocument) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_ownerDocument( This->node, domDocument ); +} + +static HRESULT WINAPI entityref_cloneNode( + IXMLDOMEntityReference *iface, + VARIANT_BOOL pbool, IXMLDOMNode** outNode) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_cloneNode( This->node, pbool, outNode ); +} + +static HRESULT WINAPI entityref_get_nodeTypeString( + IXMLDOMEntityReference *iface, + BSTR* p) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_nodeTypeString( This->node, p ); +} + +static HRESULT WINAPI entityref_get_text( + IXMLDOMEntityReference *iface, + BSTR* p) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_text( This->node, p ); +} + +static HRESULT WINAPI entityref_put_text( + IXMLDOMEntityReference *iface, + BSTR p) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_put_text( This->node, p ); +} + +static HRESULT WINAPI entityref_get_specified( + IXMLDOMEntityReference *iface, + VARIANT_BOOL* pbool) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_specified( This->node, pbool ); +} + +static HRESULT WINAPI entityref_get_definition( + IXMLDOMEntityReference *iface, + IXMLDOMNode** domNode) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_definition( This->node, domNode ); +} + +static HRESULT WINAPI entityref_get_nodeTypedValue( + IXMLDOMEntityReference *iface, + VARIANT* var1) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_nodeTypedValue( This->node, var1 ); +} + +static HRESULT WINAPI entityref_put_nodeTypedValue( + IXMLDOMEntityReference *iface, + VARIANT var1) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_put_nodeTypedValue( This->node, var1 ); +} + +static HRESULT WINAPI entityref_get_dataType( + IXMLDOMEntityReference *iface, + VARIANT* var1) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_dataType( This->node, var1 ); +} + +static HRESULT WINAPI entityref_put_dataType( + IXMLDOMEntityReference *iface, + BSTR p) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_put_dataType( This->node, p ); +} + +static HRESULT WINAPI entityref_get_xml( + IXMLDOMEntityReference *iface, + BSTR* p) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_xml( This->node, p ); +} + +static HRESULT WINAPI entityref_transformNode( + IXMLDOMEntityReference *iface, + IXMLDOMNode* domNode, BSTR* p) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_transformNode( This->node, domNode, p ); +} + +static HRESULT WINAPI entityref_selectNodes( + IXMLDOMEntityReference *iface, + BSTR p, IXMLDOMNodeList** outList) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_selectNodes( This->node, p, outList ); +} + +static HRESULT WINAPI entityref_selectSingleNode( + IXMLDOMEntityReference *iface, + BSTR p, IXMLDOMNode** outNode) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_selectSingleNode( This->node, p, outNode ); +} + +static HRESULT WINAPI entityref_get_parsed( + IXMLDOMEntityReference *iface, + VARIANT_BOOL* pbool) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_parsed( This->node, pbool ); +} + +static HRESULT WINAPI entityref_get_namespaceURI( + IXMLDOMEntityReference *iface, + BSTR* p) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_namespaceURI( This->node, p ); +} + +static HRESULT WINAPI entityref_get_prefix( + IXMLDOMEntityReference *iface, + BSTR* p) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_prefix( This->node, p ); +} + +static HRESULT WINAPI entityref_get_baseName( + IXMLDOMEntityReference *iface, + BSTR* p) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_get_baseName( This->node, p ); +} + +static HRESULT WINAPI entityref_transformNodeToObject( + IXMLDOMEntityReference *iface, + IXMLDOMNode* domNode, VARIANT var1) +{ + entityref *This = impl_from_IXMLDOMEntityReference( iface ); + return IXMLDOMNode_transformNodeToObject( This->node, domNode, var1 ); +} + +static const struct IXMLDOMEntityReferenceVtbl entityref_vtbl = +{ + entityref_QueryInterface, + entityref_AddRef, + entityref_Release, + entityref_GetTypeInfoCount, + entityref_GetTypeInfo, + entityref_GetIDsOfNames, + entityref_Invoke, + entityref_get_nodeName, + entityref_get_nodeValue, + entityref_put_nodeValue, + entityref_get_nodeType, + entityref_get_parentNode, + entityref_get_childNodes, + entityref_get_firstChild, + entityref_get_lastChild, + entityref_get_previousSibling, + entityref_get_nextSibling, + entityref_get_attributes, + entityref_insertBefore, + entityref_replaceChild, + entityref_removeChild, + entityref_appendChild, + entityref_hasChildNodes, + entityref_get_ownerDocument, + entityref_cloneNode, + entityref_get_nodeTypeString, + entityref_get_text, + entityref_put_text, + entityref_get_specified, + entityref_get_definition, + entityref_get_nodeTypedValue, + entityref_put_nodeTypedValue, + entityref_get_dataType, + entityref_put_dataType, + entityref_get_xml, + entityref_transformNode, + entityref_selectNodes, + entityref_selectSingleNode, + entityref_get_parsed, + entityref_get_namespaceURI, + entityref_get_prefix, + entityref_get_baseName, + entityref_transformNodeToObject, +}; + +IUnknown* create_doc_entity_ref( xmlNodePtr entity ) +{ + entityref *This; + HRESULT hr; + + This = HeapAlloc( GetProcessHeap(), 0, sizeof *This ); + if ( !This ) + return NULL; + + This->lpVtbl = &entityref_vtbl; + This->ref = 1; + + This->node_unk = create_basic_node( entity, (IUnknown*)&This->lpVtbl ); + if(!This->node_unk) + { + HeapFree(GetProcessHeap(), 0, This); + return NULL; + } + + hr = IUnknown_QueryInterface(This->node_unk, &IID_IXMLDOMNode, (LPVOID*)&This->node); + if(FAILED(hr)) + { + IUnknown_Release(This->node_unk); + HeapFree( GetProcessHeap(), 0, This ); + return NULL; + } + /* The ref on This->node is actually looped back into this object, so release it */ + IXMLDOMNode_Release(This->node); + + return (IUnknown*) &This->lpVtbl; +} + +#endif diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h index 6f40fa2a592..33b2c9efe9c 100644 --- a/dlls/msxml3/msxml_private.h +++ b/dlls/msxml3/msxml_private.h @@ -46,6 +46,7 @@ extern IXMLDOMNodeList *create_children_nodelist( xmlNodePtr ); extern IXMLDOMNamedNodeMap *create_nodemap( IXMLDOMNode *node ); extern IUnknown *create_doc_Implementation(); extern IUnknown *create_doc_fragment( xmlNodePtr fragment ); +extern IUnknown *create_doc_entity_ref( xmlNodePtr entity ); extern HRESULT queryresult_create( xmlNodePtr, LPWSTR, IXMLDOMNodeList ** ); diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c index 692dd363b9a..4507d08710b 100644 --- a/dlls/msxml3/tests/domdoc.c +++ b/dlls/msxml3/tests/domdoc.c @@ -156,6 +156,9 @@ static WCHAR szCDataXML[] = {'<','!','[','C','D','A','T','A','[','[','1',']','*' static WCHAR szCDataNodeText[] = {'#','c','d','a','t','a','-','s','e','c','t','i','o','n',0 }; static WCHAR szDocFragmentText[] = {'#','d','o','c','u','m','e','n','t','-','f','r','a','g','m','e','n','t',0 }; +static WCHAR szEntityRef[] = {'E','n','t','i','t','y','r','e','f',0 }; +static WCHAR szEntityRefXML[] = {'&','e','n','t','i','t','y','r','e','f',';',0 }; + #define expect_bstr_eq_and_free(bstr, expect) { \ BSTR bstrExp = alloc_str_from_narrow(expect); \ ok(lstrcmpW(bstr, bstrExp) == 0, "String differs\n"); \ @@ -1875,6 +1878,7 @@ static void test_xmlTypes(void) IXMLDOMCDATASection *pCDataSec; IXMLDOMImplementation *pIXMLDOMImplementation = NULL; IXMLDOMDocumentFragment *pDocFrag = NULL; + IXMLDOMEntityReference *pEntityRef = NULL; BSTR str; IXMLDOMNode *pNextChild = (IXMLDOMNode *)0x1; /* Used for testing Siblings */ VARIANT v; @@ -2259,8 +2263,46 @@ static void test_xmlTypes(void) IXMLDOMDocumentFragment_Release(pCDataSec); } + /* Entity References */ + hr = IXMLDOMDocument_createEntityReference(doc, szEntityRef, NULL); + ok(hr == E_INVALIDARG, "ret %08x\n", hr ); + hr = IXMLDOMDocument_createEntityReference(doc, szEntityRef, &pEntityRef); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pEntityRef, NULL); + ok(hr == S_OK, "ret %08x\n", hr ); + /* get Attribute Tests */ + hr = IXMLDOMEntityReference_get_attributes(pEntityRef, NULL); + ok(hr == E_INVALIDARG, "ret %08x\n", hr ); + + pAttribs = (IXMLDOMNamedNodeMap*)0x1; + hr = IXMLDOMEntityReference_get_attributes(pEntityRef, &pAttribs); + ok(hr == S_FALSE, "ret %08x\n", hr ); + ok(pAttribs == NULL, "pAttribs != NULL\n"); + + /* test dataType */ + hr = IXMLDOMEntityReference_get_dataType(pEntityRef, &v); + ok(hr == S_FALSE, "ret %08x\n", hr ); + ok( V_VT(&v) == VT_NULL, "incorrect dataType type\n"); + VariantClear(&v); + + /* test nodeTypeString */ + hr = IXMLDOMEntityReference_get_nodeTypeString(pEntityRef, &str); + ok(hr == S_OK, "ret %08x\n", hr ); + ok( !lstrcmpW( str, _bstr_("entityreference") ), "incorrect nodeTypeString string\n"); + SysFreeString(str); + + /* test get_xml*/ + hr = IXMLDOMEntityReference_get_xml(pEntityRef, &str); + ok(hr == S_OK, "ret %08x\n", hr ); + todo_wine ok( !lstrcmpW( str, szEntityRefXML ), "incorrect xml string\n"); + SysFreeString(str); + + IXMLDOMEntityReference_Release(pEntityRef); + } IXMLDOMElement_Release( pRoot ); }