1c2c66affSColin Finck /*
2c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory
3c2c66affSColin Finck * PROJECT: ReactOS Run-Time Library
4c2c66affSColin Finck * PURPOSE: User-mode exception support for IA-32
5c2c66affSColin Finck * FILE: lib/rtl/i386/except.c
6c2c66affSColin Finck * PROGRAMERS: Alex Ionescu (alex@relsoft.net)
7c2c66affSColin Finck * Casper S. Hornstrup (chorns@users.sourceforge.net)
8c2c66affSColin Finck */
9c2c66affSColin Finck
10c2c66affSColin Finck /* INCLUDES *****************************************************************/
11c2c66affSColin Finck
12c2c66affSColin Finck #include <rtl.h>
13c2c66affSColin Finck #define NDEBUG
14c2c66affSColin Finck #include <debug.h>
15c2c66affSColin Finck
16c2c66affSColin Finck /* PUBLIC FUNCTIONS **********************************************************/
17c2c66affSColin Finck
18c2c66affSColin Finck /*
19c2c66affSColin Finck * @implemented
20c2c66affSColin Finck */
21c2c66affSColin Finck VOID
22c2c66affSColin Finck NTAPI
RtlGetCallersAddress(OUT PVOID * CallersAddress,OUT PVOID * CallersCaller)23c2c66affSColin Finck RtlGetCallersAddress(OUT PVOID *CallersAddress,
24c2c66affSColin Finck OUT PVOID *CallersCaller)
25c2c66affSColin Finck {
26c2c66affSColin Finck USHORT FrameCount;
27c2c66affSColin Finck PVOID BackTrace[2];
28c2c66affSColin Finck PULONG BackTraceHash = NULL;
29c2c66affSColin Finck
30c2c66affSColin Finck /* Get the tow back trace address */
31c2c66affSColin Finck FrameCount = RtlCaptureStackBackTrace(2, 2, &BackTrace[0],BackTraceHash);
32c2c66affSColin Finck
33c2c66affSColin Finck /* Only if user want it */
34c2c66affSColin Finck if (CallersAddress != NULL)
35c2c66affSColin Finck {
36c2c66affSColin Finck /* only when first frames exist */
37c2c66affSColin Finck if (FrameCount >= 1)
38c2c66affSColin Finck {
39c2c66affSColin Finck *CallersAddress = BackTrace[0];
40c2c66affSColin Finck }
41c2c66affSColin Finck else
42c2c66affSColin Finck {
43c2c66affSColin Finck *CallersAddress = NULL;
44c2c66affSColin Finck }
45c2c66affSColin Finck }
46c2c66affSColin Finck
47c2c66affSColin Finck /* Only if user want it */
48c2c66affSColin Finck if (CallersCaller != NULL)
49c2c66affSColin Finck {
50c2c66affSColin Finck /* only when second frames exist */
51c2c66affSColin Finck if (FrameCount >= 2)
52c2c66affSColin Finck {
53c2c66affSColin Finck *CallersCaller = BackTrace[1];
54c2c66affSColin Finck }
55c2c66affSColin Finck else
56c2c66affSColin Finck {
57c2c66affSColin Finck *CallersCaller = NULL;
58c2c66affSColin Finck }
59c2c66affSColin Finck }
60c2c66affSColin Finck }
61c2c66affSColin Finck
62c2c66affSColin Finck /*
63c2c66affSColin Finck * @implemented
64c2c66affSColin Finck */
65c2c66affSColin Finck BOOLEAN
66c2c66affSColin Finck NTAPI
RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,IN PCONTEXT Context)67c2c66affSColin Finck RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
68c2c66affSColin Finck IN PCONTEXT Context)
69c2c66affSColin Finck {
70c2c66affSColin Finck PEXCEPTION_REGISTRATION_RECORD RegistrationFrame, NestedFrame = NULL;
71c2c66affSColin Finck DISPATCHER_CONTEXT DispatcherContext;
72c2c66affSColin Finck EXCEPTION_RECORD ExceptionRecord2;
73c2c66affSColin Finck EXCEPTION_DISPOSITION Disposition;
74c2c66affSColin Finck ULONG_PTR StackLow, StackHigh;
75c2c66affSColin Finck ULONG_PTR RegistrationFrameEnd;
76c2c66affSColin Finck
77c2c66affSColin Finck /* Perform vectored exception handling for user mode */
78c2c66affSColin Finck if (RtlCallVectoredExceptionHandlers(ExceptionRecord, Context))
79c2c66affSColin Finck {
80c2c66affSColin Finck /* Exception handled, now call vectored continue handlers */
81c2c66affSColin Finck RtlCallVectoredContinueHandlers(ExceptionRecord, Context);
82c2c66affSColin Finck
83c2c66affSColin Finck /* Continue execution */
84c2c66affSColin Finck return TRUE;
85c2c66affSColin Finck }
86c2c66affSColin Finck
87c2c66affSColin Finck /* Get the current stack limits and registration frame */
88c2c66affSColin Finck RtlpGetStackLimits(&StackLow, &StackHigh);
89c2c66affSColin Finck RegistrationFrame = RtlpGetExceptionList();
90c2c66affSColin Finck
91c2c66affSColin Finck /* Now loop every frame */
92c2c66affSColin Finck while (RegistrationFrame != EXCEPTION_CHAIN_END)
93c2c66affSColin Finck {
94c2c66affSColin Finck /* Registration chain entries are never NULL */
95c2c66affSColin Finck ASSERT(RegistrationFrame != NULL);
96c2c66affSColin Finck
97c2c66affSColin Finck /* Find out where it ends */
98c2c66affSColin Finck RegistrationFrameEnd = (ULONG_PTR)RegistrationFrame +
99c2c66affSColin Finck sizeof(EXCEPTION_REGISTRATION_RECORD);
100c2c66affSColin Finck
101c2c66affSColin Finck /* Make sure the registration frame is located within the stack */
102c2c66affSColin Finck if ((RegistrationFrameEnd > StackHigh) ||
103c2c66affSColin Finck ((ULONG_PTR)RegistrationFrame < StackLow) ||
104c2c66affSColin Finck ((ULONG_PTR)RegistrationFrame & 0x3))
105c2c66affSColin Finck {
106c2c66affSColin Finck /* Check if this happened in the DPC Stack */
107c2c66affSColin Finck if (RtlpHandleDpcStackException(RegistrationFrame,
108c2c66affSColin Finck RegistrationFrameEnd,
109c2c66affSColin Finck &StackLow,
110c2c66affSColin Finck &StackHigh))
111c2c66affSColin Finck {
112c2c66affSColin Finck /* Use DPC Stack Limits and restart */
113c2c66affSColin Finck continue;
114c2c66affSColin Finck }
115c2c66affSColin Finck
116*a4b6e0d9SHermès Bélusca-Maïto /* Set invalid stack and bail out */
117c2c66affSColin Finck ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
118c2c66affSColin Finck return FALSE;
119c2c66affSColin Finck }
120c2c66affSColin Finck
121*a4b6e0d9SHermès Bélusca-Maïto //
122*a4b6e0d9SHermès Bélusca-Maïto // TODO: Implement and call here RtlIsValidHandler(RegistrationFrame->Handler)
123*a4b6e0d9SHermès Bélusca-Maïto // for supporting SafeSEH functionality, see the following articles:
124*a4b6e0d9SHermès Bélusca-Maïto // https://www.optiv.com/blog/old-meets-new-microsoft-windows-safeseh-incompatibility
125*a4b6e0d9SHermès Bélusca-Maïto // https://msrc-blog.microsoft.com/2012/01/10/more-information-on-the-impact-of-ms12-001/
126*a4b6e0d9SHermès Bélusca-Maïto //
127*a4b6e0d9SHermès Bélusca-Maïto
128c2c66affSColin Finck /* Check if logging is enabled */
129c2c66affSColin Finck RtlpCheckLogException(ExceptionRecord,
130c2c66affSColin Finck Context,
131c2c66affSColin Finck RegistrationFrame,
132c2c66affSColin Finck sizeof(*RegistrationFrame));
133c2c66affSColin Finck
134c2c66affSColin Finck /* Call the handler */
135c2c66affSColin Finck Disposition = RtlpExecuteHandlerForException(ExceptionRecord,
136c2c66affSColin Finck RegistrationFrame,
137c2c66affSColin Finck Context,
138c2c66affSColin Finck &DispatcherContext,
139c2c66affSColin Finck RegistrationFrame->Handler);
140c2c66affSColin Finck
141c2c66affSColin Finck /* Check if this is a nested frame */
142c2c66affSColin Finck if (RegistrationFrame == NestedFrame)
143c2c66affSColin Finck {
144c2c66affSColin Finck /* Mask out the flag and the nested frame */
145c2c66affSColin Finck ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NESTED_CALL;
146c2c66affSColin Finck NestedFrame = NULL;
147c2c66affSColin Finck }
148c2c66affSColin Finck
149c2c66affSColin Finck /* Handle the dispositions */
150c2c66affSColin Finck switch (Disposition)
151c2c66affSColin Finck {
152c2c66affSColin Finck /* Continue execution */
153c2c66affSColin Finck case ExceptionContinueExecution:
154*a4b6e0d9SHermès Bélusca-Maïto {
155c2c66affSColin Finck /* Check if it was non-continuable */
156c2c66affSColin Finck if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
157c2c66affSColin Finck {
158c2c66affSColin Finck /* Set up the exception record */
159c2c66affSColin Finck ExceptionRecord2.ExceptionRecord = ExceptionRecord;
160c2c66affSColin Finck ExceptionRecord2.ExceptionCode =
161c2c66affSColin Finck STATUS_NONCONTINUABLE_EXCEPTION;
162c2c66affSColin Finck ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
163c2c66affSColin Finck ExceptionRecord2.NumberParameters = 0;
164c2c66affSColin Finck
165c2c66affSColin Finck /* Raise the exception */
166c2c66affSColin Finck RtlRaiseException(&ExceptionRecord2);
167c2c66affSColin Finck }
168c2c66affSColin Finck else
169c2c66affSColin Finck {
170c2c66affSColin Finck /* In user mode, call any registered vectored continue handlers */
171*a4b6e0d9SHermès Bélusca-Maïto RtlCallVectoredContinueHandlers(ExceptionRecord, Context);
172c2c66affSColin Finck
173c2c66affSColin Finck /* Execution continues */
174c2c66affSColin Finck return TRUE;
175c2c66affSColin Finck }
176*a4b6e0d9SHermès Bélusca-Maïto }
177c2c66affSColin Finck
178c2c66affSColin Finck /* Continue searching */
179c2c66affSColin Finck case ExceptionContinueSearch:
180*a4b6e0d9SHermès Bélusca-Maïto if (ExceptionRecord->ExceptionFlags & EXCEPTION_STACK_INVALID)
181*a4b6e0d9SHermès Bélusca-Maïto {
182*a4b6e0d9SHermès Bélusca-Maïto /* We have an invalid stack, bail out */
183*a4b6e0d9SHermès Bélusca-Maïto return FALSE;
184*a4b6e0d9SHermès Bélusca-Maïto }
185c2c66affSColin Finck break;
186c2c66affSColin Finck
187c2c66affSColin Finck /* Nested exception */
188c2c66affSColin Finck case ExceptionNestedException:
189*a4b6e0d9SHermès Bélusca-Maïto {
190c2c66affSColin Finck /* Turn the nested flag on */
191c2c66affSColin Finck ExceptionRecord->ExceptionFlags |= EXCEPTION_NESTED_CALL;
192c2c66affSColin Finck
193c2c66affSColin Finck /* Update the current nested frame */
194c2c66affSColin Finck if (DispatcherContext.RegistrationPointer > NestedFrame)
195c2c66affSColin Finck {
196c2c66affSColin Finck /* Get the frame from the dispatcher context */
197c2c66affSColin Finck NestedFrame = DispatcherContext.RegistrationPointer;
198c2c66affSColin Finck }
199c2c66affSColin Finck break;
200*a4b6e0d9SHermès Bélusca-Maïto }
201c2c66affSColin Finck
202c2c66affSColin Finck /* Anything else */
203c2c66affSColin Finck default:
204*a4b6e0d9SHermès Bélusca-Maïto {
205c2c66affSColin Finck /* Set up the exception record */
206c2c66affSColin Finck ExceptionRecord2.ExceptionRecord = ExceptionRecord;
207c2c66affSColin Finck ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION;
208c2c66affSColin Finck ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
209c2c66affSColin Finck ExceptionRecord2.NumberParameters = 0;
210c2c66affSColin Finck
211c2c66affSColin Finck /* Raise the exception */
212c2c66affSColin Finck RtlRaiseException(&ExceptionRecord2);
213c2c66affSColin Finck break;
214c2c66affSColin Finck }
215*a4b6e0d9SHermès Bélusca-Maïto }
216c2c66affSColin Finck
217c2c66affSColin Finck /* Go to the next frame */
218c2c66affSColin Finck RegistrationFrame = RegistrationFrame->Next;
219c2c66affSColin Finck }
220c2c66affSColin Finck
221*a4b6e0d9SHermès Bélusca-Maïto /* Unhandled, bail out */
222c2c66affSColin Finck return FALSE;
223c2c66affSColin Finck }
224c2c66affSColin Finck
225c2c66affSColin Finck /*
226c2c66affSColin Finck * @implemented
227c2c66affSColin Finck */
228c2c66affSColin Finck VOID
229c2c66affSColin Finck NTAPI
RtlUnwind(IN PVOID TargetFrame OPTIONAL,IN PVOID TargetIp OPTIONAL,IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL,IN PVOID ReturnValue)230c2c66affSColin Finck RtlUnwind(IN PVOID TargetFrame OPTIONAL,
231c2c66affSColin Finck IN PVOID TargetIp OPTIONAL,
232c2c66affSColin Finck IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL,
233c2c66affSColin Finck IN PVOID ReturnValue)
234c2c66affSColin Finck {
235c2c66affSColin Finck PEXCEPTION_REGISTRATION_RECORD RegistrationFrame, OldFrame;
236c2c66affSColin Finck DISPATCHER_CONTEXT DispatcherContext;
237c2c66affSColin Finck EXCEPTION_RECORD ExceptionRecord2, ExceptionRecord3;
238c2c66affSColin Finck EXCEPTION_DISPOSITION Disposition;
239c2c66affSColin Finck ULONG_PTR StackLow, StackHigh;
240c2c66affSColin Finck ULONG_PTR RegistrationFrameEnd;
241c2c66affSColin Finck CONTEXT LocalContext;
242c2c66affSColin Finck PCONTEXT Context;
243c2c66affSColin Finck
244c2c66affSColin Finck /* Get the current stack limits */
245c2c66affSColin Finck RtlpGetStackLimits(&StackLow, &StackHigh);
246c2c66affSColin Finck
247c2c66affSColin Finck /* Check if we don't have an exception record */
248c2c66affSColin Finck if (!ExceptionRecord)
249c2c66affSColin Finck {
250c2c66affSColin Finck /* Overwrite the argument */
251c2c66affSColin Finck ExceptionRecord = &ExceptionRecord3;
252c2c66affSColin Finck
253c2c66affSColin Finck /* Setup a local one */
254c2c66affSColin Finck ExceptionRecord3.ExceptionFlags = 0;
255c2c66affSColin Finck ExceptionRecord3.ExceptionCode = STATUS_UNWIND;
256c2c66affSColin Finck ExceptionRecord3.ExceptionRecord = NULL;
257c2c66affSColin Finck ExceptionRecord3.ExceptionAddress = _ReturnAddress();
258c2c66affSColin Finck ExceptionRecord3.NumberParameters = 0;
259c2c66affSColin Finck }
260c2c66affSColin Finck
261c2c66affSColin Finck /* Check if we have a frame */
262c2c66affSColin Finck if (TargetFrame)
263c2c66affSColin Finck {
264c2c66affSColin Finck /* Set it as unwinding */
265c2c66affSColin Finck ExceptionRecord->ExceptionFlags |= EXCEPTION_UNWINDING;
266c2c66affSColin Finck }
267c2c66affSColin Finck else
268c2c66affSColin Finck {
269c2c66affSColin Finck /* Set the Exit Unwind flag as well */
270c2c66affSColin Finck ExceptionRecord->ExceptionFlags |= (EXCEPTION_UNWINDING |
271c2c66affSColin Finck EXCEPTION_EXIT_UNWIND);
272c2c66affSColin Finck }
273c2c66affSColin Finck
274c2c66affSColin Finck /* Now capture the context */
275c2c66affSColin Finck Context = &LocalContext;
276c2c66affSColin Finck LocalContext.ContextFlags = CONTEXT_INTEGER |
277c2c66affSColin Finck CONTEXT_CONTROL |
278c2c66affSColin Finck CONTEXT_SEGMENTS;
279c2c66affSColin Finck RtlpCaptureContext(Context);
280c2c66affSColin Finck
281c2c66affSColin Finck /* Pop the current arguments off */
282c2c66affSColin Finck Context->Esp += sizeof(TargetFrame) +
283c2c66affSColin Finck sizeof(TargetIp) +
284c2c66affSColin Finck sizeof(ExceptionRecord) +
285c2c66affSColin Finck sizeof(ReturnValue);
286c2c66affSColin Finck
287c2c66affSColin Finck /* Set the new value for EAX */
288c2c66affSColin Finck Context->Eax = (ULONG)ReturnValue;
289c2c66affSColin Finck
290c2c66affSColin Finck /* Get the current frame */
291c2c66affSColin Finck RegistrationFrame = RtlpGetExceptionList();
292c2c66affSColin Finck
293c2c66affSColin Finck /* Now loop every frame */
294c2c66affSColin Finck while (RegistrationFrame != EXCEPTION_CHAIN_END)
295c2c66affSColin Finck {
296c2c66affSColin Finck /* Registration chain entries are never NULL */
297c2c66affSColin Finck ASSERT(RegistrationFrame != NULL);
298c2c66affSColin Finck
299c2c66affSColin Finck /* If this is the target */
300c2c66affSColin Finck if (RegistrationFrame == TargetFrame) ZwContinue(Context, FALSE);
301c2c66affSColin Finck
302c2c66affSColin Finck /* Check if the frame is too low */
303c2c66affSColin Finck if ((TargetFrame) &&
304c2c66affSColin Finck ((ULONG_PTR)TargetFrame < (ULONG_PTR)RegistrationFrame))
305c2c66affSColin Finck {
306c2c66affSColin Finck /* Create an invalid unwind exception */
307c2c66affSColin Finck ExceptionRecord2.ExceptionCode = STATUS_INVALID_UNWIND_TARGET;
308c2c66affSColin Finck ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
309c2c66affSColin Finck ExceptionRecord2.ExceptionRecord = ExceptionRecord;
310c2c66affSColin Finck ExceptionRecord2.NumberParameters = 0;
311c2c66affSColin Finck
312c2c66affSColin Finck /* Raise the exception */
313c2c66affSColin Finck RtlRaiseException(&ExceptionRecord2);
314c2c66affSColin Finck }
315c2c66affSColin Finck
316c2c66affSColin Finck /* Find out where it ends */
317c2c66affSColin Finck RegistrationFrameEnd = (ULONG_PTR)RegistrationFrame +
318c2c66affSColin Finck sizeof(EXCEPTION_REGISTRATION_RECORD);
319c2c66affSColin Finck
320c2c66affSColin Finck /* Make sure the registration frame is located within the stack */
321c2c66affSColin Finck if ((RegistrationFrameEnd > StackHigh) ||
322c2c66affSColin Finck ((ULONG_PTR)RegistrationFrame < StackLow) ||
323c2c66affSColin Finck ((ULONG_PTR)RegistrationFrame & 0x3))
324c2c66affSColin Finck {
325c2c66affSColin Finck /* Check if this happened in the DPC Stack */
326c2c66affSColin Finck if (RtlpHandleDpcStackException(RegistrationFrame,
327c2c66affSColin Finck RegistrationFrameEnd,
328c2c66affSColin Finck &StackLow,
329c2c66affSColin Finck &StackHigh))
330c2c66affSColin Finck {
331c2c66affSColin Finck /* Use DPC Stack Limits and restart */
332c2c66affSColin Finck continue;
333c2c66affSColin Finck }
334c2c66affSColin Finck
335c2c66affSColin Finck /* Create an invalid stack exception */
336c2c66affSColin Finck ExceptionRecord2.ExceptionCode = STATUS_BAD_STACK;
337c2c66affSColin Finck ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
338c2c66affSColin Finck ExceptionRecord2.ExceptionRecord = ExceptionRecord;
339c2c66affSColin Finck ExceptionRecord2.NumberParameters = 0;
340c2c66affSColin Finck
341c2c66affSColin Finck /* Raise the exception */
342c2c66affSColin Finck RtlRaiseException(&ExceptionRecord2);
343c2c66affSColin Finck }
344c2c66affSColin Finck else
345c2c66affSColin Finck {
346c2c66affSColin Finck /* Call the handler */
347c2c66affSColin Finck Disposition = RtlpExecuteHandlerForUnwind(ExceptionRecord,
348c2c66affSColin Finck RegistrationFrame,
349c2c66affSColin Finck Context,
350c2c66affSColin Finck &DispatcherContext,
351c2c66affSColin Finck RegistrationFrame->Handler);
352*a4b6e0d9SHermès Bélusca-Maïto
353c2c66affSColin Finck switch(Disposition)
354c2c66affSColin Finck {
355c2c66affSColin Finck /* Continue searching */
356c2c66affSColin Finck case ExceptionContinueSearch:
357c2c66affSColin Finck break;
358c2c66affSColin Finck
359*a4b6e0d9SHermès Bélusca-Maïto /* Collision */
360c2c66affSColin Finck case ExceptionCollidedUnwind:
361*a4b6e0d9SHermès Bélusca-Maïto {
362c2c66affSColin Finck /* Get the original frame */
363c2c66affSColin Finck RegistrationFrame = DispatcherContext.RegistrationPointer;
364c2c66affSColin Finck break;
365*a4b6e0d9SHermès Bélusca-Maïto }
366c2c66affSColin Finck
367c2c66affSColin Finck /* Anything else */
368c2c66affSColin Finck default:
369*a4b6e0d9SHermès Bélusca-Maïto {
370c2c66affSColin Finck /* Set up the exception record */
371c2c66affSColin Finck ExceptionRecord2.ExceptionRecord = ExceptionRecord;
372c2c66affSColin Finck ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION;
373c2c66affSColin Finck ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
374c2c66affSColin Finck ExceptionRecord2.NumberParameters = 0;
375c2c66affSColin Finck
376c2c66affSColin Finck /* Raise the exception */
377c2c66affSColin Finck RtlRaiseException(&ExceptionRecord2);
378c2c66affSColin Finck break;
379c2c66affSColin Finck }
380*a4b6e0d9SHermès Bélusca-Maïto }
381c2c66affSColin Finck
382c2c66affSColin Finck /* Go to the next frame */
383c2c66affSColin Finck OldFrame = RegistrationFrame;
384c2c66affSColin Finck RegistrationFrame = RegistrationFrame->Next;
385c2c66affSColin Finck
386c2c66affSColin Finck /* Remove this handler */
387c2c66affSColin Finck RtlpSetExceptionList(OldFrame);
388c2c66affSColin Finck }
389c2c66affSColin Finck }
390c2c66affSColin Finck
391c2c66affSColin Finck /* Check if we reached the end */
392c2c66affSColin Finck if (TargetFrame == EXCEPTION_CHAIN_END)
393c2c66affSColin Finck {
394c2c66affSColin Finck /* Unwind completed, so we don't exit */
395c2c66affSColin Finck ZwContinue(Context, FALSE);
396c2c66affSColin Finck }
397c2c66affSColin Finck else
398c2c66affSColin Finck {
399c2c66affSColin Finck /* This is an exit_unwind or the frame wasn't present in the list */
400c2c66affSColin Finck ZwRaiseException(ExceptionRecord, Context, FALSE);
401c2c66affSColin Finck }
402c2c66affSColin Finck }
403c2c66affSColin Finck
404c2c66affSColin Finck /* EOF */
405