- Remove ke/error.c and add its functions into ke/catch.c where they belong.
- Create ex/error.c and move Executive functions present in ke/error.c to it.
- Implement NtRaiseHardError and move it from ke/error.c to ex/error.c.
- Increase Exceptions Dispatched count in dispatch code and comment code more throughly.

svn path=/trunk/; revision=13982
This commit is contained in:
Thomas Bluemel
2005-03-12 21:26:29 +00:00
parent 566c2840b9
commit 7bc94f8976
4 changed files with 357 additions and 322 deletions
+1 -1
View File
@@ -100,7 +100,6 @@ OBJECTS_KE = \
ke/critical.o \
ke/dpc.o \
ke/device.o \
ke/error.o \
ke/event.o \
ke/kqueue.o \
ke/kthread.o \
@@ -237,6 +236,7 @@ OBJECTS_PS = \
OBJECTS_EX = \
ex/btree.o \
ex/callback.o \
ex/error.o \
ex/event.o \
ex/evtpair.o \
ex/fmutex.o \
+163
View File
@@ -0,0 +1,163 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ex/error.c
* PURPOSE: Error Functions and Status/Exception Dispatching/Raising
*
* PROGRAMMERS: Alex Ionescu ([email protected]) - Created File
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
/* GLOBALS ****************************************************************/
BOOLEAN ExReadyForErrors = FALSE;
PEPORT ExpDefaultErrorPort = NULL;
PEPROCESS ExpDefaultErrorPortProcess = NULL;
/* FUNCTIONS ****************************************************************/
/*
* @implemented
*/
VOID
STDCALL
ExRaiseAccessViolation(VOID)
{
/* Raise the Right Status */
ExRaiseStatus (STATUS_ACCESS_VIOLATION);
}
/*
* @implemented
*/
VOID
STDCALL
ExRaiseDatatypeMisalignment (VOID)
{
/* Raise the Right Status */
ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
}
/*
* @implemented
*/
VOID
STDCALL
ExRaiseStatus(IN NTSTATUS Status)
{
EXCEPTION_RECORD ExceptionRecord;
DPRINT("ExRaiseStatus(%x)\n", Status);
/* Set up an Exception Record */
ExceptionRecord.ExceptionRecord = NULL;
ExceptionRecord.NumberParameters = 0;
ExceptionRecord.ExceptionCode = Status;
ExceptionRecord.ExceptionFlags = 0;
/* Call the Rtl Function */
RtlRaiseException(&ExceptionRecord);
}
/*
* @implemented
*/
VOID
STDCALL
ExRaiseException (PEXCEPTION_RECORD ExceptionRecord)
{
/* Call the Rtl function */
RtlRaiseException(ExceptionRecord);
}
/*
* @implemented
*/
BOOLEAN
STDCALL
ExSystemExceptionFilter(VOID)
{
return KeGetPreviousMode() != KernelMode ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
}
/*
* @unimplemented
*/
VOID
STDCALL
ExRaiseHardError(IN NTSTATUS ErrorStatus,
IN ULONG NumberOfParameters,
IN PUNICODE_STRING UnicodeStringParameterMask OPTIONAL,
IN PVOID *Parameters,
IN HARDERROR_RESPONSE_OPTION ResponseOption,
OUT PHARDERROR_RESPONSE Response)
{
UNIMPLEMENTED;
}
NTSTATUS
STDCALL
NtRaiseHardError(IN NTSTATUS ErrorStatus,
IN ULONG NumberOfParameters,
IN PUNICODE_STRING UnicodeStringParameterMask OPTIONAL,
IN PVOID *Parameters,
IN HARDERROR_RESPONSE_OPTION ResponseOption,
OUT PHARDERROR_RESPONSE Response)
{
DPRINT1("Hard error %x\n", ErrorStatus);
/* Call the Executive Function (WE SHOULD PUT SEH HERE/CAPTURE!) */
ExRaiseHardError(ErrorStatus,
NumberOfParameters,
UnicodeStringParameterMask,
Parameters,
ResponseOption,
Response);
/* Return Success */
return STATUS_SUCCESS;
}
NTSTATUS
STDCALL
NtSetDefaultHardErrorPort(IN HANDLE PortHandle)
{
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_UNSUCCESSFUL;
/* Check if we have the Privilege */
if(!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode)) {
DPRINT1("NtSetDefaultHardErrorPort: Caller requires the SeTcbPrivilege privilege!\n");
return STATUS_PRIVILEGE_NOT_HELD;
}
/* Only called once during bootup, make sure we weren't called yet */
if(!ExReadyForErrors) {
Status = ObReferenceObjectByHandle(PortHandle,
0,
LpcPortObjectType,
PreviousMode,
(PVOID*)&ExpDefaultErrorPort,
NULL);
/* Check for Success */
if(NT_SUCCESS(Status)) {
/* Save the data */
ExpDefaultErrorPortProcess = PsGetCurrentProcess();
ExReadyForErrors = TRUE;
}
}
return Status;
}
/* EOF */
+193 -223
View File
@@ -1,5 +1,4 @@
/* $Id$
*
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/catch.c
@@ -21,223 +20,14 @@ ULONG
RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context);
VOID
KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
PCONTEXT Context,
PKTRAP_FRAME Tf,
KPROCESSOR_MODE PreviousMode,
BOOLEAN SearchFrames)
{
EXCEPTION_DISPOSITION Value;
CONTEXT TContext;
KD_CONTINUE_TYPE Action = kdHandleException;
DPRINT("KiDispatchException() called\n");
/* PCR->KeExceptionDispatchCount++; */
if (Context == NULL)
{
TContext.ContextFlags = CONTEXT_FULL;
if (PreviousMode == UserMode)
{
TContext.ContextFlags = TContext.ContextFlags | CONTEXT_DEBUGGER;
}
KeTrapFrameToContext(Tf, &TContext);
Context = &TContext;
}
#if 0
if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT)
{
Context->Eip--;
}
#endif
if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB)
{
Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
}
if (Action == kdContinue)
{
return;
}
if (Action != kdDoNotHandleException)
{
if (PreviousMode == UserMode)
{
if (SearchFrames)
{
PULONG Stack;
ULONG CDest;
char temp_space[12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)]; /* FIXME: HACKHACK */
PULONG pNewUserStack = (PULONG)(Tf->Esp - (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
NTSTATUS StatusOfCopy;
#ifdef KDBG
Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
Context, Tf, TRUE);
if (Action == kdContinue)
{
return;
}
#endif
/* FIXME: Forward exception to user mode debugger */
/* FIXME: Check user mode stack for enough space */
/*
* Let usermode try and handle the exception
*/
Stack = (PULONG)temp_space;
CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4);
/* Return address */
Stack[0] = 0;
/* Pointer to EXCEPTION_RECORD structure */
Stack[1] = (ULONG)&pNewUserStack[3];
/* Pointer to CONTEXT structure */
Stack[2] = (ULONG)&pNewUserStack[CDest];
memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
StatusOfCopy = MmCopyToCaller(pNewUserStack,
temp_space,
(12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
if (NT_SUCCESS(StatusOfCopy))
{
Tf->Esp = (ULONG)pNewUserStack;
}
else
{
/* Now it really hit the ventilation device. Sorry,
* can do nothing but kill the sucker.
*/
ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
DPRINT1("User-mode stack was invalid. Terminating target thread\n");
}
Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
return;
}
/* FIXME: Forward the exception to the debugger */
/* FIXME: Forward the exception to the process exception port */
#ifdef KDBG
Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
Context, Tf, FALSE);
if (Action == kdContinue)
{
return;
}
#endif
/* Terminate the offending thread */
DPRINT1("Unhandled UserMode exception, terminating thread\n");
ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
}
else
{
/* PreviousMode == KernelMode */
#ifdef KDBG
Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
Context, Tf, TRUE);
if (Action == kdContinue)
{
return;
}
#endif
Value = RtlpDispatchException (ExceptionRecord, Context);
DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
/*
* If RtlpDispatchException() does not handle the exception then
* bugcheck
*/
if (Value != ExceptionContinueExecution ||
0 != (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE))
{
DPRINT("ExceptionRecord->ExceptionAddress = 0x%x\n",
ExceptionRecord->ExceptionAddress );
#ifdef KDBG
Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
Context, Tf, FALSE);
if (Action == kdContinue)
{
return;
}
#endif
KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED, 0, 0, 0, 0, Tf);
}
}
}
}
/*
* @implemented
*/
VOID STDCALL
ExRaiseAccessViolation (VOID)
{
ExRaiseStatus (STATUS_ACCESS_VIOLATION);
}
/*
* @implemented
*/
VOID STDCALL
ExRaiseDatatypeMisalignment (VOID)
{
ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
}
/*
* @implemented
*/
VOID STDCALL
ExRaiseStatus (IN NTSTATUS Status)
{
EXCEPTION_RECORD ExceptionRecord;
DPRINT("ExRaiseStatus(%x)\n", Status);
ExceptionRecord.ExceptionRecord = NULL;
ExceptionRecord.NumberParameters = 0;
ExceptionRecord.ExceptionCode = Status;
ExceptionRecord.ExceptionFlags = 0;
RtlRaiseException(&ExceptionRecord);
}
/*
* @implemented
* @unimplemented
*/
VOID
STDCALL
ExRaiseException (
PEXCEPTION_RECORD ExceptionRecord
)
KiCoprocessorError(VOID)
{
RtlRaiseException(ExceptionRecord);
}
/*
* @implemented
*/
BOOLEAN
STDCALL
ExSystemExceptionFilter(VOID)
{
return KeGetPreviousMode() != KernelMode ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
UNIMPLEMENTED;
}
/*
@@ -245,16 +35,196 @@ ExSystemExceptionFilter(VOID)
*/
VOID
STDCALL
ExRaiseHardError (
IN NTSTATUS ErrorStatus,
IN ULONG NumberOfParameters,
IN PUNICODE_STRING UnicodeStringParameterMask OPTIONAL,
IN PVOID *Parameters,
IN HARDERROR_RESPONSE_OPTION ResponseOption,
OUT PHARDERROR_RESPONSE Response
)
KiUnexpectedInterrupt(VOID)
{
UNIMPLEMENTED;
UNIMPLEMENTED;
}
VOID
KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
PCONTEXT Context,
PKTRAP_FRAME Tf,
KPROCESSOR_MODE PreviousMode,
BOOLEAN SearchFrames)
{
EXCEPTION_DISPOSITION Value;
CONTEXT TContext;
KD_CONTINUE_TYPE Action = kdHandleException;
DPRINT("KiDispatchException() called\n");
/* Increase number of Exception Dispatches */
KeGetCurrentPrcb()->KeExceptionDispatchCount++;
if (!Context) {
/* Assume Full context */
TContext.ContextFlags = CONTEXT_FULL;
/* Check the mode */
if (PreviousMode == UserMode) {
/* Add Debugger Registers if this is User Mode */
TContext.ContextFlags = TContext.ContextFlags | CONTEXT_DEBUGGER;
}
/* Convert the Trapframe into a Context */
KeTrapFrameToContext(Tf, &TContext);
/* Use local stack context */
Context = &TContext;
}
#if 0 /* FIXME: Isn't this right? With a break after? */
if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) {
Context->Eip--;
}
#endif
/* Check if a Debugger is enabled */
if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB) {
/* Break into it */
Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
}
/* If the debugger said continue, then continue */
if (Action == kdContinue) return;
/* If the Debugger couldn't handle it... */
if (Action != kdDoNotHandleException) {
/* See what kind of Exception this is */
if (PreviousMode == UserMode) {
/* User mode exception, search the frames if we have to */
if (SearchFrames) {
PULONG Stack;
ULONG CDest;
char temp_space[12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)]; /* FIXME: HACKHACK */
PULONG pNewUserStack = (PULONG)(Tf->Esp - (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
NTSTATUS StatusOfCopy;
#ifdef KDBG
/* Enter KDB if available */
Action = KdbEnterDebuggerException(ExceptionRecord,
PreviousMode,
Context,
Tf,
TRUE);
/* Exit if we're continuing */
if (Action == kdContinue) return;
#endif
/* FIXME: Forward exception to user mode debugger */
/* FIXME: Check user mode stack for enough space */
/* Let usermode try and handle the exception. Setup Stack */
Stack = (PULONG)temp_space;
CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4);
/* Return Address */
Stack[0] = 0;
/* Pointer to EXCEPTION_RECORD structure */
Stack[1] = (ULONG)&pNewUserStack[3];
/* Pointer to CONTEXT structure */
Stack[2] = (ULONG)&pNewUserStack[CDest];
memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
/* Copy Stack */
StatusOfCopy = MmCopyToCaller(pNewUserStack,
temp_space,
(12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
/* Check for success */
if (NT_SUCCESS(StatusOfCopy)) {
/* Set new Stack Pointer */
Tf->Esp = (ULONG)pNewUserStack;
} else {
/*
* Now it really hit the ventilation device. Sorry,
* can do nothing but kill the sucker.
*/
ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
DPRINT1("User-mode stack was invalid. Terminating target thread\n");
}
/* Set EIP to the User-mode Dispathcer */
Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
return;
}
/* FIXME: Forward the exception to the debugger */
/* FIXME: Forward the exception to the process exception port */
#ifdef KDBG
/* Enter KDB if available */
Action = KdbEnterDebuggerException(ExceptionRecord,
PreviousMode,
Context,
Tf,
FALSE);
/* Exit if we're continuing */
if (Action == kdContinue) return;
#endif
/* Terminate the offending thread */
DPRINT1("Unhandled UserMode exception, terminating thread\n");
ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
} else {
/* This is Kernel Mode */
#ifdef KDBG
/* Enter KDB if available */
Action = KdbEnterDebuggerException(ExceptionRecord,
PreviousMode,
Context,
Tf,
TRUE);
/* Exit if we're continuing */
if (Action == kdContinue) return;
#endif
/* Dispatch the Exception */
Value = RtlpDispatchException (ExceptionRecord, Context);
DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
/* If RtlpDispatchException() did not handle the exception then bugcheck */
if (Value != ExceptionContinueExecution ||
0 != (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)) {
DPRINT("ExceptionRecord->ExceptionAddress = 0x%x\n", ExceptionRecord->ExceptionAddress);
#ifdef KDBG
/* Enter KDB if available */
Action = KdbEnterDebuggerException(ExceptionRecord,
PreviousMode,
Context,
Tf,
FALSE);
/* Exit if we're continuing */
if (Action == kdContinue) return;
#endif
KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED,
ExceptionRecord->ExceptionCode,
(ULONG)ExceptionRecord->ExceptionAddress,
ExceptionRecord->ExceptionInformation[0],
ExceptionRecord->ExceptionInformation[1],
Tf);
}
}
}
}
/* EOF */
-98
View File
@@ -1,98 +0,0 @@
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/error.c
* PURPOSE: Error reason setting/getting
*
* PROGRAMMERS: David Welch
*/
/* INCLUDE *****************************************************************/
#include <ntoskrnl.h>
#include <internal/debug.h>
/* FUNCTIONS ***************************************************************/
BOOLEAN ExReadyForErrors = FALSE;
PEPORT ExpDefaultErrorPort = NULL;
PEPROCESS ExpDefaultErrorPortProcess = NULL;
/*
* @unimplemented
*/
VOID
STDCALL
KiCoprocessorError(
VOID
)
{
UNIMPLEMENTED;
}
/*
* @unimplemented
*/
VOID
STDCALL
KiUnexpectedInterrupt(
VOID
)
{
UNIMPLEMENTED;
}
NTSTATUS STDCALL
NtRaiseHardError(IN NTSTATUS ErrorStatus,
IN ULONG NumberOfParameters,
IN PUNICODE_STRING UnicodeStringParameterMask OPTIONAL,
IN PVOID *Parameters,
IN HARDERROR_RESPONSE_OPTION ResponseOption,
OUT PHARDERROR_RESPONSE Response)
{
DPRINT1("Hard error %x\n", ErrorStatus);
return(STATUS_SUCCESS);
}
NTSTATUS STDCALL
NtSetDefaultHardErrorPort(IN HANDLE PortHandle)
{
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
PreviousMode = ExGetPreviousMode();
if(!SeSinglePrivilegeCheck(SeTcbPrivilege,
PreviousMode))
{
DPRINT1("NtSetDefaultHardErrorPort: Caller requires the SeTcbPrivilege privilege!\n");
return STATUS_PRIVILEGE_NOT_HELD;
}
/* serialization shouldn't be required here as it usually is just called once
during startup */
if(!ExReadyForErrors)
{
Status = ObReferenceObjectByHandle(PortHandle,
0,
LpcPortObjectType,
PreviousMode,
(PVOID*)&ExpDefaultErrorPort,
NULL);
if(NT_SUCCESS(Status))
{
ExpDefaultErrorPortProcess = PsGetCurrentProcess();
ExReadyForErrors = TRUE;
}
}
else
{
Status = STATUS_UNSUCCESSFUL;
}
return Status;
}
/* EOF */