User32 bitmap.c:
[reactos.git] / reactos / include / reactos / libs / pseh / framebased.h
1 /*
2 Copyright (c) 2004/2005 KJK::Hyperion
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy of
5 this software and associated documentation files (the "Software"), to deal in
6 the Software without restriction, including without limitation the rights to
7 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8 of the Software, and to permit persons to whom the Software is furnished to do
9 so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in all
12 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 FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 SOFTWARE.
21 */
22
23 #ifndef KJK_PSEH_FRAMEBASED_H_
24 #define KJK_PSEH_FRAMEBASED_H_
25
26 #include <pseh/framebased/internal.h>
27 #include <pseh/excpt.h>
28
29 #ifndef offsetof
30 # include <stddef.h>
31 #endif
32
33 /*
34 Fall back to non-optimal, non-native NLG implementation for environments
35 without their own (e.g., currently, kernel-mode ReactOS/Windows). THIS IS NOT
36 RECOMMENDED AND IT WILL BE DROPPED IN A FUTURE VERSION BECAUSE IT MAY CAUSE
37 SEVERE STACK CORRUPTION. REIMPLEMENT OR PORT YOUR COMPILER'S NATIVE NLG
38 IMPLEMENTATION INSTEAD.
39 */
40 #ifdef _SEH_NO_NATIVE_NLG
41 # include <pseh/setjmp.h>
42 #else
43 # include <setjmp.h>
44 # define _SEHLongJmp longjmp
45 # define _SEHSetJmp setjmp
46 # define _SEHJmpBuf_t jmp_buf
47 #endif
48 unsigned long DbgPrint(const char * Format,...);
49 typedef struct __SEHFrame
50 {
51 _SEHPortableFrame_t SEH_Header;
52 void * SEH_Locals;
53 }
54 _SEHFrame_t;
55
56 typedef struct __SEHTryLevel
57 {
58 _SEHPortableTryLevel_t ST_Header;
59 _SEHJmpBuf_t ST_JmpBuf;
60 }
61 _SEHTryLevel_t;
62
63 static __declspec(noreturn) __inline void __stdcall _SEHCompilerSpecificHandler
64 (
65 _SEHPortableTryLevel_t * trylevel
66 )
67 {
68 _SEHTryLevel_t * mytrylevel;
69 mytrylevel = _SEH_CONTAINING_RECORD(trylevel, _SEHTryLevel_t, ST_Header);
70 _SEHLongJmp(mytrylevel->ST_JmpBuf, 1);
71 }
72
73 static const int _SEHScopeKind = 1;
74 static _SEHPortableFrame_t * const _SEHPortableFrame = 0;
75
76 /* SHARED LOCALS */
77 /* Access the locals for the current frame */
78 #define _SEH_ACCESS_LOCALS(LOCALS_) \
79 _SEH_LOCALS_TYPENAME(LOCALS_) * _SEHPLocals; \
80 _SEHPLocals = \
81 _SEH_PVOID_CAST \
82 ( \
83 _SEH_LOCALS_TYPENAME(LOCALS_) *, \
84 _SEH_CONTAINING_RECORD(_SEHPortableFrame, _SEHFrame_t, SEH_Header) \
85 ->SEH_Locals \
86 );
87
88 /* Access local variable VAR_ */
89 #define _SEH_VAR(VAR_) _SEHPLocals->VAR_
90
91 /* FILTER FUNCTIONS */
92 /* Declares a filter function's prototype */
93 #define _SEH_FILTER(NAME_) \
94 long __stdcall NAME_ \
95 ( \
96 struct _EXCEPTION_POINTERS * _SEHExceptionPointers, \
97 struct __SEHPortableFrame * _SEHPortableFrame \
98 )
99
100 /* Declares a static filter */
101 #define _SEH_STATIC_FILTER(ACTION_) ((_SEHFilter_t)((ACTION_) + 2))
102
103 /* Declares a PSEH filter wrapping a regular filter function */
104 #define _SEH_WRAP_FILTER(WRAPPER_, NAME_) \
105 static __inline _SEH_FILTER(WRAPPER_) \
106 { \
107 return (NAME_)(_SEHExceptionPointers); \
108 }
109
110 /* FINALLY FUNCTIONS */
111 /* Declares a finally function's prototype */
112 #define _SEH_FINALLYFUNC(NAME_) \
113 void __stdcall NAME_ \
114 ( \
115 struct __SEHPortableFrame * _SEHPortableFrame \
116 )
117
118 /* Declares a PSEH finally function wrapping a regular function */
119 #define _SEH_WRAP_FINALLY(WRAPPER_, NAME_) \
120 _SEH_WRAP_FINALLY_ARGS(WRAPPER_, NAME_, ())
121
122 #define _SEH_WRAP_FINALLY_ARGS(WRAPPER_, NAME_, ARGS_) \
123 static __inline _SEH_FINALLYFUNC(WRAPPER_) \
124 { \
125 NAME_ ARGS_; \
126 }
127
128 #define _SEH_WRAP_FINALLY_LOCALS_ARGS(WRAPPER_, LOCALS_, NAME_, ARGS_) \
129 static __inline _SEH_FINALLYFUNC(WRAPPER_) \
130 { \
131 _SEH_ACCESS_LOCALS(LOCALS_); \
132 NAME_ ARGS_; \
133 }
134
135 /* SAFE BLOCKS */
136 #define _SEHX_TRY_FINALLY(FINALLY_) \
137 _SEH_TRY_FILTER_FINALLY \
138 ( \
139 _SEH_STATIC_FILTER(_SEH_CONTINUE_SEARCH), \
140 (FINALLY_) \
141 )
142
143 #define _SEHX_END_FINALLY _SEH_HANDLE _SEH_END
144
145 #define _SEHX_TRY_FILTER(FILTER_) \
146 _SEH_TRY_FILTER_FINALLY((FILTER_), 0)
147
148 #define _SEHX_TRY_HANDLE_FINALLY(FINALLY_) \
149 _SEH_TRY_FILTER_FINALLY \
150 ( \
151 _SEH_STATIC_FILTER(_SEH_EXECUTE_HANDLER), \
152 (FINALLY_) \
153 )
154
155 #define _SEHX_TRY \
156 _SEH_TRY_HANDLE_FINALLY(0)
157
158 #ifdef __cplusplus
159 # define _SEH_DECLARE_HANDLERS(FILTER_, FINALLY_) \
160 static const _SEHHandlers_t _SEHHandlers = { (FILTER_), (FINALLY_) };
161 #else
162 # define _SEH_DECLARE_HANDLERS(FILTER_, FINALLY_) \
163 _SEHHandlers_t _SEHHandlers = { (0), (0) }; \
164 _SEHHandlers.SH_Filter = (FILTER_); \
165 _SEHHandlers.SH_Finally = (FINALLY_);
166 #endif
167
168 #define _SEHX_TRY_FILTER_FINALLY(FILTER_, FINALLY_) \
169 { \
170 _SEHPortableFrame_t * const _SEHCurPortableFrame = _SEHPortableFrame; \
171 \
172 { \
173 _SEHFrame_t _SEHFrame; \
174 _SEHTryLevel_t _SEHTryLevel; \
175 _SEHPortableFrame_t * const _SEHPortableFrame = \
176 _SEHScopeKind ? &_SEHFrame.SEH_Header : _SEHCurPortableFrame; \
177 \
178 (void)_SEHPortableFrame; \
179 \
180 _SEH_DECLARE_HANDLERS((FILTER_), (FINALLY_)); \
181 \
182 _SEHTryLevel.ST_Header.SPT_Handlers = &_SEHHandlers; \
183 \
184 if(_SEHScopeKind) \
185 { \
186 if(&_SEHLocals != _SEHDummyLocals) \
187 _SEHFrame.SEH_Locals = &_SEHLocals; \
188 \
189 _SEHFrame.SEH_Header.SPF_Handler = _SEHCompilerSpecificHandler; \
190 _SEHEnterFrame(&_SEHFrame.SEH_Header, &_SEHTryLevel.ST_Header); \
191 } \
192 else \
193 _SEHEnterTry(&_SEHTryLevel.ST_Header); \
194 \
195 { \
196 static const int _SEHScopeKind = 0; \
197 (void)_SEHScopeKind; \
198 \
199 if(_SEHSetJmp(_SEHTryLevel.ST_JmpBuf) == 0) \
200 { \
201 for(;;) \
202 {
203
204 #define _SEHX_HANDLE \
205 \
206 break; \
207 } \
208 \
209 _SEHLeave(); \
210 } \
211 else \
212 { \
213 _SEHLeave();
214
215 #define _SEHX_END \
216 } \
217 \
218 if(_SEHHandlers.SH_Finally) \
219 _SEHHandlers.SH_Finally(_SEHPortableFrame); \
220 } \
221 } \
222 }
223
224 #define _SEHX_LEAVE break
225
226 #define _SEHX_GetExceptionCode() (unsigned long)(_SEHPortableFrame->SPF_Code)
227
228 #define _SEHX_GetExceptionPointers() \
229 ((struct _EXCEPTION_POINTERS *)_SEHExceptionPointers)
230
231 #define _SEHX_AbnormalTermination() (_SEHPortableFrame->SPF_Code != 0)
232
233 /* New syntax */
234
235 /*
236 NOTE: do not move, remove or modify any instance of _SEH2_ASSUME and
237 _SEH2_ASSUMING without doing extensive tests for correctness. Compilers can
238 generate the wrong code in presence of __assume in unpredictable ways. BE SURE
239 IT DOESN'T HAPPEN
240 */
241 #if defined(_MSC_VER) && (_MSC_VER > 1200)
242 # define _SEH2_ASSUME(X_) __assume(X_)
243 # if !defined(_SEH_NO_NATIVE_NLG)
244 /*
245 If we use the native setjmp, the compiler stops keeping track of variables, so
246 their actual values don't matter anymore. Optimize out some assignments
247 */
248 # define _SEH2_ASSUMING(X_)
249 # else
250 /* No native setjmp, no magic, no assumptions. Actually set the values */
251 # define _SEH2_ASSUMING(X_) X_
252 # endif
253 #else
254 # define _SEH2_ASSUME(X_)
255 # define _SEH2_ASSUMING(X_) X_
256 #endif
257
258 #ifdef __cplusplus
259 # define _SEH2_INIT_CONST static const
260 #else
261 # define _SEH2_INIT_CONST register const
262 #endif
263
264 #define _SEH_LEAVE break
265
266 #define _SEH_TRY \
267 { \
268 _SEH2_INIT_CONST int _SEH2TopTryLevel = (_SEHScopeKind != 0); \
269 _SEHPortableFrame_t * const _SEH2CurPortableFrame = _SEHPortableFrame; \
270 \
271 { \
272 static const int _SEHScopeKind = 0; \
273 register int _SEH2State = 0; \
274 register int _SEH2Handle = 0; \
275 _SEHFrame_t _SEH2Frame; \
276 _SEHTryLevel_t _SEH2TryLevel; \
277 _SEHPortableFrame_t * const _SEHPortableFrame = \
278 _SEH2TopTryLevel ? &_SEH2Frame.SEH_Header : _SEH2CurPortableFrame; \
279 \
280 (void)_SEHScopeKind; \
281 (void)_SEHPortableFrame; \
282 (void)_SEH2Handle; \
283 \
284 for(;;) \
285 { \
286 if(_SEH2State) \
287 { \
288 for(;;) \
289 { \
290 {
291
292 #define _SEH_EXCEPT(FILTER_) \
293 } \
294 \
295 break; \
296 } \
297 \
298 _SEH2_ASSUME(_SEH2Handle == 0); \
299 break; \
300 } \
301 else \
302 { \
303 _SEH_DECLARE_HANDLERS((FILTER_), 0); \
304 \
305 _SEH2TryLevel.ST_Header.SPT_Handlers = &_SEHHandlers; \
306 \
307 if(_SEH2TopTryLevel) \
308 { \
309 if(&_SEHLocals != _SEHDummyLocals) \
310 _SEH2Frame.SEH_Locals = &_SEHLocals; \
311 \
312 _SEH2Frame.SEH_Header.SPF_Handler = _SEHCompilerSpecificHandler; \
313 _SEHEnterFrame(&_SEH2Frame.SEH_Header, &_SEH2TryLevel.ST_Header); \
314 } \
315 else \
316 _SEHEnterTry(&_SEH2TryLevel.ST_Header); \
317 \
318 if((_SEH2Handle = _SEHSetJmp(_SEH2TryLevel.ST_JmpBuf)) == 0) \
319 { \
320 _SEH2_ASSUMING(++ _SEH2State); \
321 _SEH2_ASSUME(_SEH2State != 0); \
322 continue; \
323 } \
324 else \
325 { \
326 break; \
327 } \
328 } \
329 \
330 break; \
331 } \
332 \
333 _SEHLeave(); \
334 \
335 if(_SEH2Handle) \
336 {
337
338 #define _SEH_FINALLY(FINALLY_) \
339 } \
340 \
341 break; \
342 } \
343 \
344 _SEHLeave(); \
345 break; \
346 } \
347 else \
348 { \
349 _SEH_DECLARE_HANDLERS(0, (FINALLY_)); \
350 \
351 _SEH2TryLevel.ST_Header.SPT_Handlers = &_SEHHandlers; \
352 \
353 if(_SEH2TopTryLevel) \
354 { \
355 if(&_SEHLocals != _SEHDummyLocals) \
356 _SEH2Frame.SEH_Locals = &_SEHLocals; \
357 \
358 _SEH2Frame.SEH_Header.SPF_Handler = 0; \
359 _SEHEnterFrame(&_SEH2Frame.SEH_Header, &_SEH2TryLevel.ST_Header); \
360 } \
361 else \
362 _SEHEnterTry(&_SEH2TryLevel.ST_Header); \
363 \
364 ++ _SEH2State; \
365 _SEH2_ASSUME(_SEH2State != 0); \
366 continue; \
367 } \
368 \
369 break; \
370 } \
371 \
372 (FINALLY_)(&_SEH2Frame.SEH_Header); \
373 if(0) \
374 {
375
376 #define _SEH_END \
377 } \
378 } \
379 }
380
381 #define _SEH_HANDLE _SEH_EXCEPT(_SEH_STATIC_FILTER(_SEH_EXECUTE_HANDLER))
382
383 #define _SEH_GetExceptionCode _SEHX_GetExceptionCode
384 #define _SEH_GetExceptionPointers _SEHX_GetExceptionPointers
385 #define _SEH_AbnormalTermination _SEHX_AbnormalTermination
386
387 #endif
388
389 /* EOF */