VirtualBox

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

Last change on this file since 16477 was 16477, checked in by vboxsync, 16 years ago

LGPL disclaimer by filemuncher

  • Property svn:eol-style set to native
File size: 11.5 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,param)
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,param)
62 *
63 * The filter_func must be defined with the WINE_EXCEPTION_FILTER
64 * macro, and return one of the EXCEPTION_* code; it can use
65 * GetExceptionInformation and GetExceptionCode to retrieve the
66 * exception info.
67 *
68 * The finally_func must be defined with the WINE_FINALLY_FUNC macro.
69 *
70 * Warning: inside a __TRY or __EXCEPT block, 'break' or 'continue' statements
71 * break out of the current block. You cannot use 'return', 'goto'
72 * or 'longjmp' to leave a __TRY block, as this will surely crash.
73 * You can use them to leave a __EXCEPT block though.
74 *
75 * -- AJ
76 */
77
78/* Define this if you want to use your compiler built-in __try/__except support.
79 * This is only useful when compiling to a native Windows binary, as the built-in
80 * compiler exceptions will most certainly not work under Winelib.
81 */
82#ifdef USE_COMPILER_EXCEPTIONS
83
84#define __TRY __try
85#define __EXCEPT(func) __except((func)(GetExceptionInformation()))
86#define __FINALLY(func) __finally { (func)(!AbnormalTermination()); }
87#define __ENDTRY /*nothing*/
88#define __EXCEPT_PAGE_FAULT __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
89#define __EXCEPT_ALL __except(EXCEPTION_EXECUTE_HANDLER)
90
91#else /* USE_COMPILER_EXCEPTIONS */
92
93#ifndef __GNUC__
94#define __attribute__(x) /* nothing */
95#endif
96
97#if defined(__MINGW32__) || defined(__CYGWIN__)
98#define sigjmp_buf jmp_buf
99#define sigsetjmp(buf,sigs) setjmp(buf)
100#define siglongjmp(buf,val) longjmp(buf,val)
101#endif
102
103#define __TRY \
104 do { __WINE_FRAME __f; \
105 int __first = 1; \
106 for (;;) if (!__first) \
107 { \
108 do {
109
110#define __EXCEPT(func) \
111 } while(0); \
112 __wine_pop_frame( &__f.frame ); \
113 break; \
114 } else { \
115 __f.frame.Handler = __wine_exception_handler; \
116 __f.u.filter = (func); \
117 if (sigsetjmp( __f.jmp, 0 )) { \
118 const __WINE_FRAME * const __eptr __attribute__((unused)) = &__f; \
119 do {
120
121/* convenience handler for page fault exceptions */
122#define __EXCEPT_PAGE_FAULT \
123 } while(0); \
124 __wine_pop_frame( &__f.frame ); \
125 break; \
126 } else { \
127 __f.frame.Handler = __wine_exception_handler_page_fault; \
128 if (sigsetjmp( __f.jmp, 0 )) { \
129 const __WINE_FRAME * const __eptr __attribute__((unused)) = &__f; \
130 do {
131
132/* convenience handler for all exception */
133#define __EXCEPT_ALL \
134 } while(0); \
135 __wine_pop_frame( &__f.frame ); \
136 break; \
137 } else { \
138 __f.frame.Handler = __wine_exception_handler_all; \
139 if (sigsetjmp( __f.jmp, 0 )) { \
140 const __WINE_FRAME * const __eptr __attribute__((unused)) = &__f; \
141 do {
142
143#define __ENDTRY \
144 } while (0); \
145 break; \
146 } \
147 __wine_push_frame( &__f.frame ); \
148 __first = 0; \
149 } \
150 } while (0);
151
152#define __FINALLY(func) \
153 } while(0); \
154 __wine_pop_frame( &__f.frame ); \
155 (func)(1); \
156 break; \
157 } else { \
158 __f.frame.Handler = __wine_finally_handler; \
159 __f.u.finally_func = (func); \
160 __wine_push_frame( &__f.frame ); \
161 __first = 0; \
162 } \
163 } while (0);
164
165
166typedef LONG (CALLBACK *__WINE_FILTER)(PEXCEPTION_POINTERS);
167typedef void (CALLBACK *__WINE_FINALLY)(BOOL);
168
169#define GetExceptionInformation() (__eptr)
170#define GetExceptionCode() (__eptr->ExceptionRecord->ExceptionCode)
171#define AbnormalTermination() (!__normal)
172
173typedef struct __tagWINE_FRAME
174{
175 EXCEPTION_REGISTRATION_RECORD frame;
176 union
177 {
178 /* exception data */
179 __WINE_FILTER filter;
180 /* finally data */
181 __WINE_FINALLY finally_func;
182 } u;
183 sigjmp_buf jmp;
184 /* hack to make GetExceptionCode() work in handler */
185 DWORD ExceptionCode;
186 const struct __tagWINE_FRAME *ExceptionRecord;
187} __WINE_FRAME;
188
189#endif /* USE_COMPILER_EXCEPTIONS */
190
191static inline EXCEPTION_REGISTRATION_RECORD *__wine_push_frame( EXCEPTION_REGISTRATION_RECORD *frame )
192{
193#if defined(__GNUC__) && defined(__i386__)
194 EXCEPTION_REGISTRATION_RECORD *prev;
195 __asm__ __volatile__(".byte 0x64\n\tmovl (0),%0"
196 "\n\tmovl %0,(%1)"
197 "\n\t.byte 0x64\n\tmovl %1,(0)"
198 : "=&r" (prev) : "r" (frame) : "memory" );
199 return prev;
200#else
201 NT_TIB *teb = (NT_TIB *)NtCurrentTeb();
202 frame->Prev = teb->ExceptionList;
203 teb->ExceptionList = frame;
204 return frame->Prev;
205#endif
206}
207
208static inline EXCEPTION_REGISTRATION_RECORD *__wine_pop_frame( EXCEPTION_REGISTRATION_RECORD *frame )
209{
210#if defined(__GNUC__) && defined(__i386__)
211 __asm__ __volatile__(".byte 0x64\n\tmovl %0,(0)"
212 : : "r" (frame->Prev) : "memory" );
213 return frame->Prev;
214
215#else
216 NT_TIB *teb = (NT_TIB *)NtCurrentTeb();
217 teb->ExceptionList = frame->Prev;
218 return frame->Prev;
219#endif
220}
221
222/* Exception handling flags - from OS/2 2.0 exception handling */
223
224/* Win32 seems to use the same flags as ExceptionFlags in an EXCEPTION_RECORD */
225#define EH_NONCONTINUABLE 0x01
226#define EH_UNWINDING 0x02
227#define EH_EXIT_UNWIND 0x04
228#define EH_STACK_INVALID 0x08
229#define EH_NESTED_CALL 0x10
230
231/* Wine-specific exceptions codes */
232
233#define EXCEPTION_WINE_STUB 0x80000100 /* stub entry point called */
234#define EXCEPTION_WINE_ASSERTION 0x80000101 /* assertion failed */
235
236/* unhandled return status from vm86 mode */
237#define EXCEPTION_VM86_INTx 0x80000110
238#define EXCEPTION_VM86_STI 0x80000111
239#define EXCEPTION_VM86_PICRETURN 0x80000112
240
241extern void __wine_enter_vm86( CONTEXT *context );
242
243#ifndef USE_COMPILER_EXCEPTIONS
244
245extern void WINAPI RtlUnwind(PVOID,PVOID,PEXCEPTION_RECORD,PVOID);
246
247/* wrapper for RtlUnwind since it clobbers registers on Windows */
248static inline void __wine_rtl_unwind( EXCEPTION_REGISTRATION_RECORD* frame, EXCEPTION_RECORD *record )
249{
250#if defined(__GNUC__) && defined(__i386__)
251 int dummy1, dummy2, dummy3;
252 __asm__ __volatile__("pushl %%ebp\n\t"
253 "pushl %%ebx\n\t"
254 "pushl $0\n\t"
255 "pushl %2\n\t"
256 "pushl $0\n\t"
257 "pushl %1\n\t"
258 "call *%0\n\t"
259 "popl %%ebx\n\t"
260 "popl %%ebp"
261 : "=a" (dummy1), "=S" (dummy2), "=D" (dummy3)
262 : "0" (RtlUnwind), "1" (frame), "2" (record)
263 : "ecx", "edx", "memory" );
264#else
265 RtlUnwind( frame, 0, record, 0 );
266#endif
267}
268
269static inline void DECLSPEC_NORETURN __wine_unwind_frame( EXCEPTION_RECORD *record,
270 EXCEPTION_REGISTRATION_RECORD *frame )
271{
272 __WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
273
274 /* hack to make GetExceptionCode() work in handler */
275 wine_frame->ExceptionCode = record->ExceptionCode;
276 wine_frame->ExceptionRecord = wine_frame;
277
278 __wine_rtl_unwind( frame, record );
279 __wine_pop_frame( frame );
280 siglongjmp( wine_frame->jmp, 1 );
281}
282
283static inline DWORD __wine_exception_handler( EXCEPTION_RECORD *record,
284 EXCEPTION_REGISTRATION_RECORD *frame,
285 CONTEXT *context,
286 EXCEPTION_REGISTRATION_RECORD **pdispatcher )
287{
288 __WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
289 EXCEPTION_POINTERS ptrs;
290
291 if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND | EH_NESTED_CALL))
292 return ExceptionContinueSearch;
293
294 ptrs.ExceptionRecord = record;
295 ptrs.ContextRecord = context;
296 switch(wine_frame->u.filter( &ptrs ))
297 {
298 case EXCEPTION_CONTINUE_SEARCH:
299 return ExceptionContinueSearch;
300 case EXCEPTION_CONTINUE_EXECUTION:
301 return ExceptionContinueExecution;
302 case EXCEPTION_EXECUTE_HANDLER:
303 break;
304 }
305 __wine_unwind_frame( record, frame );
306}
307
308static inline DWORD __wine_exception_handler_page_fault( EXCEPTION_RECORD *record,
309 EXCEPTION_REGISTRATION_RECORD *frame,
310 CONTEXT *context,
311 EXCEPTION_REGISTRATION_RECORD **pdispatcher )
312{
313 if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND | EH_NESTED_CALL))
314 return ExceptionContinueSearch;
315 if (record->ExceptionCode != STATUS_ACCESS_VIOLATION)
316 return ExceptionContinueSearch;
317 __wine_unwind_frame( record, frame );
318}
319
320static inline DWORD __wine_exception_handler_all( EXCEPTION_RECORD *record,
321 EXCEPTION_REGISTRATION_RECORD *frame,
322 CONTEXT *context,
323 EXCEPTION_REGISTRATION_RECORD **pdispatcher )
324{
325 if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND | EH_NESTED_CALL))
326 return ExceptionContinueSearch;
327 __wine_unwind_frame( record, frame );
328}
329
330static inline DWORD __wine_finally_handler( EXCEPTION_RECORD *record,
331 EXCEPTION_REGISTRATION_RECORD *frame,
332 CONTEXT *context,
333 EXCEPTION_REGISTRATION_RECORD **pdispatcher )
334{
335 if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
336 {
337 __WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
338 wine_frame->u.finally_func( FALSE );
339 }
340 return ExceptionContinueSearch;
341}
342
343#endif /* USE_COMPILER_EXCEPTIONS */
344
345#ifdef __cplusplus
346}
347#endif
348
349#endif /* __WINE_WINE_EXCEPTION_H */
Note: See TracBrowser for help on using the repository browser.

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