diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec index a07400ef8a1..c103916b591 100644 --- a/dlls/msvcr100/msvcr100.spec +++ b/dlls/msvcr100/msvcr100.spec @@ -1068,7 +1068,7 @@ @ stub _seh_longjmp_unwind4 @ stdcall -i386 _seh_longjmp_unwind(ptr) msvcrt._seh_longjmp_unwind @ cdecl _set_SSE2_enable(long) msvcrt._set_SSE2_enable -@ stub _set_abort_behavior +@ cdecl _set_abort_behavior(long long) msvcrt._set_abort_behavior @ stub _set_controlfp @ cdecl _set_doserrno(long) msvcrt._set_doserrno @ cdecl _set_errno(long) msvcrt._set_errno diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec index f98394436ab..4879e13fcc5 100644 --- a/dlls/msvcr80/msvcr80.spec +++ b/dlls/msvcr80/msvcr80.spec @@ -920,7 +920,7 @@ @ stub _seh_longjmp_unwind4 @ stdcall -i386 _seh_longjmp_unwind(ptr) msvcrt._seh_longjmp_unwind @ cdecl _set_SSE2_enable(long) msvcrt._set_SSE2_enable -@ stub _set_abort_behavior +@ cdecl _set_abort_behavior(long long) msvcrt._set_abort_behavior @ stub _set_amblksiz @ stub _set_controlfp @ cdecl _set_doserrno(long) msvcrt._set_doserrno diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec index fb9073d3298..aa0f981176a 100644 --- a/dlls/msvcr90/msvcr90.spec +++ b/dlls/msvcr90/msvcr90.spec @@ -906,7 +906,7 @@ @ stub _seh_longjmp_unwind4 @ stdcall -i386 _seh_longjmp_unwind(ptr) msvcrt._seh_longjmp_unwind @ cdecl _set_SSE2_enable(long) msvcrt._set_SSE2_enable -@ stub _set_abort_behavior +@ cdecl _set_abort_behavior(long long) msvcrt._set_abort_behavior @ stub _set_amblksiz @ stub _set_controlfp @ cdecl _set_doserrno(long) msvcrt._set_doserrno diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c index 40caa05fb54..dcf893de9a8 100644 --- a/dlls/msvcr90/tests/msvcr90.c +++ b/dlls/msvcr90/tests/msvcr90.c @@ -69,6 +69,7 @@ static int (__cdecl *p_wcsncat_s)(wchar_t *dst, size_t elem, const wchar_t *src, static void (__cdecl *p_qsort_s)(void *, size_t, size_t, int (__cdecl *)(void *, const void *, const void *), void *); static int (__cdecl *p_controlfp_s)(unsigned int *, unsigned int, unsigned int); static int (__cdecl *p_atoflt)(_CRT_FLOAT *, char *); +static unsigned int (__cdecl *p_set_abort_behavior)(unsigned int, unsigned int); static void* (WINAPI *pEncodePointer)(void *); @@ -680,6 +681,30 @@ if (0) } } +static void test__set_abort_behavior(void) +{ + unsigned int res; + + if (!p_set_abort_behavior) + { + win_skip("_set_abort_behavior not found\n"); + return; + } + + /* default is _WRITE_ABORT_MSG | _CALL_REPORTFAULT */ + res = p_set_abort_behavior(0, 0); + ok (res == (_WRITE_ABORT_MSG | _CALL_REPORTFAULT), + "got 0x%x (expected 0x%x)\n", res, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); + + /* no internal mask */ + p_set_abort_behavior(0xffffffff, 0xffffffff); + res = p_set_abort_behavior(0, 0); + ok (res == 0xffffffff, "got 0x%x (expected 0x%x)\n", res, 0xffffffff); + + /* set to default value */ + p_set_abort_behavior(_WRITE_ABORT_MSG | _CALL_REPORTFAULT, 0xffffffff); +} + START_TEST(msvcr90) { HMODULE hcrt; @@ -712,6 +737,7 @@ START_TEST(msvcr90) p_qsort_s = (void *) GetProcAddress(hcrt, "qsort_s"); p_controlfp_s = (void *) GetProcAddress(hcrt, "_controlfp_s"); p_atoflt = (void* )GetProcAddress(hcrt, "_atoflt"); + p_set_abort_behavior = (void *) GetProcAddress(hcrt, "_set_abort_behavior"); hkernel32 = GetModuleHandleA("kernel32.dll"); pEncodePointer = (void *) GetProcAddress(hkernel32, "EncodePointer"); @@ -725,4 +751,5 @@ START_TEST(msvcr90) test_qsort_s(); test_controlfp_s(); test__atoflt(); + test__set_abort_behavior(); } diff --git a/dlls/msvcrt/exit.c b/dlls/msvcrt/exit.c index 80749fc86f2..ac7e9b345d0 100644 --- a/dlls/msvcrt/exit.c +++ b/dlls/msvcrt/exit.c @@ -39,6 +39,8 @@ static const char szMsgBoxTitle[] = "Wine C++ Runtime Library"; extern int MSVCRT_app_type; extern char *MSVCRT__pgmptr; +static unsigned int MSVCRT_abort_behavior = MSVCRT__WRITE_ABORT_MSG | MSVCRT__CALL_REPORTFAULT; + void (*CDECL _aexit_rtn)(int) = MSVCRT__exit; /* INTERNAL: call atexit functions */ @@ -150,17 +152,38 @@ void CDECL _amsg_exit(int errnum) void CDECL MSVCRT_abort(void) { TRACE("()\n"); - if (MSVCRT_app_type == 2) + + if (MSVCRT_abort_behavior & MSVCRT__WRITE_ABORT_MSG) { - DoMessageBox("Runtime error!", "abnormal program termination"); + if (MSVCRT_app_type == 2) + { + DoMessageBox("Runtime error!", "abnormal program termination"); + } + else + _cputs("\nabnormal program termination\n"); } - else - _cputs("\nabnormal program termination\n"); MSVCRT_raise(MSVCRT_SIGABRT); /* in case raise() returns */ MSVCRT__exit(3); } +/********************************************************************* + * _set_abort_behavior (MSVCRT.@) + * + * Not exported by native msvcrt, added in msvcr80 + */ +unsigned int CDECL MSVCRT__set_abort_behavior(unsigned int flags, unsigned int mask) +{ + unsigned int old = MSVCRT_abort_behavior; + + TRACE("%x, %x\n", flags, mask); + if (mask & MSVCRT__CALL_REPORTFAULT) + FIXME("_WRITE_CALL_REPORTFAULT unhandled\n"); + + MSVCRT_abort_behavior = (MSVCRT_abort_behavior & ~mask) | (flags & mask); + return old; +} + /********************************************************************* * _assert (MSVCRT.@) */ diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h index 9e29d31d5c1..d2292e4e54a 100644 --- a/dlls/msvcrt/msvcrt.h +++ b/dlls/msvcrt/msvcrt.h @@ -732,6 +732,10 @@ typedef void (__cdecl *MSVCRT___sighandler_t)(int); #define _MAX__TIME64_T (((MSVCRT___time64_t)0x00000007 << 32) | 0x93406FFF) +/* _set_abort_behavior codes */ +#define MSVCRT__WRITE_ABORT_MSG 1 +#define MSVCRT__CALL_REPORTFAULT 2 + void __cdecl MSVCRT_free(void*); void* __cdecl MSVCRT_malloc(MSVCRT_size_t); void* __cdecl MSVCRT_calloc(MSVCRT_size_t,MSVCRT_size_t); diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec index a6160a4dc04..85334d3bbec 100644 --- a/dlls/msvcrt/msvcrt.spec +++ b/dlls/msvcrt/msvcrt.spec @@ -1475,6 +1475,7 @@ @ varargs wscanf_s(wstr) MSVCRT_wscanf_s # Functions not exported in native dll: +@ cdecl _set_abort_behavior(long long) MSVCRT__set_abort_behavior @ cdecl _get_invalid_parameter_handler() @ cdecl _set_invalid_parameter_handler(ptr) @ cdecl _create_locale(long str) MSVCRT__create_locale diff --git a/dlls/msvcrt/tests/headers.c b/dlls/msvcrt/tests/headers.c index 829fe47926f..f02b61ff8cc 100644 --- a/dlls/msvcrt/tests/headers.c +++ b/dlls/msvcrt/tests/headers.c @@ -453,6 +453,8 @@ static void test_defines(void) CHECK_DEF(_EM_AMBIGUOUS); CHECK_DEF(_OVERFLOW); CHECK_DEF(_UNDERFLOW); + CHECK_DEF(_WRITE_ABORT_MSG); + CHECK_DEF(_CALL_REPORTFAULT); } #endif /* __WINE_USE_MSVCRT */ diff --git a/include/msvcrt/stdlib.h b/include/msvcrt/stdlib.h index d30e483054d..6a6398d0fd6 100644 --- a/include/msvcrt/stdlib.h +++ b/include/msvcrt/stdlib.h @@ -73,6 +73,9 @@ typedef struct _ldiv_t { #define _OUT_TO_MSGBOX 2 #define _REPORT_ERRMODE 3 +/* _set_abort_behavior codes */ +#define _WRITE_ABORT_MSG 1 +#define _CALL_REPORTFAULT 2 #ifdef __cplusplus extern "C" {