From: Francis De Brabandere <francisdb@gmail.com> FuncRef_Invoke always ran the reference as an external caller, reporting errors to the host even when called from running script. Route the engine's own references through disp_call as internal calls, like class instances, so a reference reaching FuncRef_Invoke is always an external caller. --- dlls/vbscript/vbdisp.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index 554d410b57e..38e4ed140ab 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -857,6 +857,10 @@ static HRESULT WINAPI FuncRef_Invoke(IDispatch *iface, DISPID dispIdMember, REFI if(dispIdMember != DISPID_VALUE) return DISP_E_MEMBERNOTFOUND; + /* The engine runs its own references through disp_call as internal calls; + * reaching this vtable entry means the caller is outside the engine, so the + * reference is entered as an external caller and errors are reported to the + * host rather than propagated as an HRESULT. */ return exec_script(This->ctx, TRUE, This->func, NULL, pDispParams, pVarResult); } @@ -870,6 +874,11 @@ static const IDispatchVtbl FuncRefVtbl = { FuncRef_Invoke }; +static inline FuncRef *unsafe_funcref_from_IDispatch(IDispatch *iface) +{ + return iface->lpVtbl == &FuncRefVtbl ? FuncRef_from_IDispatch(iface) : NULL; +} + HRESULT create_func_ref(script_ctx_t *ctx, function_t *func, IDispatch **ret) { FuncRef *ref; @@ -2009,6 +2018,7 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, BOOL is_call, D const WORD flags = DISPATCH_METHOD|(retv ? DISPATCH_PROPERTYGET : 0); IDispatchEx *dispex; vbdisp_t *vbdisp; + FuncRef *funcref; EXCEPINFO ei; HRESULT hres; @@ -2020,6 +2030,10 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, BOOL is_call, D if(vbdisp && vbdisp->desc && vbdisp->desc->ctx == ctx) return invoke_vbdisp(vbdisp, id, flags, FALSE, is_call, dp, retv); + funcref = unsafe_funcref_from_IDispatch(disp); + if(funcref && funcref->ctx == ctx && id == DISPID_VALUE) + return exec_script(ctx, FALSE, funcref->func, NULL, dp, retv); + hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); if(SUCCEEDED(hres)) { hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, dp, retv, &ei, &ctx->vbcaller->IServiceProvider_iface); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10980