2 * msvcrt.dll exception handling
4 * Copyright 2000 Jon Griffiths
5 * Copyright 2005 Juan Lang
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * FIXME: Incomplete support for nested exceptions/try block cleanup.
25 #include "wine/port.h"
30 #define WIN32_NO_STATUS
34 #include "wine/exception.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(seh
);
42 static MSVCRT_security_error_handler security_error_handler
;
44 static MSVCRT___sighandler_t sighandlers
[MSVCRT_NSIG
] = { MSVCRT_SIG_DFL
};
46 static BOOL WINAPI
msvcrt_console_handler(DWORD ctrlType
)
53 if (sighandlers
[MSVCRT_SIGINT
])
55 if (sighandlers
[MSVCRT_SIGINT
] != MSVCRT_SIG_IGN
)
56 sighandlers
[MSVCRT_SIGINT
](MSVCRT_SIGINT
);
64 /*********************************************************************
65 * __pxcptinfoptrs (MSVCRT.@)
67 void** CDECL
MSVCRT___pxcptinfoptrs(void)
69 return (void**)&msvcrt_get_thread_data()->xcptinfo
;
72 typedef void (CDECL
*float_handler
)(int, int);
74 /* The exception codes are actually NTSTATUS values */
79 } float_exception_map
[] = {
80 { EXCEPTION_FLT_DENORMAL_OPERAND
, MSVCRT__FPE_DENORMAL
},
81 { EXCEPTION_FLT_DIVIDE_BY_ZERO
, MSVCRT__FPE_ZERODIVIDE
},
82 { EXCEPTION_FLT_INEXACT_RESULT
, MSVCRT__FPE_INEXACT
},
83 { EXCEPTION_FLT_INVALID_OPERATION
, MSVCRT__FPE_INVALID
},
84 { EXCEPTION_FLT_OVERFLOW
, MSVCRT__FPE_OVERFLOW
},
85 { EXCEPTION_FLT_STACK_CHECK
, MSVCRT__FPE_STACKOVERFLOW
},
86 { EXCEPTION_FLT_UNDERFLOW
, MSVCRT__FPE_UNDERFLOW
},
89 static LONG
msvcrt_exception_filter(struct _EXCEPTION_POINTERS
*except
)
91 LONG ret
= EXCEPTION_CONTINUE_SEARCH
;
92 MSVCRT___sighandler_t handler
;
94 if (!except
|| !except
->ExceptionRecord
)
95 return EXCEPTION_CONTINUE_SEARCH
;
97 switch (except
->ExceptionRecord
->ExceptionCode
)
99 case EXCEPTION_ACCESS_VIOLATION
:
100 if ((handler
= sighandlers
[MSVCRT_SIGSEGV
]) != MSVCRT_SIG_DFL
)
102 if (handler
!= MSVCRT_SIG_IGN
)
104 EXCEPTION_POINTERS
**ep
= (EXCEPTION_POINTERS
**)MSVCRT___pxcptinfoptrs(), *old_ep
;
108 sighandlers
[MSVCRT_SIGSEGV
] = MSVCRT_SIG_DFL
;
109 handler(MSVCRT_SIGSEGV
);
112 ret
= EXCEPTION_CONTINUE_EXECUTION
;
115 /* According to msdn,
116 * the FPE signal handler takes as a second argument the type of
117 * floating point exception.
119 case EXCEPTION_FLT_DENORMAL_OPERAND
:
120 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
121 case EXCEPTION_FLT_INEXACT_RESULT
:
122 case EXCEPTION_FLT_INVALID_OPERATION
:
123 case EXCEPTION_FLT_OVERFLOW
:
124 case EXCEPTION_FLT_STACK_CHECK
:
125 case EXCEPTION_FLT_UNDERFLOW
:
126 if ((handler
= sighandlers
[MSVCRT_SIGFPE
]) != MSVCRT_SIG_DFL
)
128 if (handler
!= MSVCRT_SIG_IGN
)
130 EXCEPTION_POINTERS
**ep
= (EXCEPTION_POINTERS
**)MSVCRT___pxcptinfoptrs(), *old_ep
;
132 int float_signal
= MSVCRT__FPE_INVALID
;
134 sighandlers
[MSVCRT_SIGFPE
] = MSVCRT_SIG_DFL
;
135 for (i
= 0; i
< sizeof(float_exception_map
) /
136 sizeof(float_exception_map
[0]); i
++)
138 if (float_exception_map
[i
].status
==
139 except
->ExceptionRecord
->ExceptionCode
)
141 float_signal
= float_exception_map
[i
].signal
;
148 ((float_handler
)handler
)(MSVCRT_SIGFPE
, float_signal
);
151 ret
= EXCEPTION_CONTINUE_EXECUTION
;
154 case EXCEPTION_ILLEGAL_INSTRUCTION
:
155 case EXCEPTION_PRIV_INSTRUCTION
:
156 if ((handler
= sighandlers
[MSVCRT_SIGILL
]) != MSVCRT_SIG_DFL
)
158 if (handler
!= MSVCRT_SIG_IGN
)
160 EXCEPTION_POINTERS
**ep
= (EXCEPTION_POINTERS
**)MSVCRT___pxcptinfoptrs(), *old_ep
;
164 sighandlers
[MSVCRT_SIGILL
] = MSVCRT_SIG_DFL
;
165 handler(MSVCRT_SIGILL
);
168 ret
= EXCEPTION_CONTINUE_EXECUTION
;
175 void msvcrt_init_signals(void)
177 SetConsoleCtrlHandler(msvcrt_console_handler
, TRUE
);
180 void msvcrt_free_signals(void)
182 SetConsoleCtrlHandler(msvcrt_console_handler
, FALSE
);
185 /*********************************************************************
187 * Some signals may never be generated except through an explicit call to
190 MSVCRT___sighandler_t CDECL
MSVCRT_signal(int sig
, MSVCRT___sighandler_t func
)
192 MSVCRT___sighandler_t ret
= MSVCRT_SIG_ERR
;
194 TRACE("(%d, %p)\n", sig
, func
);
196 if (func
== MSVCRT_SIG_ERR
) return MSVCRT_SIG_ERR
;
200 /* Cases handled internally. Note SIGTERM is never generated by Windows,
201 * so we effectively mask it.
209 case MSVCRT_SIGBREAK
:
210 ret
= sighandlers
[sig
];
211 sighandlers
[sig
] = func
;
214 ret
= MSVCRT_SIG_ERR
;
219 /*********************************************************************
222 int CDECL
MSVCRT_raise(int sig
)
224 MSVCRT___sighandler_t handler
;
226 TRACE("(%d)\n", sig
);
233 handler
= sighandlers
[sig
];
234 if (handler
== MSVCRT_SIG_DFL
) MSVCRT__exit(3);
235 if (handler
!= MSVCRT_SIG_IGN
)
237 EXCEPTION_POINTERS
**ep
= (EXCEPTION_POINTERS
**)MSVCRT___pxcptinfoptrs(), *old_ep
;
239 sighandlers
[sig
] = MSVCRT_SIG_DFL
;
243 if (sig
== MSVCRT_SIGFPE
)
244 ((float_handler
)handler
)(sig
, MSVCRT__FPE_EXPLICITGEN
);
253 case MSVCRT_SIGBREAK
:
254 handler
= sighandlers
[sig
];
255 if (handler
== MSVCRT_SIG_DFL
) MSVCRT__exit(3);
256 if (handler
!= MSVCRT_SIG_IGN
)
258 sighandlers
[sig
] = MSVCRT_SIG_DFL
;
268 /*********************************************************************
269 * _XcptFilter (MSVCRT.@)
271 int CDECL
_XcptFilter(NTSTATUS ex
, PEXCEPTION_POINTERS ptr
)
273 TRACE("(%08x,%p)\n", ex
, ptr
);
274 /* I assume ptr->ExceptionRecord->ExceptionCode is the same as ex */
275 return msvcrt_exception_filter(ptr
);
278 /*********************************************************************
279 * _abnormal_termination (MSVCRT.@)
281 int CDECL
_abnormal_termination(void)
283 FIXME("(void)stub\n");
287 /******************************************************************
288 * __uncaught_exception (MSVCRT.@)
290 BOOL CDECL
MSVCRT___uncaught_exception(void)
295 /*********************************************************************
296 * _set_security_error_handler (MSVCR70.@)
298 MSVCRT_security_error_handler CDECL
_set_security_error_handler(
299 MSVCRT_security_error_handler handler
)
301 MSVCRT_security_error_handler old
= security_error_handler
;
303 TRACE("(%p)\n", handler
);
305 security_error_handler
= handler
;
309 /*********************************************************************
310 * __security_error_handler (MSVCR70.@)
312 void CDECL
__security_error_handler(int code
, void *data
)
314 if(security_error_handler
)
315 security_error_handler(code
, data
);
317 FIXME("(%d, %p) stub\n", code
, data
);
322 /*********************************************************************
323 * __crtSetUnhandledExceptionFilter (MSVCR110.@)
325 LPTOP_LEVEL_EXCEPTION_FILTER CDECL
MSVCR110__crtSetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER filter
)
327 return SetUnhandledExceptionFilter(filter
);