- svchost: #ifdef _MSC_VER doesn't mean "using Microsoft's headers" anymore
[reactos.git] / reactos / include / reactos / libs / pseh / pseh2.h
1 /*
2 Copyright (c) 2008 KJK::Hyperion
3
4 Permission is hereby granted, free of charge, to any person obtaining a
5 copy of this software and associated documentation files (the "Software"),
6 to deal in the Software without restriction, including without limitation
7 the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 and/or sell copies of the Software, and to permit persons to whom the
9 Software is furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 DEALINGS IN THE SOFTWARE.
21 */
22
23 #ifndef KJK_PSEH2_H_
24 #define KJK_PSEH2_H_
25
26 #if !defined (__arm__)
27
28 #if defined(__GNUC__)
29 struct _EXCEPTION_RECORD;
30 struct _EXCEPTION_POINTERS;
31 struct _CONTEXT;
32
33 typedef int (__cdecl * _SEH2FrameHandler_t)
34 (
35 struct _EXCEPTION_RECORD *,
36 void *,
37 struct _CONTEXT *,
38 void *
39 );
40
41 typedef struct __SEH2Registration
42 {
43 struct __SEH2Registration * SER_Prev;
44 _SEH2FrameHandler_t SER_Handler;
45 }
46 _SEH2Registration_t;
47
48 typedef struct __SEH2Frame
49 {
50 _SEH2Registration_t SF_Registration;
51 volatile struct __SEH2TryLevel * volatile SF_TopTryLevel;
52 volatile unsigned long SF_Code;
53 }
54 _SEH2Frame_t;
55
56 typedef struct __SEH2TryLevel
57 {
58 volatile struct __SEH2TryLevel * ST_Next;
59 void * ST_Filter;
60 void * ST_Body;
61 }
62 _SEH2TryLevel_t;
63
64 typedef struct __SEH2HandleTryLevel
65 {
66 _SEH2TryLevel_t SHT_Common;
67 void * volatile SHT_Esp;
68 void * volatile SHT_Ebp;
69 void * volatile SHT_Ebx;
70 void * volatile SHT_Esi;
71 void * volatile SHT_Edi;
72 }
73 _SEH2HandleTryLevel_t;
74
75 #ifdef __cplusplus
76 extern "C"
77 {
78 #endif
79
80 extern int __cdecl _SEH2EnterFrameAndTrylevel(_SEH2Frame_t *, volatile _SEH2TryLevel_t *);
81 extern __attribute__((returns_twice)) int __cdecl _SEH2EnterFrameAndHandleTrylevel(_SEH2Frame_t *, volatile _SEH2HandleTryLevel_t *, void *);
82 extern __attribute__((returns_twice)) int __cdecl _SEH2EnterHandleTrylevel(_SEH2Frame_t *, volatile _SEH2HandleTryLevel_t *, void *);
83 extern void __cdecl _SEH2LeaveFrame(void);
84 extern void __cdecl _SEH2Return(void);
85
86 #ifdef __cplusplus
87 }
88 #endif
89
90 /* A no-op side effect that scares GCC */
91 #define __SEH_SIDE_EFFECT __asm__ __volatile__("#")
92
93 /* A no-op without any real side effects, but silences warnings */
94 #define __SEH_PRETEND_SIDE_EFFECT (void)0
95
96 /* Forces GCC to consider the specified label reachable */
97 #define __SEH_USE_LABEL(L_) if(__SEH_VOLATILE_FALSE) goto L_;
98
99 /* Makes GCC pretend the specified label is reachable, to silence warnings */
100 #define __SEH_PRETEND_USE_LABEL(L_) (void)(&&L_)
101
102 /* Soft memory barrier */
103 #define __SEH_BARRIER __asm__ __volatile__("#":::"memory")
104
105 /* GCC doesn't know that this equals zero */
106 #define __SEH_VOLATILE_ZERO ({ int zero = 0; __asm__ __volatile__("#" : "+g" (zero)); zero; })
107
108 #define __SEH_VOLATILE_FALSE __builtin_expect(__SEH_VOLATILE_ZERO, 0)
109 #define __SEH_VOLATILE_TRUE __builtin_expect(!__SEH_VOLATILE_ZERO, 1)
110
111 #define ___SEH_STRINGIFY(X_) # X_
112 #define __SEH_STRINGIFY(X_) ___SEH_STRINGIFY(X_)
113
114 #define __SEH_EXCEPT_RET long
115 #define __SEH_EXCEPT_ARGS __attribute__((unused)) _SEH2Frame_t * _SEH2FrameP, __attribute__((unused)) struct _EXCEPTION_POINTERS * _SEHExceptionInformation
116 #define __SEH_EXCEPT_ARGS_ , __SEH_EXCEPT_ARGS
117 #define __SEH_EXCEPT_PFN __SEH_DECLARE_EXCEPT_PFN
118 #define __SEH_DECLARE_EXCEPT_PFN(NAME_) __SEH_EXCEPT_RET (__cdecl * NAME_)(__SEH_EXCEPT_ARGS)
119 #define __SEH_DECLARE_EXCEPT(NAME_) __SEH_EXCEPT_RET __cdecl NAME_(__SEH_EXCEPT_ARGS)
120 #define __SEH_DEFINE_EXCEPT(NAME_) __SEH_EXCEPT_RET __cdecl NAME_(__SEH_EXCEPT_ARGS)
121
122 #define __SEH_FINALLY_RET void
123 #define __SEH_FINALLY_ARGS void
124 #define __SEH_FINALLY_ARGS_
125 #define __SEH_FINALLY_PFN __SEH_DECLARE_FINALLY_PFN
126 #define __SEH_DECLARE_FINALLY_PFN(NAME_) __SEH_FINALLY_RET (__cdecl * NAME_)(__SEH_FINALLY_ARGS)
127 #define __SEH_DECLARE_FINALLY(NAME_) __SEH_FINALLY_RET __cdecl NAME_(__SEH_FINALLY_ARGS)
128 #define __SEH_DEFINE_FINALLY(NAME_) __SEH_FINALLY_RET __cdecl NAME_(__SEH_FINALLY_ARGS)
129
130 #define __SEH_RETURN_EXCEPT(R_) return (long)(R_)
131 #define __SEH_RETURN_FINALLY() return
132
133 #define __SEH_BEGIN_TRY \
134 { \
135 __label__ _SEHEndTry; \
136 \
137 __SEH_PRETEND_USE_LABEL(_SEHEndTry); \
138 \
139 { \
140 __SEH_BARRIER;
141
142 #define __SEH_END_TRY \
143 __SEH_BARRIER; \
144 } \
145 _SEHEndTry:; \
146 }
147
148 #define __SEH_SET_TRYLEVEL(TRYLEVEL_) \
149 { \
150 __SEH_BARRIER; _SEH2FrameP->SF_TopTryLevel = (TRYLEVEL_); __SEH_BARRIER; \
151 }
152
153 #define __SEH_ENTER_FRAME_AND_TRYLEVEL(TRYLEVEL_) (_SEH2EnterFrameAndTrylevel(_SEH2FrameP, (TRYLEVEL_)))
154 #define __SEH_ENTER_TRYLEVEL(TRYLEVEL_) ((__SEH_SET_TRYLEVEL((TRYLEVEL_))), 0)
155
156 #define __SEH_ENTER_FRAME_AND_HANDLE_TRYLEVEL(TRYLEVEL_, HANDLE_) _SEH2EnterFrameAndHandleTrylevel(_SEH2FrameP, (TRYLEVEL_), (HANDLE_))
157 #define __SEH_ENTER_HANDLE_TRYLEVEL(TRYLEVEL_, HANDLE_) _SEH2EnterHandleTrylevel(_SEH2FrameP, (TRYLEVEL_), (HANDLE_))
158
159 #define __SEH_ENTER_SCOPE(TRYLEVEL_) (_SEHTopTryLevel ? __SEH_ENTER_FRAME_AND_TRYLEVEL(TRYLEVEL_) : __SEH_ENTER_TRYLEVEL(TRYLEVEL_))
160 #define __SEH_ENTER_HANDLE_SCOPE(TRYLEVEL_, HANDLE_) (({ __SEH_BARRIER; __asm__ __volatile__("mov %%esp, %0" : "=m" ((TRYLEVEL_)->SHT_Esp)); __SEH_BARRIER; }), (_SEHTopTryLevel ? __SEH_ENTER_FRAME_AND_HANDLE_TRYLEVEL((TRYLEVEL_), (HANDLE_)) : __SEH_ENTER_HANDLE_TRYLEVEL((TRYLEVEL_), (HANDLE_))))
161
162 #define __SEH_LEAVE_TRYLEVEL() \
163 if(!_SEHTopTryLevel) \
164 { \
165 __SEH_SET_TRYLEVEL(_SEHPrevTryLevelP); \
166 } \
167
168 #define __SEH_LEAVE_FRAME() \
169 if(_SEHTopTryLevel) \
170 { \
171 _SEH2LeaveFrame(); \
172 __asm__ __volatile__("mov %0, %%esp" : : "g" (_SEHStackPointer)); \
173 }
174
175 #define __SEH_END_SCOPE_CHAIN \
176 static __attribute__((unused)) const int _SEH2ScopeKind = 1; \
177 static __attribute__((unused)) _SEH2Frame_t * const _SEH2FrameP = 0; \
178 static __attribute__((unused)) _SEH2TryLevel_t * const _SEH2TryLevelP = 0;
179
180 #define __SEH_BEGIN_SCOPE \
181 for(;;) \
182 { \
183 const int _SEHTopTryLevel = (_SEH2ScopeKind != 0); \
184 _SEH2Frame_t * const _SEHCurFrameP = _SEH2FrameP; \
185 volatile _SEH2TryLevel_t * const _SEHPrevTryLevelP = _SEH2TryLevelP; \
186 __attribute__((unused)) int _SEHAbnormalTermination; \
187 \
188 (void)_SEHTopTryLevel; \
189 (void)_SEHCurFrameP; \
190 (void)_SEHPrevTryLevelP; \
191 \
192 { \
193 __label__ _SEHBeforeTry; \
194 __label__ _SEHDoTry; \
195 __label__ _SEHAfterTry; \
196 static const int _SEH2ScopeKind = 0; \
197 volatile _SEH2TryLevel_t _SEHTryLevel; \
198 volatile _SEH2HandleTryLevel_t _SEHHandleTryLevel; \
199 void * _SEHStackPointer; \
200 volatile _SEH2TryLevel_t * _SEH2TryLevelP; \
201 _SEH2Frame_t * const _SEH2FrameP = _SEHTopTryLevel ? \
202 ({ __asm__ __volatile__("mov %%esp, %0" : "=g" (_SEHStackPointer)); __builtin_alloca(sizeof(_SEH2Frame_t)); }) : \
203 _SEHCurFrameP; \
204 \
205 (void)_SEH2ScopeKind; \
206 (void)_SEHTryLevel; \
207 (void)_SEHHandleTryLevel; \
208 (void)_SEHStackPointer; \
209 (void)_SEH2FrameP; \
210 (void)_SEH2TryLevelP; \
211 \
212 goto _SEHBeforeTry; \
213 \
214 _SEHDoTry:;
215
216 #define __SEH_END_SCOPE \
217 } \
218 \
219 break; \
220 }
221
222 #define __SEH_SCOPE_LOCALS \
223 __label__ _SEHBeginExcept; \
224 __label__ _SEHEndExcept; \
225 \
226 auto __SEH_DECLARE_FINALLY(_SEHFinally);
227
228 #define _SEH2_TRY \
229 __SEH_BEGIN_SCOPE \
230 { \
231 __SEH_SCOPE_LOCALS; \
232 \
233 __SEH_BEGIN_TRY \
234 {
235
236 #define _SEH2_FINALLY \
237 } \
238 __SEH_END_TRY; \
239 \
240 goto _SEHAfterTry; \
241 _SEHBeforeTry:; \
242 \
243 __SEH_PRETEND_USE_LABEL(_SEHBeginExcept); \
244 __SEH_PRETEND_USE_LABEL(_SEHEndExcept); \
245 \
246 _SEHTryLevel.ST_Filter = 0; \
247 _SEHTryLevel.ST_Body = &_SEHFinally; \
248 _SEHTryLevel.ST_Next = _SEHPrevTryLevelP; \
249 __SEH_ENTER_SCOPE(&_SEHTryLevel); \
250 _SEH2TryLevelP = &_SEHTryLevel; \
251 \
252 _SEHAbnormalTermination = 1; \
253 \
254 goto _SEHDoTry; \
255 _SEHAfterTry:; \
256 \
257 _SEHAbnormalTermination = 0; \
258 \
259 __SEH_LEAVE_TRYLEVEL(); \
260 \
261 _SEHFinally(); \
262 goto _SEHEndExcept; \
263 \
264 _SEHBeginExcept:; \
265 \
266 __attribute__((noinline)) __SEH_DEFINE_FINALLY(_SEHFinally) \
267 { \
268 __SEH_END_SCOPE_CHAIN; \
269 \
270 (void)_SEH2ScopeKind; \
271 (void)_SEH2FrameP; \
272 (void)_SEH2TryLevelP; \
273 \
274 for(;; ({ __SEH_RETURN_FINALLY(); })) \
275 {
276
277 #define _SEH2_EXCEPT(...) \
278 } \
279 __SEH_END_TRY; \
280 \
281 goto _SEHAfterTry; \
282 \
283 _SEHBeforeTry:; \
284 \
285 { \
286 __attribute__((unused)) struct _EXCEPTION_POINTERS * volatile _SEHExceptionInformation; \
287 \
288 if(__builtin_constant_p((__VA_ARGS__)) && (__VA_ARGS__) <= 0) \
289 { \
290 if((__VA_ARGS__) < 0) \
291 { \
292 _SEHTryLevel.ST_Filter = (void *)-1; \
293 _SEHTryLevel.ST_Body = 0; \
294 } \
295 else \
296 { \
297 _SEHTryLevel.ST_Filter = (void *)0; \
298 _SEHTryLevel.ST_Body = 0; \
299 } \
300 \
301 _SEHTryLevel.ST_Next = _SEHPrevTryLevelP; \
302 __SEH_ENTER_SCOPE(&_SEHTryLevel); \
303 _SEH2TryLevelP = &_SEHTryLevel; \
304 } \
305 else \
306 { \
307 if(__builtin_constant_p((__VA_ARGS__)) && (__VA_ARGS__) > 0) \
308 _SEHHandleTryLevel.SHT_Common.ST_Filter = (void *)1; \
309 else \
310 { \
311 __SEH_DEFINE_EXCEPT(_SEHExcept) \
312 { \
313 __SEH_RETURN_EXCEPT((__VA_ARGS__)); \
314 } \
315 \
316 _SEHHandleTryLevel.SHT_Common.ST_Filter = &_SEHExcept; \
317 } \
318 \
319 _SEHHandleTryLevel.SHT_Common.ST_Next = _SEHPrevTryLevelP; \
320 _SEH2TryLevelP = &_SEHHandleTryLevel.SHT_Common; \
321 \
322 if(__builtin_expect(__SEH_ENTER_HANDLE_SCOPE(&_SEHHandleTryLevel, &&_SEHBeginExcept), 0)) \
323 goto _SEHBeginExcept; \
324 } \
325 } \
326 \
327 goto _SEHDoTry; \
328 \
329 __attribute__((unused)) __SEH_DEFINE_FINALLY(_SEHFinally) { __SEH_RETURN_FINALLY(); } \
330 \
331 _SEHAfterTry:; \
332 __SEH_LEAVE_TRYLEVEL(); \
333 \
334 goto _SEHEndExcept; \
335 \
336 _SEHBeginExcept:; \
337 { \
338 { \
339 __SEH_BARRIER;
340
341 #define _SEH2_END \
342 __SEH_BARRIER; \
343 } \
344 } \
345 \
346 _SEHEndExcept:; \
347 \
348 __SEH_LEAVE_FRAME(); \
349 } \
350 __SEH_END_SCOPE;
351
352 #define _SEH2_GetExceptionInformation() (_SEHExceptionInformation)
353 #define _SEH2_GetExceptionCode() ((_SEH2FrameP)->SF_Code)
354 #define _SEH2_AbnormalTermination() (_SEHAbnormalTermination)
355
356 #define _SEH2_YIELD(STMT_) \
357 for(;;) \
358 { \
359 if(!_SEH2ScopeKind) \
360 _SEH2Return(); \
361 \
362 STMT_; \
363 }
364
365 #define _SEH2_LEAVE goto _SEHEndTry
366
367 __SEH_END_SCOPE_CHAIN;
368
369 #else
370
371 #include <excpt.h>
372
373 #define _SEH2_TRY __try
374 #define _SEH2_FINALLY __finally
375 #define _SEH2_EXCEPT(...) __except(__VA_ARGS__)
376 #define _SEH2_END
377
378 #define _SEH2_GetExceptionInformation() (GetExceptionInformation())
379 #define _SEH2_GetExceptionCode() (GetExceptionCode())
380 #define _SEH2_AbnormalTermination() (AbnormalTermination())
381
382 #define _SEH2_YIELD(STMT_) STMT_
383 #define _SEH2_LEAVE __leave
384
385 #endif
386
387 #else
388
389 #define _SEH2_TRY {
390 #define _SEH2_FINALLY } {
391 #define _SEH2_EXCEPT(...) } if (0) {
392 #define _SEH2_END }
393
394 #define _SEH2_GetExceptionInformation()
395 #define _SEH2_GetExceptionCode() STATUS_SUCCESS
396 #define _SEH2_AbnormalTermination()
397
398 #define _SEH2_YIELD(STMT_) STMT_
399 #define _SEH2_LEAVE
400
401 #endif
402
403 #endif
404
405 /* EOF */