xref: /reactos/sdk/lib/crt/wine/except.c (revision ae0fa8ba)
19efafd64STimo Kreuzer /*
29efafd64STimo Kreuzer  * msvcrt.dll exception handling
39efafd64STimo Kreuzer  *
49efafd64STimo Kreuzer  * Copyright 2000 Jon Griffiths
59efafd64STimo Kreuzer  * Copyright 2005 Juan Lang
69efafd64STimo Kreuzer  *
79efafd64STimo Kreuzer  * This library is free software; you can redistribute it and/or
89efafd64STimo Kreuzer  * modify it under the terms of the GNU Lesser General Public
99efafd64STimo Kreuzer  * License as published by the Free Software Foundation; either
109efafd64STimo Kreuzer  * version 2.1 of the License, or (at your option) any later version.
119efafd64STimo Kreuzer  *
129efafd64STimo Kreuzer  * This library is distributed in the hope that it will be useful,
139efafd64STimo Kreuzer  * but WITHOUT ANY WARRANTY; without even the implied warranty of
149efafd64STimo Kreuzer  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
159efafd64STimo Kreuzer  * Lesser General Public License for more details.
169efafd64STimo Kreuzer  *
179efafd64STimo Kreuzer  * You should have received a copy of the GNU Lesser General Public
189efafd64STimo Kreuzer  * License along with this library; if not, write to the Free Software
199efafd64STimo Kreuzer  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
209efafd64STimo Kreuzer  *
219efafd64STimo Kreuzer  * FIXME: Incomplete support for nested exceptions/try block cleanup.
229efafd64STimo Kreuzer  */
239efafd64STimo Kreuzer 
243a61dd7fSTimo Kreuzer #include <float.h>
253a61dd7fSTimo Kreuzer #include <signal.h>
269efafd64STimo Kreuzer #include <stdarg.h>
273a61dd7fSTimo Kreuzer #include <stdbool.h>
289efafd64STimo Kreuzer 
299efafd64STimo Kreuzer #include "ntstatus.h"
309efafd64STimo Kreuzer #define WIN32_NO_STATUS
319efafd64STimo Kreuzer #include "windef.h"
329efafd64STimo Kreuzer #include "winbase.h"
339efafd64STimo Kreuzer #include "winternl.h"
343a61dd7fSTimo Kreuzer #ifdef __REACTOS__ // FIXME: Clean up wine headers!
359efafd64STimo Kreuzer #include "wine/exception.h"
363a61dd7fSTimo Kreuzer #endif // __REACTOS__
379efafd64STimo Kreuzer #include "msvcrt.h"
389efafd64STimo Kreuzer #include "excpt.h"
399efafd64STimo Kreuzer #include "wincon.h"
409efafd64STimo Kreuzer #include "wine/debug.h"
419efafd64STimo Kreuzer 
429efafd64STimo Kreuzer #include "cppexcept.h"
439efafd64STimo Kreuzer 
449efafd64STimo Kreuzer WINE_DEFAULT_DEBUG_CHANNEL(seh);
459efafd64STimo Kreuzer 
469efafd64STimo Kreuzer #if _MSVCR_VER>=70 && _MSVCR_VER<=71
479efafd64STimo Kreuzer static MSVCRT_security_error_handler security_error_handler;
489efafd64STimo Kreuzer #endif
499efafd64STimo Kreuzer 
503a61dd7fSTimo Kreuzer static __sighandler_t sighandlers[NSIG] = { SIG_DFL };
519efafd64STimo Kreuzer 
msvcrt_console_handler(DWORD ctrlType)529efafd64STimo Kreuzer static BOOL WINAPI msvcrt_console_handler(DWORD ctrlType)
539efafd64STimo Kreuzer {
549efafd64STimo Kreuzer     BOOL ret = FALSE;
559efafd64STimo Kreuzer 
569efafd64STimo Kreuzer     switch (ctrlType)
579efafd64STimo Kreuzer     {
589efafd64STimo Kreuzer     case CTRL_C_EVENT:
593a61dd7fSTimo Kreuzer         if (sighandlers[SIGINT])
609efafd64STimo Kreuzer         {
613a61dd7fSTimo Kreuzer             if (sighandlers[SIGINT] != SIG_IGN)
623a61dd7fSTimo Kreuzer                 sighandlers[SIGINT](SIGINT);
639efafd64STimo Kreuzer             ret = TRUE;
649efafd64STimo Kreuzer         }
659efafd64STimo Kreuzer         break;
669efafd64STimo Kreuzer     }
679efafd64STimo Kreuzer     return ret;
689efafd64STimo Kreuzer }
699efafd64STimo Kreuzer 
709efafd64STimo Kreuzer /*********************************************************************
719efafd64STimo Kreuzer  *              __pxcptinfoptrs (MSVCRT.@)
729efafd64STimo Kreuzer  */
__pxcptinfoptrs(void)733a61dd7fSTimo Kreuzer void** CDECL __pxcptinfoptrs(void)
749efafd64STimo Kreuzer {
759efafd64STimo Kreuzer     return (void**)&msvcrt_get_thread_data()->xcptinfo;
769efafd64STimo Kreuzer }
779efafd64STimo Kreuzer 
789efafd64STimo Kreuzer typedef void (CDECL *float_handler)(int, int);
799efafd64STimo Kreuzer 
809efafd64STimo Kreuzer /* The exception codes are actually NTSTATUS values */
819efafd64STimo Kreuzer static const struct
829efafd64STimo Kreuzer {
839efafd64STimo Kreuzer     NTSTATUS status;
849efafd64STimo Kreuzer     int signal;
859efafd64STimo Kreuzer } float_exception_map[] = {
863a61dd7fSTimo Kreuzer  { EXCEPTION_FLT_DENORMAL_OPERAND, _FPE_DENORMAL },
873a61dd7fSTimo Kreuzer  { EXCEPTION_FLT_DIVIDE_BY_ZERO, _FPE_ZERODIVIDE },
883a61dd7fSTimo Kreuzer  { EXCEPTION_FLT_INEXACT_RESULT, _FPE_INEXACT },
893a61dd7fSTimo Kreuzer  { EXCEPTION_FLT_INVALID_OPERATION, _FPE_INVALID },
903a61dd7fSTimo Kreuzer  { EXCEPTION_FLT_OVERFLOW, _FPE_OVERFLOW },
913a61dd7fSTimo Kreuzer  { EXCEPTION_FLT_STACK_CHECK, _FPE_STACKOVERFLOW },
923a61dd7fSTimo Kreuzer  { EXCEPTION_FLT_UNDERFLOW, _FPE_UNDERFLOW },
939efafd64STimo Kreuzer };
949efafd64STimo Kreuzer 
msvcrt_exception_filter(struct _EXCEPTION_POINTERS * except)959efafd64STimo Kreuzer static LONG msvcrt_exception_filter(struct _EXCEPTION_POINTERS *except)
969efafd64STimo Kreuzer {
979efafd64STimo Kreuzer     LONG ret = EXCEPTION_CONTINUE_SEARCH;
983a61dd7fSTimo Kreuzer     __sighandler_t handler;
999efafd64STimo Kreuzer 
1009efafd64STimo Kreuzer     if (!except || !except->ExceptionRecord)
1019efafd64STimo Kreuzer         return EXCEPTION_CONTINUE_SEARCH;
1029efafd64STimo Kreuzer 
1039efafd64STimo Kreuzer     switch (except->ExceptionRecord->ExceptionCode)
1049efafd64STimo Kreuzer     {
1059efafd64STimo Kreuzer     case EXCEPTION_ACCESS_VIOLATION:
1063a61dd7fSTimo Kreuzer         if ((handler = sighandlers[SIGSEGV]) != SIG_DFL)
1079efafd64STimo Kreuzer         {
1083a61dd7fSTimo Kreuzer             if (handler != SIG_IGN)
1099efafd64STimo Kreuzer             {
1103a61dd7fSTimo Kreuzer                 EXCEPTION_POINTERS **ep = (EXCEPTION_POINTERS**)__pxcptinfoptrs(), *old_ep;
1119efafd64STimo Kreuzer 
1129efafd64STimo Kreuzer                 old_ep = *ep;
1139efafd64STimo Kreuzer                 *ep = except;
1143a61dd7fSTimo Kreuzer                 sighandlers[SIGSEGV] = SIG_DFL;
1153a61dd7fSTimo Kreuzer                 handler(SIGSEGV);
1169efafd64STimo Kreuzer                 *ep = old_ep;
1179efafd64STimo Kreuzer             }
1189efafd64STimo Kreuzer             ret = EXCEPTION_CONTINUE_EXECUTION;
1199efafd64STimo Kreuzer         }
1209efafd64STimo Kreuzer         break;
1219efafd64STimo Kreuzer     /* According to msdn,
1229efafd64STimo Kreuzer      * the FPE signal handler takes as a second argument the type of
1239efafd64STimo Kreuzer      * floating point exception.
1249efafd64STimo Kreuzer      */
1259efafd64STimo Kreuzer     case EXCEPTION_FLT_DENORMAL_OPERAND:
1269efafd64STimo Kreuzer     case EXCEPTION_FLT_DIVIDE_BY_ZERO:
1279efafd64STimo Kreuzer     case EXCEPTION_FLT_INEXACT_RESULT:
1289efafd64STimo Kreuzer     case EXCEPTION_FLT_INVALID_OPERATION:
1299efafd64STimo Kreuzer     case EXCEPTION_FLT_OVERFLOW:
1309efafd64STimo Kreuzer     case EXCEPTION_FLT_STACK_CHECK:
1319efafd64STimo Kreuzer     case EXCEPTION_FLT_UNDERFLOW:
1323a61dd7fSTimo Kreuzer         if ((handler = sighandlers[SIGFPE]) != SIG_DFL)
1339efafd64STimo Kreuzer         {
1343a61dd7fSTimo Kreuzer             if (handler != SIG_IGN)
1359efafd64STimo Kreuzer             {
1363a61dd7fSTimo Kreuzer                 EXCEPTION_POINTERS **ep = (EXCEPTION_POINTERS**)__pxcptinfoptrs(), *old_ep;
1379efafd64STimo Kreuzer                 unsigned int i;
1383a61dd7fSTimo Kreuzer                 int float_signal = _FPE_INVALID;
1399efafd64STimo Kreuzer 
1403a61dd7fSTimo Kreuzer                 sighandlers[SIGFPE] = SIG_DFL;
1419efafd64STimo Kreuzer                 for (i = 0; i < ARRAY_SIZE(float_exception_map); i++)
1429efafd64STimo Kreuzer                 {
1439efafd64STimo Kreuzer                     if (float_exception_map[i].status ==
1449efafd64STimo Kreuzer                         except->ExceptionRecord->ExceptionCode)
1459efafd64STimo Kreuzer                     {
1469efafd64STimo Kreuzer                         float_signal = float_exception_map[i].signal;
1479efafd64STimo Kreuzer                         break;
1489efafd64STimo Kreuzer                     }
1499efafd64STimo Kreuzer                 }
1509efafd64STimo Kreuzer 
1519efafd64STimo Kreuzer                 old_ep = *ep;
1529efafd64STimo Kreuzer                 *ep = except;
1533a61dd7fSTimo Kreuzer                 ((float_handler)handler)(SIGFPE, float_signal);
1549efafd64STimo Kreuzer                 *ep = old_ep;
1559efafd64STimo Kreuzer             }
1569efafd64STimo Kreuzer             ret = EXCEPTION_CONTINUE_EXECUTION;
1579efafd64STimo Kreuzer         }
1589efafd64STimo Kreuzer         break;
1599efafd64STimo Kreuzer     case EXCEPTION_ILLEGAL_INSTRUCTION:
1609efafd64STimo Kreuzer     case EXCEPTION_PRIV_INSTRUCTION:
1613a61dd7fSTimo Kreuzer         if ((handler = sighandlers[SIGILL]) != SIG_DFL)
1629efafd64STimo Kreuzer         {
1633a61dd7fSTimo Kreuzer             if (handler != SIG_IGN)
1649efafd64STimo Kreuzer             {
1653a61dd7fSTimo Kreuzer                 EXCEPTION_POINTERS **ep = (EXCEPTION_POINTERS**)__pxcptinfoptrs(), *old_ep;
1669efafd64STimo Kreuzer 
1679efafd64STimo Kreuzer                 old_ep = *ep;
1689efafd64STimo Kreuzer                 *ep = except;
1693a61dd7fSTimo Kreuzer                 sighandlers[SIGILL] = SIG_DFL;
1703a61dd7fSTimo Kreuzer                 handler(SIGILL);
1719efafd64STimo Kreuzer                 *ep = old_ep;
1729efafd64STimo Kreuzer             }
1739efafd64STimo Kreuzer             ret = EXCEPTION_CONTINUE_EXECUTION;
1749efafd64STimo Kreuzer         }
1759efafd64STimo Kreuzer         break;
1769efafd64STimo Kreuzer     }
1779efafd64STimo Kreuzer     return ret;
1789efafd64STimo Kreuzer }
1799efafd64STimo Kreuzer 
msvcrt_init_signals(void)1809efafd64STimo Kreuzer void msvcrt_init_signals(void)
1819efafd64STimo Kreuzer {
1829efafd64STimo Kreuzer     SetConsoleCtrlHandler(msvcrt_console_handler, TRUE);
1839efafd64STimo Kreuzer }
1849efafd64STimo Kreuzer 
msvcrt_free_signals(void)1859efafd64STimo Kreuzer void msvcrt_free_signals(void)
1869efafd64STimo Kreuzer {
1879efafd64STimo Kreuzer     SetConsoleCtrlHandler(msvcrt_console_handler, FALSE);
1889efafd64STimo Kreuzer }
1899efafd64STimo Kreuzer 
1903a61dd7fSTimo Kreuzer #ifndef __REACTOS__ // Own implementation in signal/signal.c
1919efafd64STimo Kreuzer /*********************************************************************
1929efafd64STimo Kreuzer  *		signal (MSVCRT.@)
1939efafd64STimo Kreuzer  * Some signals may never be generated except through an explicit call to
1949efafd64STimo Kreuzer  * raise.
1959efafd64STimo Kreuzer  */
signal(int sig,__sighandler_t func)1963a61dd7fSTimo Kreuzer __sighandler_t CDECL signal(int sig, __sighandler_t func)
1979efafd64STimo Kreuzer {
1983a61dd7fSTimo Kreuzer     __sighandler_t ret = SIG_ERR;
1999efafd64STimo Kreuzer 
2009efafd64STimo Kreuzer     TRACE("(%d, %p)\n", sig, func);
2019efafd64STimo Kreuzer 
2023a61dd7fSTimo Kreuzer     if (func == SIG_ERR) return SIG_ERR;
2039efafd64STimo Kreuzer 
2049efafd64STimo Kreuzer     switch (sig)
2059efafd64STimo Kreuzer     {
2069efafd64STimo Kreuzer     /* Cases handled internally.  Note SIGTERM is never generated by Windows,
2079efafd64STimo Kreuzer      * so we effectively mask it.
2089efafd64STimo Kreuzer      */
2093a61dd7fSTimo Kreuzer     case SIGABRT:
2103a61dd7fSTimo Kreuzer     case SIGFPE:
2113a61dd7fSTimo Kreuzer     case SIGILL:
2123a61dd7fSTimo Kreuzer     case SIGSEGV:
2133a61dd7fSTimo Kreuzer     case SIGINT:
2143a61dd7fSTimo Kreuzer     case SIGTERM:
2153a61dd7fSTimo Kreuzer     case SIGBREAK:
2169efafd64STimo Kreuzer         ret = sighandlers[sig];
2179efafd64STimo Kreuzer         sighandlers[sig] = func;
2189efafd64STimo Kreuzer         break;
2199efafd64STimo Kreuzer     default:
2203a61dd7fSTimo Kreuzer         ret = SIG_ERR;
2219efafd64STimo Kreuzer     }
2229efafd64STimo Kreuzer     return ret;
2239efafd64STimo Kreuzer }
2249efafd64STimo Kreuzer 
2259efafd64STimo Kreuzer /*********************************************************************
2269efafd64STimo Kreuzer  *		raise (MSVCRT.@)
2279efafd64STimo Kreuzer  */
raise(int sig)2283a61dd7fSTimo Kreuzer int CDECL raise(int sig)
2299efafd64STimo Kreuzer {
2303a61dd7fSTimo Kreuzer     __sighandler_t handler;
2319efafd64STimo Kreuzer 
2329efafd64STimo Kreuzer     TRACE("(%d)\n", sig);
2339efafd64STimo Kreuzer 
2349efafd64STimo Kreuzer     switch (sig)
2359efafd64STimo Kreuzer     {
2363a61dd7fSTimo Kreuzer     case SIGFPE:
2373a61dd7fSTimo Kreuzer     case SIGILL:
2383a61dd7fSTimo Kreuzer     case SIGSEGV:
2399efafd64STimo Kreuzer         handler = sighandlers[sig];
2403a61dd7fSTimo Kreuzer         if (handler == SIG_DFL) _exit(3);
2413a61dd7fSTimo Kreuzer         if (handler != SIG_IGN)
2429efafd64STimo Kreuzer         {
2433a61dd7fSTimo Kreuzer             EXCEPTION_POINTERS **ep = (EXCEPTION_POINTERS**)__pxcptinfoptrs(), *old_ep;
2449efafd64STimo Kreuzer 
2453a61dd7fSTimo Kreuzer             sighandlers[sig] = SIG_DFL;
2469efafd64STimo Kreuzer 
2479efafd64STimo Kreuzer             old_ep = *ep;
2489efafd64STimo Kreuzer             *ep = NULL;
2493a61dd7fSTimo Kreuzer             if (sig == SIGFPE)
2503a61dd7fSTimo Kreuzer                 ((float_handler)handler)(sig, _FPE_EXPLICITGEN);
2519efafd64STimo Kreuzer             else
2529efafd64STimo Kreuzer                 handler(sig);
2539efafd64STimo Kreuzer             *ep = old_ep;
2549efafd64STimo Kreuzer         }
2559efafd64STimo Kreuzer         break;
2563a61dd7fSTimo Kreuzer     case SIGABRT:
2573a61dd7fSTimo Kreuzer     case SIGINT:
2583a61dd7fSTimo Kreuzer     case SIGTERM:
2593a61dd7fSTimo Kreuzer     case SIGBREAK:
2609efafd64STimo Kreuzer         handler = sighandlers[sig];
2613a61dd7fSTimo Kreuzer         if (handler == SIG_DFL) _exit(3);
2623a61dd7fSTimo Kreuzer         if (handler != SIG_IGN)
2639efafd64STimo Kreuzer         {
2643a61dd7fSTimo Kreuzer             sighandlers[sig] = SIG_DFL;
2659efafd64STimo Kreuzer             handler(sig);
2669efafd64STimo Kreuzer         }
2679efafd64STimo Kreuzer         break;
2689efafd64STimo Kreuzer     default:
2699efafd64STimo Kreuzer         return -1;
2709efafd64STimo Kreuzer     }
2719efafd64STimo Kreuzer     return 0;
2729efafd64STimo Kreuzer }
2733a61dd7fSTimo Kreuzer #endif // __REACTOS__
2749efafd64STimo Kreuzer 
2759efafd64STimo Kreuzer /*********************************************************************
2769efafd64STimo Kreuzer  *		_XcptFilter (MSVCRT.@)
2779efafd64STimo Kreuzer  */
_XcptFilter(NTSTATUS ex,PEXCEPTION_POINTERS ptr)2789efafd64STimo Kreuzer int CDECL _XcptFilter(NTSTATUS ex, PEXCEPTION_POINTERS ptr)
2799efafd64STimo Kreuzer {
2809efafd64STimo Kreuzer     TRACE("(%08x,%p)\n", ex, ptr);
2819efafd64STimo Kreuzer     /* I assume ptr->ExceptionRecord->ExceptionCode is the same as ex */
2829efafd64STimo Kreuzer     return msvcrt_exception_filter(ptr);
2839efafd64STimo Kreuzer }
2849efafd64STimo Kreuzer 
2859efafd64STimo Kreuzer #ifndef __REACTOS__
2869efafd64STimo Kreuzer /*********************************************************************
2879efafd64STimo Kreuzer  *		_abnormal_termination (MSVCRT.@)
2889efafd64STimo Kreuzer  */
__intrinsic_abnormal_termination(void)2893a61dd7fSTimo Kreuzer int CDECL __intrinsic_abnormal_termination(void)
2909efafd64STimo Kreuzer {
2919efafd64STimo Kreuzer   FIXME("(void)stub\n");
2929efafd64STimo Kreuzer   return 0;
2939efafd64STimo Kreuzer }
2949efafd64STimo Kreuzer #endif /* __REACTOS__ */
2959efafd64STimo Kreuzer 
2969efafd64STimo Kreuzer /******************************************************************
2979efafd64STimo Kreuzer  *		__uncaught_exception (MSVCRT.@)
2989efafd64STimo Kreuzer  */
__uncaught_exception(void)2993a61dd7fSTimo Kreuzer BOOL CDECL __uncaught_exception(void)
3009efafd64STimo Kreuzer {
3019efafd64STimo Kreuzer     return msvcrt_get_thread_data()->processing_throw != 0;
3029efafd64STimo Kreuzer }
3039efafd64STimo Kreuzer 
3049efafd64STimo Kreuzer #if _MSVCR_VER>=70 && _MSVCR_VER<=71
3059efafd64STimo Kreuzer 
3069efafd64STimo Kreuzer /*********************************************************************
3079efafd64STimo Kreuzer  *		_set_security_error_handler (MSVCR70.@)
3089efafd64STimo Kreuzer  */
_set_security_error_handler(MSVCRT_security_error_handler handler)3099efafd64STimo Kreuzer MSVCRT_security_error_handler CDECL _set_security_error_handler(
3109efafd64STimo Kreuzer     MSVCRT_security_error_handler handler )
3119efafd64STimo Kreuzer {
3129efafd64STimo Kreuzer     MSVCRT_security_error_handler old = security_error_handler;
3139efafd64STimo Kreuzer 
3149efafd64STimo Kreuzer     TRACE("(%p)\n", handler);
3159efafd64STimo Kreuzer 
3169efafd64STimo Kreuzer     security_error_handler = handler;
3179efafd64STimo Kreuzer     return old;
3189efafd64STimo Kreuzer }
3199efafd64STimo Kreuzer 
3209efafd64STimo Kreuzer /*********************************************************************
3219efafd64STimo Kreuzer  *		__security_error_handler (MSVCR70.@)
3229efafd64STimo Kreuzer  */
__security_error_handler(int code,void * data)3239efafd64STimo Kreuzer void CDECL __security_error_handler(int code, void *data)
3249efafd64STimo Kreuzer {
3259efafd64STimo Kreuzer     if(security_error_handler)
3269efafd64STimo Kreuzer         security_error_handler(code, data);
3279efafd64STimo Kreuzer     else
3289efafd64STimo Kreuzer         FIXME("(%d, %p) stub\n", code, data);
3299efafd64STimo Kreuzer 
3303a61dd7fSTimo Kreuzer     _exit(3);
3319efafd64STimo Kreuzer }
3329efafd64STimo Kreuzer 
3339efafd64STimo Kreuzer #endif /* _MSVCR_VER>=70 && _MSVCR_VER<=71 */
3349efafd64STimo Kreuzer 
3359efafd64STimo Kreuzer #if _MSVCR_VER>=110
3369efafd64STimo Kreuzer /*********************************************************************
3379efafd64STimo Kreuzer  *  __crtSetUnhandledExceptionFilter (MSVCR110.@)
3389efafd64STimo Kreuzer  */
__crtSetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER filter)3393a61dd7fSTimo Kreuzer LPTOP_LEVEL_EXCEPTION_FILTER CDECL __crtSetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER filter)
3409efafd64STimo Kreuzer {
3419efafd64STimo Kreuzer     return SetUnhandledExceptionFilter(filter);
3429efafd64STimo Kreuzer }
3439efafd64STimo Kreuzer #endif
3449efafd64STimo Kreuzer 
3459efafd64STimo Kreuzer /*********************************************************************
3469efafd64STimo Kreuzer  * _CreateFrameInfo (MSVCR80.@)
3479efafd64STimo Kreuzer  */
_CreateFrameInfo(frame_info * fi,void * obj)3489efafd64STimo Kreuzer frame_info* CDECL _CreateFrameInfo(frame_info *fi, void *obj)
3499efafd64STimo Kreuzer {
3509efafd64STimo Kreuzer     thread_data_t *data = msvcrt_get_thread_data();
3519efafd64STimo Kreuzer 
3529efafd64STimo Kreuzer     TRACE("(%p, %p)\n", fi, obj);
3539efafd64STimo Kreuzer 
3549efafd64STimo Kreuzer     fi->next = data->frame_info_head;
3559efafd64STimo Kreuzer     data->frame_info_head = fi;
3569efafd64STimo Kreuzer     fi->object = obj;
3579efafd64STimo Kreuzer     return fi;
3589efafd64STimo Kreuzer }
3599efafd64STimo Kreuzer 
3609efafd64STimo Kreuzer /*********************************************************************
3619efafd64STimo Kreuzer  * _FindAndUnlinkFrame (MSVCR80.@)
3629efafd64STimo Kreuzer  */
_FindAndUnlinkFrame(frame_info * fi)3639efafd64STimo Kreuzer void CDECL _FindAndUnlinkFrame(frame_info *fi)
3649efafd64STimo Kreuzer {
3659efafd64STimo Kreuzer     thread_data_t *data = msvcrt_get_thread_data();
3669efafd64STimo Kreuzer     frame_info *cur = data->frame_info_head;
3679efafd64STimo Kreuzer 
3689efafd64STimo Kreuzer     TRACE("(%p)\n", fi);
3699efafd64STimo Kreuzer 
3709efafd64STimo Kreuzer     if (cur == fi)
3719efafd64STimo Kreuzer     {
3729efafd64STimo Kreuzer         data->frame_info_head = cur->next;
3739efafd64STimo Kreuzer         return;
3749efafd64STimo Kreuzer     }
3759efafd64STimo Kreuzer 
3769efafd64STimo Kreuzer     for (; cur->next; cur = cur->next)
3779efafd64STimo Kreuzer     {
3789efafd64STimo Kreuzer         if (cur->next == fi)
3799efafd64STimo Kreuzer         {
3809efafd64STimo Kreuzer             cur->next = fi->next;
3819efafd64STimo Kreuzer             return;
3829efafd64STimo Kreuzer         }
3839efafd64STimo Kreuzer     }
3849efafd64STimo Kreuzer 
3859efafd64STimo Kreuzer     ERR("frame not found, native crashes in this case\n");
3869efafd64STimo Kreuzer }
3879efafd64STimo Kreuzer 
3889efafd64STimo Kreuzer /*********************************************************************
3899efafd64STimo Kreuzer  *              _IsExceptionObjectToBeDestroyed (MSVCR80.@)
3909efafd64STimo Kreuzer  */
_IsExceptionObjectToBeDestroyed(const void * obj)3919efafd64STimo Kreuzer BOOL __cdecl _IsExceptionObjectToBeDestroyed(const void *obj)
3929efafd64STimo Kreuzer {
3939efafd64STimo Kreuzer     frame_info *cur;
3949efafd64STimo Kreuzer 
3959efafd64STimo Kreuzer     TRACE( "%p\n", obj );
3969efafd64STimo Kreuzer 
3979efafd64STimo Kreuzer     for (cur = msvcrt_get_thread_data()->frame_info_head; cur; cur = cur->next)
3989efafd64STimo Kreuzer     {
3999efafd64STimo Kreuzer         if (cur->object == obj)
4009efafd64STimo Kreuzer             return FALSE;
4019efafd64STimo Kreuzer     }
4029efafd64STimo Kreuzer 
4039efafd64STimo Kreuzer     return TRUE;
4049efafd64STimo Kreuzer }
4059efafd64STimo Kreuzer 
4069efafd64STimo Kreuzer /*********************************************************************
4079efafd64STimo Kreuzer  * __DestructExceptionObject (MSVCRT.@)
4089efafd64STimo Kreuzer  */
__DestructExceptionObject(EXCEPTION_RECORD * rec)4099efafd64STimo Kreuzer void CDECL __DestructExceptionObject(EXCEPTION_RECORD *rec)
4109efafd64STimo Kreuzer {
4119efafd64STimo Kreuzer     cxx_exception_type *info = (cxx_exception_type*) rec->ExceptionInformation[2];
4129efafd64STimo Kreuzer     void *object = (void*)rec->ExceptionInformation[1];
4139efafd64STimo Kreuzer 
4149efafd64STimo Kreuzer     TRACE("(%p)\n", rec);
4159efafd64STimo Kreuzer 
4169efafd64STimo Kreuzer     if (rec->ExceptionCode != CXX_EXCEPTION) return;
4179efafd64STimo Kreuzer #ifndef __x86_64__
4189efafd64STimo Kreuzer     if (rec->NumberParameters != 3) return;
4199efafd64STimo Kreuzer #else
4209efafd64STimo Kreuzer     if (rec->NumberParameters != 4) return;
4219efafd64STimo Kreuzer #endif
4229efafd64STimo Kreuzer     if (rec->ExceptionInformation[0] < CXX_FRAME_MAGIC_VC6 ||
4239efafd64STimo Kreuzer             rec->ExceptionInformation[0] > CXX_FRAME_MAGIC_VC8) return;
4249efafd64STimo Kreuzer 
4259efafd64STimo Kreuzer     if (!info || !info->destructor)
4269efafd64STimo Kreuzer         return;
4279efafd64STimo Kreuzer 
4289efafd64STimo Kreuzer #if defined(__i386__)
4299efafd64STimo Kreuzer #ifdef _MSC_VER
4309efafd64STimo Kreuzer     ((void(__fastcall*)(void*))info->destructor)(object);
4319efafd64STimo Kreuzer #else
4329efafd64STimo Kreuzer     __asm__ __volatile__("call *%0" : : "r" (info->destructor), "c" (object) : "eax", "edx", "memory");
4339efafd64STimo Kreuzer #endif
4349efafd64STimo Kreuzer #elif defined(__x86_64__)
4359efafd64STimo Kreuzer     ((void (__cdecl*)(void*))(info->destructor+rec->ExceptionInformation[3]))(object);
4369efafd64STimo Kreuzer #else
4379efafd64STimo Kreuzer     ((void (__cdecl*)(void*))info->destructor)(object);
4389efafd64STimo Kreuzer #endif
4399efafd64STimo Kreuzer }
4409efafd64STimo Kreuzer 
4419efafd64STimo Kreuzer /*********************************************************************
4429efafd64STimo Kreuzer  *  __CxxRegisterExceptionObject (MSVCRT.@)
4439efafd64STimo Kreuzer  */
__CxxRegisterExceptionObject(EXCEPTION_POINTERS * ep,cxx_frame_info * frame_info)4449efafd64STimo Kreuzer BOOL CDECL __CxxRegisterExceptionObject(EXCEPTION_POINTERS *ep, cxx_frame_info *frame_info)
4459efafd64STimo Kreuzer {
4469efafd64STimo Kreuzer     thread_data_t *data = msvcrt_get_thread_data();
4479efafd64STimo Kreuzer 
4489efafd64STimo Kreuzer     TRACE("(%p, %p)\n", ep, frame_info);
4499efafd64STimo Kreuzer 
4509efafd64STimo Kreuzer     if (!ep || !ep->ExceptionRecord)
4519efafd64STimo Kreuzer     {
4529efafd64STimo Kreuzer         frame_info->rec = (void*)-1;
4539efafd64STimo Kreuzer         frame_info->context = (void*)-1;
4549efafd64STimo Kreuzer         return TRUE;
4559efafd64STimo Kreuzer     }
4569efafd64STimo Kreuzer 
4579efafd64STimo Kreuzer     frame_info->rec = data->exc_record;
4589efafd64STimo Kreuzer     frame_info->context = data->ctx_record;
4599efafd64STimo Kreuzer     data->exc_record = ep->ExceptionRecord;
4609efafd64STimo Kreuzer     data->ctx_record = ep->ContextRecord;
4619efafd64STimo Kreuzer     _CreateFrameInfo(&frame_info->frame_info, (void*)ep->ExceptionRecord->ExceptionInformation[1]);
4629efafd64STimo Kreuzer     return TRUE;
4639efafd64STimo Kreuzer }
4649efafd64STimo Kreuzer 
4659efafd64STimo Kreuzer /*********************************************************************
4669efafd64STimo Kreuzer  *  __CxxUnregisterExceptionObject (MSVCRT.@)
4679efafd64STimo Kreuzer  */
__CxxUnregisterExceptionObject(cxx_frame_info * frame_info,BOOL in_use)4689efafd64STimo Kreuzer void CDECL __CxxUnregisterExceptionObject(cxx_frame_info *frame_info, BOOL in_use)
4699efafd64STimo Kreuzer {
4709efafd64STimo Kreuzer     thread_data_t *data = msvcrt_get_thread_data();
4719efafd64STimo Kreuzer 
4729efafd64STimo Kreuzer     TRACE("(%p)\n", frame_info);
4739efafd64STimo Kreuzer 
4749efafd64STimo Kreuzer     if(frame_info->rec == (void*)-1)
4759efafd64STimo Kreuzer         return;
4769efafd64STimo Kreuzer 
4779efafd64STimo Kreuzer     _FindAndUnlinkFrame(&frame_info->frame_info);
4789efafd64STimo Kreuzer     if(data->exc_record->ExceptionCode == CXX_EXCEPTION && !in_use
4799efafd64STimo Kreuzer             && _IsExceptionObjectToBeDestroyed((void*)data->exc_record->ExceptionInformation[1]))
4809efafd64STimo Kreuzer         __DestructExceptionObject(data->exc_record);
4819efafd64STimo Kreuzer     data->exc_record = frame_info->rec;
4829efafd64STimo Kreuzer     data->ctx_record = frame_info->context;
4839efafd64STimo Kreuzer }
4849efafd64STimo Kreuzer 
4859efafd64STimo Kreuzer struct __std_exception_data {
4869efafd64STimo Kreuzer     char *what;
4873a61dd7fSTimo Kreuzer     char dofree;
4889efafd64STimo Kreuzer };
4899efafd64STimo Kreuzer 
490*ae0fa8baSTimo Kreuzer #if _MSVCR_VER>=140 || defined(__UCRTSUPPORT__)
4919efafd64STimo Kreuzer 
4929efafd64STimo Kreuzer /*********************************************************************
4939efafd64STimo Kreuzer  *  __std_exception_copy (UCRTBASE.@)
4949efafd64STimo Kreuzer  */
__std_exception_copy(const struct __std_exception_data * src,struct __std_exception_data * dst)4953a61dd7fSTimo Kreuzer void CDECL __std_exception_copy(const struct __std_exception_data *src,
4969efafd64STimo Kreuzer                                        struct __std_exception_data *dst)
4979efafd64STimo Kreuzer {
4989efafd64STimo Kreuzer     TRACE("(%p %p)\n", src, dst);
4999efafd64STimo Kreuzer 
5009efafd64STimo Kreuzer     if(src->dofree && src->what) {
5013a61dd7fSTimo Kreuzer         dst->what   = _strdup(src->what);
5029efafd64STimo Kreuzer         dst->dofree = 1;
5039efafd64STimo Kreuzer     } else {
5049efafd64STimo Kreuzer         dst->what   = src->what;
5059efafd64STimo Kreuzer         dst->dofree = 0;
5069efafd64STimo Kreuzer     }
5079efafd64STimo Kreuzer }
5089efafd64STimo Kreuzer 
5099efafd64STimo Kreuzer /*********************************************************************
5109efafd64STimo Kreuzer  *  __std_exception_destroy (UCRTBASE.@)
5119efafd64STimo Kreuzer  */
__std_exception_destroy(struct __std_exception_data * data)5123a61dd7fSTimo Kreuzer void CDECL __std_exception_destroy(struct __std_exception_data *data)
5139efafd64STimo Kreuzer {
5149efafd64STimo Kreuzer     TRACE("(%p)\n", data);
5159efafd64STimo Kreuzer 
5169efafd64STimo Kreuzer     if(data->dofree)
5173a61dd7fSTimo Kreuzer         free(data->what);
5189efafd64STimo Kreuzer     data->what   = NULL;
5199efafd64STimo Kreuzer     data->dofree = 0;
5209efafd64STimo Kreuzer }
5219efafd64STimo Kreuzer 
5229efafd64STimo Kreuzer /*********************************************************************
5239efafd64STimo Kreuzer  *  __current_exception (UCRTBASE.@)
5249efafd64STimo Kreuzer  */
__current_exception(void)5259efafd64STimo Kreuzer void** CDECL __current_exception(void)
5269efafd64STimo Kreuzer {
5279efafd64STimo Kreuzer     TRACE("()\n");
5289efafd64STimo Kreuzer     return (void**)&msvcrt_get_thread_data()->exc_record;
5299efafd64STimo Kreuzer }
5309efafd64STimo Kreuzer 
5319efafd64STimo Kreuzer /*********************************************************************
5329efafd64STimo Kreuzer  *  __current_exception_context (UCRTBASE.@)
5339efafd64STimo Kreuzer  */
__current_exception_context(void)5349efafd64STimo Kreuzer void** CDECL __current_exception_context(void)
5359efafd64STimo Kreuzer {
5369efafd64STimo Kreuzer     TRACE("()\n");
5379efafd64STimo Kreuzer     return (void**)&msvcrt_get_thread_data()->ctx_record;
5389efafd64STimo Kreuzer }
5399efafd64STimo Kreuzer 
5409efafd64STimo Kreuzer /*********************************************************************
5419efafd64STimo Kreuzer  *  __processing_throw (UCRTBASE.@)
5429efafd64STimo Kreuzer  */
__processing_throw(void)5439efafd64STimo Kreuzer int* CDECL __processing_throw(void)
5449efafd64STimo Kreuzer {
5459efafd64STimo Kreuzer     TRACE("()\n");
5469efafd64STimo Kreuzer     return &msvcrt_get_thread_data()->processing_throw;
5479efafd64STimo Kreuzer }
5489efafd64STimo Kreuzer 
5499efafd64STimo Kreuzer #endif /* _MSVCR_VER>=140 */
550