VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Wine/include/wine/exception.h@ 23571

Last change on this file since 23571 was 21731, checked in by vboxsync, 15 years ago

crOpenGL: update to wine 1.1.26

  • Property svn:eol-style set to native
File size: 12.3 KB
Line 
1/*
2 * Wine exception handling
3 *
4 * Copyright (c) 1999 Alexandre Julliard
5 *
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.
10 *
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.
15 *
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
19 */
20
21/*
22 * Sun LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
23 * other than GPL or LGPL is available it will apply instead, Sun elects to use only
24 * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
25 * a choice of LGPL license versions is made available with the language indicating
26 * that LGPLv2 or any later version may be used, or where a choice of which version
27 * of the LGPL is applied is otherwise unspecified.
28 */
29
30#ifndef __WINE_WINE_EXCEPTION_H
31#define __WINE_WINE_EXCEPTION_H
32
33#include <setjmp.h>
34#include <windef.h>
35#include <excpt.h>
36
37#ifdef __cplusplus
38extern "C" {
39#endif
40
41/* The following definitions allow using exceptions in Wine and Winelib code
42 *
43 * They should be used like this:
44 *
45 * __TRY
46 * {
47 * do some stuff that can raise an exception
48 * }
49 * __EXCEPT(filter_func)
50 * {
51 * handle the exception here
52 * }
53 * __ENDTRY
54 *
55 * or
56 *
57 * __TRY
58 * {
59 * do some stuff that can raise an exception
60 * }
61 * __FINALLY(finally_func)
62 *
63 * The filter_func and finally_func functions must be defined like this:
64 *
65 * LONG CALLBACK filter_func( PEXCEPTION_POINTERS __eptr ) { ... }
66 *
67 * void CALLBACK finally_func( BOOL __normal ) { ... }
68 *
69 * The filter function must return one of the EXCEPTION_* code; it can
70 * use GetExceptionInformation() and GetExceptionCode() to retrieve the
71 * exception info.
72 *
73 * Warning: inside a __TRY or __EXCEPT block, 'break' or 'continue' statements
74 * break out of the current block. You cannot use 'return', 'goto'
75 * or 'longjmp' to leave a __TRY block, as this will surely crash.
76 * You can use them to leave a __EXCEPT block though.
77 *
78 * -- AJ
79 */
80
81/* Define this if you want to use your compiler built-in __try/__except support.
82 * This is only useful when compiling to a native Windows binary, as the built-in
83 * compiler exceptions will most certainly not work under Winelib.
84 */
85#ifdef USE_COMPILER_EXCEPTIONS
86
87#define __TRY __try
88#define __EXCEPT(func) __except((func)(GetExceptionInformation()))
89#define __FINALLY(func) __finally { (func)(!AbnormalTermination()); }
90#define __ENDTRY /*nothing*/
91#define __EXCEPT_PAGE_FAULT __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
92#define __EXCEPT_ALL __except(EXCEPTION_EXECUTE_HANDLER)
93
94#else /* USE_COMPILER_EXCEPTIONS */
95
96#ifndef __GNUC__
97#define __attribute__(x) /* nothing */
98#endif
99
100#if defined(__MINGW32__) || defined(__CYGWIN__)
101#define sigjmp_buf jmp_buf
102#define sigsetjmp(buf,sigs) setjmp(buf)
103#define siglongjmp(buf,val) longjmp(buf,val)
104#endif
105
106#define __TRY \
107 do { __WINE_FRAME __f; \
108 int __first = 1; \
109 for (;;) if (!__first) \
110 { \
111 do {
112
113#define __EXCEPT(func) \
114 } while(0); \
115 __wine_pop_frame( &__f.frame ); \
116 break; \
117 } else { \
118 __f.frame.Handler = __wine_exception_handler; \
119 __f.u.filter = (func); \
120 if (sigsetjmp( __f.jmp, 0 )) { \
121 const __WINE_FRAME * const __eptr __attribute__((unused)) = &__f; \
122 do {
123
124/* convenience handler for page fault exceptions */
125#define __EXCEPT_PAGE_FAULT \
126 } while(0); \
127 __wine_pop_frame( &__f.frame ); \
128 break; \
129 } else { \
130 __f.frame.Handler = __wine_exception_handler_page_fault; \
131 if (sigsetjmp( __f.jmp, 0 )) { \
132 const __WINE_FRAME * const __eptr __attribute__((unused)) = &__f; \
133 do {
134
135/* convenience handler for all exception */
136#define __EXCEPT_ALL \
137 } while(0); \
138 __wine_pop_frame( &__f.frame ); \
139 break; \
140 } else { \
141 __f.frame.Handler = __wine_exception_handler_all; \
142 if (sigsetjmp( __f.jmp, 0 )) { \
143 const __WINE_FRAME * const __eptr __attribute__((unused)) = &__f; \
144 do {
145
146#define __ENDTRY \
147 } while (0); \
148 break; \
149 } \
150 __wine_push_frame( &__f.frame ); \
151 __first = 0; \
152 } \
153 } while (0);
154
155#define __FINALLY(func) \
156 } while(0); \
157 __wine_pop_frame( &__f.frame ); \
158 (func)(1); \
159 break; \
160 } else { \
161 __f.frame.Handler = __wine_finally_handler; \
162 __f.u.finally_func = (func); \
163 __wine_push_frame( &__f.frame ); \
164 __first = 0; \
165 } \
166 } while (0);
167
168
169typedef LONG (CALLBACK *__WINE_FILTER)(PEXCEPTION_POINTERS);
170typedef void (CALLBACK *__WINE_FINALLY)(BOOL);
171
172#define GetExceptionInformation() (__eptr)
173#define GetExceptionCode() (__eptr->ExceptionRecord->ExceptionCode)
174#define AbnormalTermination() (!__normal)
175
176typedef struct __tagWINE_FRAME
177{
178 EXCEPTION_REGISTRATION_RECORD frame;
179 union
180 {
181 /* exception data */
182 __WINE_FILTER filter;
183 /* finally data */
184 __WINE_FINALLY finally_func;
185 } u;
186 sigjmp_buf jmp;
187 /* hack to make GetExceptionCode() work in handler */
188 DWORD ExceptionCode;
189 const struct __tagWINE_FRAME *ExceptionRecord;
190} __WINE_FRAME;
191
192#endif /* USE_COMPILER_EXCEPTIONS */
193
194static inline EXCEPTION_REGISTRATION_RECORD *__wine_push_frame( EXCEPTION_REGISTRATION_RECORD *frame )
195{
196#if defined(__GNUC__) && defined(__i386__)
197 EXCEPTION_REGISTRATION_RECORD *prev;
198 __asm__ __volatile__(".byte 0x64\n\tmovl (0),%0"
199 "\n\tmovl %0,(%1)"
200 "\n\t.byte 0x64\n\tmovl %1,(0)"
201 : "=&r" (prev) : "r" (frame) : "memory" );
202 return prev;
203#else
204 NT_TIB *teb = (NT_TIB *)NtCurrentTeb();
205 frame->Prev = teb->ExceptionList;
206 teb->ExceptionList = frame;
207 return frame->Prev;
208#endif
209}
210
211static inline EXCEPTION_REGISTRATION_RECORD *__wine_pop_frame( EXCEPTION_REGISTRATION_RECORD *frame )
212{
213#if defined(__GNUC__) && defined(__i386__)
214 __asm__ __volatile__(".byte 0x64\n\tmovl %0,(0)"
215 : : "r" (frame->Prev) : "memory" );
216 return frame->Prev;
217
218#else
219 NT_TIB *teb = (NT_TIB *)NtCurrentTeb();
220 teb->ExceptionList = frame->Prev;
221 return frame->Prev;
222#endif
223}
224
225static inline EXCEPTION_REGISTRATION_RECORD *__wine_get_frame(void)
226{
227#if defined(__GNUC__) && defined(__i386__)
228 EXCEPTION_REGISTRATION_RECORD *ret;
229 __asm__ __volatile__(".byte 0x64\n\tmovl (0),%0" : "=r" (ret) );
230 return ret;
231#else
232 NT_TIB *teb = (NT_TIB *)NtCurrentTeb();
233 return teb->ExceptionList;
234#endif
235}
236
237/* Exception handling flags - from OS/2 2.0 exception handling */
238
239/* Win32 seems to use the same flags as ExceptionFlags in an EXCEPTION_RECORD */
240#define EH_NONCONTINUABLE 0x01
241#define EH_UNWINDING 0x02
242#define EH_EXIT_UNWIND 0x04
243#define EH_STACK_INVALID 0x08
244#define EH_NESTED_CALL 0x10
245
246/* Wine-specific exceptions codes */
247
248#define EXCEPTION_WINE_STUB 0x80000100 /* stub entry point called */
249#define EXCEPTION_WINE_ASSERTION 0x80000101 /* assertion failed */
250
251/* unhandled return status from vm86 mode */
252#define EXCEPTION_VM86_INTx 0x80000110
253#define EXCEPTION_VM86_STI 0x80000111
254#define EXCEPTION_VM86_PICRETURN 0x80000112
255
256extern void __wine_enter_vm86( CONTEXT *context );
257
258#ifndef USE_COMPILER_EXCEPTIONS
259
260NTSYSAPI void WINAPI RtlUnwind(PVOID,PVOID,PEXCEPTION_RECORD,PVOID);
261
262static inline void DECLSPEC_NORETURN __wine_unwind_target(void)
263{
264 __WINE_FRAME *wine_frame = (__WINE_FRAME *)__wine_get_frame();
265 __wine_pop_frame( &wine_frame->frame );
266 siglongjmp( wine_frame->jmp, 1 );
267}
268
269/* wrapper for RtlUnwind since it clobbers registers on Windows */
270static inline void DECLSPEC_NORETURN __wine_rtl_unwind( EXCEPTION_REGISTRATION_RECORD* frame,
271 EXCEPTION_RECORD *record,
272 void (*target)(void) )
273{
274#if defined(__GNUC__) && defined(__i386__)
275 int dummy1, dummy2, dummy3, dummy4;
276 __asm__ __volatile__("pushl %%ebp\n\t"
277 "pushl %%ebx\n\t"
278 "pushl $0\n\t"
279 "pushl %3\n\t"
280 "pushl %2\n\t"
281 "pushl %1\n\t"
282 "call *%0\n\t"
283 "popl %%ebx\n\t"
284 "popl %%ebp"
285 : "=a" (dummy1), "=S" (dummy2), "=D" (dummy3), "=c" (dummy4)
286 : "0" (RtlUnwind), "1" (frame), "2" (target), "3" (record)
287 : "edx", "memory" );
288#else
289 RtlUnwind( frame, target, record, 0 );
290#endif
291 for (;;) target();
292}
293
294static inline void DECLSPEC_NORETURN __wine_unwind_frame( EXCEPTION_RECORD *record,
295 EXCEPTION_REGISTRATION_RECORD *frame )
296{
297 __WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
298
299 /* hack to make GetExceptionCode() work in handler */
300 wine_frame->ExceptionCode = record->ExceptionCode;
301 wine_frame->ExceptionRecord = wine_frame;
302
303 __wine_rtl_unwind( frame, record, __wine_unwind_target );
304}
305
306static inline DWORD __wine_exception_handler( EXCEPTION_RECORD *record,
307 EXCEPTION_REGISTRATION_RECORD *frame,
308 CONTEXT *context,
309 EXCEPTION_REGISTRATION_RECORD **pdispatcher )
310{
311 __WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
312 EXCEPTION_POINTERS ptrs;
313
314 if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND | EH_NESTED_CALL))
315 return ExceptionContinueSearch;
316
317 ptrs.ExceptionRecord = record;
318 ptrs.ContextRecord = context;
319 switch(wine_frame->u.filter( &ptrs ))
320 {
321 case EXCEPTION_CONTINUE_SEARCH:
322 return ExceptionContinueSearch;
323 case EXCEPTION_CONTINUE_EXECUTION:
324 return ExceptionContinueExecution;
325 case EXCEPTION_EXECUTE_HANDLER:
326 break;
327 }
328 __wine_unwind_frame( record, frame );
329}
330
331static inline DWORD __wine_exception_handler_page_fault( EXCEPTION_RECORD *record,
332 EXCEPTION_REGISTRATION_RECORD *frame,
333 CONTEXT *context,
334 EXCEPTION_REGISTRATION_RECORD **pdispatcher )
335{
336 if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND | EH_NESTED_CALL))
337 return ExceptionContinueSearch;
338 if (record->ExceptionCode != STATUS_ACCESS_VIOLATION)
339 return ExceptionContinueSearch;
340 __wine_unwind_frame( record, frame );
341}
342
343static inline DWORD __wine_exception_handler_all( EXCEPTION_RECORD *record,
344 EXCEPTION_REGISTRATION_RECORD *frame,
345 CONTEXT *context,
346 EXCEPTION_REGISTRATION_RECORD **pdispatcher )
347{
348 if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND | EH_NESTED_CALL))
349 return ExceptionContinueSearch;
350 __wine_unwind_frame( record, frame );
351}
352
353static inline DWORD __wine_finally_handler( EXCEPTION_RECORD *record,
354 EXCEPTION_REGISTRATION_RECORD *frame,
355 CONTEXT *context,
356 EXCEPTION_REGISTRATION_RECORD **pdispatcher )
357{
358 if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
359 {
360 __WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
361 wine_frame->u.finally_func( FALSE );
362 }
363 return ExceptionContinueSearch;
364}
365
366#endif /* USE_COMPILER_EXCEPTIONS */
367
368#ifdef __cplusplus
369}
370#endif
371
372#endif /* __WINE_WINE_EXCEPTION_H */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette