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 #include "cppexcept.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(seh
);
44 #if _MSVCR_VER>=70 && _MSVCR_VER<=71
45 static MSVCRT_security_error_handler security_error_handler
;
48 static MSVCRT___sighandler_t sighandlers
[MSVCRT_NSIG
] = { MSVCRT_SIG_DFL
};
50 static BOOL WINAPI
msvcrt_console_handler(DWORD ctrlType
)
57 if (sighandlers
[MSVCRT_SIGINT
])
59 if (sighandlers
[MSVCRT_SIGINT
] != MSVCRT_SIG_IGN
)
60 sighandlers
[MSVCRT_SIGINT
](MSVCRT_SIGINT
);
68 /*********************************************************************
69 * __pxcptinfoptrs (MSVCRT.@)
71 void** CDECL
MSVCRT___pxcptinfoptrs(void)
73 return (void**)&msvcrt_get_thread_data()->xcptinfo
;
76 typedef void (CDECL
*float_handler
)(int, int);
78 /* The exception codes are actually NTSTATUS values */
83 } float_exception_map
[] = {
84 { EXCEPTION_FLT_DENORMAL_OPERAND
, MSVCRT__FPE_DENORMAL
},
85 { EXCEPTION_FLT_DIVIDE_BY_ZERO
, MSVCRT__FPE_ZERODIVIDE
},
86 { EXCEPTION_FLT_INEXACT_RESULT
, MSVCRT__FPE_INEXACT
},
87 { EXCEPTION_FLT_INVALID_OPERATION
, MSVCRT__FPE_INVALID
},
88 { EXCEPTION_FLT_OVERFLOW
, MSVCRT__FPE_OVERFLOW
},
89 { EXCEPTION_FLT_STACK_CHECK
, MSVCRT__FPE_STACKOVERFLOW
},
90 { EXCEPTION_FLT_UNDERFLOW
, MSVCRT__FPE_UNDERFLOW
},
93 static LONG
msvcrt_exception_filter(struct _EXCEPTION_POINTERS
*except
)
95 LONG ret
= EXCEPTION_CONTINUE_SEARCH
;
96 MSVCRT___sighandler_t handler
;
98 if (!except
|| !except
->ExceptionRecord
)
99 return EXCEPTION_CONTINUE_SEARCH
;
101 switch (except
->ExceptionRecord
->ExceptionCode
)
103 case EXCEPTION_ACCESS_VIOLATION
:
104 if ((handler
= sighandlers
[MSVCRT_SIGSEGV
]) != MSVCRT_SIG_DFL
)
106 if (handler
!= MSVCRT_SIG_IGN
)
108 EXCEPTION_POINTERS
**ep
= (EXCEPTION_POINTERS
**)MSVCRT___pxcptinfoptrs(), *old_ep
;
112 sighandlers
[MSVCRT_SIGSEGV
] = MSVCRT_SIG_DFL
;
113 handler(MSVCRT_SIGSEGV
);
116 ret
= EXCEPTION_CONTINUE_EXECUTION
;
119 /* According to msdn,
120 * the FPE signal handler takes as a second argument the type of
121 * floating point exception.
123 case EXCEPTION_FLT_DENORMAL_OPERAND
:
124 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
125 case EXCEPTION_FLT_INEXACT_RESULT
:
126 case EXCEPTION_FLT_INVALID_OPERATION
:
127 case EXCEPTION_FLT_OVERFLOW
:
128 case EXCEPTION_FLT_STACK_CHECK
:
129 case EXCEPTION_FLT_UNDERFLOW
:
130 if ((handler
= sighandlers
[MSVCRT_SIGFPE
]) != MSVCRT_SIG_DFL
)
132 if (handler
!= MSVCRT_SIG_IGN
)
134 EXCEPTION_POINTERS
**ep
= (EXCEPTION_POINTERS
**)MSVCRT___pxcptinfoptrs(), *old_ep
;
136 int float_signal
= MSVCRT__FPE_INVALID
;
138 sighandlers
[MSVCRT_SIGFPE
] = MSVCRT_SIG_DFL
;
139 for (i
= 0; i
< sizeof(float_exception_map
) /
140 sizeof(float_exception_map
[0]); i
++)
142 if (float_exception_map
[i
].status
==
143 except
->ExceptionRecord
->ExceptionCode
)
145 float_signal
= float_exception_map
[i
].signal
;
152 ((float_handler
)handler
)(MSVCRT_SIGFPE
, float_signal
);
155 ret
= EXCEPTION_CONTINUE_EXECUTION
;
158 case EXCEPTION_ILLEGAL_INSTRUCTION
:
159 case EXCEPTION_PRIV_INSTRUCTION
:
160 if ((handler
= sighandlers
[MSVCRT_SIGILL
]) != MSVCRT_SIG_DFL
)
162 if (handler
!= MSVCRT_SIG_IGN
)
164 EXCEPTION_POINTERS
**ep
= (EXCEPTION_POINTERS
**)MSVCRT___pxcptinfoptrs(), *old_ep
;
168 sighandlers
[MSVCRT_SIGILL
] = MSVCRT_SIG_DFL
;
169 handler(MSVCRT_SIGILL
);
172 ret
= EXCEPTION_CONTINUE_EXECUTION
;
179 void msvcrt_init_signals(void)
181 SetConsoleCtrlHandler(msvcrt_console_handler
, TRUE
);
184 void msvcrt_free_signals(void)
186 SetConsoleCtrlHandler(msvcrt_console_handler
, FALSE
);
189 /*********************************************************************
191 * Some signals may never be generated except through an explicit call to
194 MSVCRT___sighandler_t CDECL
MSVCRT_signal(int sig
, MSVCRT___sighandler_t func
)
196 MSVCRT___sighandler_t ret
= MSVCRT_SIG_ERR
;
198 TRACE("(%d, %p)\n", sig
, func
);
200 if (func
== MSVCRT_SIG_ERR
) return MSVCRT_SIG_ERR
;
204 /* Cases handled internally. Note SIGTERM is never generated by Windows,
205 * so we effectively mask it.
213 case MSVCRT_SIGBREAK
:
214 ret
= sighandlers
[sig
];
215 sighandlers
[sig
] = func
;
218 ret
= MSVCRT_SIG_ERR
;
223 /*********************************************************************
226 int CDECL
MSVCRT_raise(int sig
)
228 MSVCRT___sighandler_t handler
;
230 TRACE("(%d)\n", sig
);
237 handler
= sighandlers
[sig
];
238 if (handler
== MSVCRT_SIG_DFL
) MSVCRT__exit(3);
239 if (handler
!= MSVCRT_SIG_IGN
)
241 EXCEPTION_POINTERS
**ep
= (EXCEPTION_POINTERS
**)MSVCRT___pxcptinfoptrs(), *old_ep
;
243 sighandlers
[sig
] = MSVCRT_SIG_DFL
;
247 if (sig
== MSVCRT_SIGFPE
)
248 ((float_handler
)handler
)(sig
, MSVCRT__FPE_EXPLICITGEN
);
257 case MSVCRT_SIGBREAK
:
258 handler
= sighandlers
[sig
];
259 if (handler
== MSVCRT_SIG_DFL
) MSVCRT__exit(3);
260 if (handler
!= MSVCRT_SIG_IGN
)
262 sighandlers
[sig
] = MSVCRT_SIG_DFL
;
272 /*********************************************************************
273 * _XcptFilter (MSVCRT.@)
275 int CDECL
_XcptFilter(NTSTATUS ex
, PEXCEPTION_POINTERS ptr
)
277 TRACE("(%08x,%p)\n", ex
, ptr
);
278 /* I assume ptr->ExceptionRecord->ExceptionCode is the same as ex */
279 return msvcrt_exception_filter(ptr
);
282 /*********************************************************************
283 * _abnormal_termination (MSVCRT.@)
285 int CDECL
_abnormal_termination(void)
287 FIXME("(void)stub\n");
291 /******************************************************************
292 * __uncaught_exception (MSVCRT.@)
294 BOOL CDECL
MSVCRT___uncaught_exception(void)
299 #if _MSVCR_VER>=70 && _MSVCR_VER<=71
301 /*********************************************************************
302 * _set_security_error_handler (MSVCR70.@)
304 MSVCRT_security_error_handler CDECL
_set_security_error_handler(
305 MSVCRT_security_error_handler handler
)
307 MSVCRT_security_error_handler old
= security_error_handler
;
309 TRACE("(%p)\n", handler
);
311 security_error_handler
= handler
;
315 /*********************************************************************
316 * __security_error_handler (MSVCR70.@)
318 void CDECL
__security_error_handler(int code
, void *data
)
320 if(security_error_handler
)
321 security_error_handler(code
, data
);
323 FIXME("(%d, %p) stub\n", code
, data
);
328 #endif /* _MSVCR_VER>=70 && _MSVCR_VER<=71 */
331 /*********************************************************************
332 * __crtSetUnhandledExceptionFilter (MSVCR110.@)
334 LPTOP_LEVEL_EXCEPTION_FILTER CDECL
MSVCR110__crtSetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER filter
)
336 return SetUnhandledExceptionFilter(filter
);
340 /*********************************************************************
341 * _CreateFrameInfo (MSVCR80.@)
343 frame_info
* CDECL
_CreateFrameInfo(frame_info
*fi
, void *obj
)
345 thread_data_t
*data
= msvcrt_get_thread_data();
347 TRACE("(%p, %p)\n", fi
, obj
);
349 fi
->next
= data
->frame_info_head
;
350 data
->frame_info_head
= fi
;
355 /*********************************************************************
356 * _FindAndUnlinkFrame (MSVCR80.@)
358 void CDECL
_FindAndUnlinkFrame(frame_info
*fi
)
360 thread_data_t
*data
= msvcrt_get_thread_data();
361 frame_info
*cur
= data
->frame_info_head
;
367 data
->frame_info_head
= cur
->next
;
371 for (; cur
->next
; cur
= cur
->next
)
375 cur
->next
= fi
->next
;
380 ERR("frame not found, native crashes in this case\n");
383 /*********************************************************************
384 * _IsExceptionObjectToBeDestroyed (MSVCR80.@)
386 BOOL __cdecl
_IsExceptionObjectToBeDestroyed(const void *obj
)
390 TRACE( "%p\n", obj
);
392 for (cur
= msvcrt_get_thread_data()->frame_info_head
; cur
; cur
= cur
->next
)
394 if (cur
->object
== obj
)
401 /*********************************************************************
402 * __DestructExceptionObject (MSVCRT.@)
404 void CDECL
__DestructExceptionObject(EXCEPTION_RECORD
*rec
)
406 cxx_exception_type
*info
= (cxx_exception_type
*) rec
->ExceptionInformation
[2];
407 void *object
= (void*)rec
->ExceptionInformation
[1];
409 TRACE("(%p)\n", rec
);
411 if (rec
->ExceptionCode
!= CXX_EXCEPTION
) return;
413 if (rec
->NumberParameters
!= 3) return;
415 if (rec
->NumberParameters
!= 4) return;
417 if (rec
->ExceptionInformation
[0] < CXX_FRAME_MAGIC_VC6
||
418 rec
->ExceptionInformation
[0] > CXX_FRAME_MAGIC_VC8
) return;
420 if (!info
|| !info
->destructor
)
423 #if defined(__i386__)
424 __asm__
__volatile__("call *%0" : : "r" (info
->destructor
), "c" (object
) : "eax", "edx", "memory" );
425 #elif defined(__x86_64__)
426 ((void (__cdecl
*)(void*))(info
->destructor
+rec
->ExceptionInformation
[3]))(object
);
428 ((void (__cdecl
*)(void*))info
->destructor
)(object
);
432 /*********************************************************************
433 * __CxxRegisterExceptionObject (MSVCRT.@)
435 BOOL CDECL
__CxxRegisterExceptionObject(EXCEPTION_RECORD
**rec
, cxx_frame_info
*frame_info
)
437 thread_data_t
*data
= msvcrt_get_thread_data();
439 TRACE("(%p, %p)\n", rec
, frame_info
);
443 frame_info
->rec
= (void*)-1;
444 frame_info
->unk
= (void*)-1;
448 frame_info
->rec
= data
->exc_record
;
450 data
->exc_record
= *rec
;
451 _CreateFrameInfo(&frame_info
->frame_info
, (void*)(*rec
)->ExceptionInformation
[1]);
455 /*********************************************************************
456 * __CxxUnregisterExceptionObject (MSVCRT.@)
458 void CDECL
__CxxUnregisterExceptionObject(cxx_frame_info
*frame_info
, BOOL in_use
)
460 thread_data_t
*data
= msvcrt_get_thread_data();
462 TRACE("(%p)\n", frame_info
);
464 if(frame_info
->rec
== (void*)-1)
467 _FindAndUnlinkFrame(&frame_info
->frame_info
);
468 if(data
->exc_record
->ExceptionCode
== CXX_EXCEPTION
&& !in_use
469 && _IsExceptionObjectToBeDestroyed((void*)data
->exc_record
->ExceptionInformation
[1]))
470 __DestructExceptionObject(data
->exc_record
);
471 data
->exc_record
= frame_info
->rec
;
474 struct __std_exception_data
{
481 /*********************************************************************
482 * __std_exception_copy (UCRTBASE.@)
484 void CDECL
MSVCRT___std_exception_copy(const struct __std_exception_data
*src
,
485 struct __std_exception_data
*dst
)
487 TRACE("(%p %p)\n", src
, dst
);
489 if(src
->dofree
&& src
->what
) {
490 dst
->what
= MSVCRT__strdup(src
->what
);
493 dst
->what
= src
->what
;
498 /*********************************************************************
499 * __std_exception_destroy (UCRTBASE.@)
501 void CDECL
MSVCRT___std_exception_destroy(struct __std_exception_data
*data
)
503 TRACE("(%p)\n", data
);
506 MSVCRT_free(data
->what
);
511 #endif /* _MSVCR_VER>=140 */