Map known HRESULT values into their FACILITY_VBS counterparts
Unless the callee provided its own Description (e.g. via SetErrorInfo) VBscript maps certain well-known HRESULT values into its own error facility and messages, changing Err.Number and also setting Err.Source to itself (unless already provided, in which case it is left alone)
e.g. if the invoked method returns E_NOINTERFACE, The VBScript Err object should show
Err.Number: 0x1AE Err.Source: Microsoft VBScript runtime error Err.Description: Class doesn't support Automation
Rather than the original HRESULT
Err.Number: 0x80004002
-- v3: vbscript: do HRESULT->VBSERROR mapping for the whole EXCEPINFO at once. vbscript/tests: test throwException with Description but *not* Source. vbscript: only set EXCEPINFO strings for cases that map_hres translated. vbscript: Fix handling missing description in EXCEPINFO.
From: Jacek Caban jacek@codeweavers.com
Based on patch by Kevin Puetz. --- dlls/vbscript/interp.c | 13 ++-- dlls/vbscript/tests/run.c | 126 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 4 deletions(-)
diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index c43b5383dee..1d7482b5013 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -2490,14 +2490,19 @@ HRESULT exec_script(script_ctx_t *ctx, BOOL extern_caller, function_t *func, vbd if(FAILED(hres)) { if(hres != SCRIPT_E_RECORDED) { clear_ei(&ctx->ei); - - ctx->ei.scode = hres = map_hres(hres); - ctx->ei.bstrSource = get_vbscript_string(VBS_RUNTIME_ERROR); - ctx->ei.bstrDescription = get_vbscript_error_string(hres); + hres = map_hres(hres); + }else if(!ctx->ei.bstrDescription) { + hres = map_hres(ctx->ei.scode); }else { hres = ctx->ei.scode; }
+ ctx->ei.scode = hres; + if(!ctx->ei.bstrSource) + ctx->ei.bstrSource = get_vbscript_string(VBS_RUNTIME_ERROR); + if(!ctx->ei.bstrDescription) + ctx->ei.bstrDescription = get_vbscript_error_string(hres); + if(exec.resume_next) { unsigned stack_off;
diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index 556772e1f37..8d7c15ba70b 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -145,6 +145,7 @@ DEFINE_EXPECT(OnLeaveScript); #define DISPID_GLOBAL_THROWWITHDESC 1024 #define DISPID_GLOBAL_PROPARGSET 1025 #define DISPID_GLOBAL_UNKOBJ 1026 +#define DISPID_GLOBAL_THROWEXCEPTION 1027
#define DISPID_TESTOBJ_PROPGET 2000 #define DISPID_TESTOBJ_PROPPUT 2001 @@ -1157,6 +1158,7 @@ static HRESULT WINAPI Global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD { L"counter", DISPID_GLOBAL_COUNTER }, { L"doubleAsString", DISPID_GLOBAL_DOUBLEASSTRING }, { L"testArray", DISPID_GLOBAL_TESTARRAY }, + { L"throwException", DISPID_GLOBAL_THROWEXCEPTION }, { L"throwInt", DISPID_GLOBAL_THROWINT }, { L"testOptionalArg", DISPID_GLOBAL_TESTOPTIONALARG }, { L"testErrorObject", DISPID_GLOBAL_TESTERROROBJECT }, @@ -1540,6 +1542,54 @@ static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid,
return hres;
+ case DISPID_GLOBAL_THROWEXCEPTION: { + VARIANT *v = pdp->rgvarg + pdp->cArgs - 1; + + ok((wFlags & ~INVOKE_PROPERTYGET) == INVOKE_FUNC, "wFlags = %x\n", wFlags); + 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(pei != NULL, "pei == NULL\n"); + + if(pvarRes) { + ok(V_VT(pvarRes) == VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes)); + V_VT(pvarRes) = VT_BOOL; + V_BOOL(pvarRes) = VARIANT_FALSE; + } + + if(V_VT(v) == (VT_VARIANT|VT_BYREF)) + v = V_VARIANTREF(v); + + memset(pei, 0, sizeof(*pei)); + switch(V_VT(v)) { + case VT_I2: + pei->scode = V_I2(v); + break; + case VT_I4: + pei->scode = V_I4(v); + break; + default: + ok(0, "unexpected vt %d\n", V_VT(v)); + return E_INVALIDARG; + } + + if(pdp->cArgs >= 2) { + v = pdp->rgvarg + pdp->cArgs - 2; + ok(V_VT(v) == VT_BSTR, "v = %s\n", debugstr_variant(v)); + pei->bstrSource = SysAllocString(V_BSTR(v)); + } + + if(pdp->cArgs >= 3) { + v = pdp->rgvarg + pdp->cArgs - 3; + ok(V_VT(v) == VT_BSTR, "v = %s\n", debugstr_variant(v)); + pei->bstrDescription = SysAllocString(V_BSTR(v)); + } + + return DISP_E_EXCEPTION; + } + case DISPID_GLOBAL_THROWWITHDESC: pei->scode = 0xdeadbeef; pei->bstrDescription = SysAllocString(L"test"); @@ -2351,6 +2401,82 @@ static void test_callbacks(void) IActiveScriptParse_Release(parser); close_script(script); strict_enter_script = FALSE; + + store_script_error = &error1; + SET_EXPECT(OnScriptError); + hres = parse_script_ar("throwException &h80004002&"); + ok(hres == MAKE_VBSERROR(430), "got error: %08lx\n", hres); + CHECK_CALLED(OnScriptError); + + memset(&ei, 0xcc, sizeof(ei)); + hres = IActiveScriptError_GetExceptionInfo(error1, &ei); + ok(hres == S_OK, "GetExceptionInfo returned %08lx\n", hres); + ok(!ei.wCode, "wCode = %x\n", ei.wCode); + ok(!ei.wReserved, "wReserved = %x\n", ei.wReserved); + if(is_english) { + ok(!wcscmp(ei.bstrSource, L"Microsoft VBScript runtime error"), + "bstrSource = %s\n", wine_dbgstr_w(ei.bstrSource)); + ok(!wcscmp(ei.bstrDescription, L"Class doesn't support Automation"), + "bstrDescription = %s\n", wine_dbgstr_w(ei.bstrDescription)); + } + ok(!ei.bstrHelpFile, "bstrHelpFile = %s\n", wine_dbgstr_w(ei.bstrHelpFile)); + ok(!ei.dwHelpContext, "dwHelpContext = %lx\n", ei.dwHelpContext); + ok(!ei.pvReserved, "pvReserved = %p\n", ei.pvReserved); + ok(!ei.pfnDeferredFillIn, "pfnDeferredFillIn = %p\n", ei.pfnDeferredFillIn); + ok(ei.scode == MAKE_VBSERROR(430), "scode = %lx\n", ei.scode); + free_ei(&ei); + + IActiveScriptError_Release(error1); + + store_script_error = &error1; + SET_EXPECT(OnScriptError); + hres = parse_script_ar("throwException &h80004002&, "test src""); + ok(hres == MAKE_VBSERROR(430), "got error: %08lx\n", hres); + CHECK_CALLED(OnScriptError); + + memset(&ei, 0xcc, sizeof(ei)); + hres = IActiveScriptError_GetExceptionInfo(error1, &ei); + ok(hres == S_OK, "GetExceptionInfo returned %08lx\n", hres); + ok(!ei.wCode, "wCode = %x\n", ei.wCode); + ok(!ei.wReserved, "wReserved = %x\n", ei.wReserved); + if(is_english) { + ok(!wcscmp(ei.bstrSource, L"test src"), "bstrSource = %s\n", wine_dbgstr_w(ei.bstrSource)); + ok(!wcscmp(ei.bstrDescription, L"Class doesn't support Automation"), + "bstrDescription = %s\n", wine_dbgstr_w(ei.bstrDescription)); + } + ok(!ei.bstrHelpFile, "bstrHelpFile = %s\n", wine_dbgstr_w(ei.bstrHelpFile)); + ok(!ei.dwHelpContext, "dwHelpContext = %lx\n", ei.dwHelpContext); + ok(!ei.pvReserved, "pvReserved = %p\n", ei.pvReserved); + ok(!ei.pfnDeferredFillIn, "pfnDeferredFillIn = %p\n", ei.pfnDeferredFillIn); + ok(ei.scode == MAKE_VBSERROR(430), "scode = %lx\n", ei.scode); + free_ei(&ei); + + IActiveScriptError_Release(error1); + + store_script_error = &error1; + SET_EXPECT(OnScriptError); + hres = parse_script_ar("throwException &h80004002&, "test src", "test desc""); + ok(hres == E_NOINTERFACE, "got error: %08lx\n", hres); + CHECK_CALLED(OnScriptError); + + memset(&ei, 0xcc, sizeof(ei)); + hres = IActiveScriptError_GetExceptionInfo(error1, &ei); + ok(hres == S_OK, "GetExceptionInfo returned %08lx\n", hres); + ok(!ei.wCode, "wCode = %x\n", ei.wCode); + ok(!ei.wReserved, "wReserved = %x\n", ei.wReserved); + if(is_english) { + ok(!wcscmp(ei.bstrSource, L"test src"), "bstrSource = %s\n", wine_dbgstr_w(ei.bstrSource)); + ok(!wcscmp(ei.bstrDescription, L"test desc"), + "bstrDescription = %s\n", wine_dbgstr_w(ei.bstrDescription)); + } + ok(!ei.bstrHelpFile, "bstrHelpFile = %s\n", wine_dbgstr_w(ei.bstrHelpFile)); + ok(!ei.dwHelpContext, "dwHelpContext = %lx\n", ei.dwHelpContext); + ok(!ei.pvReserved, "pvReserved = %p\n", ei.pvReserved); + ok(!ei.pfnDeferredFillIn, "pfnDeferredFillIn = %p\n", ei.pfnDeferredFillIn); + ok(ei.scode == E_NOINTERFACE, "scode = %lx\n", ei.scode); + free_ei(&ei); + + IActiveScriptError_Release(error1); }
static void test_gc(void)
From: Kevin Puetz PuetzKevinA@JohnDeere.com
add test for E_UNEXPECTED --- dlls/vbscript/interp.c | 11 +++++++---- dlls/vbscript/tests/run.c | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-)
diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index 1d7482b5013..fae2c0fccbb 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -2498,10 +2498,13 @@ HRESULT exec_script(script_ctx_t *ctx, BOOL extern_caller, function_t *func, vbd }
ctx->ei.scode = hres; - if(!ctx->ei.bstrSource) - ctx->ei.bstrSource = get_vbscript_string(VBS_RUNTIME_ERROR); - if(!ctx->ei.bstrDescription) - ctx->ei.bstrDescription = get_vbscript_error_string(hres); + if(HRESULT_FACILITY(hres) == FACILITY_VBS) + { + if(!ctx->ei.bstrSource) + ctx->ei.bstrSource = get_vbscript_string(VBS_RUNTIME_ERROR); + if(!ctx->ei.bstrDescription) + ctx->ei.bstrDescription = get_vbscript_error_string(hres); + }
if(exec.resume_next) { unsigned stack_off; diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index 8d7c15ba70b..ef26641d01d 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -2477,6 +2477,32 @@ static void test_callbacks(void) free_ei(&ei);
IActiveScriptError_Release(error1); + + store_script_error = &error1; + SET_EXPECT(OnScriptError); + hres = parse_script_ar("throwException &h8000FFFF&"); + ok(hres == E_UNEXPECTED, "got error: %08lx\n", hres); + CHECK_CALLED(OnScriptError); + + memset(&ei, 0xcc, sizeof(ei)); + hres = IActiveScriptError_GetExceptionInfo(error1, &ei); + ok(hres == S_OK, "GetExceptionInfo returned %08lx\n", hres); + ok(!ei.wCode, "wCode = %x\n", ei.wCode); + ok(!ei.wReserved, "wReserved = %x\n", ei.wReserved); + if(is_english) { + ok(!ei.bstrSource, + "bstrSource = %s\n", wine_dbgstr_w(ei.bstrSource)); + ok(!ei.bstrDescription, + "bstrDescription = %s\n", wine_dbgstr_w(ei.bstrDescription)); + } + ok(!ei.bstrHelpFile, "bstrHelpFile = %s\n", wine_dbgstr_w(ei.bstrHelpFile)); + ok(!ei.dwHelpContext, "dwHelpContext = %lx\n", ei.dwHelpContext); + ok(!ei.pvReserved, "pvReserved = %p\n", ei.pvReserved); + ok(!ei.pfnDeferredFillIn, "pfnDeferredFillIn = %p\n", ei.pfnDeferredFillIn); + ok(ei.scode == E_UNEXPECTED, "scode = %lx\n", ei.scode); + free_ei(&ei); + + IActiveScriptError_Release(error1); }
static void test_gc(void)
From: Kevin Puetz PuetzKevinA@JohnDeere.com
It occurred to me to wonder whether it was really Description, Source, or both that results in skipping the map_vbs_exception logic.
It turns out we had it right (it's just description, and it's null-pointer and not empty string that makes the difference).
But the fact that it's not obvious still makes it a good testcase --- dlls/vbscript/tests/run.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-)
diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index ef26641d01d..31ac03ab8d7 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -1577,8 +1577,11 @@ static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid,
if(pdp->cArgs >= 2) { v = pdp->rgvarg + pdp->cArgs - 2; - ok(V_VT(v) == VT_BSTR, "v = %s\n", debugstr_variant(v)); - pei->bstrSource = SysAllocString(V_BSTR(v)); + if(!(V_VT(v) == VT_ERROR && V_ERROR(v) == DISP_E_PARAMNOTFOUND)) /* != vtMissing */ + { + ok(V_VT(v) == VT_BSTR, "v = %s\n", debugstr_variant(v)); + pei->bstrSource = SysAllocString(V_BSTR(v)); + } }
if(pdp->cArgs >= 3) { @@ -2453,6 +2456,31 @@ static void test_callbacks(void)
IActiveScriptError_Release(error1);
+ store_script_error = &error1; + SET_EXPECT(OnScriptError); + hres = parse_script_ar("throwException &h80004002&, , "test desc""); + ok(hres == E_NOINTERFACE, "got error: %08lx\n", hres); + CHECK_CALLED(OnScriptError); + + memset(&ei, 0xcc, sizeof(ei)); + hres = IActiveScriptError_GetExceptionInfo(error1, &ei); + ok(hres == S_OK, "GetExceptionInfo returned %08lx\n", hres); + ok(!ei.wCode, "wCode = %x\n", ei.wCode); + ok(!ei.wReserved, "wReserved = %x\n", ei.wReserved); + if(is_english) { + ok(!ei.bstrSource, "bstrSource = %s\n", wine_dbgstr_w(ei.bstrSource)); + ok(!wcscmp(ei.bstrDescription, L"test desc"), + "bstrDescription = %s\n", wine_dbgstr_w(ei.bstrDescription)); + } + ok(!ei.bstrHelpFile, "bstrHelpFile = %s\n", wine_dbgstr_w(ei.bstrHelpFile)); + ok(!ei.dwHelpContext, "dwHelpContext = %lx\n", ei.dwHelpContext); + ok(!ei.pvReserved, "pvReserved = %p\n", ei.pvReserved); + ok(!ei.pfnDeferredFillIn, "pfnDeferredFillIn = %p\n", ei.pfnDeferredFillIn); + ok(ei.scode == E_NOINTERFACE, "scode = %lx\n", ei.scode); + free_ei(&ei); + + IActiveScriptError_Release(error1); + store_script_error = &error1; SET_EXPECT(OnScriptError); hres = parse_script_ar("throwException &h80004002&, "test src", "test desc"");
From: Kevin Puetz PuetzKevinA@JohnDeere.com
--- dlls/vbscript/compile.c | 4 +- dlls/vbscript/global.c | 12 ++-- dlls/vbscript/interp.c | 19 ++---- dlls/vbscript/vbdisp.c | 121 ++++++++++++++++++---------------- dlls/vbscript/vbscript.h | 3 +- dlls/vbscript/vbscript_main.c | 8 --- 6 files changed, 77 insertions(+), 90 deletions(-)
diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index 50c68a6e6b5..79819c39026 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -399,9 +399,9 @@ static HRESULT compile_error(script_ctx_t *ctx, compile_ctx_t *compiler, HRESULT return error;
clear_ei(&ctx->ei); - ctx->ei.scode = error = map_hres(error); + ctx->ei.scode = error; ctx->ei.bstrSource = get_vbscript_string(VBS_COMPILE_ERROR); - ctx->ei.bstrDescription = get_vbscript_error_string(error); + map_vbs_exception(&ctx->ei); return report_script_error(ctx, compiler->code, compiler->loc); }
diff --git a/dlls/vbscript/global.c b/dlls/vbscript/global.c index 4b5dee6ebc3..f35c4ac2fc4 100644 --- a/dlls/vbscript/global.c +++ b/dlls/vbscript/global.c @@ -3288,7 +3288,7 @@ static HRESULT Err_Raise(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VA { BSTR source = NULL, description = NULL, helpfile = NULL; int code, helpcontext = 0; - HRESULT hres, error; + HRESULT hres;
TRACE("%s %u...\n", debugstr_variant(args), args_cnt);
@@ -3310,20 +3310,14 @@ static HRESULT Err_Raise(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VA if(SUCCEEDED(hres)) { script_ctx_t *ctx = This->ctx;
- error = (code & ~0xffff) ? map_hres(code) : MAKE_VBSERROR(code); - if(source) { SysFreeString(ctx->ei.bstrSource); ctx->ei.bstrSource = source; } - if(!ctx->ei.bstrSource) - ctx->ei.bstrSource = get_vbscript_string(VBS_RUNTIME_ERROR); if(description) { SysFreeString(ctx->ei.bstrDescription); ctx->ei.bstrDescription = description; } - if(!ctx->ei.bstrDescription) - ctx->ei.bstrDescription = get_vbscript_error_string(error); if(helpfile) { SysFreeString(ctx->ei.bstrHelpFile); ctx->ei.bstrHelpFile = helpfile; @@ -3331,7 +3325,9 @@ static HRESULT Err_Raise(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VA if(args_cnt >= 5) ctx->ei.dwHelpContext = helpcontext;
- ctx->ei.scode = error; + ctx->ei.scode = (code & ~0xffff) ? code : MAKE_VBSERROR(code); + map_vbs_exception(&ctx->ei); + hres = SCRIPT_E_RECORDED; }else { SysFreeString(source); diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index fae2c0fccbb..2d40e6efe47 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -2489,27 +2489,18 @@ HRESULT exec_script(script_ctx_t *ctx, BOOL extern_caller, function_t *func, vbd hres = op_funcs[op](&exec); if(FAILED(hres)) { if(hres != SCRIPT_E_RECORDED) { + /* SCRIPT_E_RECORDED means ctx->ei is already populated */ clear_ei(&ctx->ei); - hres = map_hres(hres); - }else if(!ctx->ei.bstrDescription) { - hres = map_hres(ctx->ei.scode); - }else { - hres = ctx->ei.scode; + ctx->ei.scode = hres; }
- ctx->ei.scode = hres; - if(HRESULT_FACILITY(hres) == FACILITY_VBS) - { - if(!ctx->ei.bstrSource) - ctx->ei.bstrSource = get_vbscript_string(VBS_RUNTIME_ERROR); - if(!ctx->ei.bstrDescription) - ctx->ei.bstrDescription = get_vbscript_error_string(hres); - } + if(!ctx->ei.bstrDescription) + map_vbs_exception(&ctx->ei);
if(exec.resume_next) { unsigned stack_off;
- WARN("Failed %08lx in resume next mode\n", hres); + WARN("Failed %08lx in resume next mode\n", ctx->ei.scode);
/* * Unwinding here is simple. We need to find the next OP_catch, which contains diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index 1c6f68255bd..74da0a21fb0 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -1563,65 +1563,74 @@ HRESULT disp_get_id(IDispatch *disp, BSTR name, vbdisp_invoke_type_t invoke_type
#define RPC_E_SERVER_UNAVAILABLE 0x800706ba
-HRESULT map_hres(HRESULT hres) +void map_vbs_exception(EXCEPINFO *ei) { - if(SUCCEEDED(hres) || HRESULT_FACILITY(hres) == FACILITY_VBS) - return hres; + int vbse_number;
- switch(hres) { - case E_NOTIMPL: return MAKE_VBSERROR(VBSE_ACTION_NOT_SUPPORTED); - case E_NOINTERFACE: return MAKE_VBSERROR(VBSE_OLE_NOT_SUPPORTED); - case DISP_E_UNKNOWNINTERFACE: return MAKE_VBSERROR(VBSE_OLE_NO_PROP_OR_METHOD); - case DISP_E_MEMBERNOTFOUND: return MAKE_VBSERROR(VBSE_OLE_NO_PROP_OR_METHOD); - case DISP_E_PARAMNOTFOUND: return MAKE_VBSERROR(VBSE_NAMED_PARAM_NOT_FOUND); - case DISP_E_TYPEMISMATCH: return MAKE_VBSERROR(VBSE_TYPE_MISMATCH); - case DISP_E_UNKNOWNNAME: return MAKE_VBSERROR(VBSE_OLE_NO_PROP_OR_METHOD); - case DISP_E_NONAMEDARGS: return MAKE_VBSERROR(VBSE_NAMED_ARGS_NOT_SUPPORTED); - case DISP_E_BADVARTYPE: return MAKE_VBSERROR(VBSE_INVALID_TYPELIB_VARIABLE); - case DISP_E_OVERFLOW: return MAKE_VBSERROR(VBSE_OVERFLOW); - case DISP_E_BADINDEX: return MAKE_VBSERROR(VBSE_OUT_OF_BOUNDS); - case DISP_E_UNKNOWNLCID: return MAKE_VBSERROR(VBSE_LOCALE_SETTING_NOT_SUPPORTED); - case DISP_E_ARRAYISLOCKED: return MAKE_VBSERROR(VBSE_ARRAY_LOCKED); - case DISP_E_BADPARAMCOUNT: return MAKE_VBSERROR(VBSE_FUNC_ARITY_MISMATCH); - case DISP_E_PARAMNOTOPTIONAL: return MAKE_VBSERROR(VBSE_PARAMETER_NOT_OPTIONAL); - case DISP_E_NOTACOLLECTION: return MAKE_VBSERROR(VBSE_NOT_ENUM); - case TYPE_E_DLLFUNCTIONNOTFOUND: return MAKE_VBSERROR(VBSE_INVALID_DLL_FUNCTION_NAME); - case TYPE_E_TYPEMISMATCH: return MAKE_VBSERROR(VBSE_TYPE_MISMATCH); - case TYPE_E_OUTOFBOUNDS: return MAKE_VBSERROR(VBSE_OUT_OF_BOUNDS); - case TYPE_E_IOERROR: return MAKE_VBSERROR(VBSE_IO_ERROR); - case TYPE_E_CANTCREATETMPFILE: return MAKE_VBSERROR(VBSE_CANT_CREATE_TMP_FILE); - case STG_E_FILENOTFOUND: return MAKE_VBSERROR(VBSE_OLE_FILE_NOT_FOUND); - case STG_E_PATHNOTFOUND: return MAKE_VBSERROR(VBSE_PATH_NOT_FOUND); - case STG_E_TOOMANYOPENFILES: return MAKE_VBSERROR(VBSE_TOO_MANY_FILES); - case STG_E_ACCESSDENIED: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED); - case STG_E_INSUFFICIENTMEMORY: return MAKE_VBSERROR(VBSE_OUT_OF_MEMORY); - case STG_E_NOMOREFILES: return MAKE_VBSERROR(VBSE_TOO_MANY_FILES); - case STG_E_DISKISWRITEPROTECTED: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED); - case STG_E_WRITEFAULT: return MAKE_VBSERROR(VBSE_IO_ERROR); - case STG_E_READFAULT: return MAKE_VBSERROR(VBSE_IO_ERROR); - case STG_E_SHAREVIOLATION: return MAKE_VBSERROR(VBSE_PATH_FILE_ACCESS); - case STG_E_LOCKVIOLATION: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED); - case STG_E_FILEALREADYEXISTS: return MAKE_VBSERROR(VBSE_FILE_ALREADY_EXISTS); - case STG_E_MEDIUMFULL: return MAKE_VBSERROR(VBSE_DISK_FULL); - case STG_E_INVALIDNAME: return MAKE_VBSERROR(VBSE_FILE_NOT_FOUND); - case STG_E_INUSE: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED); - case STG_E_NOTCURRENT: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED); - case STG_E_CANTSAVE: return MAKE_VBSERROR(VBSE_IO_ERROR); - case REGDB_E_CLASSNOTREG: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT); - case MK_E_UNAVAILABLE: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT); - case MK_E_INVALIDEXTENSION: return MAKE_VBSERROR(VBSE_OLE_FILE_NOT_FOUND); - case MK_E_CANTOPENFILE: return MAKE_VBSERROR(VBSE_OLE_FILE_NOT_FOUND); - case CO_E_CLASSSTRING: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT); - case CO_E_APPNOTFOUND: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT); - case CO_E_APPDIDNTREG: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT); - case E_ACCESSDENIED: return MAKE_VBSERROR(VBSE_PERMISSION_DENIED); - case E_OUTOFMEMORY: return MAKE_VBSERROR(VBSE_OUT_OF_MEMORY); - case E_INVALIDARG: return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL); - case RPC_E_SERVER_UNAVAILABLE: return MAKE_VBSERROR(VBSE_SERVER_NOT_FOUND); - case CO_E_SERVER_EXEC_FAILURE: return MAKE_VBSERROR(VBSE_CANT_CREATE_OBJECT); + if(HRESULT_FACILITY(ei->scode) == FACILITY_VBS) + vbse_number = HRESULT_CODE(ei->scode); + else + { + switch(ei->scode) { + case E_NOTIMPL: vbse_number = VBSE_ACTION_NOT_SUPPORTED; break; + case E_NOINTERFACE: vbse_number = VBSE_OLE_NOT_SUPPORTED; break; + case DISP_E_UNKNOWNINTERFACE: vbse_number = VBSE_OLE_NO_PROP_OR_METHOD; break; + case DISP_E_MEMBERNOTFOUND: vbse_number = VBSE_OLE_NO_PROP_OR_METHOD; break; + case DISP_E_PARAMNOTFOUND: vbse_number = VBSE_NAMED_PARAM_NOT_FOUND; break; + case DISP_E_TYPEMISMATCH: vbse_number = VBSE_TYPE_MISMATCH; break; + case DISP_E_UNKNOWNNAME: vbse_number = VBSE_OLE_NO_PROP_OR_METHOD; break; + case DISP_E_NONAMEDARGS: vbse_number = VBSE_NAMED_ARGS_NOT_SUPPORTED; break; + case DISP_E_BADVARTYPE: vbse_number = VBSE_INVALID_TYPELIB_VARIABLE; break; + case DISP_E_OVERFLOW: vbse_number = VBSE_OVERFLOW; break; + case DISP_E_BADINDEX: vbse_number = VBSE_OUT_OF_BOUNDS; break; + case DISP_E_UNKNOWNLCID: vbse_number = VBSE_LOCALE_SETTING_NOT_SUPPORTED; break; + case DISP_E_ARRAYISLOCKED: vbse_number = VBSE_ARRAY_LOCKED; break; + case DISP_E_BADPARAMCOUNT: vbse_number = VBSE_FUNC_ARITY_MISMATCH; break; + case DISP_E_PARAMNOTOPTIONAL: vbse_number = VBSE_PARAMETER_NOT_OPTIONAL; break; + case DISP_E_NOTACOLLECTION: vbse_number = VBSE_NOT_ENUM; break; + case TYPE_E_DLLFUNCTIONNOTFOUND: vbse_number = VBSE_INVALID_DLL_FUNCTION_NAME; break; + case TYPE_E_TYPEMISMATCH: vbse_number = VBSE_TYPE_MISMATCH; break; + case TYPE_E_OUTOFBOUNDS: vbse_number = VBSE_OUT_OF_BOUNDS; break; + case TYPE_E_IOERROR: vbse_number = VBSE_IO_ERROR; break; + case TYPE_E_CANTCREATETMPFILE: vbse_number = VBSE_CANT_CREATE_TMP_FILE; break; + case STG_E_FILENOTFOUND: vbse_number = VBSE_OLE_FILE_NOT_FOUND; break; + case STG_E_PATHNOTFOUND: vbse_number = VBSE_PATH_NOT_FOUND; break; + case STG_E_TOOMANYOPENFILES: vbse_number = VBSE_TOO_MANY_FILES; break; + case STG_E_ACCESSDENIED: vbse_number = VBSE_PERMISSION_DENIED; break; + case STG_E_INSUFFICIENTMEMORY: vbse_number = VBSE_OUT_OF_MEMORY; break; + case STG_E_NOMOREFILES: vbse_number = VBSE_TOO_MANY_FILES; break; + case STG_E_DISKISWRITEPROTECTED: vbse_number = VBSE_PERMISSION_DENIED; break; + case STG_E_WRITEFAULT: vbse_number = VBSE_IO_ERROR; break; + case STG_E_READFAULT: vbse_number = VBSE_IO_ERROR; break; + case STG_E_SHAREVIOLATION: vbse_number = VBSE_PATH_FILE_ACCESS; break; + case STG_E_LOCKVIOLATION: vbse_number = VBSE_PERMISSION_DENIED; break; + case STG_E_FILEALREADYEXISTS: vbse_number = VBSE_FILE_ALREADY_EXISTS; break; + case STG_E_MEDIUMFULL: vbse_number = VBSE_DISK_FULL; break; + case STG_E_INVALIDNAME: vbse_number = VBSE_FILE_NOT_FOUND; break; + case STG_E_INUSE: vbse_number = VBSE_PERMISSION_DENIED; break; + case STG_E_NOTCURRENT: vbse_number = VBSE_PERMISSION_DENIED; break; + case STG_E_CANTSAVE: vbse_number = VBSE_IO_ERROR; break; + case REGDB_E_CLASSNOTREG: vbse_number = VBSE_CANT_CREATE_OBJECT; break; + case MK_E_UNAVAILABLE: vbse_number = VBSE_CANT_CREATE_OBJECT; break; + case MK_E_INVALIDEXTENSION: vbse_number = VBSE_OLE_FILE_NOT_FOUND; break; + case MK_E_CANTOPENFILE: vbse_number = VBSE_OLE_FILE_NOT_FOUND; break; + case CO_E_CLASSSTRING: vbse_number = VBSE_CANT_CREATE_OBJECT; break; + case CO_E_APPNOTFOUND: vbse_number = VBSE_CANT_CREATE_OBJECT; break; + case CO_E_APPDIDNTREG: vbse_number = VBSE_CANT_CREATE_OBJECT; break; + case E_ACCESSDENIED: vbse_number = VBSE_PERMISSION_DENIED; break; + case E_OUTOFMEMORY: vbse_number = VBSE_OUT_OF_MEMORY; break; + case E_INVALIDARG: vbse_number = VBSE_ILLEGAL_FUNC_CALL; break; + case RPC_E_SERVER_UNAVAILABLE: vbse_number = VBSE_SERVER_NOT_FOUND; break; + case CO_E_SERVER_EXEC_FAILURE: vbse_number = VBSE_CANT_CREATE_OBJECT; break; + default: return; /* early return, all other HRESULT left as-is */ + } + ei->scode = MAKE_VBSERROR(vbse_number); } - - return hres; + if(!ei->bstrSource) + ei->bstrSource = get_vbscript_string(VBS_RUNTIME_ERROR); + if(!ei->bstrDescription) + if(!(ei->bstrDescription = get_vbscript_string(vbse_number))) + ei->bstrDescription = get_vbscript_string(VBS_UNKNOWN_RUNTIME_ERROR); }
HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, DISPPARAMS *dp, VARIANT *retv) diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index f5353b33cae..11564345aa3 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -399,7 +399,7 @@ static inline BOOL is_digit(WCHAR c) HRESULT create_regexp(IDispatch**) DECLSPEC_HIDDEN; BSTR string_replace(BSTR,BSTR,BSTR,int,int,int) DECLSPEC_HIDDEN;
-HRESULT map_hres(HRESULT) DECLSPEC_HIDDEN; +void map_vbs_exception(EXCEPINFO *) DECLSPEC_HIDDEN;
HRESULT create_safearray_iter(SAFEARRAY *sa, IEnumVARIANT **ev) DECLSPEC_HIDDEN;
@@ -410,7 +410,6 @@ HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,vo HRESULT WINAPI VBScriptRegExpFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**) DECLSPEC_HIDDEN;
BSTR get_vbscript_string(int) DECLSPEC_HIDDEN; -BSTR get_vbscript_error_string(HRESULT) DECLSPEC_HIDDEN;
static inline LPWSTR heap_strdupW(LPCWSTR str) { diff --git a/dlls/vbscript/vbscript_main.c b/dlls/vbscript/vbscript_main.c index c7f63c791ae..be74e4c458c 100644 --- a/dlls/vbscript/vbscript_main.c +++ b/dlls/vbscript/vbscript_main.c @@ -43,14 +43,6 @@ BSTR get_vbscript_string(int id) return SysAllocString(buf); }
-BSTR get_vbscript_error_string(HRESULT error) -{ - BSTR ret; - if(HRESULT_FACILITY(error) != FACILITY_VBS || !(ret = get_vbscript_string(HRESULT_CODE(error)))) - ret = get_vbscript_string(VBS_UNKNOWN_RUNTIME_ERROR); - return ret; -} - #define MIN_BLOCK_SIZE 128 #define ARENA_FREE_FILLER 0xaa
On Sat Sep 24 01:19:14 2022 +0000, Kevin Puetz wrote:
changed this line in [version 3 of the diff](/wine/wine/-/merge_requests/899/diffs?diff_id=12074&start_sha=69e9124991c0c86e3dd2ae9c086579e4e5b87cc1#19e0bfbc7699f0fd97292b7764d96290529571cd_1665_1666)
Done. I left it as your original commit, the extra test/minimal fix above, one more extra test case I thought of, and then a commit refactoring map_hres into map_vbs_exception, since I figured that makes it the easiest to read. But if you want it squashed to merge, just ask (or feel free to just do so)
This merge request was approved by Jacek Caban.