reactos/sdk/lib/crt/except/xcptfil.c

99 lines
2.9 KiB
C

#include <precomp.h>
#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;
}