Move some internal headers to /reactos, set it as a default include path, move pseh...
[reactos.git] / reactos / lib / pseh / framebased.c
1 /*
2 Copyright (c) 2004 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 #define STRICT
24 #define WIN32_LEAN_AND_MEAN
25 #include <windows.h>
26
27 #include <pseh/pseh.h>
28 #include <pseh/framebased/internal.h>
29 #include <pseh/excpt.h>
30 #include <pseh/framebased.h>
31
32 #include <excpt.h>
33
34 /* Assembly helpers, see i386/framebased.asm */
35 extern void __cdecl _SEHCleanHandlerEnvironment(void);
36 extern struct __SEHRegistration * __cdecl _SEHRegisterFrame(_SEHRegistration_t *);
37 extern void __cdecl _SEHUnregisterFrame(void);
38 extern void __cdecl _SEHGlobalUnwind(_SEHPortableFrame_t *);
39 extern _SEHRegistration_t * __cdecl _SEHCurrentRegistration(void);
40
41 /* Borland C++ uses a different decoration (i.e. none) for stdcall functions */
42 extern void __stdcall RtlUnwind(void *, void *, void *, void *);
43 void const * _SEHRtlUnwind = RtlUnwind;
44
45 void __stdcall _SEHLocalUnwind
46 (
47 _SEHPortableFrame_t * frame,
48 _SEHPortableTryLevel_t * dsttrylevel
49 )
50 {
51 _SEHPortableTryLevel_t * trylevel;
52
53 for
54 (
55 trylevel = frame->SPF_TopTryLevel;
56 trylevel != dsttrylevel;
57 trylevel = trylevel->SPT_Next
58 )
59 {
60 _SEHFinally_t pfnFinally;
61
62 /* ASSERT(trylevel); */
63
64 pfnFinally = trylevel->SPT_Handlers->SH_Finally;
65
66 if(pfnFinally)
67 pfnFinally(frame);
68 }
69 }
70
71 __declspec(noreturn) void __cdecl _SEHCallHandler
72 (
73 _SEHPortableFrame_t * frame,
74 _SEHPortableTryLevel_t * trylevel
75 )
76 {
77 DbgPrint("_SEHCallHandler: REG %p\n", _SEHCurrentRegistration());
78 _SEHGlobalUnwind(frame);
79 DbgPrint("_SEHCallHandler: REG %p\n", _SEHCurrentRegistration());
80 _SEHLocalUnwind(frame, trylevel);
81 DbgPrint("_SEHCallHandler: REG %p\n", _SEHCurrentRegistration());
82 frame->SPF_Handler(trylevel);
83 }
84
85 int __cdecl _SEHFrameHandler
86 (
87 struct _EXCEPTION_RECORD * ExceptionRecord,
88 void * EstablisherFrame,
89 struct _CONTEXT * ContextRecord,
90 void * DispatcherContext
91 )
92 {
93 _SEHPortableFrame_t * frame;
94
95 _SEHCleanHandlerEnvironment();
96
97 frame = EstablisherFrame;
98
99 /* Unwinding */
100 if(ExceptionRecord->ExceptionFlags & (4 | 2))
101 _SEHLocalUnwind(frame, NULL);
102 /* Handling */
103 else
104 {
105 int ret;
106 _SEHPortableTryLevel_t * trylevel;
107
108 if(ExceptionRecord->ExceptionCode)
109 frame->SPF_Code = ExceptionRecord->ExceptionCode;
110 else
111 frame->SPF_Code = 0xC0000001;
112
113 for
114 (
115 trylevel = frame->SPF_TopTryLevel;
116 trylevel != NULL;
117 trylevel = trylevel->SPT_Next
118 )
119 {
120 _SEHFilter_t pfnFilter = trylevel->SPT_Handlers->SH_Filter;
121
122 switch((UINT_PTR)pfnFilter)
123 {
124 case (UINT_PTR)_SEH_STATIC_FILTER(_SEH_EXECUTE_HANDLER):
125 case (UINT_PTR)_SEH_STATIC_FILTER(_SEH_CONTINUE_SEARCH):
126 case (UINT_PTR)_SEH_STATIC_FILTER(_SEH_CONTINUE_EXECUTION):
127 {
128 ret = (int)((UINT_PTR)pfnFilter) - 2;
129 break;
130 }
131
132 default:
133 {
134 if(trylevel->SPT_Handlers->SH_Filter)
135 {
136 EXCEPTION_POINTERS ep;
137
138 ep.ExceptionRecord = ExceptionRecord;
139 ep.ContextRecord = ContextRecord;
140
141 ret = pfnFilter(&ep, frame);
142 }
143 else
144 ret = _SEH_CONTINUE_SEARCH;
145
146 break;
147 }
148 }
149
150 /* _SEH_CONTINUE_EXECUTION */
151 if(ret < 0)
152 return ExceptionContinueExecution;
153 /* _SEH_EXECUTE_HANDLER */
154 else if(ret > 0)
155 _SEHCallHandler(frame, trylevel);
156 /* _SEH_CONTINUE_SEARCH */
157 else
158 continue;
159 }
160
161 /* FALLTHROUGH */
162 }
163
164 return ExceptionContinueSearch;
165 }
166
167 void __stdcall _SEHEnterFrame_s
168 (
169 _SEHPortableFrame_t * frame,
170 _SEHPortableTryLevel_t * trylevel
171 )
172 {
173 _SEHEnterFrame_f(frame, trylevel);
174 }
175
176 void __stdcall _SEHEnterTry_s(_SEHPortableTryLevel_t * trylevel)
177 {
178 _SEHEnterTry_f(trylevel);
179 }
180
181 void __stdcall _SEHLeave_s(void)
182 {
183 _SEHLeave_f();
184 }
185
186 void _SEH_FASTCALL _SEHEnterFrame_f
187 (
188 _SEHPortableFrame_t * frame,
189 _SEHPortableTryLevel_t * trylevel
190 )
191 {
192 /* ASSERT(frame); */
193 /* ASSERT(trylevel); */
194 frame->SPF_Registration.SER_Handler = _SEHFrameHandler;
195 frame->SPF_Code = 0;
196 frame->SPF_TopTryLevel = trylevel;
197 trylevel->SPT_Next = NULL;
198 _SEHRegisterFrame(&frame->SPF_Registration);
199 }
200
201 void _SEH_FASTCALL _SEHEnterTry_f(_SEHPortableTryLevel_t * trylevel)
202 {
203 _SEHPortableFrame_t * frame;
204
205 frame = _SEH_CONTAINING_RECORD
206 (
207 _SEHCurrentRegistration(),
208 _SEHPortableFrame_t,
209 SPF_Registration
210 );
211
212 trylevel->SPT_Next = frame->SPF_TopTryLevel;
213 frame->SPF_TopTryLevel = trylevel;
214 }
215
216 void _SEH_FASTCALL _SEHLeave_f(void)
217 {
218 _SEHPortableFrame_t * frame;
219 _SEHPortableTryLevel_t * trylevel;
220
221 frame = _SEH_CONTAINING_RECORD
222 (
223 _SEHCurrentRegistration(),
224 _SEHPortableFrame_t,
225 SPF_Registration
226 );
227
228 /* ASSERT(frame); */
229
230 trylevel = frame->SPF_TopTryLevel;
231
232 /* ASSERT(trylevel); */
233
234 if(trylevel->SPT_Next)
235 frame->SPF_TopTryLevel = trylevel->SPT_Next;
236 else
237 _SEHUnregisterFrame();
238 }
239
240 /* EOF */