oleaut32: Use a saner calling convention for the marshaller asm thunks.
[wine] / dlls / msvcrt / except.c
1 /*
2  * msvcrt.dll exception handling
3  *
4  * Copyright 2000 Jon Griffiths
5  * Copyright 2005 Juan Lang
6  *
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.
11  *
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.
16  *
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
20  *
21  * FIXME: Incomplete support for nested exceptions/try block cleanup.
22  */
23
24 #include "config.h"
25 #include "wine/port.h"
26
27 #include <stdarg.h>
28
29 #include "ntstatus.h"
30 #define WIN32_NO_STATUS
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winternl.h"
34 #include "wine/exception.h"
35 #include "msvcrt.h"
36 #include "excpt.h"
37 #include "wincon.h"
38 #include "wine/debug.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(seh);
41
42 static MSVCRT_security_error_handler security_error_handler;
43
44 static MSVCRT___sighandler_t sighandlers[MSVCRT_NSIG] = { MSVCRT_SIG_DFL };
45
46 static BOOL WINAPI msvcrt_console_handler(DWORD ctrlType)
47 {
48     BOOL ret = FALSE;
49
50     switch (ctrlType)
51     {
52     case CTRL_C_EVENT:
53         if (sighandlers[MSVCRT_SIGINT])
54         {
55             if (sighandlers[MSVCRT_SIGINT] != MSVCRT_SIG_IGN)
56                 sighandlers[MSVCRT_SIGINT](MSVCRT_SIGINT);
57             ret = TRUE;
58         }
59         break;
60     }
61     return ret;
62 }
63
64 typedef void (CDECL *float_handler)(int, int);
65
66 /* The exception codes are actually NTSTATUS values */
67 static const struct
68 {
69     NTSTATUS status;
70     int signal;
71 } float_exception_map[] = {
72  { EXCEPTION_FLT_DENORMAL_OPERAND, MSVCRT__FPE_DENORMAL },
73  { EXCEPTION_FLT_DIVIDE_BY_ZERO, MSVCRT__FPE_ZERODIVIDE },
74  { EXCEPTION_FLT_INEXACT_RESULT, MSVCRT__FPE_INEXACT },
75  { EXCEPTION_FLT_INVALID_OPERATION, MSVCRT__FPE_INVALID },
76  { EXCEPTION_FLT_OVERFLOW, MSVCRT__FPE_OVERFLOW },
77  { EXCEPTION_FLT_STACK_CHECK, MSVCRT__FPE_STACKOVERFLOW },
78  { EXCEPTION_FLT_UNDERFLOW, MSVCRT__FPE_UNDERFLOW },
79 };
80
81 static LONG WINAPI msvcrt_exception_filter(struct _EXCEPTION_POINTERS *except)
82 {
83     LONG ret = EXCEPTION_CONTINUE_SEARCH;
84     MSVCRT___sighandler_t handler;
85
86     if (!except || !except->ExceptionRecord)
87         return EXCEPTION_CONTINUE_SEARCH;
88
89     switch (except->ExceptionRecord->ExceptionCode)
90     {
91     case EXCEPTION_ACCESS_VIOLATION:
92         if ((handler = sighandlers[MSVCRT_SIGSEGV]) != MSVCRT_SIG_DFL)
93         {
94             if (handler != MSVCRT_SIG_IGN)
95             {
96                 sighandlers[MSVCRT_SIGSEGV] = MSVCRT_SIG_DFL;
97                 handler(MSVCRT_SIGSEGV);
98             }
99             ret = EXCEPTION_CONTINUE_EXECUTION;
100         }
101         break;
102     /* According to msdn,
103      * the FPE signal handler takes as a second argument the type of
104      * floating point exception.
105      */
106     case EXCEPTION_FLT_DENORMAL_OPERAND:
107     case EXCEPTION_FLT_DIVIDE_BY_ZERO:
108     case EXCEPTION_FLT_INEXACT_RESULT:
109     case EXCEPTION_FLT_INVALID_OPERATION:
110     case EXCEPTION_FLT_OVERFLOW:
111     case EXCEPTION_FLT_STACK_CHECK:
112     case EXCEPTION_FLT_UNDERFLOW:
113         if ((handler = sighandlers[MSVCRT_SIGFPE]) != MSVCRT_SIG_DFL)
114         {
115             if (handler != MSVCRT_SIG_IGN)
116             {
117                 unsigned int i;
118                 int float_signal = MSVCRT__FPE_INVALID;
119
120                 sighandlers[MSVCRT_SIGFPE] = MSVCRT_SIG_DFL;
121                 for (i = 0; i < sizeof(float_exception_map) /
122                          sizeof(float_exception_map[0]); i++)
123                 {
124                     if (float_exception_map[i].status ==
125                         except->ExceptionRecord->ExceptionCode)
126                     {
127                         float_signal = float_exception_map[i].signal;
128                         break;
129                     }
130                 }
131                 ((float_handler)handler)(MSVCRT_SIGFPE, float_signal);
132             }
133             ret = EXCEPTION_CONTINUE_EXECUTION;
134         }
135         break;
136     case EXCEPTION_ILLEGAL_INSTRUCTION:
137     case EXCEPTION_PRIV_INSTRUCTION:
138         if ((handler = sighandlers[MSVCRT_SIGILL]) != MSVCRT_SIG_DFL)
139         {
140             if (handler != MSVCRT_SIG_IGN)
141             {
142                 sighandlers[MSVCRT_SIGILL] = MSVCRT_SIG_DFL;
143                 handler(MSVCRT_SIGILL);
144             }
145             ret = EXCEPTION_CONTINUE_EXECUTION;
146         }
147         break;
148     }
149     return ret;
150 }
151
152 void msvcrt_init_signals(void)
153 {
154     SetConsoleCtrlHandler(msvcrt_console_handler, TRUE);
155     SetUnhandledExceptionFilter(msvcrt_exception_filter);
156 }
157
158 void msvcrt_free_signals(void)
159 {
160     SetConsoleCtrlHandler(msvcrt_console_handler, FALSE);
161     SetUnhandledExceptionFilter(NULL);
162 }
163
164 /*********************************************************************
165  *              signal (MSVCRT.@)
166  * Some signals may never be generated except through an explicit call to
167  * raise.
168  */
169 MSVCRT___sighandler_t CDECL MSVCRT_signal(int sig, MSVCRT___sighandler_t func)
170 {
171     MSVCRT___sighandler_t ret = MSVCRT_SIG_ERR;
172
173     TRACE("(%d, %p)\n", sig, func);
174
175     if (func == MSVCRT_SIG_ERR) return MSVCRT_SIG_ERR;
176
177     switch (sig)
178     {
179     /* Cases handled internally.  Note SIGTERM is never generated by Windows,
180      * so we effectively mask it.
181      */
182     case MSVCRT_SIGABRT:
183     case MSVCRT_SIGFPE:
184     case MSVCRT_SIGILL:
185     case MSVCRT_SIGSEGV:
186     case MSVCRT_SIGINT:
187     case MSVCRT_SIGTERM:
188     case MSVCRT_SIGBREAK:
189         ret = sighandlers[sig];
190         sighandlers[sig] = func;
191         break;
192     default:
193         ret = MSVCRT_SIG_ERR;
194     }
195     return ret;
196 }
197
198 /*********************************************************************
199  *              raise (MSVCRT.@)
200  */
201 int CDECL MSVCRT_raise(int sig)
202 {
203     MSVCRT___sighandler_t handler;
204
205     TRACE("(%d)\n", sig);
206
207     switch (sig)
208     {
209     case MSVCRT_SIGABRT:
210     case MSVCRT_SIGFPE:
211     case MSVCRT_SIGILL:
212     case MSVCRT_SIGSEGV:
213     case MSVCRT_SIGINT:
214     case MSVCRT_SIGTERM:
215     case MSVCRT_SIGBREAK:
216         handler = sighandlers[sig];
217         if (handler == MSVCRT_SIG_DFL) MSVCRT__exit(3);
218         if (handler != MSVCRT_SIG_IGN)
219         {
220             sighandlers[sig] = MSVCRT_SIG_DFL;
221             if (sig == MSVCRT_SIGFPE)
222                 ((float_handler)handler)(sig, MSVCRT__FPE_EXPLICITGEN);
223             else
224                 handler(sig);
225         }
226         break;
227     default:
228         return -1;
229     }
230     return 0;
231 }
232
233 /*********************************************************************
234  *              _XcptFilter (MSVCRT.@)
235  */
236 int CDECL _XcptFilter(NTSTATUS ex, PEXCEPTION_POINTERS ptr)
237 {
238     TRACE("(%08x,%p)\n", ex, ptr);
239     /* I assume ptr->ExceptionRecord->ExceptionCode is the same as ex */
240     return msvcrt_exception_filter(ptr);
241 }
242
243 /*********************************************************************
244  *              _abnormal_termination (MSVCRT.@)
245  */
246 int CDECL _abnormal_termination(void)
247 {
248   FIXME("(void)stub\n");
249   return 0;
250 }
251
252 /******************************************************************
253  *              MSVCRT___uncaught_exception
254  */
255 BOOL CDECL MSVCRT___uncaught_exception(void)
256 {
257     return FALSE;
258 }
259
260 /* _set_security_error_handler - not exported in native msvcrt, added in msvcr70 */
261 MSVCRT_security_error_handler CDECL _set_security_error_handler(
262     MSVCRT_security_error_handler handler )
263 {
264     MSVCRT_security_error_handler old = security_error_handler;
265
266     TRACE("(%p)\n", handler);
267
268     security_error_handler = handler;
269     return old;
270 }