Temporarly disable a correct bugcheck in order to hide a ReactOS bug, now that the...
[reactos.git] / reactos / ntoskrnl / ke / i386 / exp.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ke/i386/exp.c
5 * PURPOSE: Handling exceptions
6 *
7 * PROGRAMMERS: David Welch (welch@cwcom.net)
8 * Skywing (skywing@valhallalegends.com)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 #if defined (ALLOC_PRAGMA)
19 #pragma alloc_text(INIT, KeInitExceptions)
20 #endif
21
22
23 /*
24 * FIXMES:
25 * - Put back VEH.
26 * - Clean up file.
27 * - Sanitize some context fields.
28 * - Add PSEH handler when an exception occurs in an exception (KiCopyExceptionRecord).
29 * - Implement official stack trace functions (exported) and remove stuff here.
30 * - Forward exceptions to user-mode debugger.
31 */
32
33 VOID
34 NTAPI
35 Ki386AdjustEsp0(IN PKTRAP_FRAME TrapFrame);
36
37 /* GLOBALS *****************************************************************/
38
39 #define FLAG_IF (1<<9)
40
41 #define _STR(x) #x
42 #define STR(x) _STR(x)
43
44 #ifndef ARRAY_SIZE
45 # define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0]))
46 #endif
47
48 extern void KiSystemService(void);
49 extern void KiDebugService(void);
50
51 extern VOID KiTrap0(VOID);
52 extern VOID KiTrap1(VOID);
53 extern VOID KiTrap2(VOID);
54 extern VOID KiTrap3(VOID);
55 extern VOID KiTrap4(VOID);
56 extern VOID KiTrap5(VOID);
57 extern VOID KiTrap6(VOID);
58 extern VOID KiTrap7(VOID);
59 extern VOID KiTrap8(VOID);
60 extern VOID KiTrap9(VOID);
61 extern VOID KiTrap10(VOID);
62 extern VOID KiTrap11(VOID);
63 extern VOID KiTrap12(VOID);
64 extern VOID KiTrap13(VOID);
65 extern VOID KiTrap14(VOID);
66 extern VOID KiTrap15(VOID);
67 extern VOID KiTrap16(VOID);
68 extern VOID KiTrap17(VOID);
69 extern VOID KiTrap18(VOID);
70 extern VOID KiTrap19(VOID);
71 extern VOID KiTrapUnknown(VOID);
72
73 extern ULONG init_stack;
74 extern ULONG init_stack_top;
75
76 extern BOOLEAN Ke386NoExecute;
77
78 static char *ExceptionTypeStrings[] =
79 {
80 "Divide Error",
81 "Debug Trap",
82 "NMI",
83 "Breakpoint",
84 "Overflow",
85 "BOUND range exceeded",
86 "Invalid Opcode",
87 "No Math Coprocessor",
88 "Double Fault",
89 "Unknown(9)",
90 "Invalid TSS",
91 "Segment Not Present",
92 "Stack Segment Fault",
93 "General Protection",
94 "Page Fault",
95 "Reserved(15)",
96 "Math Fault",
97 "Alignment Check",
98 "Machine Check",
99 "SIMD Fault"
100 };
101
102 NTSTATUS ExceptionToNtStatus[] =
103 {
104 STATUS_INTEGER_DIVIDE_BY_ZERO,
105 STATUS_SINGLE_STEP,
106 STATUS_ACCESS_VIOLATION,
107 STATUS_BREAKPOINT,
108 STATUS_INTEGER_OVERFLOW,
109 STATUS_ARRAY_BOUNDS_EXCEEDED,
110 STATUS_ILLEGAL_INSTRUCTION,
111 STATUS_FLOAT_INVALID_OPERATION,
112 STATUS_ACCESS_VIOLATION,
113 STATUS_ACCESS_VIOLATION,
114 STATUS_ACCESS_VIOLATION,
115 STATUS_ACCESS_VIOLATION,
116 STATUS_STACK_OVERFLOW,
117 STATUS_ACCESS_VIOLATION,
118 STATUS_ACCESS_VIOLATION,
119 STATUS_ACCESS_VIOLATION, /* RESERVED */
120 STATUS_FLOAT_INVALID_OPERATION, /* Should not be used, the FPU can give more specific info */
121 STATUS_DATATYPE_MISALIGNMENT,
122 STATUS_ACCESS_VIOLATION,
123 STATUS_FLOAT_MULTIPLE_TRAPS,
124 };
125
126 /* FUNCTIONS ****************************************************************/
127
128 BOOLEAN STDCALL
129 KiRosPrintAddress(PVOID address)
130 {
131 PLIST_ENTRY current_entry;
132 PLDR_DATA_TABLE_ENTRY current;
133 extern LIST_ENTRY ModuleListHead;
134 ULONG_PTR RelativeAddress;
135 ULONG i = 0;
136
137 do
138 {
139 current_entry = ModuleListHead.Flink;
140
141 while (current_entry != &ModuleListHead)
142 {
143 current =
144 CONTAINING_RECORD(current_entry, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
145
146 if (address >= (PVOID)current->DllBase &&
147 address < (PVOID)((ULONG_PTR)current->DllBase + current->SizeOfImage))
148 {
149 RelativeAddress = (ULONG_PTR) address - (ULONG_PTR) current->DllBase;
150 DbgPrint("<%wZ: %x>", &current->FullDllName, RelativeAddress);
151 return(TRUE);
152 }
153 current_entry = current_entry->Flink;
154 }
155
156 address = (PVOID)((ULONG_PTR)address & ~(ULONG_PTR)MmSystemRangeStart);
157 } while(++i <= 1);
158
159 return(FALSE);
160 }
161
162 ULONG
163 KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
164 {
165 EXCEPTION_RECORD Er;
166
167 Er.ExceptionFlags = 0;
168 Er.ExceptionRecord = NULL;
169 Er.ExceptionAddress = (PVOID)Tf->Eip;
170
171 if (ExceptionNr == 14)
172 {
173 Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
174 Er.NumberParameters = 2;
175 Er.ExceptionInformation[0] = Tf->ErrCode & 0x1;
176 Er.ExceptionInformation[1] = (ULONG)Cr2;
177 }
178 else
179 {
180 if (ExceptionNr < ARRAY_SIZE(ExceptionToNtStatus))
181 {
182 Er.ExceptionCode = ExceptionToNtStatus[ExceptionNr];
183 }
184 else
185 {
186 Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
187 }
188 Er.NumberParameters = 0;
189 }
190
191 /* FIXME: Which exceptions are noncontinuable? */
192 Er.ExceptionFlags = 0;
193
194 KiDispatchException(&Er, NULL, Tf, KernelMode, TRUE);
195
196 return(0);
197 }
198
199 VOID
200 KiDoubleFaultHandler(VOID)
201 {
202 #if 0
203 unsigned int cr2;
204 ULONG StackLimit;
205 ULONG StackBase;
206 ULONG Esp0;
207 ULONG ExceptionNr = 8;
208 KTSS* OldTss;
209 PULONG Frame;
210 ULONG OldCr3;
211 #if 0
212 ULONG i, j;
213 static PVOID StackTrace[MM_STACK_SIZE / sizeof(PVOID)];
214 static ULONG StackRepeatCount[MM_STACK_SIZE / sizeof(PVOID)];
215 static ULONG StackRepeatLength[MM_STACK_SIZE / sizeof(PVOID)];
216 ULONG TraceLength;
217 BOOLEAN FoundRepeat;
218 #endif
219
220 OldTss = KeGetCurrentKPCR()->TSS;
221 Esp0 = OldTss->Esp0;
222
223 /* Get CR2 */
224 cr2 = Ke386GetCr2();
225 if (PsGetCurrentThread() != NULL &&
226 PsGetCurrentThread()->ThreadsProcess != NULL)
227 {
228 OldCr3 = (ULONG)
229 PsGetCurrentThread()->ThreadsProcess->Pcb.DirectoryTableBase.QuadPart;
230 }
231 else
232 {
233 OldCr3 = 0xBEADF0AL;
234 }
235
236 /*
237 * Check for stack underflow
238 */
239 if (PsGetCurrentThread() != NULL &&
240 Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
241 {
242 DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
243 Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit);
244 ExceptionNr = 12;
245 }
246
247 /*
248 * Print out the CPU registers
249 */
250 if (ExceptionNr < ARRAY_SIZE(ExceptionTypeStrings))
251 {
252 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
253 ExceptionNr, 0);
254 }
255 else
256 {
257 DbgPrint("Exception: %d(%x)\n", ExceptionNr, 0);
258 }
259 DbgPrint("CS:EIP %x:%x ", OldTss->Cs, OldTss->Eip);
260 KeRosPrintAddress((PVOID)OldTss->Eip);
261 DbgPrint("\n");
262 DbgPrint("cr2 %x cr3 %x ", cr2, OldCr3);
263 DbgPrint("Proc: %x ",PsGetCurrentProcess());
264 if (PsGetCurrentProcess() != NULL)
265 {
266 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
267 DbgPrint("%.16s> ", PsGetCurrentProcess()->ImageFileName);
268 }
269 if (PsGetCurrentThread() != NULL)
270 {
271 DbgPrint("Thrd: %x Tid: %x",
272 PsGetCurrentThread(),
273 PsGetCurrentThread()->Cid.UniqueThread);
274 }
275 DbgPrint("\n");
276 DbgPrint("DS %x ES %x FS %x GS %x\n", OldTss->Ds, OldTss->Es,
277 OldTss->Fs, OldTss->Gs);
278 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", OldTss->Eax, OldTss->Ebx,
279 OldTss->Ecx);
280 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\nESP: %.8x ", OldTss->Edx,
281 OldTss->Ebp, OldTss->Esi, Esp0);
282 DbgPrint("EDI: %.8x EFLAGS: %.8x ", OldTss->Edi, OldTss->Eflags);
283 if (OldTss->Cs == KGDT_R0_CODE)
284 {
285 DbgPrint("kESP %.8x ", Esp0);
286 if (PsGetCurrentThread() != NULL)
287 {
288 DbgPrint("kernel stack base %x\n",
289 PsGetCurrentThread()->Tcb.StackLimit);
290
291 }
292 }
293 else
294 {
295 DbgPrint("User ESP %.8x\n", OldTss->Esp);
296 }
297 if ((OldTss->Cs & 0xffff) == KGDT_R0_CODE)
298 {
299 if (PsGetCurrentThread() != NULL)
300 {
301 StackLimit = (ULONG)PsGetCurrentThread()->Tcb.StackBase;
302 StackBase = (ULONG)PsGetCurrentThread()->Tcb.StackLimit;
303 }
304 else
305 {
306 StackLimit = (ULONG)init_stack_top;
307 StackBase = (ULONG)init_stack;
308 }
309
310 /*
311 Change to an #if 0 to reduce the amount of information printed on
312 a recursive stack trace.
313 */
314 #if 1
315 DbgPrint("Frames: ");
316 Frame = (PULONG)OldTss->Ebp;
317 while (Frame != NULL && (ULONG)Frame >= StackBase)
318 {
319 KeRosPrintAddress((PVOID)Frame[1]);
320 Frame = (PULONG)Frame[0];
321 DbgPrint("\n");
322 }
323 #else
324 DbgPrint("Frames: ");
325 i = 0;
326 Frame = (PULONG)OldTss->Ebp;
327 while (Frame != NULL && (ULONG)Frame >= StackBase)
328 {
329 StackTrace[i] = (PVOID)Frame[1];
330 Frame = (PULONG)Frame[0];
331 i++;
332 }
333 TraceLength = i;
334
335 i = 0;
336 while (i < TraceLength)
337 {
338 StackRepeatCount[i] = 0;
339 j = i + 1;
340 FoundRepeat = FALSE;
341 while ((j - i) <= (TraceLength - j) && FoundRepeat == FALSE)
342 {
343 if (memcmp(&StackTrace[i], &StackTrace[j],
344 (j - i) * sizeof(PVOID)) == 0)
345 {
346 StackRepeatCount[i] = 2;
347 StackRepeatLength[i] = j - i;
348 FoundRepeat = TRUE;
349 }
350 else
351 {
352 j++;
353 }
354 }
355 if (FoundRepeat == FALSE)
356 {
357 i++;
358 continue;
359 }
360 j = j + StackRepeatLength[i];
361 while ((TraceLength - j) >= StackRepeatLength[i] &&
362 FoundRepeat == TRUE)
363 {
364 if (memcmp(&StackTrace[i], &StackTrace[j],
365 StackRepeatLength[i] * sizeof(PVOID)) == 0)
366 {
367 StackRepeatCount[i]++;
368 j = j + StackRepeatLength[i];
369 }
370 else
371 {
372 FoundRepeat = FALSE;
373 }
374 }
375 i = j;
376 }
377
378 i = 0;
379 while (i < TraceLength)
380 {
381 if (StackRepeatCount[i] == 0)
382 {
383 KeRosPrintAddress(StackTrace[i]);
384 i++;
385 }
386 else
387 {
388 DbgPrint("{");
389 if (StackRepeatLength[i] == 0)
390 {
391 for(;;);
392 }
393 for (j = 0; j < StackRepeatLength[i]; j++)
394 {
395 KeRosPrintAddress(StackTrace[i + j]);
396 }
397 DbgPrint("}*%d", StackRepeatCount[i]);
398 i = i + StackRepeatLength[i] * StackRepeatCount[i];
399 }
400 }
401 #endif
402 }
403 #endif
404 DbgPrint("\n");
405 for(;;);
406 }
407
408 VOID
409 NTAPI
410 KiDumpTrapFrame(PKTRAP_FRAME Tf, ULONG Parameter1, ULONG Parameter2)
411 {
412 ULONG cr3_;
413 ULONG StackLimit;
414 ULONG Esp0;
415 ULONG ExceptionNr = (ULONG)Tf->DbgArgMark;
416 ULONG cr2 = (ULONG)Tf->DbgArgPointer;
417
418 Esp0 = (ULONG)Tf;
419
420 /*
421 * Print out the CPU registers
422 */
423 if (ExceptionNr < ARRAY_SIZE(ExceptionTypeStrings))
424 {
425 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
426 ExceptionNr, Tf->ErrCode&0xffff);
427 }
428 else
429 {
430 DbgPrint("Exception: %d(%x)\n", ExceptionNr, Tf->ErrCode&0xffff);
431 }
432 DbgPrint("Processor: %d CS:EIP %x:%x ", KeGetCurrentProcessorNumber(),
433 Tf->SegCs&0xffff, Tf->Eip);
434 KeRosPrintAddress((PVOID)Tf->Eip);
435 DbgPrint("\n");
436 Ke386GetPageTableDirectory(cr3_);
437 DbgPrint("cr2 %x cr3 %x ", cr2, cr3_);
438 DbgPrint("Proc: %x ",PsGetCurrentProcess());
439 if (PsGetCurrentProcess() != NULL)
440 {
441 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
442 DbgPrint("%.16s> ", PsGetCurrentProcess()->ImageFileName);
443 }
444 if (PsGetCurrentThread() != NULL)
445 {
446 DbgPrint("Thrd: %x Tid: %x",
447 PsGetCurrentThread(),
448 PsGetCurrentThread()->Cid.UniqueThread);
449 }
450 DbgPrint("\n");
451 DbgPrint("DS %x ES %x FS %x GS %x\n", Tf->SegDs&0xffff, Tf->SegEs&0xffff,
452 Tf->SegFs&0xffff, Tf->SegGs&0xfff);
453 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", Tf->Eax, Tf->Ebx, Tf->Ecx);
454 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x ESP: %.8x\n", Tf->Edx,
455 Tf->Ebp, Tf->Esi, Esp0);
456 DbgPrint("EDI: %.8x EFLAGS: %.8x ", Tf->Edi, Tf->EFlags);
457 if ((Tf->SegCs&0xffff) == KGDT_R0_CODE)
458 {
459 DbgPrint("kESP %.8x ", Esp0);
460 if (PsGetCurrentThread() != NULL)
461 {
462 DbgPrint("kernel stack base %x\n",
463 PsGetCurrentThread()->Tcb.StackLimit);
464
465 }
466 }
467
468 if (PsGetCurrentThread() != NULL)
469 {
470 StackLimit = (ULONG)PsGetCurrentThread()->Tcb.StackBase;
471 }
472 else
473 {
474 StackLimit = (ULONG)init_stack_top;
475 }
476
477 /*
478 * Dump the stack frames
479 */
480 KeDumpStackFrames((PULONG)Tf->Ebp);
481 }
482
483 ULONG
484 KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
485 /*
486 * FUNCTION: Called by the lowlevel execption handlers to print an amusing
487 * message and halt the computer
488 * ARGUMENTS:
489 * Complete CPU context
490 */
491 {
492 ULONG_PTR cr2;
493 NTSTATUS Status;
494 ULONG Esp0;
495
496 ASSERT(ExceptionNr != 14);
497
498 /* Store the exception number in an unused field in the trap frame. */
499 Tf->DbgArgMark = ExceptionNr;
500
501 /* Use the address of the trap frame as approximation to the ring0 esp */
502 Esp0 = (ULONG)&Tf->Eip;
503
504 /* Get CR2 */
505 cr2 = Ke386GetCr2();
506 Tf->DbgArgPointer = cr2;
507
508 /*
509 * If this was a V86 mode exception then handle it specially
510 */
511 if (Tf->EFlags & (1 << 17))
512 {
513 DPRINT("Tf->Eflags, %x, Tf->Eip %x, ExceptionNr: %d\n", Tf->EFlags, Tf->Eip, ExceptionNr);
514 return(KeV86Exception(ExceptionNr, Tf, cr2));
515 }
516
517 /*
518 * Check for stack underflow, this may be obsolete
519 */
520 if (PsGetCurrentThread() != NULL &&
521 Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
522 {
523 DPRINT1("Stack underflow (tf->esp %x Limit %x Eip %x)\n",
524 Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit, Tf->Eip);
525 ExceptionNr = 12;
526 }
527
528 if (ExceptionNr == 15)
529 {
530 /*
531 * FIXME:
532 * This exception should never occur. The P6 has a bug, which does sometimes deliver
533 * the apic spurious interrupt as exception 15. On an athlon64, I get one exception
534 * in the early boot phase in apic mode (using the smp build). I've looked to the linux
535 * sources. Linux does ignore this exception.
536 *
537 * Hartmut Birr
538 */
539 DPRINT1("Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
540 return(0);
541 }
542
543 /*
544 * Check for a breakpoint that was only for the attention of the debugger.
545 */
546 if (ExceptionNr == 3 && Tf->Eip == ((ULONG)DbgBreakPointNoBugCheck) + 1)
547 {
548 /*
549 EIP is already adjusted by the processor to point to the instruction
550 after the breakpoint.
551 */
552 return(0);
553 }
554
555 /*
556 * Try to handle device-not-present, math-fault and xmm-fault exceptions.
557 */
558 if (ExceptionNr == 7 || ExceptionNr == 16 || ExceptionNr == 19)
559 {
560 Status = KiHandleFpuFault(Tf, ExceptionNr);
561 if (NT_SUCCESS(Status))
562 {
563 return(0);
564 }
565 }
566
567 /*
568 * Handle user exceptions differently
569 */
570 if ((Tf->SegCs & 0xFFFF) == (KGDT_R3_CODE | RPL_MASK))
571 {
572 return(KiUserTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
573 }
574 else
575 {
576 return(KiKernelTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
577 }
578 }
579
580 ULONG
581 NTAPI
582 KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
583 {
584 /* Check if this is user-mode or V86 */
585 if ((TrapFrame->SegCs & MODE_MASK) || (TrapFrame->EFlags & X86_EFLAGS_VM))
586 {
587 /* Return it directly */
588 return TrapFrame->HardwareEsp;
589 }
590 else
591 {
592 /* Edited frame */
593 if (!(TrapFrame->SegCs & FRAME_EDITED))
594 {
595 /* Return edited value */
596 return TrapFrame->TempEsp;
597 }
598 else
599 {
600 /* Virgin frame, calculate */
601 return (ULONG)&TrapFrame->HardwareEsp;
602 }
603 }
604 }
605
606 VOID
607 NTAPI
608 KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame,
609 IN ULONG Esp)
610 {
611 ULONG Previous = KiEspFromTrapFrame(TrapFrame);
612
613 /* Check if this is user-mode or V86 */
614 if ((TrapFrame->SegCs & MODE_MASK) || (TrapFrame->EFlags & X86_EFLAGS_VM))
615 {
616 /* Write it directly */
617 TrapFrame->HardwareEsp = Esp;
618 }
619 else
620 {
621 /* Don't allow ESP to be lowered, this is illegal */
622 if (Esp < Previous)
623 {
624 KeBugCheck(SET_OF_INVALID_CONTEXT);
625 }
626
627 /* Create an edit frame, check if it was alrady */
628 if (!(TrapFrame->SegCs & FRAME_EDITED))
629 {
630 /* Update the value */
631 TrapFrame->TempEsp = Esp;
632 }
633 else
634 {
635 /* Check if ESP changed */
636 if (Previous != Esp)
637 {
638 /* Save CS */
639 TrapFrame->TempSegCs = TrapFrame->SegCs;
640 TrapFrame->SegCs &= ~FRAME_EDITED;
641
642 /* Save ESP */
643 TrapFrame->TempEsp = Esp;
644 }
645 }
646 }
647 }
648
649 ULONG
650 NTAPI
651 KiSsFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
652 {
653 /* If this was V86 Mode */
654 if (TrapFrame->EFlags & X86_EFLAGS_VM)
655 {
656 /* Just return it */
657 return TrapFrame->HardwareSegSs;
658 }
659 else if (TrapFrame->SegCs & MODE_MASK)
660 {
661 /* Usermode, return the User SS */
662 return TrapFrame->HardwareSegSs | RPL_MASK;
663 }
664 else
665 {
666 /* Kernel mode */
667 return KGDT_R0_DATA;
668 }
669 }
670
671 VOID
672 NTAPI
673 KiSsToTrapFrame(IN PKTRAP_FRAME TrapFrame,
674 IN ULONG Ss)
675 {
676 /* Remove the high-bits */
677 Ss &= 0xFFFF;
678
679 /* If this was V86 Mode */
680 if (TrapFrame->EFlags & X86_EFLAGS_VM)
681 {
682 /* Just write it */
683 TrapFrame->HardwareSegSs = Ss;
684 }
685 else if (TrapFrame->SegCs & MODE_MASK)
686 {
687 /* Usermode, save the User SS */
688 TrapFrame->HardwareSegSs = Ss | RPL_MASK;
689 }
690 }
691
692 BOOLEAN
693 NTAPI
694 KeContextToTrapFrame(IN PCONTEXT Context,
695 IN OUT PKEXCEPTION_FRAME ExceptionFrame,
696 IN OUT PKTRAP_FRAME TrapFrame,
697 IN KPROCESSOR_MODE PreviousMode)
698 {
699 BOOLEAN V86Switch = FALSE;
700
701 /* Start with the basic Registers */
702 if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
703 {
704 /* Check if we went through a V86 switch */
705 if ((Context->EFlags & X86_EFLAGS_VM) !=
706 (TrapFrame->EFlags & X86_EFLAGS_VM))
707 {
708 /* We did, remember this for later */
709 V86Switch = TRUE;
710 }
711
712 /* Copy EFLAGS. FIXME: Needs to be sanitized */
713 TrapFrame->EFlags = Context->EFlags;
714
715 /* Copy EBP and EIP */
716 TrapFrame->Ebp = Context->Ebp;
717 TrapFrame->Eip = Context->Eip;
718
719 /* Check if we were in V86 Mode */
720 if (TrapFrame->EFlags & X86_EFLAGS_VM)
721 {
722 /* Simply copy the CS value */
723 TrapFrame->SegCs = Context->SegCs;
724 }
725 else
726 {
727 /* We weren't in V86, so sanitize the CS (FIXME!) */
728 TrapFrame->SegCs = Context->SegCs;
729
730 /* Don't let it under 8, that's invalid */
731 if ((PreviousMode != KernelMode) && (TrapFrame->SegCs < 8))
732 {
733 /* Force it to User CS */
734 TrapFrame->SegCs = (KGDT_R3_CODE | RPL_MASK);
735 }
736 }
737
738 /* Handle SS Specially for validation */
739 KiSsToTrapFrame(TrapFrame, Context->SegSs);
740
741 /* Write ESP back; take into account Edited Trap Frames */
742 KiEspToTrapFrame(TrapFrame, Context->Esp);
743
744 /* Handle our V86 Bias if we went through a switch */
745 if (V86Switch) Ki386AdjustEsp0(TrapFrame);
746 }
747
748 /* Process the Integer Registers */
749 if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
750 {
751 TrapFrame->Eax = Context->Eax;
752 TrapFrame->Ebx = Context->Ebx;
753 TrapFrame->Ecx = Context->Ecx;
754 TrapFrame->Edx = Context->Edx;
755 TrapFrame->Esi = Context->Esi;
756 TrapFrame->Edi = Context->Edi;
757 }
758
759 /* Process the Context Segments */
760 if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
761 {
762 /* Check if we were in V86 Mode */
763 if (TrapFrame->EFlags & X86_EFLAGS_VM)
764 {
765 /* Copy the V86 Segments directlry */
766 TrapFrame->V86Ds = Context->SegDs;
767 TrapFrame->V86Es = Context->SegEs;
768 TrapFrame->V86Fs = Context->SegFs;
769 TrapFrame->V86Gs = Context->SegGs;
770 }
771 else if (!(TrapFrame->SegCs & MODE_MASK))
772 {
773 /* For user mode, write the values directly */
774 TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK;
775 TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK;
776 TrapFrame->SegFs = Context->SegFs;
777 TrapFrame->SegGs = 0;
778 }
779 else
780 {
781 /* For kernel-mode, return the values */
782 TrapFrame->SegDs = Context->SegDs;
783 TrapFrame->SegEs = Context->SegEs;
784 TrapFrame->SegFs = Context->SegFs;
785
786 /* Handle GS specially */
787 if (TrapFrame->SegCs == (KGDT_R3_CODE | RPL_MASK))
788 {
789 /* Don't use it, if user */
790 TrapFrame->SegGs = 0;
791 }
792 else
793 {
794 /* Copy it if kernel */
795 TrapFrame->SegGs = Context->SegGs;
796 }
797 }
798 }
799
800 /* Handle the Debug Registers */
801 if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
802 {
803 /* FIXME: All these should be sanitized */
804 TrapFrame->Dr0 = Context->Dr0;
805 TrapFrame->Dr1 = Context->Dr1;
806 TrapFrame->Dr2 = Context->Dr2;
807 TrapFrame->Dr3 = Context->Dr3;
808 TrapFrame->Dr6 = Context->Dr6;
809 TrapFrame->Dr7 = Context->Dr7;
810
811 /* Check if usermode */
812 if (PreviousMode != KernelMode)
813 {
814 /* Set the Debug Flag */
815 KeGetCurrentThread()->DispatcherHeader.DebugActive = (Context->Dr7 & DR7_ACTIVE);
816 }
817 }
818
819 /* Handle FPU and Extended Registers */
820 return KiContextToFxSaveArea((PFX_SAVE_AREA)(TrapFrame + 1), Context);
821 }
822
823 VOID
824 NTAPI
825 KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
826 IN PKEXCEPTION_FRAME ExceptionFrame,
827 IN OUT PCONTEXT Context)
828 {
829 PFX_SAVE_AREA FxSaveArea = NULL;
830
831 /* Start with the Control flags */
832 if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
833 {
834 /* EBP, EIP and EFLAGS */
835 Context->Ebp = TrapFrame->Ebp;
836 Context->Eip = TrapFrame->Eip;
837 Context->EFlags = TrapFrame->EFlags;
838
839 /* Return the correct CS */
840 if (!(TrapFrame->SegCs & FRAME_EDITED) &&
841 !(TrapFrame->EFlags & X86_EFLAGS_VM))
842 {
843 /* Get it from the Temp location */
844 Context->SegCs = TrapFrame->TempSegCs & 0xFFFF;
845 }
846 else
847 {
848 /* Return it directly */
849 Context->SegCs = TrapFrame->SegCs & 0xFFFF;
850 }
851
852 /* Get the Ss and ESP */
853 Context->SegSs = KiSsFromTrapFrame(TrapFrame);
854 Context->Esp = KiEspFromTrapFrame(TrapFrame);
855 }
856
857 /* Handle the Segments */
858 if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
859 {
860 /* Do V86 Mode first */
861 if (TrapFrame->EFlags & X86_EFLAGS_VM)
862 {
863 /* Return from the V86 location */
864 Context->SegGs = TrapFrame->V86Gs & 0xFFFF;
865 Context->SegFs = TrapFrame->V86Fs & 0xFFFF;
866 Context->SegEs = TrapFrame->V86Es & 0xFFFF;
867 Context->SegDs = TrapFrame->V86Ds & 0xFFFF;
868 }
869 else
870 {
871 /* Check if this was a Kernel Trap */
872 if (TrapFrame->SegCs == KGDT_R0_CODE)
873 {
874 /* Set valid selectors */
875 TrapFrame->SegGs = 0;
876 TrapFrame->SegFs = KGDT_R0_PCR;
877 TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK;
878 TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK;
879 }
880
881 /* Return the segments */
882 Context->SegGs = TrapFrame->SegGs & 0xFFFF;
883 Context->SegFs = TrapFrame->SegFs & 0xFFFF;
884 Context->SegEs = TrapFrame->SegEs & 0xFFFF;
885 Context->SegDs = TrapFrame->SegDs & 0xFFFF;
886 }
887 }
888
889 /* Handle the simple registers */
890 if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
891 {
892 /* Return them directly */
893 Context->Eax = TrapFrame->Eax;
894 Context->Ebx = TrapFrame->Ebx;
895 Context->Ecx = TrapFrame->Ecx;
896 Context->Edx = TrapFrame->Edx;
897 Context->Esi = TrapFrame->Esi;
898 Context->Edi = TrapFrame->Edi;
899 }
900
901 if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
902 {
903 /*
904 * FIXME: Implement this case
905 */
906 Context->ContextFlags &= (~CONTEXT_DEBUG_REGISTERS) | CONTEXT_i386;
907 }
908 if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
909 {
910 FxSaveArea = KiGetFpuState(KeGetCurrentThread());
911 if (FxSaveArea != NULL)
912 {
913 KiFxSaveAreaToFloatingSaveArea(&Context->FloatSave, FxSaveArea);
914 }
915 else
916 {
917 Context->ContextFlags &= (~CONTEXT_FLOATING_POINT) | CONTEXT_i386;
918 }
919 }
920 if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
921 {
922 if (FxSaveArea == NULL)
923 FxSaveArea = KiGetFpuState(KeGetCurrentThread());
924 if (FxSaveArea != NULL)
925 {
926 memcpy(Context->ExtendedRegisters, &FxSaveArea->U.FxArea,
927 min(sizeof (Context->ExtendedRegisters), sizeof (FxSaveArea->U.FxArea)) );
928 }
929 else
930 {
931 Context->ContextFlags &= (~CONTEXT_EXTENDED_REGISTERS) | CONTEXT_i386;
932 }
933 }
934 }
935
936 VOID
937 NTAPI
938 KeDumpStackFrames(PULONG Frame)
939 {
940 PULONG StackBase, StackEnd;
941 MEMORY_BASIC_INFORMATION mbi;
942 ULONG ResultLength = sizeof(mbi);
943 NTSTATUS Status;
944
945 DbgPrint("Frames:\n");
946 _SEH_TRY
947 {
948 Status = MiQueryVirtualMemory (
949 (HANDLE)-1,
950 Frame,
951 MemoryBasicInformation,
952 &mbi,
953 sizeof(mbi),
954 &ResultLength );
955 if ( !NT_SUCCESS(Status) )
956 {
957 DPRINT1("Can't dump stack frames: MiQueryVirtualMemory() failed: %x\n", Status );
958 return;
959 }
960
961 StackBase = Frame;
962 StackEnd = (PULONG)((ULONG_PTR)mbi.BaseAddress + mbi.RegionSize);
963
964 while ( Frame >= StackBase && Frame < StackEnd )
965 {
966 ULONG Addr = Frame[1];
967 if (!KeRosPrintAddress((PVOID)Addr))
968 DbgPrint("<%X>", Addr);
969 if ( Addr == 0 || Addr == 0xDEADBEEF )
970 break;
971 StackBase = Frame;
972 Frame = (PULONG)Frame[0];
973 DbgPrint("\n");
974 }
975 }
976 _SEH_HANDLE
977 {
978 }
979 _SEH_END;
980 DbgPrint("\n");
981 }
982
983 VOID STDCALL
984 KeRosDumpStackFrames ( PULONG Frame, ULONG FrameCount )
985 {
986 ULONG i=0;
987 PULONG StackBase, StackEnd;
988 MEMORY_BASIC_INFORMATION mbi;
989 ULONG ResultLength = sizeof(mbi);
990 NTSTATUS Status;
991
992 DbgPrint("Frames: ");
993 _SEH_TRY
994 {
995 if ( !Frame )
996 {
997 #if defined __GNUC__
998 __asm__("mov %%ebp, %0" : "=r" (Frame) : );
999 #elif defined(_MSC_VER)
1000 __asm mov [Frame], ebp
1001 #endif
1002 //Frame = (PULONG)Frame[0]; // step out of KeRosDumpStackFrames
1003 }
1004
1005 Status = MiQueryVirtualMemory (
1006 (HANDLE)-1,
1007 Frame,
1008 MemoryBasicInformation,
1009 &mbi,
1010 sizeof(mbi),
1011 &ResultLength );
1012 if ( !NT_SUCCESS(Status) )
1013 {
1014 DPRINT1("Can't dump stack frames: MiQueryVirtualMemory() failed: %x\n", Status );
1015 return;
1016 }
1017
1018 StackBase = Frame;
1019 StackEnd = (PULONG)((ULONG_PTR)mbi.BaseAddress + mbi.RegionSize);
1020
1021 while ( Frame >= StackBase && Frame < StackEnd && i++ < FrameCount )
1022 {
1023 ULONG Addr = Frame[1];
1024 if (!KeRosPrintAddress((PVOID)Addr))
1025 DbgPrint("<%X>", Addr);
1026 if ( Addr == 0 || Addr == 0xDEADBEEF )
1027 break;
1028 StackBase = Frame;
1029 Frame = (PULONG)Frame[0];
1030 DbgPrint(" ");
1031 }
1032 }
1033 _SEH_HANDLE
1034 {
1035 }
1036 _SEH_END;
1037 DbgPrint("\n");
1038 }
1039
1040 ULONG STDCALL
1041 KeRosGetStackFrames ( PULONG Frames, ULONG FrameCount )
1042 {
1043 ULONG Count = 0;
1044 PULONG StackBase, StackEnd, Frame;
1045 MEMORY_BASIC_INFORMATION mbi;
1046 ULONG ResultLength = sizeof(mbi);
1047 NTSTATUS Status;
1048
1049 _SEH_TRY
1050 {
1051 #if defined __GNUC__
1052 __asm__("mov %%ebp, %0" : "=r" (Frame) : );
1053 #elif defined(_MSC_VER)
1054 __asm mov [Frame], ebp
1055 #endif
1056
1057 Status = MiQueryVirtualMemory (
1058 (HANDLE)-1,
1059 Frame,
1060 MemoryBasicInformation,
1061 &mbi,
1062 sizeof(mbi),
1063 &ResultLength );
1064 if ( !NT_SUCCESS(Status) )
1065 {
1066 DPRINT1("Can't get stack frames: MiQueryVirtualMemory() failed: %x\n", Status );
1067 return 0;
1068 }
1069
1070 StackBase = Frame;
1071 StackEnd = (PULONG)((ULONG_PTR)mbi.BaseAddress + mbi.RegionSize);
1072
1073 while ( Count < FrameCount && Frame >= StackBase && Frame < StackEnd )
1074 {
1075 Frames[Count++] = Frame[1];
1076 StackBase = Frame;
1077 Frame = (PULONG)Frame[0];
1078 }
1079 }
1080 _SEH_HANDLE
1081 {
1082 }
1083 _SEH_END;
1084 return Count;
1085 }
1086
1087 static void
1088 set_system_call_gate(unsigned int sel, unsigned int func)
1089 {
1090 DPRINT("sel %x %d\n",sel,sel);
1091 KiIdt[sel].a = (((int)func)&0xffff) +
1092 (KGDT_R0_CODE << 16);
1093 KiIdt[sel].b = 0xef00 + (((int)func)&0xffff0000);
1094 DPRINT("idt[sel].b %x\n",KiIdt[sel].b);
1095 }
1096
1097 static void set_interrupt_gate(unsigned int sel, unsigned int func)
1098 {
1099 DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel,func);
1100 KiIdt[sel].a = (((int)func)&0xffff) +
1101 (KGDT_R0_CODE << 16);
1102 KiIdt[sel].b = 0x8e00 + (((int)func)&0xffff0000);
1103 }
1104
1105 static void set_trap_gate(unsigned int sel, unsigned int func, unsigned int dpl)
1106 {
1107 DPRINT("set_trap_gate(sel %d, func %x, dpl %d)\n",sel, func, dpl);
1108 ASSERT(dpl <= 3);
1109 KiIdt[sel].a = (((int)func)&0xffff) +
1110 (KGDT_R0_CODE << 16);
1111 KiIdt[sel].b = 0x8f00 + (dpl << 13) + (((int)func)&0xffff0000);
1112 }
1113
1114 static void
1115 set_task_gate(unsigned int sel, unsigned task_sel)
1116 {
1117 KiIdt[sel].a = task_sel << 16;
1118 KiIdt[sel].b = 0x8500;
1119 }
1120
1121 VOID
1122 INIT_FUNCTION
1123 NTAPI
1124 KeInitExceptions(VOID)
1125 /*
1126 * FUNCTION: Initalize CPU exception handling
1127 */
1128 {
1129 int i;
1130
1131 DPRINT("KeInitExceptions()\n");
1132
1133 /*
1134 * Set up the other gates
1135 */
1136 set_trap_gate(0, (ULONG)KiTrap0, 0);
1137 set_trap_gate(1, (ULONG)KiTrap1, 0);
1138 set_trap_gate(2, (ULONG)KiTrap2, 0);
1139 set_trap_gate(3, (ULONG)KiTrap3, 3);
1140 set_trap_gate(4, (ULONG)KiTrap4, 0);
1141 set_trap_gate(5, (ULONG)KiTrap5, 0);
1142 set_trap_gate(6, (ULONG)KiTrap6, 0);
1143 set_trap_gate(7, (ULONG)KiTrap7, 0);
1144 set_task_gate(8, KGDT_DF_TSS);
1145 set_trap_gate(9, (ULONG)KiTrap9, 0);
1146 set_trap_gate(10, (ULONG)KiTrap10, 0);
1147 set_trap_gate(11, (ULONG)KiTrap11, 0);
1148 set_trap_gate(12, (ULONG)KiTrap12, 0);
1149 set_trap_gate(13, (ULONG)KiTrap13, 0);
1150 set_interrupt_gate(14, (ULONG)KiTrap14);
1151 set_trap_gate(15, (ULONG)KiTrap15, 0);
1152 set_trap_gate(16, (ULONG)KiTrap16, 0);
1153 set_trap_gate(17, (ULONG)KiTrap17, 0);
1154 set_trap_gate(18, (ULONG)KiTrap18, 0);
1155 set_trap_gate(19, (ULONG)KiTrap19, 0);
1156
1157 for (i = 20; i < 256; i++)
1158 {
1159 set_trap_gate(i,(int)KiTrapUnknown, 0);
1160 }
1161
1162 set_system_call_gate(0x2d,(int)KiDebugService);
1163 set_system_call_gate(0x2e,(int)KiSystemService);
1164 }
1165
1166 VOID
1167 NTAPI
1168 KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
1169 PKEXCEPTION_FRAME ExceptionFrame,
1170 PKTRAP_FRAME TrapFrame,
1171 KPROCESSOR_MODE PreviousMode,
1172 BOOLEAN FirstChance)
1173 {
1174 CONTEXT Context;
1175 KD_CONTINUE_TYPE Action;
1176 ULONG_PTR Stack, NewStack;
1177 ULONG Size;
1178 BOOLEAN UserDispatch = FALSE;
1179 DPRINT("KiDispatchException() called\n");
1180
1181 /* Increase number of Exception Dispatches */
1182 KeGetCurrentPrcb()->KeExceptionDispatchCount++;
1183
1184 /* Set the context flags */
1185 Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
1186
1187 /* Check if User Mode */
1188 if (PreviousMode == UserMode)
1189 {
1190 extern ULONG FxsrSupport;
1191 /* Add the FPU Flag */
1192 Context.ContextFlags |= CONTEXT_FLOATING_POINT;
1193 if (FxsrSupport)
1194 Context.ContextFlags |= CONTEXT_EXTENDED_REGISTERS;
1195 }
1196
1197 /* Get a Context */
1198 KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
1199
1200 /* Handle kernel-mode first, it's simpler */
1201 if (PreviousMode == KernelMode)
1202 {
1203 /* Check if this is a first-chance exception */
1204 if (FirstChance == TRUE)
1205 {
1206 /* Break into the debugger for the first time */
1207 Action = KdpEnterDebuggerException(ExceptionRecord,
1208 PreviousMode,
1209 &Context,
1210 TrapFrame,
1211 TRUE,
1212 TRUE);
1213
1214 /* If the debugger said continue, then continue */
1215 if (Action == kdContinue) goto Handled;
1216
1217 /* If the Debugger couldn't handle it, dispatch the exception */
1218 if (RtlDispatchException(ExceptionRecord, &Context))
1219 {
1220 /* It was handled by an exception handler, continue */
1221 goto Handled;
1222 }
1223 }
1224
1225 /* This is a second-chance exception, only for the debugger */
1226 Action = KdpEnterDebuggerException(ExceptionRecord,
1227 PreviousMode,
1228 &Context,
1229 TrapFrame,
1230 FALSE,
1231 FALSE);
1232
1233 /* If the debugger said continue, then continue */
1234 if (Action == kdContinue) goto Handled;
1235
1236 /* Third strike; you're out */
1237 KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED,
1238 ExceptionRecord->ExceptionCode,
1239 (ULONG_PTR)ExceptionRecord->ExceptionAddress,
1240 ExceptionRecord->ExceptionInformation[0],
1241 ExceptionRecord->ExceptionInformation[1],
1242 TrapFrame);
1243 }
1244 else
1245 {
1246 /* User mode exception, was it first-chance? */
1247 if (FirstChance)
1248 {
1249 /* Enter Debugger if available */
1250 Action = KdpEnterDebuggerException(ExceptionRecord,
1251 PreviousMode,
1252 &Context,
1253 TrapFrame,
1254 TRUE,
1255 TRUE);
1256
1257 /* Exit if we're continuing */
1258 if (Action == kdContinue) goto Handled;
1259
1260 /* FIXME: Forward exception to user mode debugger */
1261
1262 /* Set up the user-stack */
1263 _SEH_TRY
1264 {
1265 /* Align context size and get stack pointer */
1266 Size = (sizeof(CONTEXT) + 3) & ~3;
1267 Stack = (Context.Esp & ~3) - Size;
1268 DPRINT("Stack: %lx\n", Stack);
1269
1270 /* Probe stack and copy Context */
1271 ProbeForWrite((PVOID)Stack, Size, sizeof(ULONG));
1272 RtlCopyMemory((PVOID)Stack, &Context, sizeof(CONTEXT));
1273
1274 /* Align exception record size and get stack pointer */
1275 Size = (sizeof(EXCEPTION_RECORD) -
1276 (EXCEPTION_MAXIMUM_PARAMETERS - ExceptionRecord->NumberParameters) *
1277 sizeof(ULONG) + 3) & ~3;
1278 NewStack = Stack - Size;
1279 DPRINT("NewStack: %lx\n", NewStack);
1280
1281 /* Probe stack and copy exception record. Don't forget to add the two params */
1282 ProbeForWrite((PVOID)(NewStack - 2 * sizeof(ULONG_PTR)),
1283 Size + 2 * sizeof(ULONG_PTR),
1284 sizeof(ULONG));
1285 RtlCopyMemory((PVOID)NewStack, ExceptionRecord, Size);
1286
1287 /* Now write the two params for the user-mode dispatcher */
1288 *(PULONG_PTR)(NewStack - 1 * sizeof(ULONG_PTR)) = Stack;
1289 *(PULONG_PTR)(NewStack - 2 * sizeof(ULONG_PTR)) = NewStack;
1290
1291 /* Set new Stack Pointer */
1292 KiEspToTrapFrame(TrapFrame, NewStack - 2 * sizeof(ULONG_PTR));
1293
1294 /* Set EIP to the User-mode Dispathcer */
1295 TrapFrame->Eip = (ULONG)KeUserExceptionDispatcher;
1296 UserDispatch = TRUE;
1297 _SEH_LEAVE;
1298 }
1299 _SEH_HANDLE
1300 {
1301 /* Do second-chance */
1302 }
1303 _SEH_END;
1304 }
1305
1306 /* If we dispatch to user, return now */
1307 if (UserDispatch) return;
1308
1309 /* FIXME: Forward the exception to the debugger for 2nd chance */
1310
1311 /* 3rd strike, kill the thread */
1312 DPRINT1("Unhandled UserMode exception, terminating thread\n");
1313 ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
1314 KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED,
1315 ExceptionRecord->ExceptionCode,
1316 (ULONG_PTR)ExceptionRecord->ExceptionAddress,
1317 ExceptionRecord->ExceptionInformation[0],
1318 ExceptionRecord->ExceptionInformation[1],
1319 TrapFrame);
1320 }
1321
1322 Handled:
1323 /* Convert the context back into Trap/Exception Frames */
1324 KeContextToTrapFrame(&Context, NULL, TrapFrame, PreviousMode);
1325 return;
1326 }
1327
1328 /*
1329 * @implemented
1330 */
1331 NTSTATUS STDCALL
1332 KeRaiseUserException(IN NTSTATUS ExceptionCode)
1333 {
1334 ULONG OldEip;
1335 PKTHREAD Thread = KeGetCurrentThread();
1336
1337 _SEH_TRY {
1338 Thread->Teb->ExceptionCode = ExceptionCode;
1339 } _SEH_HANDLE {
1340 return(ExceptionCode);
1341 } _SEH_END;
1342
1343 OldEip = Thread->TrapFrame->Eip;
1344 Thread->TrapFrame->Eip = (ULONG_PTR)KeRaiseUserExceptionDispatcher;
1345 return((NTSTATUS)OldEip);
1346 }
1347