#include #include "internal/wine/msvcrt.h" #include "internal/wine/cppexcept.h" typedef void (*sighandler_t)(int); static sighandler_t sighandlers[NSIG] = { SIG_DFL }; /* The exception codes are actually NTSTATUS values */ static const struct { NTSTATUS status; int signal; } float_exception_map[] = { { EXCEPTION_FLT_DENORMAL_OPERAND, _FPE_DENORMAL }, { EXCEPTION_FLT_DIVIDE_BY_ZERO, _FPE_ZERODIVIDE }, { EXCEPTION_FLT_INEXACT_RESULT, _FPE_INEXACT }, { EXCEPTION_FLT_INVALID_OPERATION, _FPE_INVALID }, { EXCEPTION_FLT_OVERFLOW, _FPE_OVERFLOW }, { EXCEPTION_FLT_STACK_CHECK, _FPE_STACKOVERFLOW }, { EXCEPTION_FLT_UNDERFLOW, _FPE_UNDERFLOW }, }; /* * @implemented */ int CDECL _XcptFilter(NTSTATUS ExceptionCode, struct _EXCEPTION_POINTERS * except) { LONG ret = EXCEPTION_CONTINUE_SEARCH; sighandler_t handler; if (!except || !except->ExceptionRecord) return EXCEPTION_CONTINUE_SEARCH; switch (except->ExceptionRecord->ExceptionCode) { case EXCEPTION_ACCESS_VIOLATION: if ((handler = sighandlers[SIGSEGV]) != SIG_DFL) { if (handler != SIG_IGN) { sighandlers[SIGSEGV] = SIG_DFL; handler(SIGSEGV); } ret = EXCEPTION_CONTINUE_EXECUTION; } break; /* According to msdn, * the FPE signal handler takes as a second argument the type of * floating point exception. */ case EXCEPTION_FLT_DENORMAL_OPERAND: case EXCEPTION_FLT_DIVIDE_BY_ZERO: case EXCEPTION_FLT_INEXACT_RESULT: case EXCEPTION_FLT_INVALID_OPERATION: case EXCEPTION_FLT_OVERFLOW: case EXCEPTION_FLT_STACK_CHECK: case EXCEPTION_FLT_UNDERFLOW: if ((handler = sighandlers[SIGFPE]) != SIG_DFL) { if (handler != SIG_IGN) { unsigned int i; int float_signal = _FPE_INVALID; sighandlers[SIGFPE] = SIG_DFL; for (i = 0; i < sizeof(float_exception_map) / sizeof(float_exception_map[0]); i++) { if (float_exception_map[i].status == except->ExceptionRecord->ExceptionCode) { float_signal = float_exception_map[i].signal; break; } } ((float_handler)handler)(SIGFPE, float_signal); } ret = EXCEPTION_CONTINUE_EXECUTION; } break; case EXCEPTION_ILLEGAL_INSTRUCTION: case EXCEPTION_PRIV_INSTRUCTION: if ((handler = sighandlers[SIGILL]) != SIG_DFL) { if (handler != SIG_IGN) { sighandlers[SIGILL] = SIG_DFL; handler(SIGILL); } ret = EXCEPTION_CONTINUE_EXECUTION; } break; } return ret; }