d3d11/tests: Add test for shaders interstage interface.
[wine.git] / dlls / winecrt0 / exception.c
blob0e00f73a6fd968061b50c6f742617647a592a39a
1 /*
2 * Support functions for Wine exception handling
4 * Copyright (c) 1999, 2010 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include <stdarg.h>
23 #include "winternl.h"
24 #include "wine/exception.h"
26 #if defined(__x86_64__) && defined(__ASM_GLOBAL_FUNC)
27 extern void __wine_unwind_trampoline(void);
28 /* we need an extra call to make sure the stack is correctly aligned */
29 __ASM_GLOBAL_FUNC( __wine_unwind_trampoline, "callq *%rax" );
30 #endif
32 /* wrapper for RtlUnwind since it clobbers registers on Windows */
33 void __wine_rtl_unwind( EXCEPTION_REGISTRATION_RECORD* frame, EXCEPTION_RECORD *record,
34 void (*target)(void) )
36 #if defined(__GNUC__) && defined(__i386__)
37 int dummy1, dummy2, dummy3, dummy4;
38 __asm__ __volatile__("pushl %%ebp\n\t"
39 "pushl %%ebx\n\t"
40 "pushl $0\n\t"
41 "pushl %3\n\t"
42 "pushl %2\n\t"
43 "pushl %1\n\t"
44 "call *%0\n\t"
45 "popl %%ebx\n\t"
46 "popl %%ebp"
47 : "=a" (dummy1), "=S" (dummy2), "=D" (dummy3), "=c" (dummy4)
48 : "0" (RtlUnwind), "1" (frame), "2" (target), "3" (record)
49 : "edx", "memory" );
50 #elif defined(__x86_64__) && defined(__ASM_GLOBAL_FUNC)
51 RtlUnwind( frame, __wine_unwind_trampoline, record, target );
52 #else
53 RtlUnwind( frame, target, record, 0 );
54 #endif
55 for (;;) target();
58 static void DECLSPEC_NORETURN unwind_target(void)
60 __WINE_FRAME *wine_frame = (__WINE_FRAME *)__wine_get_frame();
61 __wine_pop_frame( &wine_frame->frame );
62 siglongjmp( wine_frame->jmp, 1 );
65 static void DECLSPEC_NORETURN unwind_frame( EXCEPTION_RECORD *record,
66 EXCEPTION_REGISTRATION_RECORD *frame )
68 __WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
70 /* hack to make GetExceptionCode() work in handler */
71 wine_frame->ExceptionCode = record->ExceptionCode;
72 wine_frame->ExceptionRecord = wine_frame;
74 __wine_rtl_unwind( frame, record, unwind_target );
77 DWORD __wine_exception_handler( EXCEPTION_RECORD *record,
78 EXCEPTION_REGISTRATION_RECORD *frame,
79 CONTEXT *context,
80 EXCEPTION_REGISTRATION_RECORD **pdispatcher )
82 __WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
83 EXCEPTION_POINTERS ptrs;
85 if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND | EH_NESTED_CALL))
86 return ExceptionContinueSearch;
88 ptrs.ExceptionRecord = record;
89 ptrs.ContextRecord = context;
90 switch(wine_frame->u.filter( &ptrs ))
92 case EXCEPTION_CONTINUE_SEARCH:
93 return ExceptionContinueSearch;
94 case EXCEPTION_CONTINUE_EXECUTION:
95 return ExceptionContinueExecution;
96 case EXCEPTION_EXECUTE_HANDLER:
97 break;
99 unwind_frame( record, frame );
102 DWORD __wine_exception_ctx_handler( EXCEPTION_RECORD *record,
103 EXCEPTION_REGISTRATION_RECORD *frame,
104 CONTEXT *context,
105 EXCEPTION_REGISTRATION_RECORD **pdispatcher )
107 __WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
108 EXCEPTION_POINTERS ptrs;
110 if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND | EH_NESTED_CALL))
111 return ExceptionContinueSearch;
113 ptrs.ExceptionRecord = record;
114 ptrs.ContextRecord = context;
115 switch(wine_frame->u.filter_ctx( &ptrs, wine_frame->ctx ))
117 case EXCEPTION_CONTINUE_SEARCH:
118 return ExceptionContinueSearch;
119 case EXCEPTION_CONTINUE_EXECUTION:
120 return ExceptionContinueExecution;
121 case EXCEPTION_EXECUTE_HANDLER:
122 break;
124 unwind_frame( record, frame );
127 DWORD __wine_exception_handler_page_fault( EXCEPTION_RECORD *record,
128 EXCEPTION_REGISTRATION_RECORD *frame,
129 CONTEXT *context,
130 EXCEPTION_REGISTRATION_RECORD **pdispatcher )
132 if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND | EH_NESTED_CALL))
133 return ExceptionContinueSearch;
134 if (record->ExceptionCode != STATUS_ACCESS_VIOLATION)
135 return ExceptionContinueSearch;
136 unwind_frame( record, frame );
139 DWORD __wine_exception_handler_all( EXCEPTION_RECORD *record,
140 EXCEPTION_REGISTRATION_RECORD *frame,
141 CONTEXT *context,
142 EXCEPTION_REGISTRATION_RECORD **pdispatcher )
144 if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND | EH_NESTED_CALL))
145 return ExceptionContinueSearch;
146 unwind_frame( record, frame );
149 DWORD __wine_finally_handler( EXCEPTION_RECORD *record,
150 EXCEPTION_REGISTRATION_RECORD *frame,
151 CONTEXT *context,
152 EXCEPTION_REGISTRATION_RECORD **pdispatcher )
154 if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
156 __WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
157 wine_frame->u.finally_func( FALSE );
159 return ExceptionContinueSearch;
162 DWORD __wine_finally_ctx_handler( EXCEPTION_RECORD *record,
163 EXCEPTION_REGISTRATION_RECORD *frame,
164 CONTEXT *context,
165 EXCEPTION_REGISTRATION_RECORD **pdispatcher )
167 if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
169 __WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
170 wine_frame->u.finally_func_ctx( FALSE, wine_frame->ctx );
172 return ExceptionContinueSearch;