Commit 03ca06e7 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

msvcrt: Partially implement _set_abort_behavior.

parent 103ef913
...@@ -1068,7 +1068,7 @@ ...@@ -1068,7 +1068,7 @@
@ stub _seh_longjmp_unwind4 @ stub _seh_longjmp_unwind4
@ stdcall -i386 _seh_longjmp_unwind(ptr) msvcrt._seh_longjmp_unwind @ stdcall -i386 _seh_longjmp_unwind(ptr) msvcrt._seh_longjmp_unwind
@ cdecl _set_SSE2_enable(long) msvcrt._set_SSE2_enable @ 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 @ stub _set_controlfp
@ cdecl _set_doserrno(long) msvcrt._set_doserrno @ cdecl _set_doserrno(long) msvcrt._set_doserrno
@ cdecl _set_errno(long) msvcrt._set_errno @ cdecl _set_errno(long) msvcrt._set_errno
......
...@@ -920,7 +920,7 @@ ...@@ -920,7 +920,7 @@
@ stub _seh_longjmp_unwind4 @ stub _seh_longjmp_unwind4
@ stdcall -i386 _seh_longjmp_unwind(ptr) msvcrt._seh_longjmp_unwind @ stdcall -i386 _seh_longjmp_unwind(ptr) msvcrt._seh_longjmp_unwind
@ cdecl _set_SSE2_enable(long) msvcrt._set_SSE2_enable @ 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_amblksiz
@ stub _set_controlfp @ stub _set_controlfp
@ cdecl _set_doserrno(long) msvcrt._set_doserrno @ cdecl _set_doserrno(long) msvcrt._set_doserrno
......
...@@ -906,7 +906,7 @@ ...@@ -906,7 +906,7 @@
@ stub _seh_longjmp_unwind4 @ stub _seh_longjmp_unwind4
@ stdcall -i386 _seh_longjmp_unwind(ptr) msvcrt._seh_longjmp_unwind @ stdcall -i386 _seh_longjmp_unwind(ptr) msvcrt._seh_longjmp_unwind
@ cdecl _set_SSE2_enable(long) msvcrt._set_SSE2_enable @ 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_amblksiz
@ stub _set_controlfp @ stub _set_controlfp
@ cdecl _set_doserrno(long) msvcrt._set_doserrno @ cdecl _set_doserrno(long) msvcrt._set_doserrno
......
...@@ -69,6 +69,7 @@ static int (__cdecl *p_wcsncat_s)(wchar_t *dst, size_t elem, const wchar_t *src, ...@@ -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 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_controlfp_s)(unsigned int *, unsigned int, unsigned int);
static int (__cdecl *p_atoflt)(_CRT_FLOAT *, char *); 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 *); static void* (WINAPI *pEncodePointer)(void *);
...@@ -680,6 +681,30 @@ if (0) ...@@ -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) START_TEST(msvcr90)
{ {
HMODULE hcrt; HMODULE hcrt;
...@@ -712,6 +737,7 @@ START_TEST(msvcr90) ...@@ -712,6 +737,7 @@ START_TEST(msvcr90)
p_qsort_s = (void *) GetProcAddress(hcrt, "qsort_s"); p_qsort_s = (void *) GetProcAddress(hcrt, "qsort_s");
p_controlfp_s = (void *) GetProcAddress(hcrt, "_controlfp_s"); p_controlfp_s = (void *) GetProcAddress(hcrt, "_controlfp_s");
p_atoflt = (void* )GetProcAddress(hcrt, "_atoflt"); p_atoflt = (void* )GetProcAddress(hcrt, "_atoflt");
p_set_abort_behavior = (void *) GetProcAddress(hcrt, "_set_abort_behavior");
hkernel32 = GetModuleHandleA("kernel32.dll"); hkernel32 = GetModuleHandleA("kernel32.dll");
pEncodePointer = (void *) GetProcAddress(hkernel32, "EncodePointer"); pEncodePointer = (void *) GetProcAddress(hkernel32, "EncodePointer");
...@@ -725,4 +751,5 @@ START_TEST(msvcr90) ...@@ -725,4 +751,5 @@ START_TEST(msvcr90)
test_qsort_s(); test_qsort_s();
test_controlfp_s(); test_controlfp_s();
test__atoflt(); test__atoflt();
test__set_abort_behavior();
} }
...@@ -39,6 +39,8 @@ static const char szMsgBoxTitle[] = "Wine C++ Runtime Library"; ...@@ -39,6 +39,8 @@ static const char szMsgBoxTitle[] = "Wine C++ Runtime Library";
extern int MSVCRT_app_type; extern int MSVCRT_app_type;
extern char *MSVCRT__pgmptr; extern char *MSVCRT__pgmptr;
static unsigned int MSVCRT_abort_behavior = MSVCRT__WRITE_ABORT_MSG | MSVCRT__CALL_REPORTFAULT;
void (*CDECL _aexit_rtn)(int) = MSVCRT__exit; void (*CDECL _aexit_rtn)(int) = MSVCRT__exit;
/* INTERNAL: call atexit functions */ /* INTERNAL: call atexit functions */
...@@ -150,18 +152,39 @@ void CDECL _amsg_exit(int errnum) ...@@ -150,18 +152,39 @@ void CDECL _amsg_exit(int errnum)
void CDECL MSVCRT_abort(void) void CDECL MSVCRT_abort(void)
{ {
TRACE("()\n"); 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); MSVCRT_raise(MSVCRT_SIGABRT);
/* in case raise() returns */ /* in case raise() returns */
MSVCRT__exit(3); 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.@) * _assert (MSVCRT.@)
*/ */
void CDECL MSVCRT__assert(const char* str, const char* file, unsigned int line) void CDECL MSVCRT__assert(const char* str, const char* file, unsigned int line)
......
...@@ -732,6 +732,10 @@ typedef void (__cdecl *MSVCRT___sighandler_t)(int); ...@@ -732,6 +732,10 @@ typedef void (__cdecl *MSVCRT___sighandler_t)(int);
#define _MAX__TIME64_T (((MSVCRT___time64_t)0x00000007 << 32) | 0x93406FFF) #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_free(void*);
void* __cdecl MSVCRT_malloc(MSVCRT_size_t); void* __cdecl MSVCRT_malloc(MSVCRT_size_t);
void* __cdecl MSVCRT_calloc(MSVCRT_size_t,MSVCRT_size_t); void* __cdecl MSVCRT_calloc(MSVCRT_size_t,MSVCRT_size_t);
......
...@@ -1475,6 +1475,7 @@ ...@@ -1475,6 +1475,7 @@
@ varargs wscanf_s(wstr) MSVCRT_wscanf_s @ varargs wscanf_s(wstr) MSVCRT_wscanf_s
# Functions not exported in native dll: # Functions not exported in native dll:
@ cdecl _set_abort_behavior(long long) MSVCRT__set_abort_behavior
@ cdecl _get_invalid_parameter_handler() @ cdecl _get_invalid_parameter_handler()
@ cdecl _set_invalid_parameter_handler(ptr) @ cdecl _set_invalid_parameter_handler(ptr)
@ cdecl _create_locale(long str) MSVCRT__create_locale @ cdecl _create_locale(long str) MSVCRT__create_locale
......
...@@ -453,6 +453,8 @@ static void test_defines(void) ...@@ -453,6 +453,8 @@ static void test_defines(void)
CHECK_DEF(_EM_AMBIGUOUS); CHECK_DEF(_EM_AMBIGUOUS);
CHECK_DEF(_OVERFLOW); CHECK_DEF(_OVERFLOW);
CHECK_DEF(_UNDERFLOW); CHECK_DEF(_UNDERFLOW);
CHECK_DEF(_WRITE_ABORT_MSG);
CHECK_DEF(_CALL_REPORTFAULT);
} }
#endif /* __WINE_USE_MSVCRT */ #endif /* __WINE_USE_MSVCRT */
......
...@@ -73,6 +73,9 @@ typedef struct _ldiv_t { ...@@ -73,6 +73,9 @@ typedef struct _ldiv_t {
#define _OUT_TO_MSGBOX 2 #define _OUT_TO_MSGBOX 2
#define _REPORT_ERRMODE 3 #define _REPORT_ERRMODE 3
/* _set_abort_behavior codes */
#define _WRITE_ABORT_MSG 1
#define _CALL_REPORTFAULT 2
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment