2006-11-08 11:47:44 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Kernel
|
2010-01-19 08:41:03 +00:00
|
|
|
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
2006-11-08 11:47:44 +00:00
|
|
|
* FILE: ntoskrnl/ke/except.c
|
|
|
|
* PURPOSE: Platform independent exception handling
|
2010-01-19 08:41:03 +00:00
|
|
|
* PROGRAMMERS: ReactOS Portable Systems Group
|
|
|
|
* Alex Ionescu (alex.ionescu@reactos.org)
|
2006-11-08 11:47:44 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
|
|
|
|
#include <ntoskrnl.h>
|
|
|
|
#define NDEBUG
|
2008-08-30 16:31:06 +00:00
|
|
|
#include <debug.h>
|
2006-11-08 11:47:44 +00:00
|
|
|
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
2024-04-27 14:23:02 +00:00
|
|
|
KiContinuePreviousModeUser(
|
|
|
|
_In_ PCONTEXT Context,
|
|
|
|
_Out_ PKEXCEPTION_FRAME ExceptionFrame,
|
|
|
|
_Out_ PKTRAP_FRAME TrapFrame)
|
2006-11-08 11:47:44 +00:00
|
|
|
{
|
|
|
|
CONTEXT LocalContext;
|
|
|
|
|
|
|
|
/* We'll have to make a copy and probe it */
|
|
|
|
ProbeForRead(Context, sizeof(CONTEXT), sizeof(ULONG));
|
|
|
|
RtlCopyMemory(&LocalContext, Context, sizeof(CONTEXT));
|
|
|
|
Context = &LocalContext;
|
|
|
|
|
|
|
|
/* Convert the context into Exception/Trap Frames */
|
|
|
|
KeContextToTrapFrame(&LocalContext,
|
|
|
|
ExceptionFrame,
|
|
|
|
TrapFrame,
|
|
|
|
LocalContext.ContextFlags,
|
|
|
|
UserMode);
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
KiContinue(IN PCONTEXT Context,
|
|
|
|
IN PKEXCEPTION_FRAME ExceptionFrame,
|
|
|
|
IN PKTRAP_FRAME TrapFrame)
|
|
|
|
{
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
KIRQL OldIrql = APC_LEVEL;
|
|
|
|
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
|
|
|
|
|
|
|
|
/* Raise to APC_LEVEL, only if needed */
|
|
|
|
if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
|
|
|
|
|
|
|
|
/* Set up SEH to validate the context */
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_TRY
|
2006-11-08 11:47:44 +00:00
|
|
|
{
|
|
|
|
/* Check the previous mode */
|
|
|
|
if (PreviousMode != KernelMode)
|
|
|
|
{
|
|
|
|
/* Validate from user-mode */
|
|
|
|
KiContinuePreviousModeUser(Context,
|
|
|
|
ExceptionFrame,
|
|
|
|
TrapFrame);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Convert the context into Exception/Trap Frames */
|
|
|
|
KeContextToTrapFrame(Context,
|
|
|
|
ExceptionFrame,
|
|
|
|
TrapFrame,
|
|
|
|
Context->ContextFlags,
|
|
|
|
KernelMode);
|
|
|
|
}
|
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
2006-11-08 11:47:44 +00:00
|
|
|
{
|
|
|
|
/* Save the exception code */
|
2008-11-24 13:40:26 +00:00
|
|
|
Status = _SEH2_GetExceptionCode();
|
2006-11-08 11:47:44 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_END;
|
2006-11-08 11:47:44 +00:00
|
|
|
|
|
|
|
/* Lower the IRQL if needed */
|
|
|
|
if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);
|
|
|
|
|
|
|
|
/* Return status */
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
2024-04-27 14:23:02 +00:00
|
|
|
KiRaiseException(
|
|
|
|
_In_ PEXCEPTION_RECORD ExceptionRecord,
|
|
|
|
_In_ PCONTEXT Context,
|
|
|
|
_Out_ PKEXCEPTION_FRAME ExceptionFrame,
|
|
|
|
_Out_ PKTRAP_FRAME TrapFrame,
|
|
|
|
_In_ BOOLEAN SearchFrames)
|
2006-11-08 11:47:44 +00:00
|
|
|
{
|
|
|
|
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
|
|
|
|
CONTEXT LocalContext;
|
|
|
|
EXCEPTION_RECORD LocalExceptionRecord;
|
|
|
|
ULONG ParameterCount, Size;
|
|
|
|
|
2009-08-24 19:58:15 +00:00
|
|
|
/* Check if we need to probe */
|
|
|
|
if (PreviousMode != KernelMode)
|
2006-11-08 11:47:44 +00:00
|
|
|
{
|
2009-08-24 19:58:15 +00:00
|
|
|
/* Set up SEH */
|
|
|
|
_SEH2_TRY
|
2006-11-08 11:47:44 +00:00
|
|
|
{
|
|
|
|
/* Probe the context */
|
|
|
|
ProbeForRead(Context, sizeof(CONTEXT), sizeof(ULONG));
|
|
|
|
|
|
|
|
/* Probe the Exception Record */
|
|
|
|
ProbeForRead(ExceptionRecord,
|
|
|
|
FIELD_OFFSET(EXCEPTION_RECORD, NumberParameters) +
|
|
|
|
sizeof(ULONG),
|
|
|
|
sizeof(ULONG));
|
2009-08-24 19:58:15 +00:00
|
|
|
|
2006-11-08 11:47:44 +00:00
|
|
|
/* Validate the maximum parameters */
|
|
|
|
if ((ParameterCount = ExceptionRecord->NumberParameters) >
|
|
|
|
EXCEPTION_MAXIMUM_PARAMETERS)
|
|
|
|
{
|
|
|
|
/* Too large */
|
2009-08-26 14:52:00 +00:00
|
|
|
_SEH2_YIELD(return STATUS_INVALID_PARAMETER);
|
2006-11-08 11:47:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Probe the entire parameters now*/
|
2021-06-11 12:29:21 +00:00
|
|
|
Size = (sizeof(EXCEPTION_RECORD) -
|
2006-11-08 11:47:44 +00:00
|
|
|
((EXCEPTION_MAXIMUM_PARAMETERS - ParameterCount) * sizeof(ULONG)));
|
|
|
|
ProbeForRead(ExceptionRecord, Size, sizeof(ULONG));
|
|
|
|
|
|
|
|
/* Now make copies in the stack */
|
|
|
|
RtlCopyMemory(&LocalContext, Context, sizeof(CONTEXT));
|
|
|
|
RtlCopyMemory(&LocalExceptionRecord, ExceptionRecord, Size);
|
|
|
|
Context = &LocalContext;
|
|
|
|
ExceptionRecord = &LocalExceptionRecord;
|
|
|
|
|
|
|
|
/* Update the parameter count */
|
|
|
|
ExceptionRecord->NumberParameters = ParameterCount;
|
|
|
|
}
|
2009-08-24 19:58:15 +00:00
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
2009-08-24 20:07:12 +00:00
|
|
|
/* Don't fail silently */
|
2009-08-24 20:08:45 +00:00
|
|
|
DPRINT1("KiRaiseException: Failed to Probe\n");
|
2009-08-24 19:58:15 +00:00
|
|
|
|
|
|
|
/* Return the exception code */
|
|
|
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
|
|
|
}
|
|
|
|
_SEH2_END;
|
2006-11-08 11:47:44 +00:00
|
|
|
}
|
|
|
|
|
- Fix KiDispatchException to unmask KI_EXCEPTION_INTERNAL when setting the exception code, so that usermode/SEH filters get proper exception codes again.
- Fixes and compatible merges from KD Branch:
- Add stubs for KdSave, KdRestore, KdDebuggerInitialize0, KdSendPacket, KdReceivePacket to kdcom.dll
- Implement and export KeTryToAcquireSpinLockAtDpcLevel.
- Add EXCEPTION_RECORD64 and LIST_ENTRY64, KeTryToAcquireSpinLockAtDpcLevel, BREAKPOINT_COMMAND_STRING, Ke386SetCr2, Ke386SetDr3, Ke386SetDr6.
- Remove non-kernel routines from kdfuncs.h and remove deprecated routines from ke.h.
- Implement KiRestoreProcessorControlState, KeFreezeExecution, KeThawExecution, ExAcquireTimeRefreshLock, ExReleaseTimeRefreshLock.
- Rename ModuleLoadList to PsLoadedModuleList. Add PsNtosImageBase and set value in it.
- Add skeleton wdbgexts.h with what's needed until now, this is a PSDK header.
- Add kddll.h for KDCOM/1394/USB2.DLL prototypes.
- Add windbgkd.h with KD protocol definitions. Used to be an NT5 DDK header, but was removed, so this goes into include\reactos.
- Fix KiDebugService to load EDX from KTRAP_FRAME_EDX, not KTRAP_FRAME_EAX!.
- Fix CommonDispatchException to check for the argument count in ECX, not EAX. Previously we were ignoring parameter counts and never filling out exception records!
- Add KdDebuggerInitialize1 and enable call to it.
- Fix KD_SYMBOLS_INFO definition and DbgLoadImageSymbols prototype.
- Implement DbgUnLoadImageSymbols.
- Fix some small bugs in KeBugCheckWithTf and add various debugger calls/checks where needed.
- Fix bugcheck recursion code which was incorrect.
- Only save/restore CR4 if KeFeatureBits indicates CR4 support exists.
- Export KdDebuggerNotPresent since KDCOM needs it.
- Add KCONTINUE_STATUS.
- Add DBGKD_ANY_CONTROL_SET and X86/IA64/AMD64 control sets.
- Add DBGKD_MANIPULATE_STATE64 and all sub-structures (READ_MEMORY, WRITE_MEMORY, etc).
- Create GCC_ULONG64 type to hack around a bug in GCC which is incapable of creating entries for externals at compile-time for 64-bit pointers.
- Rename NameSpaceRoot to ObpRootDirectoryObject, IopLogListHead to IopErrorLogListHead, BugcheckCallbackListHead to KeBugcheckCallbackListHead, BugcheckReasonCallbackListHead to KeBugcheckReasonCallbackListHead, ObTypeObjectType to ObpTypeObjectType.
- Create ntverp.h and common.ver files. These are the standard files used by the NT/DDK build systems and we should try to support them as well instead of re-defining everything our own way (especially if we want to build ddk-compatible drivers later on).
- Made init.c use version data from ntverp.h instead of hard-coding.
- Defined NT 5.2.3790.1830 as the version we report.
- Fixed up .rc file to be correct and match DDK-sytnax/style.
- For now only the kernel uses this new versionning scheme, but we should change the build system later to use this for every component.
- Fix KiSaveProcessorControlState and KiRestoreProcessorControlSate. The latter doesn't freeze the CPU anymore so it's enabled, and the former doesn't cause WinDBG to panic anymore and display weird data.
- KPROCESSOR_STATE is not 4-byte aligned.
- Use DR_MASK and DR7_OVERRIDE_V in KiUpdateDr7, KiRecordDr7 instead of DR_ACTIVE_MASK.
- Add ExceptionRecord32To64.
- Fix generation of driver name for symbol load.
svn path=/trunk/; revision=25937
2007-03-01 19:51:20 +00:00
|
|
|
/* Convert the context record */
|
|
|
|
KeContextToTrapFrame(Context,
|
|
|
|
ExceptionFrame,
|
|
|
|
TrapFrame,
|
|
|
|
Context->ContextFlags,
|
|
|
|
PreviousMode);
|
|
|
|
|
|
|
|
/* Dispatch the exception */
|
|
|
|
ExceptionRecord->ExceptionCode &= ~KI_EXCEPTION_INTERNAL;
|
|
|
|
KiDispatchException(ExceptionRecord,
|
|
|
|
ExceptionFrame,
|
|
|
|
TrapFrame,
|
|
|
|
PreviousMode,
|
|
|
|
SearchFrames);
|
2006-11-08 11:47:44 +00:00
|
|
|
|
2009-08-26 14:52:00 +00:00
|
|
|
/* We are done */
|
|
|
|
return STATUS_SUCCESS;
|
2006-11-08 11:47:44 +00:00
|
|
|
}
|
|
|
|
|
2010-01-19 08:41:03 +00:00
|
|
|
/* SYSTEM CALLS ***************************************************************/
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
2024-04-27 14:23:02 +00:00
|
|
|
NtRaiseException(
|
|
|
|
_In_ PEXCEPTION_RECORD ExceptionRecord,
|
|
|
|
_In_ PCONTEXT Context,
|
|
|
|
_In_ BOOLEAN FirstChance)
|
2010-01-19 08:41:03 +00:00
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
PKTHREAD Thread;
|
|
|
|
PKTRAP_FRAME TrapFrame;
|
2024-03-25 17:04:58 +00:00
|
|
|
#ifdef _M_IX86
|
|
|
|
PKEXCEPTION_FRAME ExceptionFrame = NULL;
|
|
|
|
#else
|
|
|
|
KEXCEPTION_FRAME LocalExceptionFrame;
|
|
|
|
PKEXCEPTION_FRAME ExceptionFrame = &LocalExceptionFrame;
|
|
|
|
#endif
|
2010-01-19 08:41:03 +00:00
|
|
|
|
2024-03-25 17:04:58 +00:00
|
|
|
/* Get trap frame and link previous one */
|
2010-01-19 08:41:03 +00:00
|
|
|
Thread = KeGetCurrentThread();
|
|
|
|
TrapFrame = Thread->TrapFrame;
|
2010-02-01 03:51:45 +00:00
|
|
|
Thread->TrapFrame = KiGetLinkedTrapFrame(TrapFrame);
|
2021-06-11 12:29:21 +00:00
|
|
|
|
2010-01-19 08:41:03 +00:00
|
|
|
/* Set exception list */
|
2010-02-01 03:51:45 +00:00
|
|
|
#ifdef _M_IX86
|
2010-03-12 16:28:04 +00:00
|
|
|
KeGetPcr()->NtTib.ExceptionList = TrapFrame->ExceptionList;
|
2010-02-01 03:51:45 +00:00
|
|
|
#endif
|
2021-06-11 12:29:21 +00:00
|
|
|
|
2010-01-19 08:41:03 +00:00
|
|
|
/* Raise the exception */
|
|
|
|
Status = KiRaiseException(ExceptionRecord,
|
|
|
|
Context,
|
2024-03-25 17:04:58 +00:00
|
|
|
ExceptionFrame,
|
2010-01-19 08:41:03 +00:00
|
|
|
TrapFrame,
|
|
|
|
FirstChance);
|
2024-04-27 14:23:02 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2010-01-19 08:41:03 +00:00
|
|
|
{
|
2024-04-27 14:23:02 +00:00
|
|
|
DPRINT1("KiRaiseException failed. Status = 0x%lx\n", Status);
|
|
|
|
return Status;
|
2010-01-19 08:41:03 +00:00
|
|
|
}
|
2021-06-11 12:29:21 +00:00
|
|
|
|
2024-04-27 14:23:02 +00:00
|
|
|
/* It was handled, so exit restoring all state */
|
|
|
|
KiExceptionExit(TrapFrame, ExceptionFrame);
|
2010-01-19 08:41:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
2024-04-27 14:23:02 +00:00
|
|
|
NtContinue(
|
|
|
|
_In_ PCONTEXT Context,
|
|
|
|
_In_ BOOLEAN TestAlert)
|
2010-01-19 08:41:03 +00:00
|
|
|
{
|
|
|
|
PKTHREAD Thread;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PKTRAP_FRAME TrapFrame;
|
2024-03-25 17:04:58 +00:00
|
|
|
#ifdef _M_IX86
|
|
|
|
PKEXCEPTION_FRAME ExceptionFrame = NULL;
|
|
|
|
#else
|
|
|
|
KEXCEPTION_FRAME LocalExceptionFrame;
|
|
|
|
PKEXCEPTION_FRAME ExceptionFrame = &LocalExceptionFrame;
|
|
|
|
#endif
|
2021-06-11 12:29:21 +00:00
|
|
|
|
2010-01-19 08:41:03 +00:00
|
|
|
/* Get trap frame and link previous one*/
|
|
|
|
Thread = KeGetCurrentThread();
|
|
|
|
TrapFrame = Thread->TrapFrame;
|
2010-02-01 03:51:45 +00:00
|
|
|
Thread->TrapFrame = KiGetLinkedTrapFrame(TrapFrame);
|
2021-06-11 12:29:21 +00:00
|
|
|
|
2010-01-19 08:41:03 +00:00
|
|
|
/* Continue from this point on */
|
2024-03-25 17:04:58 +00:00
|
|
|
Status = KiContinue(Context, ExceptionFrame, TrapFrame);
|
2024-04-27 14:23:02 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2010-01-19 08:41:03 +00:00
|
|
|
{
|
2024-04-27 14:23:02 +00:00
|
|
|
DPRINT1("KiContinue failed. Status = 0x%lx\n", Status);
|
|
|
|
return Status;
|
2010-01-19 08:41:03 +00:00
|
|
|
}
|
2024-04-27 14:23:02 +00:00
|
|
|
|
|
|
|
/* Check if alert was requested */
|
|
|
|
if (TestAlert)
|
2010-01-19 08:41:03 +00:00
|
|
|
{
|
2024-04-27 14:23:02 +00:00
|
|
|
KeTestAlertThread(Thread->PreviousMode);
|
2010-01-19 08:41:03 +00:00
|
|
|
}
|
2021-06-11 12:29:21 +00:00
|
|
|
|
2024-04-27 14:23:02 +00:00
|
|
|
/* Exit to new context */
|
|
|
|
KiExceptionExit(TrapFrame, ExceptionFrame);
|
2010-01-19 08:41:03 +00:00
|
|
|
}
|
|
|
|
|
2006-11-08 11:47:44 +00:00
|
|
|
/* EOF */
|