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.
30 #define WIN32_NO_STATUS
37 #include "wine/debug.h"
39 #include "cppexcept.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(seh
);
43 #if _MSVCR_VER>=70 && _MSVCR_VER<=71
44 static MSVCRT_security_error_handler security_error_handler
;
47 static __sighandler_t sighandlers
[NSIG
] = { SIG_DFL
};
49 static BOOL WINAPI
msvcrt_console_handler(DWORD ctrlType
)
56 if (sighandlers
[SIGINT
])
58 if (sighandlers
[SIGINT
] != SIG_IGN
)
59 sighandlers
[SIGINT
](SIGINT
);
67 /*********************************************************************
68 * __pxcptinfoptrs (MSVCRT.@)
70 void** CDECL
__pxcptinfoptrs(void)
72 return (void**)&msvcrt_get_thread_data()->xcptinfo
;
75 typedef void (CDECL
*float_handler
)(int, int);
77 /* The exception codes are actually NTSTATUS values */
82 } float_exception_map
[] = {
83 { EXCEPTION_FLT_DENORMAL_OPERAND
, _FPE_DENORMAL
},
84 { EXCEPTION_FLT_DIVIDE_BY_ZERO
, _FPE_ZERODIVIDE
},
85 { EXCEPTION_FLT_INEXACT_RESULT
, _FPE_INEXACT
},
86 { EXCEPTION_FLT_INVALID_OPERATION
, _FPE_INVALID
},
87 { EXCEPTION_FLT_OVERFLOW
, _FPE_OVERFLOW
},
88 { EXCEPTION_FLT_STACK_CHECK
, _FPE_STACKOVERFLOW
},
89 { EXCEPTION_FLT_UNDERFLOW
, _FPE_UNDERFLOW
},
92 static LONG
msvcrt_exception_filter(struct _EXCEPTION_POINTERS
*except
)
94 LONG ret
= EXCEPTION_CONTINUE_SEARCH
;
95 __sighandler_t handler
;
97 if (!except
|| !except
->ExceptionRecord
)
98 return EXCEPTION_CONTINUE_SEARCH
;
100 switch (except
->ExceptionRecord
->ExceptionCode
)
102 case EXCEPTION_ACCESS_VIOLATION
:
103 if ((handler
= sighandlers
[SIGSEGV
]) != SIG_DFL
)
105 if (handler
!= SIG_IGN
)
107 EXCEPTION_POINTERS
**ep
= (EXCEPTION_POINTERS
**)__pxcptinfoptrs(), *old_ep
;
111 sighandlers
[SIGSEGV
] = SIG_DFL
;
115 ret
= EXCEPTION_CONTINUE_EXECUTION
;
118 /* According to msdn,
119 * the FPE signal handler takes as a second argument the type of
120 * floating point exception.
122 case EXCEPTION_FLT_DENORMAL_OPERAND
:
123 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
124 case EXCEPTION_FLT_INEXACT_RESULT
:
125 case EXCEPTION_FLT_INVALID_OPERATION
:
126 case EXCEPTION_FLT_OVERFLOW
:
127 case EXCEPTION_FLT_STACK_CHECK
:
128 case EXCEPTION_FLT_UNDERFLOW
:
129 if ((handler
= sighandlers
[SIGFPE
]) != SIG_DFL
)
131 if (handler
!= SIG_IGN
)
133 EXCEPTION_POINTERS
**ep
= (EXCEPTION_POINTERS
**)__pxcptinfoptrs(), *old_ep
;
135 int float_signal
= _FPE_INVALID
;
137 sighandlers
[SIGFPE
] = SIG_DFL
;
138 for (i
= 0; i
< ARRAY_SIZE(float_exception_map
); i
++)
140 if (float_exception_map
[i
].status
==
141 except
->ExceptionRecord
->ExceptionCode
)
143 float_signal
= float_exception_map
[i
].signal
;
150 ((float_handler
)handler
)(SIGFPE
, float_signal
);
153 ret
= EXCEPTION_CONTINUE_EXECUTION
;
156 case EXCEPTION_ILLEGAL_INSTRUCTION
:
157 case EXCEPTION_PRIV_INSTRUCTION
:
158 if ((handler
= sighandlers
[SIGILL
]) != SIG_DFL
)
160 if (handler
!= SIG_IGN
)
162 EXCEPTION_POINTERS
**ep
= (EXCEPTION_POINTERS
**)__pxcptinfoptrs(), *old_ep
;
166 sighandlers
[SIGILL
] = SIG_DFL
;
170 ret
= EXCEPTION_CONTINUE_EXECUTION
;
177 void msvcrt_init_signals(void)
179 SetConsoleCtrlHandler(msvcrt_console_handler
, TRUE
);
182 void msvcrt_free_signals(void)
184 SetConsoleCtrlHandler(msvcrt_console_handler
, FALSE
);
187 /*********************************************************************
189 * Some signals may never be generated except through an explicit call to
192 __sighandler_t CDECL
signal(int sig
, __sighandler_t func
)
194 __sighandler_t ret
= SIG_ERR
;
196 TRACE("(%d, %p)\n", sig
, func
);
198 if (func
== SIG_ERR
) return SIG_ERR
;
202 /* Cases handled internally. Note SIGTERM is never generated by Windows,
203 * so we effectively mask it.
212 ret
= sighandlers
[sig
];
213 sighandlers
[sig
] = func
;
221 /*********************************************************************
224 int CDECL
raise(int sig
)
226 __sighandler_t handler
;
228 TRACE("(%d)\n", sig
);
235 handler
= sighandlers
[sig
];
236 if (handler
== SIG_DFL
) _exit(3);
237 if (handler
!= SIG_IGN
)
239 EXCEPTION_POINTERS
**ep
= (EXCEPTION_POINTERS
**)__pxcptinfoptrs(), *old_ep
;
241 sighandlers
[sig
] = SIG_DFL
;
246 ((float_handler
)handler
)(sig
, _FPE_EXPLICITGEN
);
256 handler
= sighandlers
[sig
];
257 if (handler
== SIG_DFL
) _exit(3);
258 if (handler
!= SIG_IGN
)
260 sighandlers
[sig
] = SIG_DFL
;
270 /*********************************************************************
271 * _XcptFilter (MSVCRT.@)
273 int CDECL
_XcptFilter(NTSTATUS ex
, PEXCEPTION_POINTERS ptr
)
275 TRACE("(%08x,%p)\n", ex
, ptr
);
276 /* I assume ptr->ExceptionRecord->ExceptionCode is the same as ex */
277 return msvcrt_exception_filter(ptr
);
280 /*********************************************************************
281 * _abnormal_termination (MSVCRT.@)
283 int CDECL
__intrinsic_abnormal_termination(void)
285 FIXME("(void)stub\n");
289 /******************************************************************
290 * __uncaught_exception (MSVCRT.@)
292 BOOL CDECL
__uncaught_exception(void)
294 return msvcrt_get_thread_data()->processing_throw
!= 0;
297 #if _MSVCR_VER>=70 && _MSVCR_VER<=71
299 /*********************************************************************
300 * _set_security_error_handler (MSVCR70.@)
302 MSVCRT_security_error_handler CDECL
_set_security_error_handler(
303 MSVCRT_security_error_handler handler
)
305 MSVCRT_security_error_handler old
= security_error_handler
;
307 TRACE("(%p)\n", handler
);
309 security_error_handler
= handler
;
313 /*********************************************************************
314 * __security_error_handler (MSVCR70.@)
316 void CDECL
__security_error_handler(int code
, void *data
)
318 if(security_error_handler
)
319 security_error_handler(code
, data
);
321 FIXME("(%d, %p) stub\n", code
, data
);
326 #endif /* _MSVCR_VER>=70 && _MSVCR_VER<=71 */
329 /*********************************************************************
330 * __crtSetUnhandledExceptionFilter (MSVCR110.@)
332 LPTOP_LEVEL_EXCEPTION_FILTER CDECL
__crtSetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER filter
)
334 return SetUnhandledExceptionFilter(filter
);
338 /*********************************************************************
339 * _CreateFrameInfo (MSVCR80.@)
341 frame_info
* CDECL
_CreateFrameInfo(frame_info
*fi
, void *obj
)
343 thread_data_t
*data
= msvcrt_get_thread_data();
345 TRACE("(%p, %p)\n", fi
, obj
);
347 fi
->next
= data
->frame_info_head
;
348 data
->frame_info_head
= fi
;
353 /*********************************************************************
354 * _FindAndUnlinkFrame (MSVCR80.@)
356 void CDECL
_FindAndUnlinkFrame(frame_info
*fi
)
358 thread_data_t
*data
= msvcrt_get_thread_data();
359 frame_info
*cur
= data
->frame_info_head
;
365 data
->frame_info_head
= cur
->next
;
369 for (; cur
->next
; cur
= cur
->next
)
373 cur
->next
= fi
->next
;
378 ERR("frame not found, native crashes in this case\n");
381 /*********************************************************************
382 * _IsExceptionObjectToBeDestroyed (MSVCR80.@)
384 BOOL __cdecl
_IsExceptionObjectToBeDestroyed(const void *obj
)
388 TRACE( "%p\n", obj
);
390 for (cur
= msvcrt_get_thread_data()->frame_info_head
; cur
; cur
= cur
->next
)
392 if (cur
->object
== obj
)
399 /*********************************************************************
400 * __DestructExceptionObject (MSVCRT.@)
402 void CDECL
__DestructExceptionObject(EXCEPTION_RECORD
*rec
)
404 cxx_exception_type
*info
= (cxx_exception_type
*) rec
->ExceptionInformation
[2];
405 void *object
= (void*)rec
->ExceptionInformation
[1];
407 TRACE("(%p)\n", rec
);
409 if (rec
->ExceptionCode
!= CXX_EXCEPTION
) return;
411 if (rec
->NumberParameters
!= 3) return;
413 if (rec
->NumberParameters
!= 4) return;
415 if (rec
->ExceptionInformation
[0] < CXX_FRAME_MAGIC_VC6
||
416 rec
->ExceptionInformation
[0] > CXX_FRAME_MAGIC_VC8
) return;
418 if (!info
|| !info
->destructor
)
421 #if defined(__i386__)
422 __asm__
__volatile__("call *%0" : : "r" (info
->destructor
), "c" (object
) : "eax", "edx", "memory" );
423 #elif defined(__x86_64__)
424 ((void (__cdecl
*)(void*))(info
->destructor
+rec
->ExceptionInformation
[3]))(object
);
426 ((void (__cdecl
*)(void*))info
->destructor
)(object
);
430 /*********************************************************************
431 * __CxxRegisterExceptionObject (MSVCRT.@)
433 BOOL CDECL
__CxxRegisterExceptionObject(EXCEPTION_POINTERS
*ep
, cxx_frame_info
*frame_info
)
435 thread_data_t
*data
= msvcrt_get_thread_data();
437 TRACE("(%p, %p)\n", ep
, frame_info
);
439 if (!ep
|| !ep
->ExceptionRecord
)
441 frame_info
->rec
= (void*)-1;
442 frame_info
->context
= (void*)-1;
446 frame_info
->rec
= data
->exc_record
;
447 frame_info
->context
= data
->ctx_record
;
448 data
->exc_record
= ep
->ExceptionRecord
;
449 data
->ctx_record
= ep
->ContextRecord
;
450 _CreateFrameInfo(&frame_info
->frame_info
, (void*)ep
->ExceptionRecord
->ExceptionInformation
[1]);
454 /*********************************************************************
455 * __CxxUnregisterExceptionObject (MSVCRT.@)
457 void CDECL
__CxxUnregisterExceptionObject(cxx_frame_info
*frame_info
, BOOL in_use
)
459 thread_data_t
*data
= msvcrt_get_thread_data();
461 TRACE("(%p)\n", frame_info
);
463 if(frame_info
->rec
== (void*)-1)
466 _FindAndUnlinkFrame(&frame_info
->frame_info
);
467 if(data
->exc_record
->ExceptionCode
== CXX_EXCEPTION
&& !in_use
468 && _IsExceptionObjectToBeDestroyed((void*)data
->exc_record
->ExceptionInformation
[1]))
469 __DestructExceptionObject(data
->exc_record
);
470 data
->exc_record
= frame_info
->rec
;
471 data
->ctx_record
= frame_info
->context
;
474 struct __std_exception_data
{
481 /*********************************************************************
482 * __std_exception_copy (UCRTBASE.@)
484 void CDECL
__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
= _strdup(src
->what
);
493 dst
->what
= src
->what
;
498 /*********************************************************************
499 * __std_exception_destroy (UCRTBASE.@)
501 void CDECL
__std_exception_destroy(struct __std_exception_data
*data
)
503 TRACE("(%p)\n", data
);
511 /*********************************************************************
512 * __current_exception (UCRTBASE.@)
514 void** CDECL
__current_exception(void)
517 return (void**)&msvcrt_get_thread_data()->exc_record
;
520 /*********************************************************************
521 * __current_exception_context (UCRTBASE.@)
523 void** CDECL
__current_exception_context(void)
526 return (void**)&msvcrt_get_thread_data()->ctx_record
;
529 /*********************************************************************
530 * __processing_throw (UCRTBASE.@)
532 int* CDECL
__processing_throw(void)
535 return &msvcrt_get_thread_data()->processing_throw
;
538 #endif /* _MSVCR_VER>=140 */