mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
Improve (hardware) exception handling and reporting
svn path=/trunk/; revision=4514
This commit is contained in:
parent
e81de9962d
commit
2602dec603
7 changed files with 118 additions and 112 deletions
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: create.c,v 1.64 2003/03/26 22:11:27 hbirr Exp $
|
/* $Id: create.c,v 1.65 2003/04/07 23:10:07 gvg Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS system libraries
|
* PROJECT: ReactOS system libraries
|
||||||
|
@ -171,29 +171,32 @@ _except_handler(
|
||||||
struct _CONTEXT *ContextRecord,
|
struct _CONTEXT *ContextRecord,
|
||||||
void * DispatcherContext )
|
void * DispatcherContext )
|
||||||
{
|
{
|
||||||
DPRINT("Process terminated abnormally...\n");
|
DPRINT1("Process terminated abnormally due to unhandled exception\n");
|
||||||
|
|
||||||
if (++_except_recursion_trap > 3) {
|
if (3 < ++_except_recursion_trap)
|
||||||
DPRINT("_except_handler(...) appears to be recursing.\n");
|
{
|
||||||
DPRINT("Process HALTED.\n");
|
DPRINT1("_except_handler(...) appears to be recursing.\n");
|
||||||
for (;;) {}
|
DPRINT1("Process HALTED.\n");
|
||||||
}
|
for (;;)
|
||||||
|
|
||||||
if (/* FIXME: */ TRUE) /* Not a service */
|
|
||||||
{
|
{
|
||||||
DPRINT(" calling ExitProcess(0) no, lets try ExitThread . . .\n");
|
|
||||||
//ExitProcess(0);
|
|
||||||
ExitThread(0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DPRINT(" calling ExitThread(0) . . .\n");
|
|
||||||
ExitThread(0);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DPRINT(" We should not get to here !!!\n");
|
if (/* FIXME: */ TRUE) /* Not a service */
|
||||||
/* We should not get to here */
|
{
|
||||||
return ExceptionContinueSearch;
|
DPRINT(" calling ExitProcess(0) no, lets try ExitThread . . .\n");
|
||||||
|
/* ExitProcess(0); */
|
||||||
|
ExitThread(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT(" calling ExitThread(0) . . .\n");
|
||||||
|
ExitThread(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT1(" We should not get to here !!!\n");
|
||||||
|
/* We should not get to here */
|
||||||
|
return ExceptionContinueSearch;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID STDCALL
|
VOID STDCALL
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: exception.c,v 1.12 2003/03/16 14:16:54 chorns Exp $
|
/* $Id: exception.c,v 1.13 2003/04/07 23:10:08 gvg Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -58,7 +58,7 @@ KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord,
|
||||||
VOID STDCALL
|
VOID STDCALL
|
||||||
RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord)
|
RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord)
|
||||||
{
|
{
|
||||||
DbgPrint("RtlRaiseException()");
|
DPRINT("RtlRaiseException()\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID STDCALL
|
VOID STDCALL
|
||||||
|
|
|
@ -90,7 +90,7 @@
|
||||||
#include <internal/module.h>
|
#include <internal/module.h>
|
||||||
#include <internal/ldr.h>
|
#include <internal/ldr.h>
|
||||||
|
|
||||||
#undef NDEBUG
|
#define NDEBUG
|
||||||
#include <internal/debug.h>
|
#include <internal/debug.h>
|
||||||
|
|
||||||
extern LIST_ENTRY PiThreadListHead;
|
extern LIST_ENTRY PiThreadListHead;
|
||||||
|
@ -354,7 +354,7 @@ GspPutPacketNoWait (PCHAR Buffer)
|
||||||
/* Indicate to caller of GspMem2Hex or GspHex2Mem that there has been an
|
/* Indicate to caller of GspMem2Hex or GspHex2Mem that there has been an
|
||||||
error. */
|
error. */
|
||||||
static volatile BOOLEAN GspMemoryError = FALSE;
|
static volatile BOOLEAN GspMemoryError = FALSE;
|
||||||
static void *GspAccessLocation = NULL;
|
static volatile void *GspAccessLocation = NULL;
|
||||||
|
|
||||||
|
|
||||||
/* Convert the memory pointed to by Address into hex, placing result in Buffer */
|
/* Convert the memory pointed to by Address into hex, placing result in Buffer */
|
||||||
|
@ -370,6 +370,12 @@ GspMem2Hex (PCHAR Address,
|
||||||
ULONG i;
|
ULONG i;
|
||||||
CHAR ch;
|
CHAR ch;
|
||||||
|
|
||||||
|
if (NULL == Address && MayFault)
|
||||||
|
{
|
||||||
|
GspMemoryError = TRUE;
|
||||||
|
return Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < (ULONG) Count; i++)
|
for (i = 0; i < (ULONG) Count; i++)
|
||||||
{
|
{
|
||||||
if (MayFault)
|
if (MayFault)
|
||||||
|
@ -457,14 +463,12 @@ GspComputeSignal (NTSTATUS ExceptionCode)
|
||||||
SigVal = 8;
|
SigVal = 8;
|
||||||
break; /* divide by zero */
|
break; /* divide by zero */
|
||||||
case STATUS_SINGLE_STEP:
|
case STATUS_SINGLE_STEP:
|
||||||
SigVal = 5;
|
/* debug exception */
|
||||||
break; /* debug exception */
|
|
||||||
case STATUS_BREAKPOINT:
|
case STATUS_BREAKPOINT:
|
||||||
SigVal = 5;
|
SigVal = 5;
|
||||||
break; /* breakpoint */
|
break; /* breakpoint */
|
||||||
case STATUS_INTEGER_OVERFLOW:
|
case STATUS_INTEGER_OVERFLOW:
|
||||||
SigVal = 16;
|
/* into instruction (overflow) */
|
||||||
break; /* into instruction (overflow) */
|
|
||||||
case STATUS_ARRAY_BOUNDS_EXCEEDED:
|
case STATUS_ARRAY_BOUNDS_EXCEEDED:
|
||||||
SigVal = 16;
|
SigVal = 16;
|
||||||
break; /* bound instruction */
|
break; /* bound instruction */
|
||||||
|
@ -477,11 +481,12 @@ GspComputeSignal (NTSTATUS ExceptionCode)
|
||||||
break; /* coprocessor not available */
|
break; /* coprocessor not available */
|
||||||
#endif
|
#endif
|
||||||
case STATUS_STACK_OVERFLOW:
|
case STATUS_STACK_OVERFLOW:
|
||||||
SigVal = 11;
|
/* stack exception */
|
||||||
break; /* stack exception */
|
|
||||||
case STATUS_DATATYPE_MISALIGNMENT:
|
case STATUS_DATATYPE_MISALIGNMENT:
|
||||||
SigVal = 11;
|
/* page fault */
|
||||||
break; /* page fault */
|
case STATUS_ACCESS_VIOLATION:
|
||||||
|
SigVal = 11; /* access violation */
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
SigVal = 7; /* "software generated" */
|
SigVal = 7; /* "software generated" */
|
||||||
}
|
}
|
||||||
|
@ -746,7 +751,6 @@ GspQuery(PCHAR Request)
|
||||||
ETHREAD, Tcb.ThreadListEntry);
|
ETHREAD, Tcb.ThreadListEntry);
|
||||||
Value = (ULONG) GspEnumThread->Cid.UniqueThread;
|
Value = (ULONG) GspEnumThread->Cid.UniqueThread;
|
||||||
GspLong2Hex (&ptr, Value);
|
GspLong2Hex (&ptr, Value);
|
||||||
DPRINT("fThreadInfo 0x%08x\n", (ULONG) GspEnumThread->Cid.UniqueThread);
|
|
||||||
}
|
}
|
||||||
else if (strncmp (Command, "sThreadInfo", 11) == 0)
|
else if (strncmp (Command, "sThreadInfo", 11) == 0)
|
||||||
{
|
{
|
||||||
|
@ -760,12 +764,10 @@ DPRINT("fThreadInfo 0x%08x\n", (ULONG) GspEnumThread->Cid.UniqueThread);
|
||||||
GspOutBuffer[0] = 'm';
|
GspOutBuffer[0] = 'm';
|
||||||
Value = (ULONG) GspEnumThread->Cid.UniqueThread;
|
Value = (ULONG) GspEnumThread->Cid.UniqueThread;
|
||||||
GspLong2Hex (&ptr, Value);
|
GspLong2Hex (&ptr, Value);
|
||||||
DPRINT("sThreadInfo 0x%08x\n", (ULONG) GspEnumThread->Cid.UniqueThread);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GspOutBuffer[0] = 'l';
|
GspOutBuffer[0] = 'l';
|
||||||
DPRINT("End of threads\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strncmp (Command, "ThreadExtraInfo", 15) == 0)
|
else if (strncmp (Command, "ThreadExtraInfo", 15) == 0)
|
||||||
|
@ -983,13 +985,15 @@ KdEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
|
||||||
/* Disable hardware debugging while we are inside the stub */
|
/* Disable hardware debugging while we are inside the stub */
|
||||||
__asm__("movl %0,%%db7" : /* no output */ : "r" (0));
|
__asm__("movl %0,%%db7" : /* no output */ : "r" (0));
|
||||||
|
|
||||||
if (NULL != GspAccessLocation &&
|
if (STATUS_ACCESS_VIOLATION == ExceptionRecord->ExceptionCode &&
|
||||||
|
NULL != GspAccessLocation &&
|
||||||
(ULONG_PTR) GspAccessLocation ==
|
(ULONG_PTR) GspAccessLocation ==
|
||||||
(ULONG_PTR) ExceptionRecord->ExceptionInformation[1])
|
(ULONG_PTR) ExceptionRecord->ExceptionInformation[1])
|
||||||
{
|
{
|
||||||
GspAccessLocation = NULL;
|
GspAccessLocation = NULL;
|
||||||
GspMemoryError = TRUE;
|
GspMemoryError = TRUE;
|
||||||
TrapFrame->Eip += 2;
|
TrapFrame->Eip += 2;
|
||||||
|
ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NONCONTINUABLE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1044,16 +1048,9 @@ KdEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
|
||||||
break;
|
break;
|
||||||
case 'g': /* return the value of the CPU Registers */
|
case 'g': /* return the value of the CPU Registers */
|
||||||
if (GspDbgThread)
|
if (GspDbgThread)
|
||||||
{
|
|
||||||
DPRINT("GspDbgThread active\n");
|
|
||||||
GspGetRegistersFromTrapFrame (&GspOutBuffer[0], Context, GspDbgThread->Tcb.TrapFrame);
|
GspGetRegistersFromTrapFrame (&GspOutBuffer[0], Context, GspDbgThread->Tcb.TrapFrame);
|
||||||
/*GspGetRegistersFromTrapFrame (&GspOutBuffer[0], Context, TrapFrame);*/
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
DPRINT("GspDbgThread not active\n");
|
|
||||||
GspGetRegistersFromTrapFrame (&GspOutBuffer[0], Context, TrapFrame);
|
GspGetRegistersFromTrapFrame (&GspOutBuffer[0], Context, TrapFrame);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'G': /* set the value of the CPU Registers - return OK */
|
case 'G': /* set the value of the CPU Registers - return OK */
|
||||||
if (GspDbgThread)
|
if (GspDbgThread)
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: bug.c,v 1.27 2002/09/08 10:23:28 chorns Exp $
|
/* $Id: bug.c,v 1.28 2003/04/07 23:10:08 gvg Exp $
|
||||||
*
|
*
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/ke/bug.c
|
* FILE: ntoskrnl/ke/bug.c
|
||||||
|
@ -163,9 +163,13 @@ KeBugCheckEx(ULONG BugCheckCode,
|
||||||
{
|
{
|
||||||
__asm__("sti\n\t");
|
__asm__("sti\n\t");
|
||||||
DbgBreakPoint();
|
DbgBreakPoint();
|
||||||
|
__asm__("cli\n\t");
|
||||||
}
|
}
|
||||||
|
|
||||||
for(;;);
|
for (;;)
|
||||||
|
{
|
||||||
|
__asm__("hlt\n\t");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID STDCALL
|
VOID STDCALL
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: catch.c,v 1.29 2003/03/06 23:57:02 gvg Exp $
|
/* $Id: catch.c,v 1.30 2003/04/07 23:10:08 gvg Exp $
|
||||||
*
|
*
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/ke/catch.c
|
* FILE: ntoskrnl/ke/catch.c
|
||||||
|
@ -53,6 +53,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
|
||||||
{
|
{
|
||||||
EXCEPTION_DISPOSITION Value;
|
EXCEPTION_DISPOSITION Value;
|
||||||
CONTEXT TContext;
|
CONTEXT TContext;
|
||||||
|
KD_CONTINUE_TYPE Action = kdContinue;
|
||||||
|
|
||||||
DPRINT("KiDispatchException() called\n");
|
DPRINT("KiDispatchException() called\n");
|
||||||
|
|
||||||
|
@ -77,69 +78,65 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
|
||||||
Context->Eip--;
|
Context->Eip--;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (PreviousMode == UserMode)
|
|
||||||
|
if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB)
|
||||||
{
|
{
|
||||||
if (SearchFrames)
|
Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
|
||||||
{
|
|
||||||
PULONG Stack;
|
|
||||||
ULONG CDest;
|
|
||||||
|
|
||||||
/* FIXME: Give the kernel debugger a chance */
|
|
||||||
|
|
||||||
/* FIXME: Forward exception to user mode debugger */
|
|
||||||
|
|
||||||
/* FIXME: Check user mode stack for enough space */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Let usermode try and handle the exception
|
|
||||||
*/
|
|
||||||
Tf->Esp = Tf->Esp -
|
|
||||||
(12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT));
|
|
||||||
Stack = (PULONG)Tf->Esp;
|
|
||||||
CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4);
|
|
||||||
/* Return address */
|
|
||||||
Stack[0] = 0;
|
|
||||||
/* Pointer to EXCEPTION_RECORD structure */
|
|
||||||
Stack[1] = (ULONG)&Stack[3];
|
|
||||||
/* Pointer to CONTEXT structure */
|
|
||||||
Stack[2] = (ULONG)&Stack[CDest];
|
|
||||||
memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
|
|
||||||
memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
|
|
||||||
|
|
||||||
Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: Forward the exception to the debugger */
|
|
||||||
|
|
||||||
/* FIXME: Forward the exception to the process exception port */
|
|
||||||
|
|
||||||
/* Terminate the offending thread */
|
|
||||||
ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
|
|
||||||
|
|
||||||
/* If that fails then bugcheck */
|
|
||||||
DbgPrint("Could not terminate thread\n");
|
|
||||||
KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
KD_CONTINUE_TYPE Action = kdContinue;
|
|
||||||
|
|
||||||
/* PreviousMode == KernelMode */
|
|
||||||
|
|
||||||
if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB)
|
|
||||||
{
|
|
||||||
Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
|
|
||||||
}
|
|
||||||
#ifdef KDBG
|
#ifdef KDBG
|
||||||
else if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_KDB)
|
else if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_KDB)
|
||||||
{
|
{
|
||||||
Action = KdbEnterDebuggerException (ExceptionRecord, Context, Tf);
|
Action = KdbEnterDebuggerException (ExceptionRecord, Context, Tf);
|
||||||
}
|
}
|
||||||
#endif /* KDBG */
|
#endif /* KDBG */
|
||||||
if (Action != kdHandleException)
|
if (Action != kdHandleException)
|
||||||
|
{
|
||||||
|
if (PreviousMode == UserMode)
|
||||||
{
|
{
|
||||||
|
if (SearchFrames)
|
||||||
|
{
|
||||||
|
PULONG Stack;
|
||||||
|
ULONG CDest;
|
||||||
|
|
||||||
|
/* FIXME: Forward exception to user mode debugger */
|
||||||
|
|
||||||
|
/* FIXME: Check user mode stack for enough space */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Let usermode try and handle the exception
|
||||||
|
*/
|
||||||
|
Tf->Esp = Tf->Esp -
|
||||||
|
(12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT));
|
||||||
|
Stack = (PULONG)Tf->Esp;
|
||||||
|
CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4);
|
||||||
|
/* Return address */
|
||||||
|
Stack[0] = 0;
|
||||||
|
/* Pointer to EXCEPTION_RECORD structure */
|
||||||
|
Stack[1] = (ULONG)&Stack[3];
|
||||||
|
/* Pointer to CONTEXT structure */
|
||||||
|
Stack[2] = (ULONG)&Stack[CDest];
|
||||||
|
memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
|
||||||
|
memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
|
||||||
|
|
||||||
|
Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: Forward the exception to the debugger */
|
||||||
|
|
||||||
|
/* FIXME: Forward the exception to the process exception port */
|
||||||
|
|
||||||
|
/* Terminate the offending thread */
|
||||||
|
DPRINT1("Unhandled UserMode exception, terminating thread\n");
|
||||||
|
ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
|
||||||
|
|
||||||
|
/* If that fails then bugcheck */
|
||||||
|
DPRINT1("Could not terminate thread\n");
|
||||||
|
KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* PreviousMode == KernelMode */
|
||||||
Value = RtlpDispatchException (ExceptionRecord, Context);
|
Value = RtlpDispatchException (ExceptionRecord, Context);
|
||||||
|
|
||||||
DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
|
DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
|
||||||
|
@ -147,17 +144,16 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
|
||||||
* If RtlpDispatchException() does not handle the exception then
|
* If RtlpDispatchException() does not handle the exception then
|
||||||
* bugcheck
|
* bugcheck
|
||||||
*/
|
*/
|
||||||
#ifdef TODO
|
if (Value != ExceptionContinueExecution ||
|
||||||
if (Value != ExceptionContinueExecution)
|
0 != (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE))
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
KeBugCheck (KMODE_EXCEPTION_NOT_HANDLED);
|
KeBugCheck (KMODE_EXCEPTION_NOT_HANDLED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
KeContextToTrapFrame (Context, KeGetCurrentThread()->TrapFrame);
|
{
|
||||||
}
|
KeContextToTrapFrame (Context, KeGetCurrentThread()->TrapFrame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -181,6 +181,9 @@ KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
|
||||||
Er.NumberParameters = 0;
|
Er.NumberParameters = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Er.ExceptionFlags = (STATUS_SINGLE_STEP == Er.ExceptionCode || STATUS_BREAKPOINT == Er.ExceptionCode ?
|
||||||
|
0 : EXCEPTION_NONCONTINUABLE);
|
||||||
|
|
||||||
KiDispatchException(&Er, 0, Tf, KernelMode, TRUE);
|
KiDispatchException(&Er, 0, Tf, KernelMode, TRUE);
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
|
|
|
@ -144,6 +144,9 @@ KiUserTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Er.ExceptionFlags = (STATUS_SINGLE_STEP == Er.ExceptionCode || STATUS_BREAKPOINT == Er.ExceptionCode ?
|
||||||
|
0 : EXCEPTION_NONCONTINUABLE);
|
||||||
|
|
||||||
KiDispatchException(&Er, 0, Tf, UserMode, TRUE);
|
KiDispatchException(&Er, 0, Tf, UserMode, TRUE);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue