2 Copyright (c) 2008 KJK::Hyperion
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:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
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.
25 #define WIN32_LEAN_AND_MEAN
28 #include <pseh/pseh2.h>
32 #ifndef EXCEPTION_EXIT_UNWIND
33 #define EXCEPTION_EXIT_UNWIND 4
36 #ifndef EXCEPTION_UNWINDING
37 #define EXCEPTION_UNWINDING 2
40 extern _SEH2Registration_t
* __cdecl
_SEH2CurrentRegistration(void);
42 extern int __SEH2Except(void *, void *);
43 extern void __SEH2Finally(void *, void *);
44 extern DECLSPEC_NORETURN
int __SEH2Handle(void *, void *, void *);
46 extern void __cdecl
__SEH2EnterFrame(_SEH2Registration_t
*);
47 extern void __cdecl
__SEH2LeaveFrame(void);
49 extern int __cdecl
__SEH2FrameHandler(struct _EXCEPTION_RECORD
*, void *, struct _CONTEXT
*, void *);
50 extern int __cdecl
__SEH2NestedHandler(struct _EXCEPTION_RECORD
*, void *, struct _CONTEXT
*, void *);
53 void _SEH2GlobalUnwind(void * target
)
62 "call %c[RtlUnwind]\n"
63 "Return%=: pop %%ebp\n" :
65 [target
] "g" (target
), [RtlUnwind
] "g" (&RtlUnwind
) :
66 "eax", "ebx", "ecx", "edx", "esi", "edi", "flags", "memory"
71 int _SEH2Except(_SEH2Frame_t
* frame
, volatile _SEH2TryLevel_t
* trylevel
)
73 void * filter
= trylevel
->ST_Filter
;
74 void * context
= NULL
;
76 if(filter
== (void *)0)
79 if(filter
== (void *)1)
82 if(filter
== (void *)-1)
85 if(_SEHIsTrampoline((_SEHTrampoline_t
*)filter
))
87 context
= _SEHClosureFromTrampoline((_SEHTrampoline_t
*)filter
);
88 filter
= _SEHFunctionFromTrampoline((_SEHTrampoline_t
*)filter
);
91 return __SEH2Except(filter
, context
);
95 void _SEH2Finally(_SEH2Frame_t
* frame
, volatile _SEH2TryLevel_t
* trylevel
)
97 if(trylevel
->ST_Filter
== NULL
&& trylevel
->ST_Body
!= NULL
)
99 void * body
= trylevel
->ST_Body
;
100 void * context
= NULL
;
102 if(_SEHIsTrampoline((_SEHTrampoline_t
*)body
))
104 context
= _SEHClosureFromTrampoline((_SEHTrampoline_t
*)body
);
105 body
= _SEHFunctionFromTrampoline((_SEHTrampoline_t
*)body
);
108 __SEH2Finally(body
, context
);
113 int __cdecl _SEH2NestedHandler
115 struct _EXCEPTION_RECORD
* ExceptionRecord
,
116 void * EstablisherFrame
,
117 struct _CONTEXT
* ContextRecord
,
118 void * DispatcherContext
121 if(ExceptionRecord
->ExceptionFlags
& (EXCEPTION_EXIT_UNWIND
| EXCEPTION_UNWINDING
))
122 return ExceptionContinueSearch
;
124 *((void **)DispatcherContext
) = EstablisherFrame
;
125 return ExceptionCollidedUnwind
;
129 void _SEH2LocalUnwind(_SEH2Frame_t
* frame
, volatile _SEH2TryLevel_t
* dsttrylevel
)
131 volatile _SEH2TryLevel_t
* trylevel
;
132 _SEH2Registration_t nestedframe
;
134 nestedframe
.SER_Handler
= &__SEH2NestedHandler
;
135 __SEH2EnterFrame(&nestedframe
);
137 for(trylevel
= frame
->SF_TopTryLevel
; trylevel
&& trylevel
!= dsttrylevel
; trylevel
= trylevel
->ST_Next
)
138 _SEH2Finally(frame
, trylevel
);
140 frame
->SF_TopTryLevel
= dsttrylevel
;
145 static DECLSPEC_NORETURN
146 void _SEH2Handle(_SEH2Frame_t
* frame
, volatile _SEH2TryLevel_t
* trylevel
)
148 _SEH2GlobalUnwind(frame
);
149 _SEH2LocalUnwind(frame
, trylevel
);
150 __SEH2Handle(trylevel
->ST_Body
, trylevel
->ST_Ebp
, trylevel
->ST_Esp
);
154 int __cdecl _SEH2FrameHandler
156 struct _EXCEPTION_RECORD
* ExceptionRecord
,
157 void * EstablisherFrame
,
158 struct _CONTEXT
* ContextRecord
,
159 void * DispatcherContext
162 _SEH2Frame_t
* frame
;
164 frame
= EstablisherFrame
;
167 if(ExceptionRecord
->ExceptionFlags
& (EXCEPTION_EXIT_UNWIND
| EXCEPTION_UNWINDING
))
169 _SEH2LocalUnwind(frame
, NULL
);
175 volatile _SEH2TryLevel_t
* trylevel
;
176 EXCEPTION_POINTERS ep
;
178 ep
.ExceptionRecord
= ExceptionRecord
;
179 ep
.ContextRecord
= ContextRecord
;
181 frame
->SF_Code
= ExceptionRecord
->ExceptionCode
;
182 frame
->SF_ExceptionInformation
= &ep
;
184 for(trylevel
= frame
->SF_TopTryLevel
; trylevel
!= NULL
; trylevel
= trylevel
->ST_Next
)
186 ret
= _SEH2Except(frame
, trylevel
);
189 return ExceptionContinueExecution
;
191 _SEH2Handle(frame
, trylevel
);
195 return ExceptionContinueSearch
;
199 void __cdecl
_SEH2EnterFrame(_SEH2Frame_t
* frame
)
201 frame
->SF_Registration
.SER_Handler
= __SEH2FrameHandler
;
203 __SEH2EnterFrame(&frame
->SF_Registration
);
207 void __cdecl
_SEH2LeaveFrame(void)
213 void __cdecl
_SEH2Return(void)
215 _SEH2LocalUnwind(CONTAINING_RECORD(_SEH2CurrentRegistration(), _SEH2Frame_t
, SF_Registration
), NULL
);