msxml3: Add IDispatchEx support for IXMLDOMNamedNodeMap.

This commit is contained in:
Nikolay Sivov 2011-11-04 18:59:05 +03:00 committed by Alexandre Julliard
parent 5ea259e8e4
commit 70e0290dcf
5 changed files with 154 additions and 22 deletions

View File

@ -326,11 +326,6 @@ static dispex_data_t *get_dispex_data(DispatchEx *This)
return This->data->data; 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) static inline BOOL is_dynamic_dispid(DISPID id)
{ {
return DISPID_DYNPROP_0 <= id && id <= DISPID_DYNPROP_MAX; 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); 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) if(This->data->vtbl && This->data->vtbl->invoke) {
return This->data->vtbl->invoke(This->outer, id, lcid, wFlags, pdp, pvarRes, pei); hres = This->data->vtbl->invoke(This->outer, id, lcid, wFlags, pdp, pvarRes, pei);
if (hres != DISP_E_UNKNOWNNAME) return hres;
}
if(wFlags == DISPATCH_CONSTRUCT) { if(wFlags == DISPATCH_CONSTRUCT) {
FIXME("DISPATCH_CONSTRUCT not implemented\n"); FIXME("DISPATCH_CONSTRUCT not implemented\n");

View File

@ -130,9 +130,6 @@ extern void release_typelib(void) DECLSPEC_HIDDEN;
typedef struct dispex_data_t dispex_data_t; typedef struct dispex_data_t dispex_data_t;
typedef struct dispex_dynamic_data_t dispex_dynamic_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 { typedef struct {
HRESULT (*get_dispid)(IUnknown*,BSTR,DWORD,DISPID*); HRESULT (*get_dispid)(IUnknown*,BSTR,DWORD,DISPID*);
HRESULT (*invoke)(IUnknown*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*); HRESULT (*invoke)(IUnknown*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*);

View File

@ -34,6 +34,7 @@
#include "winnls.h" #include "winnls.h"
#include "ole2.h" #include "ole2.h"
#include "msxml6.h" #include "msxml6.h"
#include "msxml2did.h"
#include "msxml_private.h" #include "msxml_private.h"
@ -45,6 +46,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml);
typedef struct _xmlnodemap typedef struct _xmlnodemap
{ {
DispatchEx dispex;
IXMLDOMNamedNodeMap IXMLDOMNamedNodeMap_iface; IXMLDOMNamedNodeMap IXMLDOMNamedNodeMap_iface;
ISupportErrorInfo ISupportErrorInfo_iface; ISupportErrorInfo ISupportErrorInfo_iface;
LONG ref; LONG ref;
@ -76,6 +78,10 @@ static HRESULT WINAPI xmlnodemap_QueryInterface(
{ {
*ppvObject = iface; *ppvObject = iface;
} }
else if (dispex_query_interface(&This->dispex, riid, ppvObject))
{
return *ppvObject ? S_OK : E_NOINTERFACE;
}
else if( IsEqualGUID( riid, &IID_ISupportErrorInfo )) else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
{ {
*ppvObject = &This->ISupportErrorInfo_iface; *ppvObject = &This->ISupportErrorInfo_iface;
@ -111,6 +117,7 @@ static ULONG WINAPI xmlnodemap_Release(
if ( ref == 0 ) if ( ref == 0 )
{ {
xmldoc_release( This->node->doc ); xmldoc_release( This->node->doc );
release_dispex(&This->dispex);
heap_free( This ); heap_free( This );
} }
@ -516,23 +523,92 @@ static const struct ISupportErrorInfoVtbl support_error_vtbl =
support_error_InterfaceSupportsErrorInfo 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 ) IXMLDOMNamedNodeMap *create_nodemap( const xmlNodePtr node )
{ {
xmlnodemap *nodemap; xmlnodemap *This;
nodemap = heap_alloc( sizeof *nodemap ); This = heap_alloc( sizeof *This );
if ( !nodemap ) if ( !This )
return NULL; return NULL;
nodemap->IXMLDOMNamedNodeMap_iface.lpVtbl = &xmlnodemap_vtbl; This->IXMLDOMNamedNodeMap_iface.lpVtbl = &xmlnodemap_vtbl;
nodemap->ISupportErrorInfo_iface.lpVtbl = &support_error_vtbl; This->ISupportErrorInfo_iface.lpVtbl = &support_error_vtbl;
nodemap->node = node; This->node = node;
nodemap->ref = 1; This->ref = 1;
nodemap->iterator = 0; This->iterator = 0;
init_dispex(&This->dispex, (IUnknown*)&This->IXMLDOMNamedNodeMap_iface, &xmlnodemap_dispex);
xmldoc_add_ref(node->doc); xmldoc_add_ref(node->doc);
return &nodemap->IXMLDOMNamedNodeMap_iface; return &This->IXMLDOMNamedNodeMap_iface;
} }
#endif #endif

View File

@ -37,6 +37,7 @@
#include "winuser.h" #include "winuser.h"
#include "ole2.h" #include "ole2.h"
#include "msxml6.h" #include "msxml6.h"
#include "msxml2did.h"
#include "msxml_private.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)) if(idx >= xmlXPathNodeSetGetLength(This->result->nodesetval))
return DISP_E_UNKNOWNNAME; return DISP_E_UNKNOWNNAME;
*dispid = MSXML_DISPID_CUSTOM_MIN + idx; *dispid = DISPID_DOM_COLLECTION_BASE + idx;
TRACE("ret %x\n", *dispid); TRACE("ret %x\n", *dispid);
return S_OK; 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_VT(res) = VT_DISPATCH;
V_DISPATCH(res) = NULL; V_DISPATCH(res) = NULL;
if (id < DISPID_DOM_COLLECTION_BASE || id > DISPID_DOM_COLLECTION_MAX)
return DISP_E_UNKNOWNNAME;
switch(flags) switch(flags)
{ {
case INVOKE_PROPERTYGET: case INVOKE_PROPERTYGET:
{ {
IXMLDOMNode *disp = NULL; 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; V_DISPATCH(res) = (IDispatch*)disp;
break; break;
} }

View File

@ -1731,7 +1731,7 @@ SZ_EMAIL_DTD
static const char xpath_simple_list[] = static const char xpath_simple_list[] =
"<?xml version=\"1.0\"?>" "<?xml version=\"1.0\"?>"
"<root>" "<root>"
" <a/>" " <a attr1=\"1\" attr2=\"2\" />"
" <b/>" " <b/>"
" <c/>" " <c/>"
" <d/>" " <d/>"
@ -10628,9 +10628,15 @@ static void test_dispex(void)
const DOMNodeType *type = dispex_types_test; const DOMNodeType *type = dispex_types_test;
IXMLDOMNodeList *node_list; IXMLDOMNodeList *node_list;
IXMLDOMParseError *error; IXMLDOMParseError *error;
IXMLDOMNamedNodeMap *map;
IXMLDOMDocument *doc; IXMLDOMDocument *doc;
IXMLDOMElement *elem;
IDispatchEx *dispex;
IXMLDOMNode *node;
VARIANT_BOOL b;
IUnknown *unk; IUnknown *unk;
HRESULT hr; HRESULT hr;
DISPID did;
doc = create_document(&IID_IXMLDOMDocument); doc = create_document(&IID_IXMLDOMDocument);
@ -10672,6 +10678,58 @@ static void test_dispex(void)
IUnknown_Release(unk); IUnknown_Release(unk);
IXMLDOMParseError_Release(error); 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); IXMLDOMDocument_Release(doc);
free_bstrs(); free_bstrs();
} }