3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * PROJECT: ReactOS kernel
21 * FILE: ntoskrnl/ke/i386/exp.c
22 * PURPOSE: Handling exceptions
23 * PROGRAMMERS: David Welch (welch@cwcom.net)
24 * Skywing (skywing@valhallalegends.com)
27 * 09/12/03: KeRaiseUserException added (Skywing).
30 /* INCLUDES *****************************************************************/
35 #include <internal/debug.h>
37 /* GLOBALS *****************************************************************/
39 #define FLAG_IF (1<<9)
42 #define STR(x) _STR(x)
45 # define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0]))
48 extern void KiSystemService(void);
49 extern void interrupt_handler2d(void);
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
);
73 extern ULONG init_stack
;
74 extern ULONG init_stack_top
;
76 extern BOOLEAN Ke386NoExecute
;
78 static char *ExceptionTypeStrings
[] =
85 "BOUND range exceeded",
87 "No Math Coprocessor",
91 "Segment Not Present",
92 "Stack Segment Fault",
102 NTSTATUS ExceptionToNtStatus
[] =
104 STATUS_INTEGER_DIVIDE_BY_ZERO
,
106 STATUS_ACCESS_VIOLATION
,
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
,
126 /* FUNCTIONS ****************************************************************/
128 #if defined(DBG) || defined(KDBG)
130 KeRosPrintAddress(PVOID address
)
132 return KdbSymPrintAddress(address
);
136 KeRosPrintAddress(PVOID address
)
138 PLIST_ENTRY current_entry
;
139 MODULE_TEXT_SECTION
* current
;
140 extern LIST_ENTRY ModuleTextListHead
;
141 ULONG_PTR RelativeAddress
;
143 current_entry
= ModuleTextListHead
.Flink
;
145 while (current_entry
!= &ModuleTextListHead
&&
146 current_entry
!= NULL
)
149 CONTAINING_RECORD(current_entry
, MODULE_TEXT_SECTION
, ListEntry
);
151 if (address
>= (PVOID
)current
->Base
&&
152 address
< (PVOID
)(current
->Base
+ current
->Length
))
154 RelativeAddress
= (ULONG_PTR
) address
- current
->Base
;
155 DbgPrint("<%ws: %x>", current
->Name
, RelativeAddress
);
158 current_entry
= current_entry
->Flink
;
165 KiKernelTrapHandler(PKTRAP_FRAME Tf
, ULONG ExceptionNr
, PVOID Cr2
)
169 Er
.ExceptionFlags
= 0;
170 Er
.ExceptionRecord
= NULL
;
171 Er
.ExceptionAddress
= (PVOID
)Tf
->Eip
;
173 if (ExceptionNr
== 14)
175 Er
.ExceptionCode
= STATUS_ACCESS_VIOLATION
;
176 Er
.NumberParameters
= 2;
177 Er
.ExceptionInformation
[0] = Tf
->ErrorCode
& 0x1;
178 Er
.ExceptionInformation
[1] = (ULONG
)Cr2
;
182 if (ExceptionNr
< ARRAY_SIZE(ExceptionToNtStatus
))
184 Er
.ExceptionCode
= ExceptionToNtStatus
[ExceptionNr
];
188 Er
.ExceptionCode
= STATUS_ACCESS_VIOLATION
;
190 Er
.NumberParameters
= 0;
193 /* FIXME: Which exceptions are noncontinuable? */
194 Er
.ExceptionFlags
= 0;
196 KiDispatchException(&Er
, 0, Tf
, KernelMode
, TRUE
);
202 KiDoubleFaultHandler(VOID
)
208 ULONG ExceptionNr
= 8;
214 static PVOID StackTrace
[MM_STACK_SIZE
/ sizeof(PVOID
)];
215 static ULONG StackRepeatCount
[MM_STACK_SIZE
/ sizeof(PVOID
)];
216 static ULONG StackRepeatLength
[MM_STACK_SIZE
/ sizeof(PVOID
)];
221 OldTss
= KeGetCurrentKPCR()->TSS
;
226 if (PsGetCurrentThread() != NULL
&&
227 PsGetCurrentThread()->ThreadsProcess
!= NULL
)
230 PsGetCurrentThread()->ThreadsProcess
->Pcb
.DirectoryTableBase
.QuadPart
;
238 * Check for stack underflow
240 if (PsGetCurrentThread() != NULL
&&
241 Esp0
< (ULONG
)PsGetCurrentThread()->Tcb
.StackLimit
)
243 DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
244 Esp0
, (ULONG
)PsGetCurrentThread()->Tcb
.StackLimit
);
249 * Print out the CPU registers
251 if (ExceptionNr
< ARRAY_SIZE(ExceptionTypeStrings
))
253 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings
[ExceptionNr
],
258 DbgPrint("Exception: %d(%x)\n", ExceptionNr
, 0);
260 DbgPrint("CS:EIP %x:%x ", OldTss
->Cs
, OldTss
->Eip
);
261 KeRosPrintAddress((PVOID
)OldTss
->Eip
);
263 DbgPrint("cr2 %x cr3 %x ", cr2
, OldCr3
);
264 DbgPrint("Proc: %x ",PsGetCurrentProcess());
265 if (PsGetCurrentProcess() != NULL
)
267 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId
);
268 DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName
);
270 if (PsGetCurrentThread() != NULL
)
272 DbgPrint("Thrd: %x Tid: %x",
273 PsGetCurrentThread(),
274 PsGetCurrentThread()->Cid
.UniqueThread
);
277 DbgPrint("DS %x ES %x FS %x GS %x\n", OldTss
->Ds
, OldTss
->Es
,
278 OldTss
->Fs
, OldTss
->Gs
);
279 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", OldTss
->Eax
, OldTss
->Ebx
,
281 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n ESP: %.8x", OldTss
->Edx
,
282 OldTss
->Ebp
, OldTss
->Esi
, Esp0
);
283 DbgPrint("EDI: %.8x EFLAGS: %.8x ", OldTss
->Edi
, OldTss
->Eflags
);
284 if (OldTss
->Cs
== KERNEL_CS
)
286 DbgPrint("kESP %.8x ", Esp0
);
287 if (PsGetCurrentThread() != NULL
)
289 DbgPrint("kernel stack base %x\n",
290 PsGetCurrentThread()->Tcb
.StackLimit
);
296 DbgPrint("User ESP %.8x\n", OldTss
->Esp
);
298 if ((OldTss
->Cs
& 0xffff) == KERNEL_CS
)
300 if (PsGetCurrentThread() != NULL
)
302 StackLimit
= (ULONG
)PsGetCurrentThread()->Tcb
.StackBase
;
303 StackBase
= (ULONG
)PsGetCurrentThread()->Tcb
.StackLimit
;
307 StackLimit
= (ULONG
)&init_stack_top
;
308 StackBase
= (ULONG
)&init_stack
;
312 Change to an #if 0 to reduce the amount of information printed on
313 a recursive stack trace.
316 DbgPrint("Frames: ");
317 Frame
= (PULONG
)OldTss
->Ebp
;
318 while (Frame
!= NULL
&& (ULONG
)Frame
>= StackBase
)
320 KeRosPrintAddress((PVOID
)Frame
[1]);
321 Frame
= (PULONG
)Frame
[0];
325 DbgPrint("Frames: ");
327 Frame
= (PULONG
)OldTss
->Ebp
;
328 while (Frame
!= NULL
&& (ULONG
)Frame
>= StackBase
)
330 StackTrace
[i
] = (PVOID
)Frame
[1];
331 Frame
= (PULONG
)Frame
[0];
337 while (i
< TraceLength
)
339 StackRepeatCount
[i
] = 0;
342 while ((j
- i
) <= (TraceLength
- j
) && FoundRepeat
== FALSE
)
344 if (memcmp(&StackTrace
[i
], &StackTrace
[j
],
345 (j
- i
) * sizeof(PVOID
)) == 0)
347 StackRepeatCount
[i
] = 2;
348 StackRepeatLength
[i
] = j
- i
;
356 if (FoundRepeat
== FALSE
)
361 j
= j
+ StackRepeatLength
[i
];
362 while ((TraceLength
- j
) >= StackRepeatLength
[i
] &&
365 if (memcmp(&StackTrace
[i
], &StackTrace
[j
],
366 StackRepeatLength
[i
] * sizeof(PVOID
)) == 0)
368 StackRepeatCount
[i
]++;
369 j
= j
+ StackRepeatLength
[i
];
380 while (i
< TraceLength
)
382 if (StackRepeatCount
[i
] == 0)
384 KeRosPrintAddress(StackTrace
[i
]);
390 if (StackRepeatLength
[i
] == 0)
394 for (j
= 0; j
< StackRepeatLength
[i
]; j
++)
396 KeRosPrintAddress(StackTrace
[i
+ j
]);
398 DbgPrint("}*%d", StackRepeatCount
[i
]);
399 i
= i
+ StackRepeatLength
[i
] * StackRepeatCount
[i
];
411 KiDumpTrapFrame(PKTRAP_FRAME Tf
, ULONG Parameter1
, ULONG Parameter2
)
418 ULONG ExceptionNr
= (ULONG
)Tf
->DebugArgMark
;
419 ULONG cr2
= (ULONG
)Tf
->DebugPointer
;
424 * Print out the CPU registers
426 if (ExceptionNr
< ARRAY_SIZE(ExceptionTypeStrings
))
428 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings
[ExceptionNr
],
429 ExceptionNr
, Tf
->ErrorCode
&0xffff);
433 DbgPrint("Exception: %d(%x)\n", ExceptionNr
, Tf
->ErrorCode
&0xffff);
435 DbgPrint("Processor: %d CS:EIP %x:%x ", KeGetCurrentProcessorNumber(),
436 Tf
->Cs
&0xffff, Tf
->Eip
);
437 KeRosPrintAddress((PVOID
)Tf
->Eip
);
439 Ke386GetPageTableDirectory(cr3_
);
440 DbgPrint("cr2 %x cr3 %x ", cr2
, cr3_
);
441 DbgPrint("Proc: %x ",PsGetCurrentProcess());
442 if (PsGetCurrentProcess() != NULL
)
444 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId
);
445 DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName
);
447 if (PsGetCurrentThread() != NULL
)
449 DbgPrint("Thrd: %x Tid: %x",
450 PsGetCurrentThread(),
451 PsGetCurrentThread()->Cid
.UniqueThread
);
454 DbgPrint("DS %x ES %x FS %x GS %x\n", Tf
->Ds
&0xffff, Tf
->Es
&0xffff,
455 Tf
->Fs
&0xffff, Tf
->Gs
&0xfff);
456 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", Tf
->Eax
, Tf
->Ebx
, Tf
->Ecx
);
457 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x ESP: %.8x\n", Tf
->Edx
,
458 Tf
->Ebp
, Tf
->Esi
, Esp0
);
459 DbgPrint("EDI: %.8x EFLAGS: %.8x ", Tf
->Edi
, Tf
->Eflags
);
460 if ((Tf
->Cs
&0xffff) == KERNEL_CS
)
462 DbgPrint("kESP %.8x ", Esp0
);
463 if (PsGetCurrentThread() != NULL
)
465 DbgPrint("kernel stack base %x\n",
466 PsGetCurrentThread()->Tcb
.StackLimit
);
471 if (PsGetCurrentThread() != NULL
)
473 StackLimit
= (ULONG
)PsGetCurrentThread()->Tcb
.StackBase
;
477 StackLimit
= (ULONG
)&init_stack_top
;
481 * Dump the stack frames
483 DbgPrint("Frames: ");
484 /* Change to an #if 0 if no frames are printed because of fpo. */
487 Frame
= (PULONG
)Tf
->Ebp
;
488 while (Frame
!= NULL
)
492 Status
= MmSafeCopyFromUser(&Eip
, Frame
+ 1, sizeof(Eip
));
493 if (!NT_SUCCESS(Status
))
495 DbgPrint("<INVALID>");
498 if (!KeRosPrintAddress(Eip
))
500 DbgPrint("<%X>", Eip
);
502 Status
= MmSafeCopyFromUser(&Frame
, Frame
, sizeof(Frame
));
503 if (!NT_SUCCESS(Status
))
512 Frame
= (PULONG
)((ULONG_PTR
)Esp0
+ KTRAP_FRAME_EFLAGS
);
513 while (Frame
< (PULONG
)PsGetCurrentThread()->Tcb
.StackBase
&& i
< 50)
515 ULONG Address
= *Frame
;
516 if (KeRosPrintAddress((PVOID
)Address
))
526 KiTrapHandler(PKTRAP_FRAME Tf
, ULONG ExceptionNr
)
528 * FUNCTION: Called by the lowlevel execption handlers to print an amusing
529 * message and halt the computer
531 * Complete CPU context
538 /* Store the exception number in an unused field in the trap frame. */
539 Tf
->DebugArgMark
= (PVOID
)ExceptionNr
;
541 /* Use the address of the trap frame as approximation to the ring0 esp */
542 Esp0
= (ULONG
)&Tf
->Eip
;
546 Tf
->DebugPointer
= (PVOID
)cr2
;
548 if (ExceptionNr
== 14 && Tf
->Eflags
& FLAG_IF
)
550 Ke386EnableInterrupts();
554 * If this was a V86 mode exception then handle it specially
556 if (Tf
->Eflags
& (1 << 17))
558 return(KeV86Exception(ExceptionNr
, Tf
, cr2
));
562 * Check for stack underflow, this may be obsolete
564 if (PsGetCurrentThread() != NULL
&&
565 Esp0
< (ULONG
)PsGetCurrentThread()->Tcb
.StackLimit
)
567 DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
568 Esp0
, (ULONG
)PsGetCurrentThread()->Tcb
.StackLimit
);
573 * Maybe handle the page fault and return
575 if (ExceptionNr
== 14)
577 if (Ke386NoExecute
&& Tf
->ErrorCode
& 0x10 && cr2
>= KERNEL_BASE
)
579 KEBUGCHECKWITHTF(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY
, 0, 0, 0, 0, Tf
);
581 Status
= MmPageFault(Tf
->Cs
&0xffff,
586 if (NT_SUCCESS(Status
))
593 * Check for a breakpoint that was only for the attention of the debugger.
595 if (ExceptionNr
== 3 && Tf
->Eip
== ((ULONG
)DbgBreakPointNoBugCheck
) + 1)
598 EIP is already adjusted by the processor to point to the instruction
599 after the breakpoint.
605 * Try to handle device-not-present, math-fault and xmm-fault exceptions.
607 if (ExceptionNr
== 7 || ExceptionNr
== 16 || ExceptionNr
== 19)
609 Status
= KiHandleFpuFault(Tf
, ExceptionNr
);
610 if (NT_SUCCESS(Status
))
617 * Handle user exceptions differently
619 if ((Tf
->Cs
& 0xFFFF) == USER_CS
)
621 return(KiUserTrapHandler(Tf
, ExceptionNr
, (PVOID
)cr2
));
625 return(KiKernelTrapHandler(Tf
, ExceptionNr
, (PVOID
)cr2
));
630 KeDumpStackFrames(PULONG Frame
)
632 PULONG StackBase
, StackEnd
;
633 MEMORY_BASIC_INFORMATION mbi
;
634 ULONG ResultLength
= sizeof(mbi
);
637 DbgPrint("Frames: ");
640 Status
= MiQueryVirtualMemory (
643 MemoryBasicInformation
,
647 if ( !NT_SUCCESS(Status
) )
649 DPRINT1("Can't dump stack frames: NtQueryVirtualMemory() failed: %x\n", Status
);
654 StackEnd
= mbi
.BaseAddress
+ mbi
.RegionSize
;
656 while ( Frame
>= StackBase
&& Frame
< StackEnd
)
658 ULONG Addr
= Frame
[1];
659 if (!KeRosPrintAddress((PVOID
)Addr
))
660 DbgPrint("<%X>", Addr
);
661 if ( Addr
== 0 || Addr
== 0xDEADBEEF )
664 Frame
= (PULONG
)Frame
[0];
676 KeRosDumpStackFrames ( PULONG Frame
, ULONG FrameCount
)
679 PULONG StackBase
, StackEnd
;
680 MEMORY_BASIC_INFORMATION mbi
;
681 ULONG ResultLength
= sizeof(mbi
);
684 DbgPrint("Frames: ");
690 __asm__("mov %%ebp, %%ebx" : "=b" (Frame
) : );
691 #elif defined(_MSC_VER)
692 __asm mov
[Frame
], ebp
694 //Frame = (PULONG)Frame[0]; // step out of KeRosDumpStackFrames
697 Status
= MiQueryVirtualMemory (
700 MemoryBasicInformation
,
704 if ( !NT_SUCCESS(Status
) )
706 DPRINT1("Can't dump stack frames: NtQueryVirtualMemory() failed: %x\n", Status
);
711 StackEnd
= mbi
.BaseAddress
+ mbi
.RegionSize
;
713 while ( Frame
>= StackBase
&& Frame
< StackEnd
&& i
++ < FrameCount
)
715 ULONG Addr
= Frame
[1];
716 if (!KeRosPrintAddress((PVOID
)Addr
))
717 DbgPrint("<%X>", Addr
);
718 if ( Addr
== 0 || Addr
== 0xDEADBEEF )
721 Frame
= (PULONG
)Frame
[0];
733 KeRosGetStackFrames ( PULONG Frames
, ULONG FrameCount
)
736 PULONG StackBase
, StackEnd
, Frame
;
737 MEMORY_BASIC_INFORMATION mbi
;
738 ULONG ResultLength
= sizeof(mbi
);
744 __asm__("mov %%ebp, %%ebx" : "=b" (Frame
) : );
745 #elif defined(_MSC_VER)
746 __asm mov
[Frame
], ebp
749 Status
= MiQueryVirtualMemory (
752 MemoryBasicInformation
,
756 if ( !NT_SUCCESS(Status
) )
758 DPRINT1("Can't get stack frames: NtQueryVirtualMemory() failed: %x\n", Status
);
763 StackEnd
= mbi
.BaseAddress
+ mbi
.RegionSize
;
765 while ( Count
< FrameCount
&& Frame
>= StackBase
&& Frame
< StackEnd
)
767 Frames
[Count
++] = Frame
[1];
769 Frame
= (PULONG
)Frame
[0];
780 set_system_call_gate(unsigned int sel
, unsigned int func
)
782 DPRINT("sel %x %d\n",sel
,sel
);
783 KiIdt
[sel
].a
= (((int)func
)&0xffff) +
785 KiIdt
[sel
].b
= 0xef00 + (((int)func
)&0xffff0000);
786 DPRINT("idt[sel].b %x\n",KiIdt
[sel
].b
);
789 static void set_interrupt_gate(unsigned int sel
, unsigned int func
)
791 DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel
,func
);
792 KiIdt
[sel
].a
= (((int)func
)&0xffff) +
794 KiIdt
[sel
].b
= 0x8e00 + (((int)func
)&0xffff0000);
797 static void set_trap_gate(unsigned int sel
, unsigned int func
, unsigned int dpl
)
799 DPRINT("set_trap_gate(sel %d, func %x, dpl %d)\n",sel
, func
, dpl
);
801 KiIdt
[sel
].a
= (((int)func
)&0xffff) +
803 KiIdt
[sel
].b
= 0x8f00 + (dpl
<< 13) + (((int)func
)&0xffff0000);
807 set_task_gate(unsigned int sel
, unsigned task_sel
)
809 KiIdt
[sel
].a
= task_sel
<< 16;
810 KiIdt
[sel
].b
= 0x8500;
814 KeInitExceptions(VOID
)
816 * FUNCTION: Initalize CPU exception handling
821 DPRINT("KeInitExceptions()\n");
824 * Set up the other gates
826 set_trap_gate(0, (ULONG
)KiTrap0
, 0);
827 set_trap_gate(1, (ULONG
)KiTrap1
, 0);
828 set_trap_gate(2, (ULONG
)KiTrap2
, 0);
829 set_trap_gate(3, (ULONG
)KiTrap3
, 3);
830 set_trap_gate(4, (ULONG
)KiTrap4
, 0);
831 set_trap_gate(5, (ULONG
)KiTrap5
, 0);
832 set_trap_gate(6, (ULONG
)KiTrap6
, 0);
833 set_trap_gate(7, (ULONG
)KiTrap7
, 0);
834 set_task_gate(8, TRAP_TSS_SELECTOR
);
835 set_trap_gate(9, (ULONG
)KiTrap9
, 0);
836 set_trap_gate(10, (ULONG
)KiTrap10
, 0);
837 set_trap_gate(11, (ULONG
)KiTrap11
, 0);
838 set_trap_gate(12, (ULONG
)KiTrap12
, 0);
839 set_trap_gate(13, (ULONG
)KiTrap13
, 0);
840 set_interrupt_gate(14, (ULONG
)KiTrap14
);
841 set_trap_gate(15, (ULONG
)KiTrap15
, 0);
842 set_trap_gate(16, (ULONG
)KiTrap16
, 0);
843 set_trap_gate(17, (ULONG
)KiTrap17
, 0);
844 set_trap_gate(18, (ULONG
)KiTrap18
, 0);
845 set_trap_gate(19, (ULONG
)KiTrap19
, 0);
847 for (i
= 20; i
< 256; i
++)
849 set_trap_gate(i
,(int)KiTrapUnknown
, 0);
852 set_system_call_gate(0x2d,(int)interrupt_handler2d
);
853 set_system_call_gate(0x2e,(int)KiSystemService
);
860 KeRaiseUserException(IN NTSTATUS ExceptionCode
)
863 PKTHREAD Thread
= KeGetCurrentThread();
866 Thread
->Teb
->ExceptionCode
= ExceptionCode
;
868 return(ExceptionCode
);
871 OldEip
= Thread
->TrapFrame
->Eip
;
872 Thread
->TrapFrame
->Eip
= (ULONG_PTR
)LdrpGetSystemDllRaiseExceptionDispatcher();
873 return((NTSTATUS
)OldEip
);
882 IN PEXCEPTION_RECORD ExceptionRecord
,
884 IN BOOLEAN SearchFrames
)
886 PKTHREAD Thread
= KeGetCurrentThread();
887 PKTRAP_FRAME TrapFrame
= Thread
->TrapFrame
;
888 PKTRAP_FRAME PrevTrapFrame
= (PKTRAP_FRAME
)TrapFrame
->Edx
;
890 KeGetCurrentKPCR()->Tib
.ExceptionList
= TrapFrame
->ExceptionList
;
892 KiDispatchException(ExceptionRecord
,
898 /* Restore the user context */
899 Thread
->TrapFrame
= PrevTrapFrame
;
900 __asm__("mov %%ebx, %%esp;\n" "jmp _KiServiceExit": : "b" (TrapFrame
));
902 /* We never get here */
903 return(STATUS_SUCCESS
);