ReactOS 0.4.15-dev-7934-g1dc8d80
framebased.c
Go to the documentation of this file.
1/*
2 Copyright (c) 2004/2005 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#define _NTSYSTEM_
24#define STRICT
25#define WIN32_LEAN_AND_MEAN
26#include <windows.h>
27
28#include <pseh/pseh.h>
30#include <pseh/excpt.h>
31#include <pseh/framebased.h>
32
33#include <excpt.h>
34
35/* Tracing */
36#ifdef _SEH_ENABLE_TRACE
37extern unsigned long __cdecl DbgPrint(const char * format, ...);
38
39#define _SEH_TRACE_HEADER_(FRAME_) \
40 DbgPrint("[PSEH:%p]%s:%d:", FRAME_, __FILE__, __LINE__);
41
42#define _SEH_TRACE_TRAILER_ \
43 DbgPrint("\n");
44
45#define _SEH_FILTER_RET_STRING_(RET_) \
46 (((int)(RET_) < 0) ? "_SEH_CONTINUE_EXECUTION" : (((int)(RET_) > 0) ? "_SEH_EXECUTE_HANDLER" : "_SEH_CONTINUE_SEARCH"))
47
48#define _SEH_TRACE_LINE_(FRAME_, ARGS_) \
49{ \
50 _SEH_TRACE_HEADER_(FRAME_); \
51 DbgPrint ARGS_; \
52 _SEH_TRACE_TRAILER_; \
53}
54
55#define _SEH_TRACE_ENTER(FRAME_, FUNCNAME_, ARGS_) \
56{ \
57 if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_ENTER_LEAVE) \
58 { \
59 _SEH_TRACE_HEADER_(FRAME_); \
60 DbgPrint(">>> %s(", (FUNCNAME_)); \
61 DbgPrint ARGS_; \
62 DbgPrint(")"); \
63 _SEH_TRACE_TRAILER_; \
64 } \
65}
66
67#define _SEH_TRACE_LEAVE(FRAME_, FUNCNAME_, ARGS_) \
68{ \
69 if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_ENTER_LEAVE) \
70 { \
71 _SEH_TRACE_HEADER_(FRAME_); \
72 DbgPrint("<<< %s => ", (FUNCNAME_)); \
73 DbgPrint ARGS_; \
74 _SEH_TRACE_TRAILER_; \
75 } \
76}
77
78#define _SEH_TRACE_EXCEPTION_RECORD(FRAME_, ER_) \
79{ \
80 if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_EXCEPTION_RECORD) \
81 { \
82 _SEH_TRACE_LINE_ \
83 ( \
84 (FRAME_), \
85 ( \
86 "ExceptionRecord %p = { ExceptionCode : %08X, ExceptionFlags : %08X, ExceptionRecord : %p, ExceptionAddress : %p }", \
87 (ER_), \
88 (ER_)->ExceptionCode, \
89 (ER_)->ExceptionFlags, \
90 (ER_)->ExceptionRecord, \
91 (ER_)->ExceptionAddress \
92 ) \
93 ); \
94 } \
95}
96
97#ifdef _X86_
98#define _SEH_TRACE_CONTEXT(FRAME_, CONTEXT_) \
99{ \
100 if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_CONTEXT) \
101 { \
102 if(((CONTEXT_)->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) \
103 { \
104 _SEH_TRACE_LINE_ \
105 ( \
106 (FRAME_), \
107 ( \
108 "eax=%08X ebx=%08X ecx=%08X edx=%08X esi=%08X edi=%08X", \
109 (CONTEXT_)->Eax, \
110 (CONTEXT_)->Ebx, \
111 (CONTEXT_)->Ecx, \
112 (CONTEXT_)->Edx, \
113 (CONTEXT_)->Esi, \
114 (CONTEXT_)->Edi \
115 ) \
116 ); \
117 } \
118 \
119 if(((CONTEXT_)->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) \
120 { \
121 _SEH_TRACE_LINE_ \
122 ( \
123 (FRAME_), \
124 ( \
125 "eip=%08X esp=%08X ebp=%08X efl=%08X cs=%08X ss=%08X", \
126 (CONTEXT_)->Eip, \
127 (CONTEXT_)->Esp, \
128 (CONTEXT_)->Ebp, \
129 (CONTEXT_)->EFlags, \
130 (CONTEXT_)->SegCs, \
131 (CONTEXT_)->SegSs \
132 ) \
133 ); \
134 } \
135 \
136 if(((CONTEXT_)->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS) \
137 { \
138 _SEH_TRACE_LINE_ \
139 ( \
140 (FRAME_), \
141 ( \
142 "ds=%08X es=%08X fs=%08X gs=%08X", \
143 (CONTEXT_)->SegDs, \
144 (CONTEXT_)->SegEs, \
145 (CONTEXT_)->SegFs, \
146 (CONTEXT_)->SegGs \
147 ) \
148 ); \
149 } \
150 } \
151}
152#else
153#define _SEH_TRACE_CONTEXT(FRAME_, CONTEXT_)
154#endif
155
156#define _SEH_TRACE_UNWIND(FRAME_, ARGS_) \
157{ \
158 if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_UNWIND) \
159 { \
160 _SEH_TRACE_LINE_((FRAME_), ARGS_); \
161 } \
162}
163
164#define _SEH_TRACE_TRYLEVEL(FRAME_, TRYLEVEL_) \
165{ \
166 if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_TRYLEVEL) \
167 { \
168 _SEH_TRACE_LINE_((FRAME_), ("trylevel %p, filter %p", (TRYLEVEL_), (TRYLEVEL_)->SPT_Handlers.SH_Filter)); \
169 } \
170}
171
172#define _SEH_TRACE_ENTER_CALL_FILTER(FRAME_, TRYLEVEL_, ER_) \
173{ \
174 if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_CALL_FILTER) \
175 { \
176 _SEH_TRACE_LINE_ \
177 ( \
178 (FRAME_), \
179 ( \
180 "trylevel %p, calling filter %p, ExceptionCode %08X", \
181 (TRYLEVEL_), \
182 (TRYLEVEL_)->SPT_Handlers.SH_Filter, \
183 (ER_)->ExceptionCode \
184 ) \
185 ); \
186 } \
187}
188
189#define _SEH_TRACE_LEAVE_CALL_FILTER(FRAME_, TRYLEVEL_, RET_) \
190{ \
191 if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_CALL_FILTER) \
192 { \
193 _SEH_TRACE_LINE_ \
194 ( \
195 (FRAME_), \
196 ( \
197 "trylevel %p, filter %p => %s", \
198 (TRYLEVEL_), \
199 (TRYLEVEL_)->SPT_Handlers.SH_Filter, \
200 _SEH_FILTER_RET_STRING_(RET_) \
201 ) \
202 ); \
203 } \
204}
205
206#define _SEH_TRACE_FILTER(FRAME_, TRYLEVEL_, RET_) \
207{ \
208 if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_FILTER) \
209 { \
210 _SEH_TRACE_LINE_ \
211 ( \
212 (FRAME_), \
213 ( \
214 "trylevel %p => %s", \
215 (TRYLEVEL_), \
216 _SEH_FILTER_RET_STRING_(RET_) \
217 ) \
218 ); \
219 } \
220}
221
222#define _SEH_TRACE_ENTER_CALL_HANDLER(FRAME_, TRYLEVEL_) \
223{ \
224 if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_CALL_HANDLER) \
225 { \
226 _SEH_TRACE_LINE_((FRAME_), ("trylevel %p, handling", (TRYLEVEL_))); \
227 } \
228}
229
230#define _SEH_TRACE_ENTER_CALL_FINALLY(FRAME_, TRYLEVEL_) \
231{ \
232 if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_CALL_FINALLY) \
233 { \
234 _SEH_TRACE_LINE_ \
235 ( \
236 (FRAME_), \
237 ( \
238 "trylevel %p, calling exit routine %p", \
239 (TRYLEVEL_), \
240 (TRYLEVEL_)->SPT_Handlers.SH_Finally \
241 ) \
242 ); \
243 } \
244}
245
246#define _SEH_TRACE_LEAVE_CALL_FINALLY(FRAME_, TRYLEVEL_) \
247{ \
248 if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_CALL_FINALLY) \
249 { \
250 _SEH_TRACE_LINE_ \
251 ( \
252 (FRAME_), \
253 ( \
254 "trylevel %p, exit routine %p returned", \
255 (TRYLEVEL_), \
256 (TRYLEVEL_)->SPT_Handlers.SH_Finally \
257 ) \
258 ); \
259 } \
260}
261
262#else
263#define _SEH_TRACE_ENTER(FRAME_, FUNCNAME_, ARGS_)
264#define _SEH_TRACE_LEAVE(FRAME_, FUNCNAME_, ARGS_)
265#define _SEH_TRACE_EXCEPTION_RECORD(FRAME_, ER_)
266#define _SEH_TRACE_CONTEXT(FRAME_, CONTEXT_)
267#define _SEH_TRACE_UNWIND(FRAME_, ARGS_)
268#define _SEH_TRACE_TRYLEVEL(FRAME_, TRYLEVEL_)
269#define _SEH_TRACE_ENTER_CALL_FILTER(FRAME_, TRYLEVEL_, ER_)
270#define _SEH_TRACE_LEAVE_CALL_FILTER(FRAME_, TRYLEVEL_, RET_)
271#define _SEH_TRACE_FILTER(FRAME_, TRYLEVEL_, RET_)
272#define _SEH_TRACE_ENTER_CALL_HANDLER(FRAME_, TRYLEVEL_)
273#define _SEH_TRACE_ENTER_CALL_FINALLY(FRAME_, TRYLEVEL_)
274#define _SEH_TRACE_LEAVE_CALL_FINALLY(FRAME_, TRYLEVEL_)
275#endif
276
277/* Assembly helpers, see i386/framebased.asm */
280extern void __cdecl _SEHUnregisterFrame(void);
283
284/* Borland C++ uses a different decoration (i.e. none) for stdcall functions */
285extern void __stdcall RtlUnwind(void *, void *, PEXCEPTION_RECORD, void *);
287
289(
290 _SEHPortableFrame_t * frame,
291 _SEHPortableTryLevel_t * dsttrylevel
292)
293{
294 _SEHPortableTryLevel_t * trylevel;
295
296 _SEH_TRACE_UNWIND(frame, ("enter local unwind from %p to %p", frame->SPF_TopTryLevel, dsttrylevel));
297
298 for
299 (
300 trylevel = frame->SPF_TopTryLevel;
301 trylevel != dsttrylevel;
302 trylevel = trylevel->SPT_Next
303 )
304 {
305 _SEHFinally_t pfnFinally;
306
307 /* ASSERT(trylevel); */
308
309 pfnFinally = trylevel->SPT_Handlers.SH_Finally;
310
311 if(pfnFinally)
312 {
313 _SEH_TRACE_ENTER_CALL_FINALLY(frame, trylevel);
314 pfnFinally(frame);
315 _SEH_TRACE_LEAVE_CALL_FINALLY(frame, trylevel);
316 }
317 }
318
319 _SEH_TRACE_UNWIND(frame, ("leave local unwind from %p to %p", frame->SPF_TopTryLevel, dsttrylevel));
320}
321
323(
324 _SEHPortableFrame_t * frame,
325 _SEHPortableTryLevel_t * trylevel
326)
327{
328 _SEHGlobalUnwind(frame);
329 _SEHLocalUnwind(frame, trylevel);
330 _SEH_TRACE_ENTER_CALL_HANDLER(frame, trylevel);
331 frame->SPF_Handler(trylevel);
332 /* ASSERT(0); */
333}
334
336(
337 struct _EXCEPTION_RECORD * ExceptionRecord,
338 void * EstablisherFrame,
339 struct _CONTEXT * ContextRecord,
340 void * DispatcherContext
341)
342{
343 _SEHPortableFrame_t * frame;
344
346
347 frame = EstablisherFrame;
348
350 (
351 frame,
352 "_SEHFrameHandler",
353 (
354 "%p, %p, %p, %p",
355 ExceptionRecord,
359 )
360 );
361
362 _SEH_TRACE_EXCEPTION_RECORD(frame, ExceptionRecord);
364
365 /* Unwinding */
366 if(ExceptionRecord->ExceptionFlags & (4 | 2))
367 {
368 _SEH_TRACE_UNWIND(frame, ("enter forced unwind"));
369 _SEHLocalUnwind(frame, NULL);
370 _SEH_TRACE_UNWIND(frame, ("leave forced unwind"));
371 }
372 /* Handling */
373 else
374 {
375 int ret;
376 _SEHPortableTryLevel_t * trylevel;
377
378 if(ExceptionRecord->ExceptionCode)
379 frame->SPF_Code = ExceptionRecord->ExceptionCode;
380 else
381 frame->SPF_Code = 0xC0000001;
382
383 for
384 (
385 trylevel = frame->SPF_TopTryLevel;
386 trylevel != NULL;
387 trylevel = trylevel->SPT_Next
388 )
389 {
390 _SEHFilter_t pfnFilter = trylevel->SPT_Handlers.SH_Filter;
391
392 _SEH_TRACE_TRYLEVEL(frame, trylevel);
393
394 switch((UINT_PTR)pfnFilter)
395 {
399 {
400 ret = (int)((UINT_PTR)pfnFilter) - 2;
401 break;
402 }
403
404 default:
405 {
406 if(trylevel->SPT_Handlers.SH_Filter)
407 {
409
410 ep.ExceptionRecord = ExceptionRecord;
412
413 _SEH_TRACE_ENTER_CALL_FILTER(frame, trylevel, ExceptionRecord);
414 ret = pfnFilter(&ep, frame);
415 _SEH_TRACE_LEAVE_CALL_FILTER(frame, trylevel, ret);
416 }
417 else
419
420 break;
421 }
422 }
423
424 _SEH_TRACE_FILTER(frame, trylevel, ret);
425
426 /* _SEH_CONTINUE_EXECUTION */
427 if(ret < 0)
428 {
429 _SEH_TRACE_LEAVE(frame, "_SEHFrameHandler", ("ExceptionContinueExecution"));
431 }
432 /* _SEH_EXECUTE_HANDLER */
433 else if(ret > 0)
434 _SEHCallHandler(frame, trylevel);
435 /* _SEH_CONTINUE_SEARCH */
436 else
437 continue;
438 }
439
440 /* FALLTHROUGH */
441 }
442
443 _SEH_TRACE_LEAVE(frame, "_SEHFrameHandler", ("ExceptionContinueSearch"));
445}
446
448{
449 _SEHEnterFrame_f(frame);
450}
451
453{
455}
456
458{
459 _SEHReturn_f();
460}
461
463{
464 /* ASSERT(frame); */
465 /* ASSERT(trylevel); */
467 frame->SPF_Code = 0;
469}
470
472{
473 /* _SEHPortableFrame_t * frame;
474
475 frame = _SEH_CONTAINING_RECORD
476 (
477 _SEHCurrentRegistration(),
478 _SEHPortableFrame_t,
479 SPF_Registration
480 ); */
481
482 /* ASSERT(frame); */
483 /* ASSERT(frame->SPF_TopTryLevel == NULL) */
484
486}
487
489{
490 _SEHPortableFrame_t * frame;
491
493 (
496 SPF_Registration
497 );
498
499 _SEHLocalUnwind(frame, NULL);
501}
502
503/* EOF */
#define __cdecl
Definition: accygwin.h:79
#define NULL
Definition: types.h:112
@ ExceptionContinueSearch
Definition: compat.h:91
@ ExceptionContinueExecution
Definition: compat.h:90
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
void __stdcall _SEHReturn_s(void)
Definition: framebased.c:457
#define _SEH_TRACE_ENTER_CALL_FILTER(FRAME_, TRYLEVEL_, ER_)
Definition: framebased.c:269
void _SEH_FASTCALL _SEHEnterFrame_f(_SEHPortableFrame_t *frame)
Definition: framebased.c:462
static void __cdecl _SEHCallHandler(_SEHPortableFrame_t *frame, _SEHPortableTryLevel_t *trylevel)
Definition: framebased.c:323
#define _SEH_TRACE_ENTER_CALL_HANDLER(FRAME_, TRYLEVEL_)
Definition: framebased.c:272
void __stdcall _SEHEnterFrame_s(_SEHPortableFrame_t *frame)
Definition: framebased.c:447
void _SEH_FASTCALL _SEHLeaveFrame_f(void)
Definition: framebased.c:471
void const * _SEHRtlUnwind
Definition: framebased.c:286
void _SEH_FASTCALL _SEHReturn_f(void)
Definition: framebased.c:488
void __cdecl _SEHCleanHandlerEnvironment(void)
#define _SEH_TRACE_LEAVE_CALL_FINALLY(FRAME_, TRYLEVEL_)
Definition: framebased.c:274
#define _SEH_TRACE_EXCEPTION_RECORD(FRAME_, ER_)
Definition: framebased.c:265
static int __cdecl _SEHFrameHandler(struct _EXCEPTION_RECORD *ExceptionRecord, void *EstablisherFrame, struct _CONTEXT *ContextRecord, void *DispatcherContext)
Definition: framebased.c:336
#define _SEH_TRACE_ENTER_CALL_FINALLY(FRAME_, TRYLEVEL_)
Definition: framebased.c:273
void __stdcall RtlUnwind(void *, void *, PEXCEPTION_RECORD, void *)
void __cdecl _SEHGlobalUnwind(_SEHPortableFrame_t *)
static void __stdcall _SEHLocalUnwind(_SEHPortableFrame_t *frame, _SEHPortableTryLevel_t *dsttrylevel)
Definition: framebased.c:289
#define _SEH_TRACE_UNWIND(FRAME_, ARGS_)
Definition: framebased.c:267
_SEHRegistration_t *__cdecl _SEHCurrentRegistration(void)
#define _SEH_TRACE_ENTER(FRAME_, FUNCNAME_, ARGS_)
Definition: framebased.c:263
#define _SEH_TRACE_TRYLEVEL(FRAME_, TRYLEVEL_)
Definition: framebased.c:268
struct __SEHRegistration *__cdecl _SEHRegisterFrame(_SEHRegistration_t *)
void __cdecl _SEHUnregisterFrame(void)
void __stdcall _SEHLeaveFrame_s(void)
Definition: framebased.c:452
#define _SEH_TRACE_LEAVE_CALL_FILTER(FRAME_, TRYLEVEL_, RET_)
Definition: framebased.c:270
#define _SEH_TRACE_LEAVE(FRAME_, FUNCNAME_, ARGS_)
Definition: framebased.c:264
#define _SEH_TRACE_FILTER(FRAME_, TRYLEVEL_, RET_)
Definition: framebased.c:271
#define _SEH_TRACE_CONTEXT(FRAME_, CONTEXT_)
Definition: framebased.c:266
#define _SEH_STATIC_FILTER(ACTION_)
Definition: framebased.h:112
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
#define DbgPrint
Definition: hal.h:12
#define _SEH_CONTINUE_SEARCH
Definition: excpt.h:27
#define _SEH_CONTINUE_EXECUTION
Definition: excpt.h:26
#define _SEH_EXECUTE_HANDLER
Definition: excpt.h:28
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
_IRQL_requires_same_ _In_ PVOID EstablisherFrame
Definition: ntbasedef.h:653
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT * ContextRecord
Definition: ntbasedef.h:654
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT _In_ PVOID DispatcherContext
Definition: ntbasedef.h:655
#define _SEH_CONTAINING_RECORD(ADDR_, TYPE_, FIELD_)
Definition: pseh.h:43
void(__stdcall * _SEHFinally_t)(struct __SEHPortableFrame *)
Definition: internal.h:77
#define _SEH_FASTCALL
Definition: internal.h:118
long(__stdcall * _SEHFilter_t)(struct _EXCEPTION_POINTERS *, struct __SEHPortableFrame *)
Definition: internal.h:66
PEXCEPTION_RECORD ExceptionRecord
Definition: rtltypes.h:200
PCONTEXT ContextRecord
Definition: rtltypes.h:201
DWORD ExceptionCode
Definition: compat.h:208
DWORD ExceptionFlags
Definition: compat.h:209
_SEHFilter_t SH_Filter
Definition: internal.h:83
_SEHFinally_t SH_Finally
Definition: internal.h:84
unsigned long SPF_Code
Definition: internal.h:98
volatile _SEHHandler_t SPF_Handler
Definition: internal.h:99
_SEHRegistration_t SPF_Registration
Definition: internal.h:97
_SEHPortableTryLevel_t *volatile SPF_TopTryLevel
Definition: internal.h:100
struct __SEHPortableTryLevel *volatile SPT_Next
Definition: internal.h:90
volatile _SEHHandlers_t SPT_Handlers
Definition: internal.h:91
_SEHFrameHandler_t SER_Handler
Definition: internal.h:58
#define __stdcall
Definition: typedefs.h:25
int ret