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 /* ROS Internal. Please deprecate */
23 HalReleaseDisplayOwnership(
27 /* GLOBALS *******************************************************************/
29 LIST_ENTRY BugcheckCallbackListHead
;
30 LIST_ENTRY BugcheckReasonCallbackListHead
;
31 KSPIN_LOCK BugCheckCallbackLock
;
32 ULONG KeBugCheckActive
, KeBugCheckOwner
;
33 LONG KeBugCheckOwnerRecursionCount
;
34 PRTL_MESSAGE_RESOURCE_DATA KiBugCodeMessages
;
35 ULONG KeBugCheckCount
= 1;
36 ULONG KiHardwareTrigger
;
37 PUNICODE_STRING KiBugCheckDriver
;
38 ULONG_PTR KiBugCheckData
[5];
40 /* PRIVATE FUNCTIONS *********************************************************/
44 KiRosPrintAddress(PVOID address
)
46 PLIST_ENTRY current_entry
;
47 PLDR_DATA_TABLE_ENTRY current
;
48 extern LIST_ENTRY ModuleListHead
;
49 ULONG_PTR RelativeAddress
;
54 current_entry
= ModuleListHead
.Flink
;
56 while (current_entry
!= &ModuleListHead
)
58 current
= CONTAINING_RECORD(current_entry
,
62 if (address
>= (PVOID
)current
->DllBase
&&
63 address
< (PVOID
)((ULONG_PTR
)current
->DllBase
+
64 current
->SizeOfImage
))
66 RelativeAddress
= (ULONG_PTR
)address
-
67 (ULONG_PTR
)current
->DllBase
;
68 DbgPrint("<%wZ: %x>", ¤t
->FullDllName
, RelativeAddress
);
71 current_entry
= current_entry
->Flink
;
80 KeRosDumpStackFrames(IN PULONG Frame OPTIONAL
,
81 IN ULONG FrameCount OPTIONAL
)
86 /* If the caller didn't ask, assume 32 frames */
87 if (!FrameCount
) FrameCount
= 32;
89 /* Get the current frames */
90 FrameCount
= RtlCaptureStackBackTrace(2, FrameCount
, (PVOID
*)Frames
, NULL
);
92 /* Now loop them (skip the two. One for the dumper, one for the caller) */
93 for (i
= 0; i
< FrameCount
; i
++)
98 /* If we had a custom frame, make sure we've reached it first */
99 if ((Frame
) && (Frame
[1] == Addr
))
105 /* Skip this entry */
110 if (!KeRosPrintAddress((PVOID
)Addr
)) DbgPrint("<%X>", Addr
);
112 /* Go to the next frame */
116 /* Finish the output */
123 KiInitializeBugCheck(VOID
)
126 PRTL_MESSAGE_RESOURCE_DATA BugCheckData
;
127 LDR_RESOURCE_INFO ResourceInfo
;
128 PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry
;
131 /* Cache the Bugcheck Message Strings. Prepare the Lookup Data */
132 ResourceInfo
.Type
= 11;
133 ResourceInfo
.Name
= 1;
134 ResourceInfo
.Language
= 9;
137 Status
= LdrFindResource_U((PVOID
)KERNEL_BASE
,
142 /* Make sure it worked */
143 if (NT_SUCCESS(Status
))
145 /* Now actually get a pointer to it */
146 Status
= LdrAccessResource((PVOID
)KERNEL_BASE
,
148 (PVOID
*)&BugCheckData
,
150 if (NT_SUCCESS(Status
)) KiBugCodeMessages
= BugCheckData
;
157 KeGetBugMessageText(IN ULONG BugCheckCode
,
158 OUT PANSI_STRING OutputString OPTIONAL
)
162 ULONG_PTR MessageEntry
;
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 /* Return it in the OutputString */
192 OutputString
->Buffer
= BugCode
;
193 OutputString
->Length
= i
+ 1;
194 OutputString
->MaximumLength
= i
+ 1;
198 /* Direct Output to Screen */
199 InbvDisplayString(BugCode
);
200 InbvDisplayString("\r");
209 KiDoBugCheckCallbacks(VOID
)
211 PKBUGCHECK_CALLBACK_RECORD CurrentRecord
;
212 PLIST_ENTRY ListHead
, NextEntry
, LastEntry
;
215 /* First make sure that the list is Initialized... it might not be */
216 ListHead
= &BugcheckCallbackListHead
;
217 if ((ListHead
->Flink
) && (ListHead
->Blink
))
220 LastEntry
= ListHead
;
221 NextEntry
= ListHead
->Flink
;
222 while (NextEntry
!= ListHead
)
225 CurrentRecord
= CONTAINING_RECORD(NextEntry
,
226 KBUGCHECK_CALLBACK_RECORD
,
230 if (CurrentRecord
->Entry
.Blink
!= LastEntry
) return;
231 Checksum
= (ULONG_PTR
)CurrentRecord
->CallbackRoutine
;
232 Checksum
+= (ULONG_PTR
)CurrentRecord
->Buffer
;
233 Checksum
+= (ULONG_PTR
)CurrentRecord
->Length
;
234 Checksum
+= (ULONG_PTR
)CurrentRecord
->Component
;
236 /* Make sure it's inserted and valitdated */
237 if ((CurrentRecord
->State
== BufferInserted
) &&
238 (CurrentRecord
->Checksum
== Checksum
))
240 /* Call the routine */
241 CurrentRecord
->State
= BufferStarted
;
242 (CurrentRecord
->CallbackRoutine
)(CurrentRecord
->Buffer
,
243 CurrentRecord
->Length
);
244 CurrentRecord
->State
= BufferFinished
;
247 /* Go to the next entry */
248 LastEntry
= NextEntry
;
249 NextEntry
= NextEntry
->Flink
;
256 KiBugCheckDebugBreak(IN ULONG StatusCode
)
258 /* If KDBG isn't connected, freeze the CPU, otherwise, break */
259 if (KdDebuggerNotPresent
) for (;;) KeHaltProcessor();
260 DbgBreakPointWithStatus(StatusCode
);
265 KiPcToFileHeader(IN PVOID Eip
,
266 OUT PLDR_DATA_TABLE_ENTRY
*LdrEntry
,
267 IN BOOLEAN DriversOnly
,
268 OUT PBOOLEAN InKernel
)
272 PVOID ImageBase
, EipBase
= NULL
;
273 PLDR_DATA_TABLE_ENTRY Entry
;
274 PLIST_ENTRY ListHead
, NextEntry
;
275 extern LIST_ENTRY ModuleListHead
;
280 /* Set list pointers and make sure it's valid */
281 ListHead
= &ModuleListHead
;
282 NextEntry
= ListHead
->Flink
;
286 while (NextEntry
!= ListHead
)
291 /* Check if this is a kernel entry and we only want drivers */
292 if ((i
<= 2) && (DriversOnly
== TRUE
))
295 NextEntry
= NextEntry
->Flink
;
299 /* Get the loader entry */
300 Entry
= CONTAINING_RECORD(NextEntry
,
301 LDR_DATA_TABLE_ENTRY
,
304 /* Move to the next entry */
305 NextEntry
= NextEntry
->Flink
;
306 ImageBase
= Entry
->DllBase
;
308 /* Check if this is the right one */
309 if (((ULONG_PTR
)Eip
>= (ULONG_PTR
)Entry
->DllBase
) &&
310 ((ULONG_PTR
)Eip
< ((ULONG_PTR
)Entry
->DllBase
+ Entry
->SizeOfImage
)))
312 /* Return this entry */
316 /* Check if this was a kernel or HAL entry */
317 if (i
<= 2) *InKernel
= TRUE
;
323 /* Return the base address */
332 KeBugCheckUnicodeToAnsi(IN PUNICODE_STRING Unicode
,
340 /* Set length and normalize it */
341 i
= Unicode
->Length
/ sizeof(WCHAR
);
342 i
= min(i
, Length
- 1);
344 /* Set source and destination, and copy */
345 pw
= Unicode
->Buffer
;
347 while (i
--) *p
++ = (CHAR
)*pw
++;
349 /* Null terminate and return */
356 KiDumpParameterImages(IN PCHAR Message
,
357 IN PULONG_PTR Parameters
,
358 IN ULONG ParameterCount
,
359 IN PKE_BUGCHECK_UNICODE_TO_ANSI ConversionRoutine
)
363 PLDR_DATA_TABLE_ENTRY LdrEntry
;
365 PUNICODE_STRING DriverName
;
367 PIMAGE_NT_HEADERS NtHeader
;
369 BOOLEAN FirstRun
= TRUE
;
371 /* Loop parameters */
372 for (i
= 0; i
< ParameterCount
; i
++)
374 /* Get the base for this parameter */
375 ImageBase
= KiPcToFileHeader((PVOID
)Parameters
[i
],
381 /* Driver wasn't found, check for unloaded driver */
382 DriverName
= NULL
; // FIXME: ROS can't
383 if (!DriverName
) continue;
385 /* Convert the driver name */
386 ImageBase
= (PVOID
)Parameters
[i
];
387 ConversionRoutine(DriverName
, AnsiName
, sizeof(AnsiName
));
391 /* Get the NT Headers and Timestamp */
392 NtHeader
= RtlImageNtHeader(LdrEntry
->DllBase
);
393 TimeStamp
= NtHeader
->FileHeader
.TimeDateStamp
;
395 /* Convert the driver name */
396 DriverName
= &LdrEntry
->BaseDllName
;
397 ConversionRoutine(&LdrEntry
->BaseDllName
,
402 /* Format driver name */
404 "%s** %12s - Address %p base at %p, DateStamp %08lx\n",
405 FirstRun
? "\r\n*":"*",
407 (PVOID
)Parameters
[i
],
411 /* Check if we only had one parameter */
412 if (ParameterCount
<= 1)
414 /* Then just save the name */
415 KiBugCheckDriver
= DriverName
;
419 /* Otherwise, display the message */
420 InbvDisplayString(Message
);
430 KiDisplayBlueScreen(IN ULONG MessageId
,
431 IN BOOLEAN IsHardError
,
432 IN PCHAR HardErrCaption OPTIONAL
,
433 IN PCHAR HardErrMessage OPTIONAL
,
438 /* FIXMEs: Use inbv to clear, fill and write to screen. */
440 /* Check if this is a hard error */
443 /* Display caption and message */
444 if (HardErrCaption
) InbvDisplayString(HardErrCaption
);
445 if (HardErrMessage
) InbvDisplayString(HardErrMessage
);
449 /* Begin the display */
450 InbvDisplayString("\r\n");
452 /* Print out initial message */
453 KeGetBugMessageText(BUGCHECK_MESSAGE_INTRO
, NULL
);
454 InbvDisplayString("\r\n\r\n");
456 /* Check if we have a driver */
457 if (KiBugCheckDriver
)
459 /* Print out into to driver name */
460 KeGetBugMessageText(BUGCODE_ID_DRIVER
, NULL
);
462 /* Convert and print out driver name */
463 KeBugCheckUnicodeToAnsi(KiBugCheckDriver
, AnsiName
, sizeof(AnsiName
));
464 InbvDisplayString(" ");
465 InbvDisplayString(AnsiName
);
466 InbvDisplayString("\r\n\r\n");
469 /* Check if this is the generic message */
470 if (MessageId
== BUGCODE_PSS_MESSAGE
)
472 /* It is, so get the bug code string as well */
473 KeGetBugMessageText(KiBugCheckData
[0], NULL
);
474 InbvDisplayString("\r\n\r\n");
477 /* Print second introduction message */
478 KeGetBugMessageText(PSS_MESSAGE_INTRO
, NULL
);
479 InbvDisplayString("\r\n\r\n");
481 /* Get the bug code string */
482 KeGetBugMessageText(MessageId
, NULL
);
483 InbvDisplayString("\r\n\r\n");
485 /* Print message for technical information */
486 KeGetBugMessageText(BUGCHECK_TECH_INFO
, NULL
);
488 /* Show the techincal Data */
490 "\r\n\r\n*** STOP: 0x%08lX (0x%p,0x%p,0x%p,0x%p)\r\n\r\n",
492 (PVOID
)KiBugCheckData
[1],
493 (PVOID
)KiBugCheckData
[2],
494 (PVOID
)KiBugCheckData
[3],
495 (PVOID
)KiBugCheckData
[4]);
496 InbvDisplayString(AnsiName
);
498 /* Check if we have a driver*/
499 if (KiBugCheckDriver
)
501 /* Display technical driver data */
502 InbvDisplayString(Message
);
506 /* Dump parameter information */
507 KiDumpParameterImages(Message
,
508 (PVOID
)&KiBugCheckData
[1],
510 KeBugCheckUnicodeToAnsi
);
516 KeBugCheckWithTf(IN ULONG BugCheckCode
,
517 IN ULONG_PTR BugCheckParameter1
,
518 IN ULONG_PTR BugCheckParameter2
,
519 IN ULONG_PTR BugCheckParameter3
,
520 IN ULONG_PTR BugCheckParameter4
,
521 IN PKTRAP_FRAME TrapFrame
)
523 PKPRCB Prcb
= KeGetCurrentPrcb();
527 BOOLEAN IsSystem
, IsHardError
= FALSE
;
528 PCHAR HardErrCaption
= NULL
, HardErrMessage
= NULL
;
529 PVOID Eip
= NULL
, Memory
;
531 PLDR_DATA_TABLE_ENTRY LdrEntry
;
532 PULONG_PTR HardErrorParameters
;
535 /* Set active bugcheck */
536 KeBugCheckActive
= TRUE
;
537 KiBugCheckDriver
= NULL
;
539 /* Check if this is power failure simulation */
540 if (BugCheckCode
== POWER_FAILURE_SIMULATE
)
542 /* Call the Callbacks and reboot */;
543 KiDoBugCheckCallbacks();
544 HalReturnToFirmware(HalRebootRoutine
);
547 /* Save the IRQL and set hardware trigger */
548 Prcb
->DebuggerSavedIRQL
= KeGetCurrentIrql();
549 InterlockedIncrement((PLONG
)&KiHardwareTrigger
);
551 /* Capture the CPU Context */
552 RtlCaptureContext((PVOID
)&Prcb
->ProcessorState
.ContextFrame
);
553 Context
= Prcb
->ProcessorState
.ContextFrame
;
555 /* FIXME: Call the Watchdog if it's regsitered */
557 /* Check which bugcode this is */
558 switch (BugCheckCode
)
560 /* These bug checks already have detailed messages, keep them */
561 case UNEXPECTED_KERNEL_MODE_TRAP
:
562 case DRIVER_CORRUPTED_EXPOOL
:
563 case ACPI_BIOS_ERROR
:
564 case ACPI_BIOS_FATAL_ERROR
:
565 case THREAD_STUCK_IN_DEVICE_DRIVER
:
567 case FAT_FILE_SYSTEM
:
568 case NO_MORE_SYSTEM_PTES
:
569 case INACCESSIBLE_BOOT_DEVICE
:
570 case KMODE_EXCEPTION_NOT_HANDLED
:
572 /* Keep the same code */
573 MessageId
= BugCheckCode
;
576 /* Check if this is a kernel-mode exception */
577 case KERNEL_MODE_EXCEPTION_NOT_HANDLED
:
579 /* Use the generic text message */
580 MessageId
= KMODE_EXCEPTION_NOT_HANDLED
;
582 /* File-system errors */
583 case NTFS_FILE_SYSTEM
:
585 /* Use the generic message for FAT */
586 MessageId
= FAT_FILE_SYSTEM
;
588 /* Check if this is a coruption of the Mm's Pool */
589 case DRIVER_CORRUPTED_MMPOOL
:
591 /* Use generic corruption message */
592 MessageId
= DRIVER_CORRUPTED_EXPOOL
;
594 /* Check if this is a signature check failure */
595 case STATUS_SYSTEM_IMAGE_BAD_SIGNATURE
:
597 /* Use the generic corruption message */
598 MessageId
= BUGCODE_PSS_MESSAGE_SIGNATURE
;
600 /* All other codes */
603 /* Use the default bugcheck message */
604 MessageId
= BUGCODE_PSS_MESSAGE
;
607 /* Save bugcheck data */
608 KiBugCheckData
[0] = BugCheckCode
;
609 KiBugCheckData
[1] = BugCheckParameter1
;
610 KiBugCheckData
[2] = BugCheckParameter2
;
611 KiBugCheckData
[3] = BugCheckParameter3
;
612 KiBugCheckData
[4] = BugCheckParameter4
;
614 /* Now check what bugcheck this is */
615 switch (BugCheckCode
)
617 /* Invalid access to R/O memory or Unhandled KM Exception */
618 case KERNEL_MODE_EXCEPTION_NOT_HANDLED
:
619 case ATTEMPTED_WRITE_TO_READONLY_MEMORY
:
620 case ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY
:
622 /* Check if we have a trap frame */
625 /* Use parameter 3 as a trap frame, if it exists */
626 if (BugCheckParameter3
) TrapFrame
= (PVOID
)BugCheckParameter3
;
629 /* Check if we got one now and if we need to get EIP */
631 (BugCheckCode
!= KERNEL_MODE_EXCEPTION_NOT_HANDLED
))
635 Eip
= (PVOID
)TrapFrame
->Eip
;
636 #elif defined(_M_PPC)
637 Eip
= (PVOID
)TrapFrame
->Iar
;
643 case IRQL_NOT_LESS_OR_EQUAL
:
646 * The NT kernel has 3 special sections:
647 * MISYSPTE, POOLMI and POOLCODE. The bug check code can
648 * determine in which of these sections this bugcode happened
649 * and provide a more detailed analysis. For now, we don't.
652 /* Eip is in parameter 4 */
653 Eip
= (PVOID
)BugCheckParameter4
;
655 /* Get the driver base */
656 DriverBase
= KiPcToFileHeader(Eip
, &LdrEntry
, FALSE
, &IsSystem
);
660 * The error happened inside the kernel or HAL.
661 * Get the memory address that was being referenced.
663 Memory
= (PVOID
)BugCheckParameter1
;
665 /* Find to which driver it belongs */
666 DriverBase
= KiPcToFileHeader(Memory
,
672 /* Get the driver name and update the bug code */
673 KiBugCheckDriver
= &LdrEntry
->BaseDllName
;
674 KiBugCheckData
[0] = DRIVER_PORTION_MUST_BE_NONPAGED
;
678 /* Find the driver that unloaded at this address */
679 KiBugCheckDriver
= NULL
; // FIXME: ROS can't locate
681 /* Check if the cause was an unloaded driver */
682 if (KiBugCheckDriver
)
684 /* Update bug check code */
686 SYSTEM_SCAN_AT_RAISED_IRQL_CAUGHT_IMPROPER_DRIVER_UNLOAD
;
692 /* Update the bug check code */
693 KiBugCheckData
[0] = DRIVER_IRQL_NOT_LESS_OR_EQUAL
;
696 /* Clear EIP so we don't look it up later */
701 case FATAL_UNHANDLED_HARD_ERROR
:
703 /* Copy bug check data from hard error */
704 HardErrorParameters
= (PULONG_PTR
)BugCheckParameter2
;
705 KiBugCheckData
[0] = BugCheckParameter1
;
706 KiBugCheckData
[1] = HardErrorParameters
[0];
707 KiBugCheckData
[2] = HardErrorParameters
[1];
708 KiBugCheckData
[3] = HardErrorParameters
[2];
709 KiBugCheckData
[4] = HardErrorParameters
[3];
711 /* Remember that this is hard error and set the caption/message */
713 HardErrCaption
= (PCHAR
)BugCheckParameter3
;
714 HardErrMessage
= (PCHAR
)BugCheckParameter4
;
718 case PAGE_FAULT_IN_NONPAGED_AREA
:
720 /* Assume no driver */
723 /* Check if we have a trap frame */
726 /* We don't, use parameter 3 if possible */
727 if (BugCheckParameter3
) TrapFrame
= (PVOID
)BugCheckParameter3
;
730 /* Check if we have a frame now */
735 Eip
= (PVOID
)TrapFrame
->Eip
;
736 #elif defined(_M_PPC)
737 Eip
= (PVOID
)TrapFrame
->Iar
;
740 /* Find out if was in the kernel or drivers */
741 DriverBase
= KiPcToFileHeader(Eip
, &LdrEntry
, FALSE
, &IsSystem
);
745 * Now we should check if this happened in:
746 * 1) Special Pool 2) Free Special Pool 3) Session Pool
747 * and update the bugcheck code appropriately.
750 /* Check if we had a driver base */
753 /* Find the driver that unloaded at this address */
754 KiBugCheckDriver
= NULL
; // FIXME: ROS can't locate
756 /* Check if the cause was an unloaded driver */
757 if (KiBugCheckDriver
)
760 DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS
;
765 /* Check if the driver forgot to unlock pages */
766 case DRIVER_LEFT_LOCKED_PAGES_IN_PROCESS
:
768 /* EIP is in parameter 1 */
769 Eip
= (PVOID
)BugCheckParameter1
;
772 /* Check if the driver consumed too many PTEs */
773 case DRIVER_USED_EXCESSIVE_PTES
:
775 /* Driver base is in parameter 1 */
776 DriverBase
= (PVOID
)BugCheckParameter1
;
777 /* FIXME: LdrEntry is uninitialized for god's sake!!!
778 KiBugCheckDriver = &LdrEntry->BaseDllName; */
781 /* Check if the driver has a stuck thread */
782 case THREAD_STUCK_IN_DEVICE_DRIVER
:
784 /* The name is in Parameter 3 */
785 KiBugCheckDriver
= (PVOID
)BugCheckParameter3
;
793 /* Do we have a driver name? */
794 if (KiBugCheckDriver
)
796 /* Convert it to ANSI */
797 KeBugCheckUnicodeToAnsi(KiBugCheckDriver
, AnsiName
, sizeof(AnsiName
));
801 /* Do we have an EIP? */
804 /* Dump image name */
805 KiDumpParameterImages(AnsiName
,
808 KeBugCheckUnicodeToAnsi
);
812 /* FIXME: Check if we need to save the context for KD */
814 /* Check if a debugger is connected */
815 if ((BugCheckCode
!= MANUALLY_INITIATED_CRASH
) && (KdDebuggerEnabled
))
817 /* Crash on the debugger console */
818 DbgPrint("\n*** Fatal System Error: 0x%08lx\n"
819 " (0x%p,0x%p,0x%p,0x%p)\n\n",
826 /* Check if the debugger isn't currently connected */
827 if (!KdDebuggerNotPresent
)
829 /* Check if we have a driver to blame */
830 if (KiBugCheckDriver
)
833 DbgPrint("Driver at fault: %s.\n", AnsiName
);
836 /* Check if this was a hard error */
839 /* Print caption and message */
840 if (HardErrCaption
) DbgPrint(HardErrCaption
);
841 if (HardErrMessage
) DbgPrint(HardErrMessage
);
844 /* Break in the debugger */
845 KiBugCheckDebugBreak(DBG_STATUS_BUGCHECK_FIRST
);
851 * Ok, so debugging is enabled, but KDBG isn't there.
852 * We'll manually dump the stack for the user.
854 KeRosDumpStackFrames(NULL
, 0);
858 /* Switching back to the blue screen so we print messages on it */
859 HalReleaseDisplayOwnership();
861 /* Raise IRQL to HIGH_LEVEL */
862 KeDisableInterrupts();
863 KeRaiseIrql(HIGH_LEVEL
, &OldIrql
);
865 /* Unlock the Kernel Adress Space if we own it */
866 if (KernelAddressSpaceLock
.Owner
== KeGetCurrentThread())
868 MmUnlockAddressSpace(MmGetKernelAddressSpace());
871 /* Avoid recursion */
872 if (!InterlockedDecrement((PLONG
)&KeBugCheckCount
))
874 /* Set CPU that is bug checking now */
875 KeBugCheckOwner
= Prcb
->Number
;
878 /* Freeze the other CPUs */
879 for (i
= 0; i
< KeNumberProcessors
; i
++)
881 if (i
!= (LONG
)KeGetCurrentProcessorNumber())
883 /* Send the IPI and give them one second to catch up */
884 KiIpiSendRequest(1 << i
, IPI_FREEZE
);
885 KeStallExecutionProcessor(1000000);
890 /* Display the BSOD */
891 KiDisplayBlueScreen(MessageId
,
897 /* FIXME: Enable debugger if it was pending */
899 /* Print the last line */
900 InbvDisplayString("\r\n");
902 /* Save the context */
903 Prcb
->ProcessorState
.ContextFrame
= Context
;
905 /* FIXME: Support Triage Dump */
907 /* Write the crash dump */
908 MmDumpToPagingFile(KiBugCheckData
[4],
916 /* Increase recursioun count */
917 KeBugCheckOwnerRecursionCount
++;
918 if (KeBugCheckOwnerRecursionCount
== 2)
920 /* Break in the debugger */
921 KiBugCheckDebugBreak(DBG_STATUS_BUGCHECK_SECOND
);
923 else if (KeBugCheckOwnerRecursionCount
> 2)
926 for (;;) KeHaltProcessor();
929 /* Call the Callbacks */
930 KiDoBugCheckCallbacks();
932 /* FIXME: Call Watchdog if enabled */
934 /* Attempt to break in the debugger (otherwise halt CPU) */
935 KiBugCheckDebugBreak(DBG_STATUS_BUGCHECK_SECOND
);
938 /* PUBLIC FUNCTIONS **********************************************************/
945 KeDeregisterBugCheckCallback(IN PKBUGCHECK_CALLBACK_RECORD CallbackRecord
)
948 BOOLEAN Status
= FALSE
;
950 /* Raise IRQL to High */
951 KeRaiseIrql(HIGH_LEVEL
, &OldIrql
);
953 /* Check the Current State */
954 if (CallbackRecord
->State
== BufferInserted
)
956 /* Reset state and remove from list */
957 CallbackRecord
->State
= BufferEmpty
;
958 RemoveEntryList(&CallbackRecord
->Entry
);
962 /* Lower IRQL and return */
963 KeLowerIrql(OldIrql
);
972 KeDeregisterBugCheckReasonCallback(
973 IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord
)
976 BOOLEAN Status
= FALSE
;
978 /* Raise IRQL to High */
979 KeRaiseIrql(HIGH_LEVEL
, &OldIrql
);
981 /* Check the Current State */
982 if (CallbackRecord
->State
== BufferInserted
)
984 /* Reset state and remove from list */
985 CallbackRecord
->State
= BufferEmpty
;
986 RemoveEntryList(&CallbackRecord
->Entry
);
990 /* Lower IRQL and return */
991 KeLowerIrql(OldIrql
);
1000 KeRegisterBugCheckCallback(IN PKBUGCHECK_CALLBACK_RECORD CallbackRecord
,
1001 IN PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine
,
1004 IN PUCHAR Component
)
1007 BOOLEAN Status
= FALSE
;
1009 /* Raise IRQL to High */
1010 KeRaiseIrql(HIGH_LEVEL
, &OldIrql
);
1012 /* Check the Current State first so we don't double-register */
1013 if (CallbackRecord
->State
== BufferEmpty
)
1015 /* Set the Callback Settings and insert into the list */
1016 CallbackRecord
->Length
= Length
;
1017 CallbackRecord
->Buffer
= Buffer
;
1018 CallbackRecord
->Component
= Component
;
1019 CallbackRecord
->CallbackRoutine
= CallbackRoutine
;
1020 CallbackRecord
->State
= BufferInserted
;
1021 InsertTailList(&BugcheckCallbackListHead
, &CallbackRecord
->Entry
);
1025 /* Lower IRQL and return */
1026 KeLowerIrql(OldIrql
);
1035 KeRegisterBugCheckReasonCallback(
1036 IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord
,
1037 IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine
,
1038 IN KBUGCHECK_CALLBACK_REASON Reason
,
1039 IN PUCHAR Component
)
1042 BOOLEAN Status
= FALSE
;
1044 /* Raise IRQL to High */
1045 KeRaiseIrql(HIGH_LEVEL
, &OldIrql
);
1047 /* Check the Current State first so we don't double-register */
1048 if (CallbackRecord
->State
== BufferEmpty
)
1050 /* Set the Callback Settings and insert into the list */
1051 CallbackRecord
->Component
= Component
;
1052 CallbackRecord
->CallbackRoutine
= CallbackRoutine
;
1053 CallbackRecord
->State
= BufferInserted
;
1054 CallbackRecord
->Reason
= Reason
;
1055 InsertTailList(&BugcheckReasonCallbackListHead
,
1056 &CallbackRecord
->Entry
);
1060 /* Lower IRQL and return */
1061 KeLowerIrql(OldIrql
);
1070 KeBugCheckEx(IN ULONG BugCheckCode
,
1071 IN ULONG_PTR BugCheckParameter1
,
1072 IN ULONG_PTR BugCheckParameter2
,
1073 IN ULONG_PTR BugCheckParameter3
,
1074 IN ULONG_PTR BugCheckParameter4
)
1076 /* Call the internal API */
1077 KeBugCheckWithTf(BugCheckCode
,
1090 KeBugCheck(ULONG BugCheckCode
)
1092 /* Call the internal API */
1093 KeBugCheckWithTf(BugCheckCode
, 0, 0, 0, 0, NULL
);