From 85ce39ddca6744bfa364058f7e25270b42288823 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Sat, 19 Nov 2011 20:55:30 +0300 Subject: [PATCH] msxml3: Support IDispatchEx for IXMLDOMNodeList too. --- dlls/msxml3/nodelist.c | 148 +++++++++++++++++++++++-------------- dlls/msxml3/selection.c | 2 +- dlls/msxml3/tests/domdoc.c | 21 ++++++ 3 files changed, 114 insertions(+), 57 deletions(-) diff --git a/dlls/msxml3/nodelist.c b/dlls/msxml3/nodelist.c index 6a25463355a..5710d483e95 100644 --- a/dlls/msxml3/nodelist.c +++ b/dlls/msxml3/nodelist.c @@ -33,6 +33,7 @@ #include "winuser.h" #include "ole2.h" #include "msxml6.h" +#include "msxml2did.h" #include "msxml_private.h" @@ -53,6 +54,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml); typedef struct _xmlnodelist { + DispatchEx dispex; IXMLDOMNodeList IXMLDOMNodeList_iface; LONG ref; xmlNodePtr parent; @@ -69,7 +71,9 @@ static HRESULT WINAPI xmlnodelist_QueryInterface( REFIID riid, void** ppvObject ) { - TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppvObject); + xmlnodelist *This = impl_from_IXMLDOMNodeList( iface ); + + TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject); if ( IsEqualGUID( riid, &IID_IUnknown ) || IsEqualGUID( riid, &IID_IDispatch ) || @@ -77,6 +81,10 @@ static HRESULT WINAPI xmlnodelist_QueryInterface( { *ppvObject = iface; } + else if (dispex_query_interface(&This->dispex, riid, ppvObject)) + { + return *ppvObject ? S_OK : E_NOINTERFACE; + } else { TRACE("interface %s not implemented\n", debugstr_guid(riid)); @@ -119,12 +127,7 @@ static HRESULT WINAPI xmlnodelist_GetTypeInfoCount( UINT* pctinfo ) { xmlnodelist *This = impl_from_IXMLDOMNodeList( iface ); - - TRACE("(%p)->(%p)\n", This, pctinfo); - - *pctinfo = 1; - - return S_OK; + return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo); } static HRESULT WINAPI xmlnodelist_GetTypeInfo( @@ -134,13 +137,8 @@ static HRESULT WINAPI xmlnodelist_GetTypeInfo( ITypeInfo** ppTInfo ) { xmlnodelist *This = impl_from_IXMLDOMNodeList( iface ); - HRESULT hr; - - TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); - - hr = get_typeinfo(IXMLDOMNodeList_tid, ppTInfo); - - return hr; + return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, + iTInfo, lcid, ppTInfo); } static HRESULT WINAPI xmlnodelist_GetIDsOfNames( @@ -152,23 +150,8 @@ static HRESULT WINAPI xmlnodelist_GetIDsOfNames( DISPID* rgDispId ) { xmlnodelist *This = impl_from_IXMLDOMNodeList( iface ); - ITypeInfo *typeinfo; - HRESULT hr; - - TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, - lcid, rgDispId); - - if(!rgszNames || cNames == 0 || !rgDispId) - return E_INVALIDARG; - - hr = get_typeinfo(IXMLDOMNodeList_tid, &typeinfo); - if(SUCCEEDED(hr)) - { - hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId); - ITypeInfo_Release(typeinfo); - } - - return hr; + return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, + riid, rgszNames, cNames, lcid, rgDispId); } static HRESULT WINAPI xmlnodelist_Invoke( @@ -183,21 +166,8 @@ static HRESULT WINAPI xmlnodelist_Invoke( UINT* puArgErr ) { xmlnodelist *This = impl_from_IXMLDOMNodeList( iface ); - ITypeInfo *typeinfo; - HRESULT hr; - - TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), - lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); - - hr = get_typeinfo(IXMLDOMNodeList_tid, &typeinfo); - if(SUCCEEDED(hr)) - { - hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMNodeList_iface, dispIdMember, wFlags, - pDispParams, pVarResult, pExcepInfo, puArgErr); - ITypeInfo_Release(typeinfo); - } - - return hr; + return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, + dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); } static HRESULT WINAPI xmlnodelist_get_item( @@ -298,7 +268,6 @@ static HRESULT WINAPI xmlnodelist__newEnum( return E_NOTIMPL; } - static const struct IXMLDOMNodeListVtbl xmlnodelist_vtbl = { xmlnodelist_QueryInterface, @@ -315,22 +284,89 @@ static const struct IXMLDOMNodeListVtbl xmlnodelist_vtbl = xmlnodelist__newEnum, }; +static HRESULT xmlnodelist_get_dispid(IUnknown *iface, BSTR name, DWORD flags, DISPID *dispid) +{ + WCHAR *ptr; + int idx = 0; + + for(ptr = name; *ptr && isdigitW(*ptr); ptr++) + idx = idx*10 + (*ptr-'0'); + if(*ptr) + return DISP_E_UNKNOWNNAME; + + *dispid = DISPID_DOM_COLLECTION_BASE + idx; + TRACE("ret %x\n", *dispid); + return S_OK; +} + +static HRESULT xmlnodelist_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, + VARIANT *res, EXCEPINFO *ei) +{ + xmlnodelist *This = impl_from_IXMLDOMNodeList( (IXMLDOMNodeList*)iface ); + + TRACE("(%p)->(%x %x %x %p %p %p)\n", This, id, lcid, flags, params, res, ei); + + V_VT(res) = VT_DISPATCH; + V_DISPATCH(res) = NULL; + + if (id < DISPID_DOM_COLLECTION_BASE || id > DISPID_DOM_COLLECTION_MAX) + return DISP_E_UNKNOWNNAME; + + switch(flags) + { + case INVOKE_PROPERTYGET: + { + IXMLDOMNode *disp = NULL; + + IXMLDOMNodeList_get_item(&This->IXMLDOMNodeList_iface, id - DISPID_DOM_COLLECTION_BASE, &disp); + V_DISPATCH(res) = (IDispatch*)disp; + break; + } + default: + { + FIXME("unimplemented flags %x\n", flags); + break; + } + } + + TRACE("ret %p\n", V_DISPATCH(res)); + + return S_OK; +} + +static const dispex_static_data_vtbl_t xmlnodelist_dispex_vtbl = { + xmlnodelist_get_dispid, + xmlnodelist_invoke +}; + +static const tid_t xmlnodelist_iface_tids[] = { + IXMLDOMNodeList_tid, + 0 +}; +static dispex_static_data_t xmlnodelist_dispex = { + &xmlnodelist_dispex_vtbl, + IXMLDOMNodeList_tid, + NULL, + xmlnodelist_iface_tids +}; + IXMLDOMNodeList* create_children_nodelist( xmlNodePtr node ) { - xmlnodelist *nodelist; + xmlnodelist *This; - nodelist = heap_alloc( sizeof *nodelist ); - if ( !nodelist ) + This = heap_alloc( sizeof *This ); + if ( !This ) return NULL; - nodelist->IXMLDOMNodeList_iface.lpVtbl = &xmlnodelist_vtbl; - nodelist->ref = 1; - nodelist->parent = node; - nodelist->current = node->children; - + This->IXMLDOMNodeList_iface.lpVtbl = &xmlnodelist_vtbl; + This->ref = 1; + This->parent = node; + This->current = node->children; xmldoc_add_ref( node->doc ); - return &nodelist->IXMLDOMNodeList_iface; + init_dispex(&This->dispex, (IUnknown*)&This->IXMLDOMNodeList_iface, &xmlnodelist_dispex); + + return &This->IXMLDOMNodeList_iface; } #endif diff --git a/dlls/msxml3/selection.c b/dlls/msxml3/selection.c index aba8e7dcd36..887181773c6 100644 --- a/dlls/msxml3/selection.c +++ b/dlls/msxml3/selection.c @@ -600,7 +600,7 @@ static HRESULT domselection_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD f { IXMLDOMNode *disp = NULL; - domselection_get_item(&This->IXMLDOMSelection_iface, id - DISPID_DOM_COLLECTION_BASE, &disp); + IXMLDOMSelection_get_item(&This->IXMLDOMSelection_iface, id - DISPID_DOM_COLLECTION_BASE, &disp); V_DISPATCH(res) = (IDispatch*)disp; break; } diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c index abd0b371b32..e72e1f35a46 100644 --- a/dlls/msxml3/tests/domdoc.c +++ b/dlls/msxml3/tests/domdoc.c @@ -10531,6 +10531,27 @@ static void test_dispex(void) IUnknown_Release(unk); IXMLDOMNodeList_Release(node_list); + /* IXMLDOMNodeList for children list */ + hr = IXMLDOMDocument_get_childNodes(doc, &node_list); + EXPECT_HR(hr, S_OK); + IXMLDOMNodeList_QueryInterface(node_list, &IID_IUnknown, (void**)&unk); + test_domobj_dispex(unk); + IUnknown_Release(unk); + + /* collection dispex test, empty collection */ + hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IDispatchEx, (void**)&dispex); + EXPECT_HR(hr, S_OK); + did = 0; + hr = IDispatchEx_GetDispID(dispex, _bstr_("0"), 0, &did); + EXPECT_HR(hr, S_OK); + ok(did == DISPID_DOM_COLLECTION_BASE, "got 0x%08x\n", did); + hr = IDispatchEx_GetDispID(dispex, _bstr_("1"), 0, &did); + EXPECT_HR(hr, S_OK); + ok(did == DISPID_DOM_COLLECTION_BASE+1, "got 0x%08x\n", did); + IDispatchEx_Release(dispex); + + IXMLDOMNodeList_Release(node_list); + /* IXMLDOMParseError */ hr = IXMLDOMDocument_get_parseError(doc, &error); EXPECT_HR(hr, S_OK);