Module: wine Branch: master Commit: 274503c839de2a30aef22eab4b9dc879d254a813 URL: https://source.winehq.org/git/wine.git/?a=commit;h=274503c839de2a30aef22eab4...
Author: Jacek Caban jacek@codeweavers.com Date: Thu Jan 30 15:50:06 2020 +0100
jscript: Support DISP_E_EXCEPTION InvokeEx result.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/jscript/dispex.c | 184 +++++++++++++++++++------------------------------- 1 file changed, 69 insertions(+), 115 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index cd610e4e88..265e84aee8 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -1941,11 +1941,51 @@ HRESULT jsdisp_call_name(jsdisp_t *disp, const WCHAR *name, WORD flags, unsigned return invoke_prop_func(disp, to_disp(disp), prop, flags, argc, argv, r, NULL); }
-HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, unsigned argc, jsval_t *argv, jsval_t *ret) +static HRESULT disp_invoke(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, DISPPARAMS *params, VARIANT *r) { IDispatchEx *dispex; - jsdisp_t *jsdisp; + EXCEPINFO ei; + HRESULT hres; + + 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); + IDispatchEx_Release(dispex); + }else { + UINT err = 0; + + if(flags == DISPATCH_CONSTRUCT) { + WARN("IDispatch cannot be constructor\n"); + return DISP_E_MEMBERNOTFOUND; + } + + if(params->cNamedArgs == 1 && params->rgdispidNamedArgs[0] == DISPID_THIS) { + params->cNamedArgs = 0; + params->rgdispidNamedArgs = NULL; + params->cArgs--; + params->rgvarg++; + } + + TRACE("using IDispatch\n"); + hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, flags, params, r, &ei, &err); + } + + if(hres == DISP_E_EXCEPTION) { + TRACE("DISP_E_EXCEPTION: %08x %s %s\n", ei.scode, debugstr_w(ei.bstrSource), debugstr_w(ei.bstrDescription)); + hres = SUCCEEDED(ei.scode) ? E_FAIL : ei.scode; + SysFreeString(ei.bstrSource); + SysFreeString(ei.bstrDescription); + SysFreeString(ei.bstrHelpFile); + } + + return hres; +} + +HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, unsigned argc, jsval_t *argv, jsval_t *ret) +{ VARIANT buf[6], retv; + jsdisp_t *jsdisp; DISPPARAMS dp; unsigned i; HRESULT hres; @@ -1980,7 +2020,7 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, uns dp.rgdispidNamedArgs = NULL; }
- if(argc > 6) { + if(dp.cArgs > ARRAY_SIZE(buf)) { dp.rgvarg = heap_alloc(argc*sizeof(VARIANT)); if(!dp.rgvarg) return E_OUTOFMEMORY; @@ -2000,48 +2040,29 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, uns }
V_VT(&retv) = VT_EMPTY; - clear_ei(ctx); - hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); - if(SUCCEEDED(hres)) { - hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, &dp, ret ? &retv : NULL, &ctx->ei.ei, - &ctx->jscaller->IServiceProvider_iface); - IDispatchEx_Release(dispex); - }else { - UINT err = 0; - - if(flags == DISPATCH_CONSTRUCT) { - WARN("IDispatch cannot be constructor\n"); - return DISP_E_MEMBERNOTFOUND; - } - - TRACE("using IDispatch\n"); - hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, flags, &dp, ret ? &retv : NULL, &ctx->ei.ei, &err); - } + hres = disp_invoke(ctx, disp, id, flags, &dp, ret ? &retv : NULL);
for(i=0; i<argc; i++) VariantClear(dp.rgvarg+argc-i-1); if(dp.rgvarg != buf) heap_free(dp.rgvarg); - if(FAILED(hres)) - return hres;
- if(ret) { + if(SUCCEEDED(hres) && ret) hres = variant_to_jsval(&retv, ret); - VariantClear(&retv); - } - + VariantClear(&retv); return hres; }
HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { + VARIANT buf[6], retv, *args = buf; jsdisp_t *jsdisp; - IDispatchEx *dispex; - VARIANT buf[6], retv; DISPPARAMS dp; unsigned i; - HRESULT hres; + HRESULT hres = S_OK; + + static DISPID this_id = DISPID_THIS;
assert(!(flags & ~(DISPATCH_METHOD|DISPATCH_CONSTRUCT|DISPATCH_JSCRIPT_INTERNAL_MASK)));
@@ -2058,17 +2079,8 @@ HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, W if(r && argc && flags == DISPATCH_METHOD) flags |= DISPATCH_PROPERTYGET;
- hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); - if(FAILED(hres)) { - TRACE("using IDispatch\n"); - dispex = NULL; - jsthis = NULL; - } - if(jsthis) { - static DISPID this_id = DISPID_THIS; - - dp.cArgs = argc+1; + dp.cArgs = argc + 1; dp.cNamedArgs = 1; dp.rgdispidNamedArgs = &this_id; }else { @@ -2077,57 +2089,25 @@ HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, W dp.rgdispidNamedArgs = NULL; }
- if(dp.cArgs > ARRAY_SIZE(buf)) { - dp.rgvarg = heap_alloc(dp.cArgs*sizeof(VARIANT)); - if(!dp.rgvarg) { - if(dispex) - IDispatchEx_Release(dispex); - return E_OUTOFMEMORY; - } - }else { - dp.rgvarg = buf; - } - - for(i=0; i<argc; i++) { - hres = jsval_to_variant(argv[i], dp.rgvarg+dp.cArgs-i-1); - if(FAILED(hres)) { - while(i--) - VariantClear(dp.rgvarg+dp.cArgs-i-1); - if(dp.rgvarg != buf) - heap_free(dp.rgvarg); - if(dispex) - IDispatchEx_Release(dispex); - return hres; - } - } - if(jsthis) { - V_VT(dp.rgvarg) = VT_DISPATCH; - V_DISPATCH(dp.rgvarg) = jsthis; - } + if(argc > ARRAY_SIZE(buf) && !(args = heap_alloc(argc * sizeof(VARIANT)))) + return E_OUTOFMEMORY; + dp.rgvarg = args;
- V_VT(&retv) = VT_EMPTY; - clear_ei(ctx); - if(dispex) { - hres = IDispatchEx_InvokeEx(dispex, DISPID_VALUE, ctx->lcid, flags, &dp, r ? &retv : NULL, &ctx->ei.ei, - &ctx->jscaller->IServiceProvider_iface); - IDispatchEx_Release(dispex); - }else { - UINT err = 0; + V_VT(dp.rgvarg) = VT_DISPATCH; + V_DISPATCH(dp.rgvarg) = jsthis;
- if(flags == DISPATCH_CONSTRUCT) { - WARN("IDispatch cannot be constructor\n"); - return DISP_E_MEMBERNOTFOUND; - } + for(i=0; SUCCEEDED(hres) && i < argc; i++) + hres = jsval_to_variant(argv[i], dp.rgvarg+dp.cArgs-i-1);
- hres = IDispatch_Invoke(disp, DISPID_VALUE, &IID_NULL, ctx->lcid, flags, &dp, r ? &retv : NULL, &ctx->ei.ei, &err); + if(SUCCEEDED(hres)) { + V_VT(&retv) = VT_EMPTY; + hres = disp_invoke(ctx, disp, DISPID_VALUE, flags, &dp, r ? &retv : NULL); }
- for(i=0; i<argc; i++) - VariantClear(dp.rgvarg+dp.cArgs-i-1); - if(dp.rgvarg != buf) - heap_free(dp.rgvarg); - if(FAILED(hres)) - return hres; + for(i = 0; i < argc&&0; i++) + VariantClear(dp.rgvarg + dp.cArgs - i - 1); + if(args != buf) + heap_free(args);
if(!r) return S_OK; @@ -2185,7 +2165,6 @@ HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t val) DWORD flags = DISPATCH_PROPERTYPUT; VARIANT var; DISPPARAMS dp = {&var, &dispid, 1, 1}; - IDispatchEx *dispex;
hres = jsval_to_variant(val, &var); if(FAILED(hres)) @@ -2194,19 +2173,7 @@ HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t val) if(V_VT(&var) == VT_DISPATCH) flags |= DISPATCH_PROPERTYPUTREF;
- clear_ei(ctx); - hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); - if(SUCCEEDED(hres)) { - hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, &dp, NULL, &ctx->ei.ei, - &ctx->jscaller->IServiceProvider_iface); - IDispatchEx_Release(dispex); - }else { - ULONG err = 0; - - TRACE("using IDispatch\n"); - hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, flags, &dp, NULL, &ctx->ei.ei, &err); - } - + hres = disp_invoke(ctx, disp, id, flags, &dp, NULL); VariantClear(&var); }
@@ -2266,7 +2233,6 @@ HRESULT jsdisp_propget(jsdisp_t *jsdisp, DISPID id, jsval_t *val) HRESULT disp_propget(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t *val) { DISPPARAMS dp = {NULL,NULL,0,0}; - IDispatchEx *dispex; jsdisp_t *jsdisp; VARIANT var; HRESULT hres; @@ -2279,23 +2245,11 @@ HRESULT disp_propget(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t *val }
V_VT(&var) = VT_EMPTY; - clear_ei(ctx); - hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); + hres = disp_invoke(ctx, disp, id, INVOKE_PROPERTYGET, &dp, &var); if(SUCCEEDED(hres)) { - hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, INVOKE_PROPERTYGET, &dp, &var, &ctx->ei.ei, - &ctx->jscaller->IServiceProvider_iface); - IDispatchEx_Release(dispex); - }else { - ULONG err = 0; - - TRACE("using IDispatch\n"); - hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, INVOKE_PROPERTYGET, &dp, &var, &ctx->ei.ei, &err); + hres = variant_to_jsval(&var, val); + VariantClear(&var); } - if(FAILED(hres)) - return hres; - - hres = variant_to_jsval(&var, val); - VariantClear(&var); return hres; }