jscript: Don't pass 'this' argument to DISPID_VALUE of pure IDispatch interfaces.

This commit is contained in:
Jacek Caban 2012-12-24 11:38:28 +01:00 committed by Alexandre Julliard
parent 8ec82dfaae
commit 7726e01844
2 changed files with 155 additions and 18 deletions

View File

@ -1205,6 +1205,12 @@ HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, W
if(r && argc) if(r && argc)
flags |= DISPATCH_PROPERTYGET; flags |= DISPATCH_PROPERTYGET;
hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
if(FAILED(hres)) {
TRACE("using IDispatch\n");
dispex = NULL;
jsthis = NULL;
}
if(jsthis) { if(jsthis) {
static DISPID this_id = DISPID_THIS; static DISPID this_id = DISPID_THIS;
@ -1220,8 +1226,11 @@ HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, W
if(dp.cArgs > sizeof(buf)/sizeof(*buf)) { if(dp.cArgs > sizeof(buf)/sizeof(*buf)) {
dp.rgvarg = heap_alloc(dp.cArgs*sizeof(VARIANT)); dp.rgvarg = heap_alloc(dp.cArgs*sizeof(VARIANT));
if(!dp.rgvarg) if(!dp.rgvarg) {
if(dispex)
IDispatchEx_Release(dispex);
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
}
}else { }else {
dp.rgvarg = buf; dp.rgvarg = buf;
} }
@ -1233,6 +1242,8 @@ HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, W
VariantClear(dp.rgvarg+dp.cArgs-i-1); VariantClear(dp.rgvarg+dp.cArgs-i-1);
if(dp.rgvarg != buf) if(dp.rgvarg != buf)
heap_free(dp.rgvarg); heap_free(dp.rgvarg);
if(dispex)
IDispatchEx_Release(dispex);
return hres; return hres;
} }
} }
@ -1243,8 +1254,7 @@ HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, W
V_VT(&retv) = VT_EMPTY; V_VT(&retv) = VT_EMPTY;
clear_ei(ctx); clear_ei(ctx);
hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); if(dispex) {
if(SUCCEEDED(hres)) {
hres = IDispatchEx_InvokeEx(dispex, DISPID_VALUE, ctx->lcid, flags, &dp, r ? &retv : NULL, &ctx->ei.ei, hres = IDispatchEx_InvokeEx(dispex, DISPID_VALUE, ctx->lcid, flags, &dp, r ? &retv : NULL, &ctx->ei.ei,
&ctx->jscaller->IServiceProvider_iface); &ctx->jscaller->IServiceProvider_iface);
IDispatchEx_Release(dispex); IDispatchEx_Release(dispex);
@ -1256,7 +1266,6 @@ HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, W
return DISP_E_MEMBERNOTFOUND; return DISP_E_MEMBERNOTFOUND;
} }
TRACE("using IDispatch\n");
hres = IDispatch_Invoke(disp, DISPID_VALUE, &IID_NULL, ctx->lcid, flags, &dp, r ? &retv : NULL, &ctx->ei.ei, &err); hres = IDispatch_Invoke(disp, DISPID_VALUE, &IID_NULL, ctx->lcid, flags, &dp, r ? &retv : NULL, &ctx->ei.ei, &err);
} }

View File

