2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ke/bug.c
5 * PURPOSE: Bugcheck Support
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
13 #include <internal/debug.h>
15 #if defined (ALLOC_PRAGMA)
16 #pragma alloc_text(INIT, KiInitializeBugCheck)
19 /* GLOBALS *******************************************************************/
21 LIST_ENTRY KeBugcheckCallbackListHead
;
22 LIST_ENTRY KeBugcheckReasonCallbackListHead
;
23 KSPIN_LOCK BugCheckCallbackLock
;
24 ULONG KeBugCheckActive
, KeBugCheckOwner
;
25 LONG KeBugCheckOwnerRecursionCount
;
26 PRTL_MESSAGE_RESOURCE_DATA KiBugCodeMessages
;
27 ULONG KeBugCheckCount
= 1;
28 ULONG KiHardwareTrigger
;
29 PUNICODE_STRING KiBugCheckDriver
;
30 ULONG_PTR KiBugCheckData
[5];
32 /* PRIVATE FUNCTIONS *********************************************************/
36 KiRosPrintAddress(PVOID address
)
38 PLIST_ENTRY current_entry
;
39 PLDR_DATA_TABLE_ENTRY current
;
40 extern LIST_ENTRY PsLoadedModuleList
;
41 ULONG_PTR RelativeAddress
;
46 current_entry
= PsLoadedModuleList
.Flink
;
48 while (current_entry
!= &PsLoadedModuleList
)
50 current
= CONTAINING_RECORD(current_entry
,
54 if (address
>= (PVOID
)current
->DllBase
&&
55 address
< (PVOID
)((ULONG_PTR
)current
->DllBase
+
56 current
->SizeOfImage
))
58 RelativeAddress
= (ULONG_PTR
)address
-
59 (ULONG_PTR
)current
->DllBase
;
60 DbgPrint("<%wZ: %x>", ¤t
->FullDllName
, RelativeAddress
);
63 current_entry
= current_entry
->Flink
;
72 KeRosDumpStackFrames(IN PULONG Frame OPTIONAL
,
73 IN ULONG FrameCount OPTIONAL
)
78 /* If the caller didn't ask, assume 32 frames */
79 if (!FrameCount
) FrameCount
= 32;
81 /* Get the current frames */
82 FrameCount
= RtlCaptureStackBackTrace(2, FrameCount
, (PVOID
*)Frames
, NULL
);
84 /* Now loop them (skip the two. One for the dumper, one for the caller) */
85 for (i
= 0; i
< FrameCount
; i
++)
90 /* If we had a custom frame, make sure we've reached it first */
91 if ((Frame
) && (Frame
[1] == Addr
))
102 KiRosPrintAddress((PVOID
)Addr
);
104 /* Go to the next frame */
108 /* Finish the output */
115 KiInitializeBugCheck(VOID
)
117 PRTL_MESSAGE_RESOURCE_DATA BugCheckData
;
118 LDR_RESOURCE_INFO ResourceInfo
;
119 PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry
;
121 PLDR_DATA_TABLE_ENTRY LdrEntry
;
123 /* Get the kernel entry */
124 LdrEntry
= CONTAINING_RECORD(KeLoaderBlock
->LoadOrderListHead
.Flink
,
125 LDR_DATA_TABLE_ENTRY
,
128 /* Cache the Bugcheck Message Strings. Prepare the Lookup Data */
129 ResourceInfo
.Type
= 11;
130 ResourceInfo
.Name
= 1;
131 ResourceInfo
.Language
= 9;
134 Status
= LdrFindResource_U(LdrEntry
->DllBase
,
139 /* Make sure it worked */
140 if (NT_SUCCESS(Status
))
142 /* Now actually get a pointer to it */
143 Status
= LdrAccessResource(LdrEntry
->DllBase
,
145 (PVOID
*)&BugCheckData
,
147 if (NT_SUCCESS(Status
)) KiBugCodeMessages
= BugCheckData
;
153 KeGetBugMessageText(IN ULONG BugCheckCode
,
154 OUT PANSI_STRING OutputString OPTIONAL
)
158 ULONG_PTR MessageEntry
;
160 BOOLEAN Result
= FALSE
;
162 /* Make sure we're not bugchecking too early */
163 if (!KiBugCodeMessages
) return Result
;
165 /* Find the message. This code is based on RtlFindMesssage */
166 for (i
= 0; i
< KiBugCodeMessages
->NumberOfBlocks
; i
++)
168 /* Check if the ID Matches */
169 if ((BugCheckCode
>= KiBugCodeMessages
->Blocks
[i
].LowId
) &&
170 (BugCheckCode
<= KiBugCodeMessages
->Blocks
[i
].HighId
))
172 /* Get Offset to Entry */
173 MessageEntry
= KiBugCodeMessages
->Blocks
[i
].OffsetToEntries
+
174 (ULONG_PTR
)KiBugCodeMessages
;
175 IdOffset
= BugCheckCode
- KiBugCodeMessages
->Blocks
[i
].LowId
;
177 /* Get offset to ID */
178 for (i
= 0; i
< IdOffset
; i
++)
180 /* Advance in the Entries */
181 MessageEntry
+= ((PRTL_MESSAGE_RESOURCE_ENTRY
)MessageEntry
)->
185 /* Get the final Code */
186 BugCode
= ((PRTL_MESSAGE_RESOURCE_ENTRY
)MessageEntry
)->Text
;
189 /* Handle newlines */
190 while ((i
> 0) && ((BugCode
[i
] == '\n') ||
191 (BugCode
[i
] == '\r') ||
192 (BugCode
[i
] == ANSI_NULL
)))
194 /* Check if we have a string to return */
195 if (!OutputString
) BugCode
[i
] = ANSI_NULL
;
199 /* Check if caller wants an output string */
202 /* Return it in the OutputString */
203 OutputString
->Buffer
= BugCode
;
204 OutputString
->Length
= (USHORT
)i
+ 1;
205 OutputString
->MaximumLength
= (USHORT
)i
+ 1;
209 /* Direct Output to Screen */
210 InbvDisplayString(BugCode
);
211 InbvDisplayString("\r");
220 /* Return the result */
226 KiDoBugCheckCallbacks(VOID
)
228 PKBUGCHECK_CALLBACK_RECORD CurrentRecord
;
229 PLIST_ENTRY ListHead
, NextEntry
, LastEntry
;
232 /* First make sure that the list is Initialized... it might not be */
233 ListHead
= &KeBugcheckCallbackListHead
;
234 if ((ListHead
->Flink
) && (ListHead
->Blink
))
237 LastEntry
= ListHead
;
238 NextEntry
= ListHead
->Flink
;
239 while (NextEntry
!= ListHead
)
242 CurrentRecord
= CONTAINING_RECORD(NextEntry
,
243 KBUGCHECK_CALLBACK_RECORD
,
247 if (CurrentRecord
->Entry
.Blink
!= LastEntry
) return;
248 Checksum
= (ULONG_PTR
)CurrentRecord
->CallbackRoutine
;
249 Checksum
+= (ULONG_PTR
)CurrentRecord
->Buffer
;
250 Checksum
+= (ULONG_PTR
)CurrentRecord
->Length
;
251 Checksum
+= (ULONG_PTR
)CurrentRecord
->Component
;
253 /* Make sure it's inserted and valitdated */
254 if ((CurrentRecord
->State
== BufferInserted
) &&
255 (CurrentRecord
->Checksum
== Checksum
))
257 /* Call the routine */
258 CurrentRecord
->State
= BufferStarted
;
259 (CurrentRecord
->CallbackRoutine
)(CurrentRecord
->Buffer
,
260 CurrentRecord
->Length
);
261 CurrentRecord
->State
= BufferFinished
;
264 /* Go to the next entry */
265 LastEntry
= NextEntry
;
266 NextEntry
= NextEntry
->Flink
;
273 KiBugCheckDebugBreak(IN ULONG StatusCode
)
275 /* If KDBG isn't connected, freeze the CPU, otherwise, break */
276 if (KdDebuggerNotPresent
) for (;;) Ke386HaltProcessor();
277 DbgBreakPointWithStatus(StatusCode
);
282 KiPcToFileHeader(IN PVOID Eip
,
283 OUT PLDR_DATA_TABLE_ENTRY
*LdrEntry
,
284 IN BOOLEAN DriversOnly
,
285 OUT PBOOLEAN InKernel
)
288 PVOID ImageBase
, EipBase
= NULL
;
289 PLDR_DATA_TABLE_ENTRY Entry
;
290 PLIST_ENTRY ListHead
, NextEntry
;
291 extern LIST_ENTRY PsLoadedModuleList
;
296 /* Set list pointers and make sure it's valid */
297 ListHead
= &PsLoadedModuleList
;
298 NextEntry
= ListHead
->Flink
;
302 while (NextEntry
!= ListHead
)
307 /* Check if this is a kernel entry and we only want drivers */
308 if ((i
<= 2) && (DriversOnly
== TRUE
))
311 NextEntry
= NextEntry
->Flink
;
315 /* Get the loader entry */
316 Entry
= CONTAINING_RECORD(NextEntry
,
317 LDR_DATA_TABLE_ENTRY
,
320 /* Move to the next entry */
321 NextEntry
= NextEntry
->Flink
;
322 ImageBase
= Entry
->DllBase
;
324 /* Check if this is the right one */
325 if (((ULONG_PTR
)Eip
>= (ULONG_PTR
)Entry
->DllBase
) &&
326 ((ULONG_PTR
)Eip
< ((ULONG_PTR
)Entry
->DllBase
+ Entry
->SizeOfImage
)))
328 /* Return this entry */
332 /* Check if this was a kernel or HAL entry */
333 if (i
<= 2) *InKernel
= TRUE
;
339 /* Return the base address */
345 KeBugCheckUnicodeToAnsi(IN PUNICODE_STRING Unicode
,
353 /* Set length and normalize it */
354 i
= Unicode
->Length
/ sizeof(WCHAR
);
355 i
= min(i
, Length
- 1);
357 /* Set source and destination, and copy */
358 pw
= Unicode
->Buffer
;
360 while (i
--) *p
++ = (CHAR
)*pw
++;
362 /* Null terminate and return */
369 KiDumpParameterImages(IN PCHAR Message
,
370 IN PULONG_PTR Parameters
,
371 IN ULONG ParameterCount
,
372 IN PKE_BUGCHECK_UNICODE_TO_ANSI ConversionRoutine
)
376 PLDR_DATA_TABLE_ENTRY LdrEntry
;
378 PUNICODE_STRING DriverName
;
380 PIMAGE_NT_HEADERS NtHeader
;
382 BOOLEAN FirstRun
= TRUE
;
384 /* Loop parameters */
385 for (i
= 0; i
< ParameterCount
; i
++)
387 /* Get the base for this parameter */
388 ImageBase
= KiPcToFileHeader((PVOID
)Parameters
[i
],
394 /* Driver wasn't found, check for unloaded driver */
395 DriverName
= NULL
; // FIXME: ROS can't
396 if (!DriverName
) continue;
398 /* Convert the driver name */
399 ImageBase
= (PVOID
)Parameters
[i
];
400 ConversionRoutine(DriverName
, AnsiName
, sizeof(AnsiName
));
404 /* Get the NT Headers and Timestamp */
405 NtHeader
= RtlImageNtHeader(LdrEntry
->DllBase
);
406 TimeStamp
= NtHeader
->FileHeader
.TimeDateStamp
;
408 /* Convert the driver name */
409 DriverName
= &LdrEntry
->BaseDllName
;
410 ConversionRoutine(&LdrEntry
->BaseDllName
,
415 /* Format driver name */
417 "%s** %12s - Address %p base at %p, DateStamp %08lx\n",
418 FirstRun
? "\r\n*":"*",
420 (PVOID
)Parameters
[i
],
424 /* Check if we only had one parameter */
425 if (ParameterCount
<= 1)
427 /* Then just save the name */
428 KiBugCheckDriver
= DriverName
;
432 /* Otherwise, display the message */
433 InbvDisplayString(Message
);
443 KiDisplayBlueScreen(IN ULONG MessageId
,
444 IN BOOLEAN IsHardError
,
445 IN PCHAR HardErrCaption OPTIONAL
,
446 IN PCHAR HardErrMessage OPTIONAL
,
451 /* Check if bootvid is installed */
452 if (InbvIsBootDriverInstalled())
454 /* Acquire ownership and reset the display */
455 InbvAcquireDisplayOwnership();
458 /* Display blue screen */
459 InbvSolidColorFill(0, 0, 639, 479, 4);
460 InbvSetTextColor(15);
461 InbvInstallDisplayStringFilter(NULL
);
462 InbvEnableDisplayString(TRUE
);
463 InbvSetScrollRegion(0, 0, 639, 479);
466 /* Check if this is a hard error */
469 /* Display caption and message */
470 if (HardErrCaption
) InbvDisplayString(HardErrCaption
);
471 if (HardErrMessage
) InbvDisplayString(HardErrMessage
);
474 /* Begin the display */
475 InbvDisplayString("\r\n");
477 /* Print out initial message */
478 KeGetBugMessageText(BUGCHECK_MESSAGE_INTRO
, NULL
);
479 InbvDisplayString("\r\n\r\n");
481 /* Check if we have a driver */
482 if (KiBugCheckDriver
)
484 /* Print out into to driver name */
485 KeGetBugMessageText(BUGCODE_ID_DRIVER
, NULL
);
487 /* Convert and print out driver name */
488 KeBugCheckUnicodeToAnsi(KiBugCheckDriver
, AnsiName
, sizeof(AnsiName
));
489 InbvDisplayString(" ");
490 InbvDisplayString(AnsiName
);
491 InbvDisplayString("\r\n\r\n");
494 /* Check if this is the generic message */
495 if (MessageId
== BUGCODE_PSS_MESSAGE
)
497 /* It is, so get the bug code string as well */
498 KeGetBugMessageText(KiBugCheckData
[0], NULL
);
499 InbvDisplayString("\r\n\r\n");
502 /* Print second introduction message */
503 KeGetBugMessageText(PSS_MESSAGE_INTRO
, NULL
);
504 InbvDisplayString("\r\n\r\n");
506 /* Get the bug code string */
507 KeGetBugMessageText(MessageId
, NULL
);
508 InbvDisplayString("\r\n\r\n");
510 /* Print message for technical information */
511 KeGetBugMessageText(BUGCHECK_TECH_INFO
, NULL
);
513 /* Show the technical Data */
515 "\r\n\r\n*** STOP: 0x%08lX (0x%p,0x%p,0x%p,0x%p)\r\n\r\n",
517 (PVOID
)KiBugCheckData
[1],
518 (PVOID
)KiBugCheckData
[2],
519 (PVOID
)KiBugCheckData
[3],
520 (PVOID
)KiBugCheckData
[4]);
521 InbvDisplayString(AnsiName
);
523 /* Check if we have a driver*/
524 if (KiBugCheckDriver
)
526 /* Display technical driver data */
527 InbvDisplayString(Message
);
531 /* Dump parameter information */
532 KiDumpParameterImages(Message
,
533 (PVOID
)&KiBugCheckData
[1],
535 KeBugCheckUnicodeToAnsi
);
541 KeBugCheckWithTf(IN ULONG BugCheckCode
,
542 IN ULONG_PTR BugCheckParameter1
,
543 IN ULONG_PTR BugCheckParameter2
,
544 IN ULONG_PTR BugCheckParameter3
,
545 IN ULONG_PTR BugCheckParameter4
,
546 IN PKTRAP_FRAME TrapFrame
)
548 PKPRCB Prcb
= KeGetCurrentPrcb();
552 BOOLEAN IsSystem
, IsHardError
= FALSE
, Reboot
= FALSE
;
553 PCHAR HardErrCaption
= NULL
, HardErrMessage
= NULL
;
554 PVOID Eip
= NULL
, Memory
;
556 PLDR_DATA_TABLE_ENTRY LdrEntry
;
557 PULONG_PTR HardErrorParameters
;
563 /* Set active bugcheck */
564 KeBugCheckActive
= TRUE
;
565 KiBugCheckDriver
= NULL
;
567 /* Check if this is power failure simulation */
568 if (BugCheckCode
== POWER_FAILURE_SIMULATE
)
570 /* Call the Callbacks and reboot */;
571 KiDoBugCheckCallbacks();
572 HalReturnToFirmware(HalRebootRoutine
);
575 /* Save the IRQL and set hardware trigger */
576 Prcb
->DebuggerSavedIRQL
= KeGetCurrentIrql();
577 InterlockedIncrement((PLONG
)&KiHardwareTrigger
);
579 /* Capture the CPU Context */
580 RtlCaptureContext(&Prcb
->ProcessorState
.ContextFrame
);
581 KiSaveProcessorControlState(&Prcb
->ProcessorState
);
582 Context
= Prcb
->ProcessorState
.ContextFrame
;
584 /* FIXME: Call the Watchdog if it's registered */
586 /* Check which bugcode this is */
587 switch (BugCheckCode
)
589 /* These bug checks already have detailed messages, keep them */
590 case UNEXPECTED_KERNEL_MODE_TRAP
:
591 case DRIVER_CORRUPTED_EXPOOL
:
592 case ACPI_BIOS_ERROR
:
593 case ACPI_BIOS_FATAL_ERROR
:
594 case THREAD_STUCK_IN_DEVICE_DRIVER
:
596 case FAT_FILE_SYSTEM
:
597 case NO_MORE_SYSTEM_PTES
:
598 case INACCESSIBLE_BOOT_DEVICE
:
600 /* Keep the same code */
601 MessageId
= BugCheckCode
;
604 /* Check if this is a kernel-mode exception */
605 case KERNEL_MODE_EXCEPTION_NOT_HANDLED
:
606 //case SYSTEM_THREAD_EXCEPTION_NOT_HANDLED:
607 case KMODE_EXCEPTION_NOT_HANDLED
:
609 /* Use the generic text message */
610 MessageId
= KMODE_EXCEPTION_NOT_HANDLED
;
613 /* File-system errors */
614 case NTFS_FILE_SYSTEM
:
616 /* Use the generic message for FAT */
617 MessageId
= FAT_FILE_SYSTEM
;
620 /* Check if this is a coruption of the Mm's Pool */
621 case DRIVER_CORRUPTED_MMPOOL
:
623 /* Use generic corruption message */
624 MessageId
= DRIVER_CORRUPTED_EXPOOL
;
627 /* Check if this is a signature check failure */
628 case STATUS_SYSTEM_IMAGE_BAD_SIGNATURE
:
630 /* Use the generic corruption message */
631 MessageId
= BUGCODE_PSS_MESSAGE_SIGNATURE
;
634 /* All other codes */
637 /* Use the default bugcheck message */
638 MessageId
= BUGCODE_PSS_MESSAGE
;
642 /* Save bugcheck data */
643 KiBugCheckData
[0] = BugCheckCode
;
644 KiBugCheckData
[1] = BugCheckParameter1
;
645 KiBugCheckData
[2] = BugCheckParameter2
;
646 KiBugCheckData
[3] = BugCheckParameter3
;
647 KiBugCheckData
[4] = BugCheckParameter4
;
649 /* Now check what bugcheck this is */
650 switch (BugCheckCode
)
652 /* Invalid access to R/O memory or Unhandled KM Exception */
653 case KERNEL_MODE_EXCEPTION_NOT_HANDLED
:
654 case ATTEMPTED_WRITE_TO_READONLY_MEMORY
:
655 case ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY
:
657 /* Check if we have a trap frame */
660 /* Use parameter 3 as a trap frame, if it exists */
661 if (BugCheckParameter3
) TrapFrame
= (PVOID
)BugCheckParameter3
;
664 /* Check if we got one now and if we need to get EIP */
666 (BugCheckCode
!= KERNEL_MODE_EXCEPTION_NOT_HANDLED
))
669 Eip
= (PVOID
)TrapFrame
->Eip
;
674 case IRQL_NOT_LESS_OR_EQUAL
:
677 * The NT kernel has 3 special sections:
678 * MISYSPTE, POOLMI and POOLCODE. The bug check code can
679 * determine in which of these sections this bugcode happened
680 * and provide a more detailed analysis. For now, we don't.
683 /* Eip is in parameter 4 */
684 Eip
= (PVOID
)BugCheckParameter4
;
686 /* Get the driver base */
687 DriverBase
= KiPcToFileHeader(Eip
, &LdrEntry
, FALSE
, &IsSystem
);
691 * The error happened inside the kernel or HAL.
692 * Get the memory address that was being referenced.
694 Memory
= (PVOID
)BugCheckParameter1
;
696 /* Find to which driver it belongs */
697 DriverBase
= KiPcToFileHeader(Memory
,
703 /* Get the driver name and update the bug code */
704 KiBugCheckDriver
= &LdrEntry
->BaseDllName
;
705 KiBugCheckData
[0] = DRIVER_PORTION_MUST_BE_NONPAGED
;
709 /* Find the driver that unloaded at this address */
710 KiBugCheckDriver
= NULL
; // FIXME: ROS can't locate
712 /* Check if the cause was an unloaded driver */
713 if (KiBugCheckDriver
)
715 /* Update bug check code */
717 SYSTEM_SCAN_AT_RAISED_IRQL_CAUGHT_IMPROPER_DRIVER_UNLOAD
;
723 /* Update the bug check code */
724 KiBugCheckData
[0] = DRIVER_IRQL_NOT_LESS_OR_EQUAL
;
727 /* Clear EIP so we don't look it up later */
732 case FATAL_UNHANDLED_HARD_ERROR
:
734 /* Copy bug check data from hard error */
735 HardErrorParameters
= (PULONG_PTR
)BugCheckParameter2
;
736 KiBugCheckData
[0] = BugCheckParameter1
;
737 KiBugCheckData
[1] = HardErrorParameters
[0];
738 KiBugCheckData
[2] = HardErrorParameters
[1];
739 KiBugCheckData
[3] = HardErrorParameters
[2];
740 KiBugCheckData
[4] = HardErrorParameters
[3];
742 /* Remember that this is hard error and set the caption/message */
744 HardErrCaption
= (PCHAR
)BugCheckParameter3
;
745 HardErrMessage
= (PCHAR
)BugCheckParameter4
;
749 case PAGE_FAULT_IN_NONPAGED_AREA
:
751 /* Assume no driver */
754 /* Check if we have a trap frame */
757 /* We don't, use parameter 3 if possible */
758 if (BugCheckParameter3
) TrapFrame
= (PVOID
)BugCheckParameter3
;
761 /* Check if we have a frame now */
765 Eip
= (PVOID
)TrapFrame
->Eip
;
766 KiBugCheckData
[3] = (ULONG
)Eip
;
768 /* Find out if was in the kernel or drivers */
769 DriverBase
= KiPcToFileHeader(Eip
,
776 * Now we should check if this happened in:
777 * 1) Special Pool 2) Free Special Pool 3) Session Pool
778 * and update the bugcheck code appropriately.
781 /* Check if we didn't have a driver base */
784 /* Find the driver that unloaded at this address */
785 KiBugCheckDriver
= NULL
; // FIXME: ROS can't locate
787 /* Check if the cause was an unloaded driver */
788 if (KiBugCheckDriver
)
791 DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS
;
796 /* Check if the driver forgot to unlock pages */
797 case DRIVER_LEFT_LOCKED_PAGES_IN_PROCESS
:
799 /* EIP is in parameter 1 */
800 Eip
= (PVOID
)BugCheckParameter1
;
803 /* Check if the driver consumed too many PTEs */
804 case DRIVER_USED_EXCESSIVE_PTES
:
806 /* Loader entry is in parameter 1 */
807 LdrEntry
= (PVOID
)BugCheckParameter1
;
808 KiBugCheckDriver
= &LdrEntry
->BaseDllName
;
811 /* Check if the driver has a stuck thread */
812 case THREAD_STUCK_IN_DEVICE_DRIVER
:
814 /* The name is in Parameter 3 */
815 KiBugCheckDriver
= (PVOID
)BugCheckParameter3
;
823 /* Do we have a driver name? */
824 if (KiBugCheckDriver
)
826 /* Convert it to ANSI */
827 KeBugCheckUnicodeToAnsi(KiBugCheckDriver
, AnsiName
, sizeof(AnsiName
));
831 /* Do we have an EIP? */
834 /* Dump image name */
835 KiDumpParameterImages(AnsiName
,
838 KeBugCheckUnicodeToAnsi
);
842 /* Check if we need to save the context for KD */
844 if (!KdPitchDebugger
) KdDebuggerDataBlock
.SavedContext
= (ULONG
)&Context
;
847 /* Check if a debugger is connected */
848 if ((BugCheckCode
!= MANUALLY_INITIATED_CRASH
) && (KdDebuggerEnabled
))
850 /* Crash on the debugger console */
851 DbgPrint("\n*** Fatal System Error: 0x%08lx\n"
852 " (0x%p,0x%p,0x%p,0x%p)\n\n",
859 /* Check if the debugger isn't currently connected */
860 if (!KdDebuggerNotPresent
)
862 /* Check if we have a driver to blame */
863 if (KiBugCheckDriver
)
866 DbgPrint("Driver at fault: %s.\n", AnsiName
);
869 /* Check if this was a hard error */
872 /* Print caption and message */
873 if (HardErrCaption
) DbgPrint(HardErrCaption
);
874 if (HardErrMessage
) DbgPrint(HardErrMessage
);
877 /* Break in the debugger */
878 KiBugCheckDebugBreak(DBG_STATUS_BUGCHECK_FIRST
);
884 * Ok, so debugging is enabled, but KDBG isn't there.
885 * We'll manually dump the stack for the user.
887 KeRosDumpStackFrames(NULL
, 0);
891 /* Raise IRQL to HIGH_LEVEL */
893 KeRaiseIrql(HIGH_LEVEL
, &OldIrql
);
895 /* ROS HACK: Unlock the Kernel Address Space if we own it */
896 if (KernelAddressSpaceLock
.Owner
== KeGetCurrentThread())
898 MmUnlockAddressSpace(MmGetKernelAddressSpace());
901 /* Avoid recursion */
902 if (!InterlockedDecrement((PLONG
)&KeBugCheckCount
))
905 /* Set CPU that is bug checking now */
906 KeBugCheckOwner
= Prcb
->Number
;
908 /* Freeze the other CPUs */
909 for (i
= 0; i
< KeNumberProcessors
; i
++)
911 if (i
!= (LONG
)KeGetCurrentProcessorNumber())
913 /* Send the IPI and give them one second to catch up */
914 KiIpiSendRequest(1 << i
, IPI_FREEZE
);
915 KeStallExecutionProcessor(1000000);
920 /* Display the BSOD */
921 KiDisplayBlueScreen(MessageId
,
927 /* Check if the debugger is disabled but we can enable it */
928 if (!(KdDebuggerEnabled
) && !(KdPitchDebugger
))
932 KdEnableDebuggerWithLock(FALSE
);
937 /* Otherwise, print the last line */
938 InbvDisplayString("\r\n");
941 /* Save the context */
942 Prcb
->ProcessorState
.ContextFrame
= Context
;
944 /* FIXME: Support Triage Dump */
946 /* Write the crash dump */
947 MmDumpToPagingFile(KiBugCheckData
[4],
956 /* Increase recursion count */
957 KeBugCheckOwnerRecursionCount
++;
958 if (KeBugCheckOwnerRecursionCount
== 2)
960 /* Break in the debugger */
961 KiBugCheckDebugBreak(DBG_STATUS_BUGCHECK_SECOND
);
963 else if (KeBugCheckOwnerRecursionCount
> 2)
966 for (;;) Ke386HaltProcessor();
970 /* Call the Callbacks */
971 KiDoBugCheckCallbacks();
973 /* FIXME: Call Watchdog if enabled */
975 /* Check if we have to reboot */
979 DbgUnLoadImageSymbols(NULL
, NtCurrentProcess(), 0);
980 HalReturnToFirmware(HalRebootRoutine
);
983 /* Attempt to break in the debugger (otherwise halt CPU) */
984 KiBugCheckDebugBreak(DBG_STATUS_BUGCHECK_SECOND
);
987 /* PUBLIC FUNCTIONS **********************************************************/
994 KeDeregisterBugCheckCallback(IN PKBUGCHECK_CALLBACK_RECORD CallbackRecord
)
997 BOOLEAN Status
= FALSE
;
999 /* Raise IRQL to High */
1000 KeRaiseIrql(HIGH_LEVEL
, &OldIrql
);
1002 /* Check the Current State */
1003 if (CallbackRecord
->State
== BufferInserted
)
1005 /* Reset state and remove from list */
1006 CallbackRecord
->State
= BufferEmpty
;
1007 RemoveEntryList(&CallbackRecord
->Entry
);
1011 /* Lower IRQL and return */
1012 KeLowerIrql(OldIrql
);
1021 KeDeregisterBugCheckReasonCallback(
1022 IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord
)
1025 BOOLEAN Status
= FALSE
;
1027 /* Raise IRQL to High */
1028 KeRaiseIrql(HIGH_LEVEL
, &OldIrql
);
1030 /* Check the Current State */
1031 if (CallbackRecord
->State
== BufferInserted
)
1033 /* Reset state and remove from list */
1034 CallbackRecord
->State
= BufferEmpty
;
1035 RemoveEntryList(&CallbackRecord
->Entry
);
1039 /* Lower IRQL and return */
1040 KeLowerIrql(OldIrql
);
1049 KeRegisterBugCheckCallback(IN PKBUGCHECK_CALLBACK_RECORD CallbackRecord
,
1050 IN PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine
,
1053 IN PUCHAR Component
)
1056 BOOLEAN Status
= FALSE
;
1058 /* Raise IRQL to High */
1059 KeRaiseIrql(HIGH_LEVEL
, &OldIrql
);
1061 /* Check the Current State first so we don't double-register */
1062 if (CallbackRecord
->State
== BufferEmpty
)
1064 /* Set the Callback Settings and insert into the list */
1065 CallbackRecord
->Length
= Length
;
1066 CallbackRecord
->Buffer
= Buffer
;
1067 CallbackRecord
->Component
= Component
;
1068 CallbackRecord
->CallbackRoutine
= CallbackRoutine
;
1069 CallbackRecord
->State
= BufferInserted
;
1070 InsertTailList(&KeBugcheckCallbackListHead
, &CallbackRecord
->Entry
);
1074 /* Lower IRQL and return */
1075 KeLowerIrql(OldIrql
);
1084 KeRegisterBugCheckReasonCallback(
1085 IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord
,
1086 IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine
,
1087 IN KBUGCHECK_CALLBACK_REASON Reason
,
1088 IN PUCHAR Component
)
1091 BOOLEAN Status
= FALSE
;
1093 /* Raise IRQL to High */
1094 KeRaiseIrql(HIGH_LEVEL
, &OldIrql
);
1096 /* Check the Current State first so we don't double-register */
1097 if (CallbackRecord
->State
== BufferEmpty
)
1099 /* Set the Callback Settings and insert into the list */
1100 CallbackRecord
->Component
= Component
;
1101 CallbackRecord
->CallbackRoutine
= CallbackRoutine
;
1102 CallbackRecord
->State
= BufferInserted
;
1103 CallbackRecord
->Reason
= Reason
;
1104 InsertTailList(&KeBugcheckReasonCallbackListHead
,
1105 &CallbackRecord
->Entry
);
1109 /* Lower IRQL and return */
1110 KeLowerIrql(OldIrql
);
1119 KeBugCheckEx(IN ULONG BugCheckCode
,
1120 IN ULONG_PTR BugCheckParameter1
,
1121 IN ULONG_PTR BugCheckParameter2
,
1122 IN ULONG_PTR BugCheckParameter3
,
1123 IN ULONG_PTR BugCheckParameter4
)
1125 /* Call the internal API */
1126 KeBugCheckWithTf(BugCheckCode
,
1139 KeBugCheck(ULONG BugCheckCode
)
1141 /* Call the internal API */
1142 KeBugCheckWithTf(BugCheckCode
, 0, 0, 0, 0, NULL
);
1150 KeEnterKernelDebugger(VOID
)
1152 /* Disable interrupts */
1153 KiHardwareTrigger
= 1;
1156 /* Check the bugcheck count */
1157 if (!InterlockedDecrement((PLONG
)&KeBugCheckCount
))
1159 /* There was only one, is the debugger disabled? */
1160 if (!(KdDebuggerEnabled
) && !(KdPitchDebugger
))
1162 /* Enable the debugger */
1163 KdInitSystem(0, NULL
);
1168 KiBugCheckDebugBreak(DBG_STATUS_FATAL
);