jscript: Pass the correct ServiceProvider when invoking external prop.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
This commit is contained in:
Gabriel Ivăncescu 2023-02-01 19:26:27 +02:00 committed by Alexandre Julliard
parent 9beef3fc5a
commit c2b5538711
3 changed files with 167 additions and 17 deletions

View file

@ -572,9 +572,9 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t
TRACE("call %s %p\n", debugstr_w(prop->name), get_object(prop->u.val));
return disp_call_value(This->ctx, get_object(prop->u.val),
jsval_disp(jsthis ? jsthis : (IDispatch*)&This->IDispatchEx_iface),
flags, argc, argv, r);
return disp_call_value_with_caller(This->ctx, get_object(prop->u.val),
jsval_disp(jsthis ? jsthis : (IDispatch*)&This->IDispatchEx_iface),
flags, argc, argv, r, caller);
}
case PROP_ACCESSOR:
case PROP_IDX: {
@ -585,9 +585,9 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t
return hres;
if(is_object_instance(val)) {
hres = disp_call_value(This->ctx, get_object(val),
jsval_disp(jsthis ? jsthis : (IDispatch*)&This->IDispatchEx_iface),
flags, argc, argv, r);
hres = disp_call_value_with_caller(This->ctx, get_object(val),
jsval_disp(jsthis ? jsthis : (IDispatch*)&This->IDispatchEx_iface),
flags, argc, argv, r, caller);
}else {
FIXME("invoke %s\n", debugstr_jsval(val));
hres = E_NOTIMPL;
@ -2364,7 +2364,7 @@ HRESULT jsdisp_call(jsdisp_t *disp, DISPID id, WORD flags, unsigned argc, jsval_
if(!prop)
return DISP_E_MEMBERNOTFOUND;
return invoke_prop_func(disp, to_disp(disp), prop, flags, argc, argv, r, NULL);
return invoke_prop_func(disp, to_disp(disp), prop, flags, argc, argv, r, &disp->ctx->jscaller->IServiceProvider_iface);
}
HRESULT jsdisp_call_name(jsdisp_t *disp, const WCHAR *name, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
@ -2379,10 +2379,11 @@ HRESULT jsdisp_call_name(jsdisp_t *disp, const WCHAR *name, WORD flags, unsigned
if(!prop || prop->type == PROP_DELETED)
return JS_E_INVALID_PROPERTY;
return invoke_prop_func(disp, to_disp(disp), prop, flags, argc, argv, r, NULL);
return invoke_prop_func(disp, to_disp(disp), prop, flags, argc, argv, r, &disp->ctx->jscaller->IServiceProvider_iface);
}
static HRESULT disp_invoke(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, DISPPARAMS *params, VARIANT *r)
static HRESULT disp_invoke(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, DISPPARAMS *params, VARIANT *r,
IServiceProvider *caller)
{
IDispatchEx *dispex;
EXCEPINFO ei;
@ -2391,7 +2392,7 @@ static HRESULT disp_invoke(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD f
memset(&ei, 0, sizeof(ei));
hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
if(SUCCEEDED(hres)) {
hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, params, r, &ei, &ctx->jscaller->IServiceProvider_iface);
hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, params, r, &ei, caller);
IDispatchEx_Release(dispex);
}else {
UINT err = 0;
@ -2489,7 +2490,7 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, uns
}
V_VT(&retv) = VT_EMPTY;
hres = disp_invoke(ctx, disp, id, flags, &dp, ret ? &retv : NULL);
hres = disp_invoke(ctx, disp, id, flags, &dp, ret ? &retv : NULL, &ctx->jscaller->IServiceProvider_iface);
for(i=0; i<argc; i++)
VariantClear(dp.rgvarg+argc-i-1);
@ -2529,8 +2530,8 @@ HRESULT disp_call_name(script_ctx_t *ctx, IDispatch *disp, const WCHAR *name, WO
return disp_call(ctx, disp, id, flags, argc, argv, ret);
}
HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
jsval_t *r)
HRESULT disp_call_value_with_caller(script_ctx_t *ctx, IDispatch *disp, jsval_t vthis, WORD flags, unsigned argc,
jsval_t *argv, jsval_t *r, IServiceProvider *caller)
{
VARIANT buf[6], retv, *args = buf;
IDispatch *jsthis;
@ -2586,7 +2587,7 @@ HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, jsval_t vthis, WORD
if(SUCCEEDED(hres)) {
V_VT(&retv) = VT_EMPTY;
hres = disp_invoke(ctx, disp, DISPID_VALUE, flags, &dp, r ? &retv : NULL);
hres = disp_invoke(ctx, disp, DISPID_VALUE, flags, &dp, r ? &retv : NULL, caller);
}
for(i = 0; i < argc; i++)
@ -2665,7 +2666,7 @@ HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t val)
if(V_VT(&var) == VT_DISPATCH)
flags |= DISPATCH_PROPERTYPUTREF;
hres = disp_invoke(ctx, disp, id, flags, &dp, NULL);
hres = disp_invoke(ctx, disp, id, flags, &dp, NULL, &ctx->jscaller->IServiceProvider_iface);
VariantClear(&var);
}
@ -2773,7 +2774,7 @@ HRESULT disp_propget(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t *val
jsdisp_release(jsdisp);
V_VT(&var) = VT_EMPTY;
hres = disp_invoke(ctx, disp, id, INVOKE_PROPERTYGET, &dp, &var);
hres = disp_invoke(ctx, disp, id, INVOKE_PROPERTYGET, &dp, &var, &ctx->jscaller->IServiceProvider_iface);
if(SUCCEEDED(hres)) {
hres = variant_to_jsval(ctx, &var, val);
VariantClear(&var);

View file

@ -240,7 +240,7 @@ HRESULT init_dispex_from_constr(jsdisp_t*,script_ctx_t*,const builtin_info_t*,js
HRESULT disp_call(script_ctx_t*,IDispatch*,DISPID,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN;
HRESULT disp_call_name(script_ctx_t*,IDispatch*,const WCHAR*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN;
HRESULT disp_call_value(script_ctx_t*,IDispatch*,jsval_t,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN;
HRESULT disp_call_value_with_caller(script_ctx_t*,IDispatch*,jsval_t,WORD,unsigned,jsval_t*,jsval_t*,IServiceProvider*) DECLSPEC_HIDDEN;
HRESULT jsdisp_call_value(jsdisp_t*,jsval_t,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN;
HRESULT jsdisp_call(jsdisp_t*,DISPID,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN;
HRESULT jsdisp_call_name(jsdisp_t*,const WCHAR*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN;
@ -483,6 +483,12 @@ static inline DWORD make_grfdex(script_ctx_t *ctx, DWORD flags)
return ((ctx->version & 0xff) << 28) | flags;
}
static inline HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, jsval_t vthis, WORD flags, unsigned argc,
jsval_t *argv, jsval_t *r)
{
return disp_call_value_with_caller(ctx, disp, vthis, flags, argc, argv, r, &ctx->jscaller->IServiceProvider_iface);
}
#define FACILITY_JSCRIPT 10
#define MAKE_JSERROR(code) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_JSCRIPT, code)

View file

@ -114,6 +114,9 @@ DEFINE_EXPECT(testobj_newenum);
DEFINE_EXPECT(testobj_getidfail_d);
DEFINE_EXPECT(testobj_tolocalestr_d);
DEFINE_EXPECT(testobj_tolocalestr_i);
DEFINE_EXPECT(test_caller_get);
DEFINE_EXPECT(test_caller_null);
DEFINE_EXPECT(test_caller_obj);
DEFINE_EXPECT(testdestrobj);
DEFINE_EXPECT(enumvariant_next_0);
DEFINE_EXPECT(enumvariant_next_1);
@ -333,6 +336,44 @@ static IEnumVARIANTVtbl testEnumVARIANTVtbl = {
static IEnumVARIANT testEnumVARIANT = { &testEnumVARIANTVtbl };
static HRESULT WINAPI sp_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
{
if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IServiceProvider, riid)) {
*ppv = iface;
return S_OK;
}
ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
*ppv = NULL;
return E_NOTIMPL;
}
static ULONG WINAPI sp_AddRef(IServiceProvider *iface)
{
return 2;
}
static ULONG WINAPI sp_Release(IServiceProvider *iface)
{
return 1;
}
static HRESULT WINAPI sp_QueryService(IServiceProvider *iface, REFGUID guidService, REFIID riid, void **ppv)
{
ok(0, "unexpected call %s\n", wine_dbgstr_guid(guidService));
*ppv = NULL;
return E_NOTIMPL;
}
static const IServiceProviderVtbl sp_vtbl = {
sp_QueryInterface,
sp_AddRef,
sp_Release,
sp_QueryService
};
static IServiceProvider sp_obj = { &sp_vtbl };
static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
{
*ppv = NULL;
@ -629,6 +670,61 @@ static IDispatchExVtbl testObjVtbl = {
static IDispatchEx testObj = { &testObjVtbl };
static HRESULT WINAPI testcallerobj_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
{
ok(id == DISPID_VALUE, "id = %ld\n", id);
ok(pdp != NULL, "pdp == NULL\n");
ok(pvarRes != NULL, "pvarRes == NULL\n");
ok(V_VT(pvarRes) == VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes));
if(wFlags == DISPATCH_PROPERTYGET) {
CHECK_EXPECT(test_caller_get);
ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
ok(pei != NULL, "pei == NULL\n");
ok(pspCaller != NULL, "pspCaller == NULL\n");
ok(pspCaller != &sp_obj, "pspCaller == sp_obj\n");
V_VT(pvarRes) = VT_DISPATCH;
V_DISPATCH(pvarRes) = (IDispatch*)iface;
}else if(pspCaller) {
CHECK_EXPECT(test_caller_obj);
ok(wFlags == DISPATCH_METHOD, "wFlags = %04x\n", wFlags);
ok(pdp->rgdispidNamedArgs != NULL, "rgdispidNamedArgs == NULL\n");
ok(pdp->cNamedArgs == 1, "cNamedArgs = %d\n", pdp->cNamedArgs);
ok(pspCaller == &sp_obj, "pspCaller != sp_obj\n");
V_VT(pvarRes) = VT_I4;
V_I4(pvarRes) = 137;
}else {
CHECK_EXPECT(test_caller_null);
ok(wFlags == DISPATCH_METHOD, "wFlags = %04x\n", wFlags);
ok(pdp->rgdispidNamedArgs != NULL, "rgdispidNamedArgs == NULL\n");
ok(pdp->cNamedArgs == 1, "cNamedArgs = %d\n", pdp->cNamedArgs);
V_VT(pvarRes) = VT_I4;
V_I4(pvarRes) = 42;
}
return S_OK;
}
static IDispatchExVtbl testcallerobj_vtbl = {
DispatchEx_QueryInterface,
DispatchEx_AddRef,
DispatchEx_Release,
DispatchEx_GetTypeInfoCount,
DispatchEx_GetTypeInfo,
DispatchEx_GetIDsOfNames,
DispatchEx_Invoke,
DispatchEx_GetDispID,
testcallerobj_InvokeEx,
DispatchEx_DeleteMemberByName,
DispatchEx_DeleteMemberByDispID,
DispatchEx_GetMemberProperties,
DispatchEx_GetMemberName,
DispatchEx_GetNextDispID,
DispatchEx_GetNameSpaceParent
};
static IDispatchEx testcallerobj = { &testcallerobj_vtbl };
static LONG test_destr_ref;
static ULONG WINAPI testDestrObj_AddRef(IDispatchEx *iface)
@ -3214,6 +3310,7 @@ static void test_script_exprs(void)
static void test_invokeex(void)
{
static DISPID propput_dispid = DISPID_PROPERTYPUT;
DISPPARAMS dp = {NULL}, dp_max = {NULL};
DISPID func_id, max_id, prop_id;
IActiveScript *script;
@ -3442,6 +3539,52 @@ static void test_invokeex(void)
IDispatchEx_Release(dispex);
IActiveScript_Release(script);
/* test InvokeEx with host prop and custom caller */
hres = parse_script_expr(L"var o = {}; o", &v, &script);
ok(hres == S_OK, "parse_script_expr failed: %08lx\n", hres);
ok(V_VT(&v) == VT_DISPATCH, "V_VT(v) = %d\n", V_VT(&v));
hres = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IDispatchEx, (void**)&dispex);
ok(hres == S_OK, "Could not get IDispatchEx iface: %08lx\n", hres);
VariantClear(&v);
str = SysAllocString(L"caller");
hres = IDispatchEx_GetDispID(dispex, str, fdexNameEnsure, &func_id);
SysFreeString(str);
ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
SET_EXPECT(test_caller_get);
dp.cArgs = dp.cNamedArgs = 1;
dp.rgvarg = &arg;
dp.rgdispidNamedArgs = &propput_dispid;
V_VT(&arg) = VT_DISPATCH;
V_DISPATCH(&arg) = (IDispatch*)&testcallerobj;
hres = IDispatchEx_InvokeEx(dispex, func_id, 0, DISPATCH_PROPERTYPUT, &dp, NULL, NULL, NULL);
ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres);
todo_wine
CHECK_CALLED(test_caller_get);
SET_EXPECT(test_caller_null);
dp.cArgs = dp.cNamedArgs = 0;
dp.rgvarg = NULL;
dp.rgdispidNamedArgs = NULL;
hres = IDispatchEx_InvokeEx(dispex, func_id, 0, DISPATCH_METHOD, &dp, &v, NULL, NULL);
ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres);
ok(V_VT(&v) == VT_I4, "V_VT(v) = %d\n", V_VT(&v));
ok(V_I4(&v) == 42, "V_I4(v) = %s\n", wine_dbgstr_variant(&v));
CHECK_CALLED(test_caller_null);
V_VT(&v) = VT_EMPTY;
SET_EXPECT(test_caller_obj);
hres = IDispatchEx_InvokeEx(dispex, func_id, 0, DISPATCH_METHOD, &dp, &v, NULL, &sp_obj);
ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres);
ok(V_VT(&v) == VT_I4, "V_VT(v) = %d\n", V_VT(&v));
ok(V_I4(&v) == 137, "V_I4(v) = %s\n", wine_dbgstr_variant(&v));
CHECK_CALLED(test_caller_obj);
IDispatchEx_Release(dispex);
IActiveScript_Release(script);
}
static void test_destructors(void)