@ -90,6 +90,8 @@ DEFINE_EXPECT(global_propargput_i);
DEFINE_EXPECT(global_testargtypes_i); DEFINE_EXPECT(global_testargtypes_i);
DEFINE_EXPECT(puredisp_prop_d); DEFINE_EXPECT(puredisp_prop_d);
DEFINE_EXPECT(puredisp_noprop_d); DEFINE_EXPECT(puredisp_noprop_d);
DEFINE_EXPECT(puredisp_value);
DEFINE_EXPECT(dispexfunc_value);
DEFINE_EXPECT(testobj_delete_test); DEFINE_EXPECT(testobj_delete_test);
DEFINE_EXPECT(testobj_delete_nodelete); DEFINE_EXPECT(testobj_delete_nodelete);
DEFINE_EXPECT(testobj_value); DEFINE_EXPECT(testobj_value);
@ -131,6 +133,7 @@ DEFINE_EXPECT(DeleteMemberByDispID_false);
#define DISPID_GLOBAL_DISPUNK 0x1017 #define DISPID_GLOBAL_DISPUNK 0x1017
#define DISPID_GLOBAL_TESTRES 0x1018 #define DISPID_GLOBAL_TESTRES 0x1018
#define DISPID_GLOBAL_TESTNORES 0x1019 #define DISPID_GLOBAL_TESTNORES 0x1019
#define DISPID_GLOBAL_DISPEXFUNC 0x101a
#define DISPID_GLOBAL_TESTPROPDELETE 0x2000 #define DISPID_GLOBAL_TESTPROPDELETE 0x2000
#define DISPID_GLOBAL_TESTNOPROPDELETE 0x2001 #define DISPID_GLOBAL_TESTNOPROPDELETE 0x2001
@ -244,18 +247,6 @@ static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid,
LPOLESTR *rgszNames, UINT cNames, LPOLESTR *rgszNames, UINT cNames,
LCID lcid, DISPID *rgDispId) LCID lcid, DISPID *rgDispId)
{ {
ok(IsEqualGUID(riid, &IID_NULL), "Expected IID_NULL\n");
ok(cNames==1, "cNames = %d\n", cNames);
if(!strcmp_wa(*rgszNames, "prop")) {
CHECK_EXPECT(puredisp_prop_d);
*rgDispId = DISPID_TESTOBJ_PROP;
return S_OK;
} else if(!strcmp_wa(*rgszNames, "noprop")) {
CHECK_EXPECT(puredisp_noprop_d);
return DISP_E_UNKNOWNNAME;
}
ok(0, "unexpected call\n"); ok(0, "unexpected call\n");
return E_NOTIMPL; return E_NOTIMPL;
} }
@ -268,6 +259,12 @@ static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember,
return E_NOTIMPL; return E_NOTIMPL;
} }
static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
{ {
ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName), grfdex); ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName), grfdex);
@ -441,6 +438,60 @@ static IDispatchExVtbl testObjVtbl = {
static IDispatchEx testObj = { &testObjVtbl }; static IDispatchEx testObj = { &testObjVtbl };
static HRESULT WINAPI dispexFunc_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
VARIANT *res, EXCEPINFO *pei, IServiceProvider *pspCaller)
{
ok(pspCaller != NULL, "pspCaller = NULL\n");
switch(id) {
case DISPID_VALUE:
CHECK_EXPECT(dispexfunc_value);
ok(pdp != NULL, "pdp == NULL\n");
ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
ok(pdp->rgdispidNamedArgs != NULL, "rgdispidNamedArgs != NULL\n");
ok(*pdp->rgdispidNamedArgs == DISPID_THIS, "*rgdispidNamedArgs = %d\n", *pdp->rgdispidNamedArgs);
ok(pdp->cArgs == 2, "cArgs = %d\n", pdp->cArgs);
ok(pdp->cNamedArgs == 1, "cNamedArgs = %d\n", pdp->cNamedArgs);
ok(res != NULL, "res == NULL\n");
ok(wFlags == (DISPATCH_PROPERTYGET|DISPATCH_METHOD), "wFlags = %x\n", wFlags);
ok(pei != NULL, "pei == NULL\n");
ok(V_VT(pdp->rgvarg+1) == VT_BOOL, "V_VT(pdp->rgvarg+1) = %d\n", V_VT(pdp->rgvarg+1));
ok(!V_BOOL(pdp->rgvarg+1), "V_BOOL(pdp->rgvarg+1) = %x\n", V_BOOL(pdp->rgvarg+1));
ok(V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(pdp->rgvarg) = %d\n", V_VT(pdp->rgvarg));
ok(V_DISPATCH(pdp->rgvarg) != NULL, "V_DISPATCH(pdp->rgvarg) == NULL\n");
if(res)
V_VT(res) = VT_NULL;
return S_OK;
default:
ok(0, "unexpected call %x\n", id);
return DISP_E_MEMBERNOTFOUND;
}
}
static IDispatchExVtbl dispexFuncVtbl = {
DispatchEx_QueryInterface,
DispatchEx_AddRef,
DispatchEx_Release,
DispatchEx_GetTypeInfoCount,
DispatchEx_GetTypeInfo,
DispatchEx_GetIDsOfNames,
DispatchEx_Invoke,
DispatchEx_GetDispID,
dispexFunc_InvokeEx,
DispatchEx_DeleteMemberByName,
DispatchEx_DeleteMemberByDispID,
DispatchEx_GetMemberProperties,
DispatchEx_GetMemberName,
DispatchEx_GetNextDispID,
DispatchEx_GetNameSpaceParent
};
static IDispatchEx dispexFunc = { &dispexFuncVtbl };
static HRESULT WINAPI pureDisp_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) static HRESULT WINAPI pureDisp_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
{ {
if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDispatch)) { if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDispatch)) {
@ -452,14 +503,65 @@ static HRESULT WINAPI pureDisp_QueryInterface(IDispatchEx *iface, REFIID riid, v
return E_NOINTERFACE; return E_NOINTERFACE;
} }
static HRESULT WINAPI pureDisp_GetIDsOfNames(IDispatchEx *iface, REFIID riid,
LPOLESTR *rgszNames, UINT cNames,
LCID lcid, DISPID *rgDispId)
{
ok(IsEqualGUID(riid, &IID_NULL), "Expected IID_NULL\n");
ok(cNames==1, "cNames = %d\n", cNames);
if(!strcmp_wa(*rgszNames, "prop")) {
CHECK_EXPECT(puredisp_prop_d);
*rgDispId = DISPID_TESTOBJ_PROP;
return S_OK;
} else if(!strcmp_wa(*rgszNames, "noprop")) {
CHECK_EXPECT(puredisp_noprop_d);
return DISP_E_UNKNOWNNAME;
}
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI pureDisp_Invoke(IDispatchEx *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS *pdp, VARIANT *res, EXCEPINFO *ei, UINT *puArgErr)
{
ok(IsEqualGUID(&IID_NULL, riid), "unexpected riid\n");
switch(dispIdMember) {
case DISPID_VALUE:
CHECK_EXPECT(puredisp_value);
ok(pdp != NULL, "pdp == NULL\n");
ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
ok(res != NULL, "res == NULL\n");
ok(wFlags == (DISPATCH_PROPERTYGET|DISPATCH_METHOD), "wFlags = %x\n", wFlags);
ok(ei != NULL, "ei == NULL\n");
ok(puArgErr != NULL, "puArgErr == NULL\n");
ok(V_VT(pdp->rgvarg) == VT_BOOL, "V_VT(pdp->rgvarg) = %d\n", V_VT(pdp->rgvarg));
ok(!V_BOOL(pdp->rgvarg), "V_BOOL(pdp->rgvarg) = %x\n", V_BOOL(pdp->rgvarg));
if(res)
V_VT(res) = VT_NULL;
return S_OK;
default:
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
}
static IDispatchExVtbl pureDispVtbl = { static IDispatchExVtbl pureDispVtbl = {
pureDisp_QueryInterface, pureDisp_QueryInterface,
DispatchEx_AddRef, DispatchEx_AddRef,
DispatchEx_Release, DispatchEx_Release,
DispatchEx_GetTypeInfoCount, DispatchEx_GetTypeInfoCount,
DispatchEx_GetTypeInfo, DispatchEx_GetTypeInfo,
DispatchEx_GetIDsOfNames, pureDisp_GetIDsOfNames,
DispatchEx_Invoke pureDisp_Invoke
}; };
static IDispatchEx pureDisp = { &pureDispVtbl }; static IDispatchEx pureDisp = { &pureDispVtbl };
@ -628,6 +730,11 @@ static HRESULT WINAPI Global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD
return S_OK; return S_OK;
} }
if(!strcmp_wa(bstrName, "dispexFunc")) {
*pid = DISPID_GLOBAL_DISPEXFUNC;
return S_OK;
}
if(strict_dispid_check && strcmp_wa(bstrName, "t")) if(strict_dispid_check && strcmp_wa(bstrName, "t"))
ok(0, "unexpected call %s\n", wine_dbgstr_w(bstrName)); ok(0, "unexpected call %s\n", wine_dbgstr_w(bstrName));
return DISP_E_UNKNOWNNAME; return DISP_E_UNKNOWNNAME;
@ -809,6 +916,11 @@ static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid,
V_DISPATCH(pvarRes) = (IDispatch*)&pureDisp; V_DISPATCH(pvarRes) = (IDispatch*)&pureDisp;
return S_OK; return S_OK;
case DISPID_GLOBAL_DISPEXFUNC:
V_VT(pvarRes) = VT_DISPATCH;
V_DISPATCH(pvarRes) = (IDispatch*)&dispexFunc;
return S_OK;
case DISPID_GLOBAL_GETNULLBSTR: case DISPID_GLOBAL_GETNULLBSTR:
if(pvarRes) { if(pvarRes) {
V_VT(pvarRes) = VT_BSTR; V_VT(pvarRes) = VT_BSTR;
@ -1891,6 +2003,22 @@ static BOOL run_tests(void)
parse_script_a("ok((delete pureDisp.noprop) === true, 'delete pureDisp.noprop did not return false');"); parse_script_a("ok((delete pureDisp.noprop) === true, 'delete pureDisp.noprop did not return false');");
CHECK_CALLED(puredisp_noprop_d); CHECK_CALLED(puredisp_noprop_d);
SET_EXPECT(puredisp_value);
parse_script_a("var t=pureDisp; t=t(false);");
CHECK_CALLED(puredisp_value);
SET_EXPECT(puredisp_value);
parse_script_a("var t = {func: pureDisp}; t = t.func(false);");
CHECK_CALLED(puredisp_value);
SET_EXPECT(dispexfunc_value);
parse_script_a("var t = dispexFunc; t = t(false);");
CHECK_CALLED(dispexfunc_value);
SET_EXPECT(dispexfunc_value);
parse_script_a("var t = {func: dispexFunc}; t = t.func(false);");
CHECK_CALLED(dispexfunc_value);
parse_script_a("(function reportSuccess() {})()"); parse_script_a("(function reportSuccess() {})()");
parse_script_a("ok(typeof(test) === 'object', \"typeof(test) != 'object'\");"); parse_script_a("ok(typeof(test) === 'object', \"typeof(test) != 'object'\");");