KSPIN_LOCK BugCheckCallbackLock;
ULONG KeBugCheckActive, KeBugCheckOwner;
LONG KeBugCheckOwnerRecursionCount;
-PRTL_MESSAGE_RESOURCE_DATA KiBugCodeMessages;
+PMESSAGE_RESOURCE_DATA KiBugCodeMessages;
ULONG KeBugCheckCount = 1;
ULONG KiHardwareTrigger;
PUNICODE_STRING KiBugCheckDriver;
ULONG_PTR KiBugCheckData[5];
+PKNMI_HANDLER_CALLBACK KiNmiCallbackListHead;
+KSPIN_LOCK KiNmiCallbackListLock;
/* Bugzilla Reporting */
UNICODE_STRING KeRosProcessorName, KeRosBiosDate, KeRosBiosVersion;
PVOID
NTAPI
-KiPcToFileHeader(IN PVOID Eip,
+KiPcToFileHeader(IN PVOID Pc,
OUT PLDR_DATA_TABLE_ENTRY *LdrEntry,
IN BOOLEAN DriversOnly,
OUT PBOOLEAN InKernel)
{
ULONG i = 0;
- PVOID ImageBase, EipBase = NULL;
+ PVOID ImageBase, PcBase = NULL;
PLDR_DATA_TABLE_ENTRY Entry;
PLIST_ENTRY ListHead, NextEntry;
ImageBase = Entry->DllBase;
/* Check if this is the right one */
- if (((ULONG_PTR)Eip >= (ULONG_PTR)Entry->DllBase) &&
- ((ULONG_PTR)Eip < ((ULONG_PTR)Entry->DllBase + Entry->SizeOfImage)))
+ if (((ULONG_PTR)Pc >= (ULONG_PTR)Entry->DllBase) &&
+ ((ULONG_PTR)Pc < ((ULONG_PTR)Entry->DllBase + Entry->SizeOfImage)))
{
/* Return this entry */
*LdrEntry = Entry;
- EipBase = ImageBase;
+ PcBase = ImageBase;
/* Check if this was a kernel or HAL entry */
if (i <= 2) *InKernel = TRUE;
}
/* Return the base address */
- return EipBase;
+ return PcBase;
}
BOOLEAN
PVOID
NTAPI
-KiRosPcToUserFileHeader(IN PVOID Eip,
+KiRosPcToUserFileHeader(IN PVOID Pc,
OUT PLDR_DATA_TABLE_ENTRY *LdrEntry)
{
- PVOID ImageBase, EipBase = NULL;
+ PVOID ImageBase, PcBase = NULL;
PLDR_DATA_TABLE_ENTRY Entry;
PLIST_ENTRY ListHead, NextEntry;
ImageBase = Entry->DllBase;
/* Check if this is the right one */
- if (((ULONG_PTR)Eip >= (ULONG_PTR)Entry->DllBase) &&
- ((ULONG_PTR)Eip < ((ULONG_PTR)Entry->DllBase + Entry->SizeOfImage)))
+ if (((ULONG_PTR)Pc >= (ULONG_PTR)Entry->DllBase) &&
+ ((ULONG_PTR)Pc < ((ULONG_PTR)Entry->DllBase + Entry->SizeOfImage)))
{
/* Return this entry */
*LdrEntry = Entry;
- EipBase = ImageBase;
+ PcBase = ImageBase;
break;
}
}
}
/* Return the base address */
- return EipBase;
+ return PcBase;
}
USHORT
NTAPI
KiInitializeBugCheck(VOID)
{
- PRTL_MESSAGE_RESOURCE_DATA BugCheckData;
+ PMESSAGE_RESOURCE_DATA BugCheckData;
LDR_RESOURCE_INFO ResourceInfo;
PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry;
NTSTATUS Status;
for (i = 0; i < IdOffset; i++)
{
/* Advance in the Entries */
- MessageEntry += ((PRTL_MESSAGE_RESOURCE_ENTRY)MessageEntry)->
+ MessageEntry += ((PMESSAGE_RESOURCE_ENTRY)MessageEntry)->
Length;
}
/* Get the final Code */
- BugCode = ((PRTL_MESSAGE_RESOURCE_ENTRY)MessageEntry)->Text;
+ BugCode = ((PMESSAGE_RESOURCE_ENTRY)MessageEntry)->Text;
i = strlen(BugCode);
/* Handle newlines */
}
}
-DECLSPEC_NORETURN
VOID
NTAPI
KiBugCheckDebugBreak(IN ULONG StatusCode)
{
- /* If KDBG isn't connected, freeze the CPU, otherwise, break */
- if (KdDebuggerNotPresent) for (;;) KeArchHaltProcessor();
- DbgBreakPointWithStatus(StatusCode);
- while (TRUE);
+ /*
+ * Wrap this in SEH so we don't crash if
+ * there is no debugger or if it disconnected
+ */
+DoBreak:
+ _SEH2_TRY
+ {
+ /* Breakpoint */
+ DbgBreakPointWithStatus(StatusCode);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* No debugger, halt the CPU */
+ HalHaltSystem();
+ }
+ _SEH2_END;
+
+ /* Break again if this wasn't first try */
+ if (StatusCode != DBG_STATUS_BUGCHECK_FIRST) goto DoBreak;
}
PCHAR
CHAR AnsiName[128];
BOOLEAN IsSystem, IsHardError = FALSE, Reboot = FALSE;
PCHAR HardErrCaption = NULL, HardErrMessage = NULL;
- PVOID Eip = NULL, Memory;
+ PVOID Pc = NULL, Memory;
PVOID DriverBase;
PLDR_DATA_TABLE_ENTRY LdrEntry;
PULONG_PTR HardErrorParameters;
/* Check if this is a kernel-mode exception */
case KERNEL_MODE_EXCEPTION_NOT_HANDLED:
- //case SYSTEM_THREAD_EXCEPTION_NOT_HANDLED:
+ case SYSTEM_THREAD_EXCEPTION_NOT_HANDLED:
case KMODE_EXCEPTION_NOT_HANDLED:
/* Use the generic text message */
if (BugCheckParameter3) TrapFrame = (PVOID)BugCheckParameter3;
}
- /* Check if we got one now and if we need to get EIP */
+ /* Check if we got one now and if we need to get the Program Counter */
if ((TrapFrame) &&
(BugCheckCode != KERNEL_MODE_EXCEPTION_NOT_HANDLED))
{
-#ifdef _M_IX86
- /* Get EIP */
- Eip = (PVOID)TrapFrame->Eip;
-#elif defined(_M_PPC)
- Eip = (PVOID)TrapFrame->Dr0; /* srr0 */
-#endif
+ /* Get the Program Counter */
+ Pc = (PVOID)KeGetTrapFramePc(TrapFrame);
}
break;
* and provide a more detailed analysis. For now, we don't.
*/
- /* Eip is in parameter 4 */
- Eip = (PVOID)BugCheckParameter4;
+ /* Program Counter is in parameter 4 */
+ Pc = (PVOID)BugCheckParameter4;
/* Get the driver base */
- DriverBase = KiPcToFileHeader(Eip, &LdrEntry, FALSE, &IsSystem);
+ DriverBase = KiPcToFileHeader(Pc,
+ &LdrEntry,
+ FALSE,
+ &IsSystem);
if (IsSystem)
{
/*
KiBugCheckData[0] = DRIVER_IRQL_NOT_LESS_OR_EQUAL;
}
- /* Clear EIP so we don't look it up later */
- Eip = NULL;
+ /* Clear Pc so we don't look it up later */
+ Pc = NULL;
break;
/* Hard error */
/* Check if we have a frame now */
if (TrapFrame)
{
-#ifdef _M_IX86
- /* Get EIP */
- Eip = (PVOID)TrapFrame->Eip;
- KiBugCheckData[3] = (ULONG)Eip;
-#elif defined(_M_PPC)
- Eip = (PVOID)TrapFrame->Dr0; /* srr0 */
- KiBugCheckData[3] = (ULONG)Eip;
-#endif
+ /* Get the Program Counter */
+ Pc = (PVOID)KeGetTrapFramePc(TrapFrame);
+ KiBugCheckData[3] = (ULONG_PTR)Pc;
/* Find out if was in the kernel or drivers */
- DriverBase = KiPcToFileHeader(Eip,
+ DriverBase = KiPcToFileHeader(Pc,
&LdrEntry,
FALSE,
&IsSystem);
/* Check if the driver forgot to unlock pages */
case DRIVER_LEFT_LOCKED_PAGES_IN_PROCESS:
- /* EIP is in parameter 1 */
- Eip = (PVOID)BugCheckParameter1;
+ /* Program Counter is in parameter 1 */
+ Pc = (PVOID)BugCheckParameter1;
break;
/* Check if the driver consumed too many PTEs */
}
else
{
- /* Do we have an EIP? */
- if (Eip)
+ /* Do we have a Program Counter? */
+ if (Pc)
{
/* Dump image name */
KiDumpParameterImages(AnsiName,
- (PULONG_PTR)&Eip,
+ (PULONG_PTR)&Pc,
1,
KeBugCheckUnicodeToAnsi);
}
/* Check if we need to save the context for KD */
#ifdef _WINKD_
- if (!KdPitchDebugger) KdDebuggerDataBlock.SavedContext = (ULONG)&Context;
+ if (!KdPitchDebugger) KdDebuggerDataBlock.SavedContext = (ULONG_PTR)&Context;
#endif
/* Check if a debugger is connected */
}
else if (KeBugCheckOwnerRecursionCount > 2)
{
- /* Halt the CPU */
- for (;;) KeArchHaltProcessor();
+ /* Halt execution */
+ while (TRUE);
}
}
if (Reboot)
{
/* Unload symbols */
- DbgUnLoadImageSymbols(NULL, NtCurrentProcess(), 0);
+ DbgUnLoadImageSymbols(NULL, (PVOID)MAXULONG_PTR, 0);
HalReturnToFirmware(HalRebootRoutine);
}
/* Attempt to break in the debugger (otherwise halt CPU) */
KiBugCheckDebugBreak(DBG_STATUS_BUGCHECK_SECOND);
+
+ /* Shouldn't get here */
+ while (TRUE);
+}
+
+BOOLEAN
+NTAPI
+KiHandleNmi(VOID)
+{
+ BOOLEAN Handled = FALSE;
+ PKNMI_HANDLER_CALLBACK NmiData;
+
+ //
+ // Parse the list of callbacks
+ //
+ NmiData = KiNmiCallbackListHead;
+ while (NmiData)
+ {
+ //
+ // Save if this callback has handled it -- all it takes is one
+ //
+ Handled |= NmiData->Callback(NmiData->Context, Handled);
+ NmiData = NmiData->Next;
+ }
+
+ //
+ // Has anyone handled this?
+ //
+ return Handled;
}
/* PUBLIC FUNCTIONS **********************************************************/
return Status;
}
-/*
- * @unimplemented
- */
-NTSTATUS
-NTAPI
-KeDeregisterNmiCallback(PVOID Handle)
-{
- UNIMPLEMENTED;
- return STATUS_UNSUCCESSFUL;
-}
-
/*
* @implemented
*/
}
/*
- * @unimplemented
+ * @implemented
*/
PVOID
NTAPI
KeRegisterNmiCallback(IN PNMI_CALLBACK CallbackRoutine,
IN PVOID Context)
{
+ KIRQL OldIrql;
+ PKNMI_HANDLER_CALLBACK NmiData, Next;
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+
+ //
+ // Allocate NMI callback data
+ //
+ NmiData = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(KNMI_HANDLER_CALLBACK),
+ 'IMNK');
+ if (!NmiData) return NULL;
+
+ //
+ // Fill in the information
+ //
+ NmiData->Callback = CallbackRoutine;
+ NmiData->Context = Context;
+ NmiData->Handle = NmiData;
+
+ //
+ // Insert it into NMI callback list
+ //
+ KiAcquireNmiListLock(&OldIrql);
+ NmiData->Next = KiNmiCallbackListHead;
+ Next = InterlockedCompareExchangePointer(&KiNmiCallbackListHead,
+ NmiData,
+ NmiData->Next);
+ ASSERT(Next == NmiData->Next);
+ KiReleaseNmiListLock(OldIrql);
+
+ //
+ // Return the opaque "handle"
+ //
+ return NmiData->Handle;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+KeDeregisterNmiCallback(PVOID Handle)
+{
UNIMPLEMENTED;
- return NULL;
+ return STATUS_UNSUCCESSFUL;
}
/*
}
}
- /* Bugcheck */
+ /* Break in the debugger */
KiBugCheckDebugBreak(DBG_STATUS_FATAL);
}