From 70e0290dcf2e261dc3b7629b64586662cae3a292 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Fri, 4 Nov 2011 18:59:05 +0300 Subject: [PATCH] msxml3: Add IDispatchEx support for IXMLDOMNamedNodeMap. --- dlls/msxml3/dispex.c | 11 ++---- dlls/msxml3/msxml_private.h | 3 -- dlls/msxml3/nodemap.c | 94 ++++++++++++++++++++++++++++++++++++++++----- dlls/msxml3/selection.c | 8 +++- dlls/msxml3/tests/domdoc.c | 60 ++++++++++++++++++++++++++++- 5 files changed, 154 insertions(+), 22 deletions(-) diff --git a/dlls/msxml3/dispex.c b/dlls/msxml3/dispex.c index ae84ab9fa7b..3789134e19d 100644 --- a/dlls/msxml3/dispex.c +++ b/dlls/msxml3/dispex.c @@ -326,11 +326,6 @@ static dispex_data_t *get_dispex_data(DispatchEx *This) return This->data->data; } -static inline BOOL is_custom_dispid(DISPID id) -{ - return MSXML_DISPID_CUSTOM_MIN <= id && id <= MSXML_DISPID_CUSTOM_MAX; -} - static inline BOOL is_dynamic_dispid(DISPID id) { return DISPID_DYNPROP_0 <= id && id <= DISPID_DYNPROP_MAX; @@ -523,8 +518,10 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); - if(is_custom_dispid(id) && This->data->vtbl && This->data->vtbl->invoke) - return This->data->vtbl->invoke(This->outer, id, lcid, wFlags, pdp, pvarRes, pei); + if(This->data->vtbl && This->data->vtbl->invoke) { + hres = This->data->vtbl->invoke(This->outer, id, lcid, wFlags, pdp, pvarRes, pei); + if (hres != DISP_E_UNKNOWNNAME) return hres; + } if(wFlags == DISPATCH_CONSTRUCT) { FIXME("DISPATCH_CONSTRUCT not implemented\n"); diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h index 698655e4100..5c2ed4db00a 100644 --- a/dlls/msxml3/msxml_private.h +++ b/dlls/msxml3/msxml_private.h @@ -130,9 +130,6 @@ extern void release_typelib(void) DECLSPEC_HIDDEN; typedef struct dispex_data_t dispex_data_t; typedef struct dispex_dynamic_data_t dispex_dynamic_data_t; -#define MSXML_DISPID_CUSTOM_MIN 0x60000000 -#define MSXML_DISPID_CUSTOM_MAX 0x6fffffff - typedef struct { HRESULT (*get_dispid)(IUnknown*,BSTR,DWORD,DISPID*); HRESULT (*invoke)(IUnknown*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*); diff --git a/dlls/msxml3/nodemap.c b/dlls/msxml3/nodemap.c index 1970840672e..ebc2bd5d763 100644 --- a/dlls/msxml3/nodemap.c +++ b/dlls/msxml3/nodemap.c @@ -34,6 +34,7 @@ #include "winnls.h" #include "ole2.h" #include "msxml6.h" +#include "msxml2did.h" #include "msxml_private.h" @@ -45,6 +46,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml); typedef struct _xmlnodemap { + DispatchEx dispex; IXMLDOMNamedNodeMap IXMLDOMNamedNodeMap_iface; ISupportErrorInfo ISupportErrorInfo_iface; LONG ref; @@ -76,6 +78,10 @@ static HRESULT WINAPI xmlnodemap_QueryInterface( { *ppvObject = iface; } + else if (dispex_query_interface(&This->dispex, riid, ppvObject)) + { + return *ppvObject ? S_OK : E_NOINTERFACE; + } else if( IsEqualGUID( riid, &IID_ISupportErrorInfo )) { *ppvObject = &This->ISupportErrorInfo_iface; @@ -111,6 +117,7 @@ static ULONG WINAPI xmlnodemap_Release( if ( ref == 0 ) { xmldoc_release( This->node->doc ); + release_dispex(&This->dispex); heap_free( This ); } @@ -516,23 +523,92 @@ static const struct ISupportErrorInfoVtbl support_error_vtbl = support_error_InterfaceSupportsErrorInfo }; +static HRESULT xmlnodemap_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 xmlnodemap_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, + VARIANT *res, EXCEPINFO *ei) +{ + xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( (IXMLDOMNamedNodeMap*)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; + + IXMLDOMNamedNodeMap_get_item(&This->IXMLDOMNamedNodeMap_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 xmlnodemap_dispex_vtbl = { + xmlnodemap_get_dispid, + xmlnodemap_invoke +}; + +static const tid_t xmlnodemap_iface_tids[] = { + IXMLDOMNamedNodeMap_tid, + 0 +}; + +static dispex_static_data_t xmlnodemap_dispex = { + &xmlnodemap_dispex_vtbl, + IXMLDOMNamedNodeMap_tid, + NULL, + xmlnodemap_iface_tids +}; + IXMLDOMNamedNodeMap *create_nodemap( const xmlNodePtr node ) { - xmlnodemap *nodemap; + xmlnodemap *This; - nodemap = heap_alloc( sizeof *nodemap ); - if ( !nodemap ) + This = heap_alloc( sizeof *This ); + if ( !This ) return NULL; - nodemap->IXMLDOMNamedNodeMap_iface.lpVtbl = &xmlnodemap_vtbl; - nodemap->ISupportErrorInfo_iface.lpVtbl = &support_error_vtbl; - nodemap->node = node; - nodemap->ref = 1; - nodemap->iterator = 0; + This->IXMLDOMNamedNodeMap_iface.lpVtbl = &xmlnodemap_vtbl; + This->ISupportErrorInfo_iface.lpVtbl = &support_error_vtbl; + This->node = node; + This->ref = 1; + This->iterator = 0; + + init_dispex(&This->dispex, (IUnknown*)&This->IXMLDOMNamedNodeMap_iface, &xmlnodemap_dispex); xmldoc_add_ref(node->doc); - return &nodemap->IXMLDOMNamedNodeMap_iface; + return &This->IXMLDOMNamedNodeMap_iface; } #endif diff --git a/dlls/msxml3/selection.c b/dlls/msxml3/selection.c index 31137f34ff4..274e239d445 100644 --- a/dlls/msxml3/selection.c +++ b/dlls/msxml3/selection.c @@ -37,6 +37,7 @@ #include "winuser.h" #include "ole2.h" #include "msxml6.h" +#include "msxml2did.h" #include "msxml_private.h" @@ -617,7 +618,7 @@ static HRESULT domselection_get_dispid(IUnknown *iface, BSTR name, DWORD flags, if(idx >= xmlXPathNodeSetGetLength(This->result->nodesetval)) return DISP_E_UNKNOWNNAME; - *dispid = MSXML_DISPID_CUSTOM_MIN + idx; + *dispid = DISPID_DOM_COLLECTION_BASE + idx; TRACE("ret %x\n", *dispid); return S_OK; } @@ -632,13 +633,16 @@ static HRESULT domselection_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD f 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; - domselection_get_item(&This->IXMLDOMSelection_iface, id - MSXML_DISPID_CUSTOM_MIN, &disp); + domselection_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 e1be91201da..efd8cccc65c 100644 --- a/dlls/msxml3/tests/domdoc.c +++ b/dlls/msxml3/tests/domdoc.c @@ -1731,7 +1731,7 @@ SZ_EMAIL_DTD static const char xpath_simple_list[] = "" "" -" " +" " " " " " " " @@ -10628,9 +10628,15 @@ static void test_dispex(void) const DOMNodeType *type = dispex_types_test; IXMLDOMNodeList *node_list; IXMLDOMParseError *error; + IXMLDOMNamedNodeMap *map; IXMLDOMDocument *doc; + IXMLDOMElement *elem; + IDispatchEx *dispex; + IXMLDOMNode *node; + VARIANT_BOOL b; IUnknown *unk; HRESULT hr; + DISPID did; doc = create_document(&IID_IXMLDOMDocument); @@ -10672,6 +10678,58 @@ static void test_dispex(void) IUnknown_Release(unk); IXMLDOMParseError_Release(error); + /* IXMLDOMNamedNodeMap */ + hr = IXMLDOMDocument2_loadXML(doc, _bstr_(xpath_simple_list), &b); + EXPECT_HR(hr, S_OK); + + hr = IXMLDOMDocument_selectNodes(doc, _bstr_("root/a"), &node_list); + EXPECT_HR(hr, S_OK); + hr = IXMLDOMNodeList_get_item(node_list, 0, &node); + EXPECT_HR(hr, S_OK); + IXMLDOMNodeList_Release(node_list); + + hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&elem); + EXPECT_HR(hr, S_OK); + IXMLDOMNode_Release(node); + hr = IXMLDOMElement_get_attributes(elem, &map); + EXPECT_HR(hr, S_OK); + IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IUnknown, (void**)&unk); + test_domobj_dispex(unk); + IUnknown_Release(unk); + /* collection dispex test */ + hr = IXMLDOMNamedNodeMap_QueryInterface(map, &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); + IDispatchEx_Release(dispex); + + hr = IXMLDOMDocument_selectNodes(doc, _bstr_("root/b"), &node_list); + EXPECT_HR(hr, S_OK); + hr = IXMLDOMNodeList_get_item(node_list, 0, &node); + EXPECT_HR(hr, S_OK); + IXMLDOMNodeList_Release(node_list); + hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&elem); + EXPECT_HR(hr, S_OK); + IXMLDOMNode_Release(node); + hr = IXMLDOMElement_get_attributes(elem, &map); + EXPECT_HR(hr, S_OK); + /* collection dispex test, empty collection */ + hr = IXMLDOMNamedNodeMap_QueryInterface(map, &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); + + IXMLDOMNamedNodeMap_Release(map); + IXMLDOMElement_Release(elem); + IXMLDOMDocument_Release(doc); free_bstrs(); } -- 2.11.4.GIT