ReactOS  0.4.14-dev-554-g2f8d847
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
37 extern 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 */
278 extern void __cdecl _SEHCleanHandlerEnvironment(void);
280 extern void __cdecl _SEHUnregisterFrame(void);
283 
284 /* Borland C++ uses a different decoration (i.e. none) for stdcall functions */
285 extern void __stdcall RtlUnwind(void *, void *, PEXCEPTION_RECORD, void *);
286 void const * _SEHRtlUnwind = RtlUnwind;
287 
288 static void __stdcall _SEHLocalUnwind
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 
322 static void __cdecl _SEHCallHandler
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 
335 static int __cdecl _SEHFrameHandler
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); */
466  frame->SPF_Registration.SER_Handler = _SEHFrameHandler;
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 
492  frame = _SEH_CONTAINING_RECORD
493  (
496  SPF_Registration
497  );
498 
499  _SEHLocalUnwind(frame, NULL);
501 }
502 
503 /* EOF */
void __cdecl _SEHUnregisterFrame(void)
void _SEH_FASTCALL _SEHEnterFrame_f(_SEHPortableFrame_t *frame)
Definition: framebased.c:462
_IRQL_requires_same_ _In_ PVOID EstablisherFrame
Definition: ntbasedef.h:660
#define __cdecl
Definition: accygwin.h:79
#define DbgPrint
Definition: loader.c:25
volatile _SEHHandlers_t SPT_Handlers
Definition: internal.h:91
void __cdecl _SEHCleanHandlerEnvironment(void)
void __stdcall _SEHReturn_s(void)
Definition: framebased.c:457
struct __SEHRegistration *__cdecl _SEHRegisterFrame(_SEHRegistration_t *)
void __stdcall _SEHLeaveFrame_s(void)
Definition: framebased.c:452
void __cdecl _SEHGlobalUnwind(_SEHPortableFrame_t *)
struct __SEHPortableTryLevel *volatile SPT_Next
Definition: internal.h:90
#define _SEH_TRACE_ENTER_CALL_FILTER(FRAME_, TRYLEVEL_, ER_)
Definition: framebased.c:269
#define _SEH_CONTINUE_SEARCH
Definition: excpt.h:27
static void __stdcall _SEHLocalUnwind(_SEHPortableFrame_t *frame, _SEHPortableTryLevel_t *dsttrylevel)
Definition: framebased.c:289
#define _SEH_STATIC_FILTER(ACTION_)
Definition: framebased.h:112
#define _SEH_TRACE_CONTEXT(FRAME_, CONTEXT_)
Definition: framebased.c:266
void __stdcall RtlUnwind(void *, void *, PEXCEPTION_RECORD, void *)
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
#define _SEH_TRACE_LEAVE_CALL_FINALLY(FRAME_, TRYLEVEL_)
Definition: framebased.c:274
#define _SEH_TRACE_EXCEPTION_RECORD(FRAME_, ER_)
Definition: framebased.c:265
DWORD ExceptionCode
Definition: compat.h:196
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT _In_ PVOID DispatcherContext
Definition: ntbasedef.h:661
void _SEH_FASTCALL _SEHReturn_f(void)
Definition: framebased.c:488
#define _SEH_TRACE_LEAVE(FRAME_, FUNCNAME_, ARGS_)
Definition: framebased.c:264
smooth NULL
Definition: ftsmooth.c:416
_SEHRegistration_t SPF_Registration
Definition: internal.h:97
typedef void struct _CONTEXT void *struct __SEHRegistration _SEHRegistration_t
void _SEH_FASTCALL _SEHLeaveFrame_f(void)
Definition: framebased.c:471
PCONTEXT ContextRecord
Definition: rtltypes.h:197
void(__stdcall * _SEHFinally_t)(struct __SEHPortableFrame *)
Definition: internal.h:77
#define _SEH_TRACE_ENTER_CALL_FINALLY(FRAME_, TRYLEVEL_)
Definition: framebased.c:273
static void __cdecl _SEHCallHandler(_SEHPortableFrame_t *frame, _SEHPortableTryLevel_t *trylevel)
Definition: framebased.c:323
#define __stdcall
Definition: typedefs.h:25
_SEHFilter_t SH_Filter
Definition: internal.h:83
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
volatile _SEHHandler_t SPF_Handler
Definition: internal.h:99
#define _SEH_TRACE_ENTER(FRAME_, FUNCNAME_, ARGS_)
Definition: framebased.c:263
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT * ContextRecord
Definition: ntbasedef.h:661
#define _SEH_TRACE_LEAVE_CALL_FILTER(FRAME_, TRYLEVEL_, RET_)
Definition: framebased.c:270
int ret
_SEHFinally_t SH_Finally
Definition: internal.h:84
#define _SEH_EXECUTE_HANDLER
Definition: excpt.h:28
static int __cdecl _SEHFrameHandler(struct _EXCEPTION_RECORD *ExceptionRecord, void *EstablisherFrame, struct _CONTEXT *ContextRecord, void *DispatcherContext)
Definition: framebased.c:336
#define _SEH_TRACE_TRYLEVEL(FRAME_, TRYLEVEL_)
Definition: framebased.c:268
void const * _SEHRtlUnwind
Definition: framebased.c:286
void __stdcall _SEHEnterFrame_s(_SEHPortableFrame_t *frame)
Definition: framebased.c:447
#define _SEH_CONTINUE_EXECUTION
Definition: excpt.h:26
#define _SEH_FASTCALL
Definition: internal.h:118
#define _SEH_TRACE_FILTER(FRAME_, TRYLEVEL_, RET_)
Definition: framebased.c:271
DWORD ExceptionFlags
Definition: compat.h:197
#define _SEH_CONTAINING_RECORD(ADDR_, TYPE_, FIELD_)
Definition: pseh.h:43
PEXCEPTION_RECORD ExceptionRecord
Definition: rtltypes.h:196
_SEHRegistration_t *__cdecl _SEHCurrentRegistration(void)
#define _SEH_TRACE_ENTER_CALL_HANDLER(FRAME_, TRYLEVEL_)
Definition: framebased.c:272
_SEHPortableTryLevel_t *volatile SPF_TopTryLevel
Definition: internal.h:100
unsigned long SPF_Code
Definition: internal.h:98
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define _SEH_TRACE_UNWIND(FRAME_, ARGS_)
Definition: framebased.c:267