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 ULONG KeBugCheckActive
, KeBugCheckOwner
;
32 LONG KeBugCheckOwnerRecursionCount
;
33 PRTL_MESSAGE_RESOURCE_DATA KiBugCodeMessages
;
34 ULONG KeBugCheckCount
= 1;
35 ULONG KiHardwareTrigger
;
36 PUNICODE_STRING KiBugCheckDriver
;
37 ULONG_PTR KiBugCheckData
[5];
39 /* PRIVATE FUNCTIONS *********************************************************/
43 KiRosPrintAddress(PVOID address
)
45 PLIST_ENTRY current_entry
;
46 PLDR_DATA_TABLE_ENTRY current
;
47 extern LIST_ENTRY ModuleListHead
;
48 ULONG_PTR RelativeAddress
;
53 current_entry
= ModuleListHead
.Flink
;
55 while (current_entry
!= &ModuleListHead
)
57 current
= CONTAINING_RECORD(current_entry
,
61 if (address
>= (PVOID
)current
->DllBase
&&
62 address
< (PVOID
)((ULONG_PTR
)current
->DllBase
+
63 current
->SizeOfImage
))
65 RelativeAddress
= (ULONG_PTR
)address
-
66 (ULONG_PTR
)current
->DllBase
;
67 DbgPrint("<%wZ: %x>", ¤t
->FullDllName
, RelativeAddress
);
70 current_entry
= current_entry
->Flink
;
79 KeRosDumpStackFrames(IN PULONG Frame OPTIONAL
,
80 IN ULONG FrameCount OPTIONAL
)
85 /* If the caller didn't ask, assume 32 frames */
86 if (!FrameCount
) FrameCount
= 32;
88 /* Get the current frames */
89 FrameCount
= RtlCaptureStackBackTrace(2, FrameCount
, (PVOID
*)Frames
, NULL
);
91 /* Now loop them (skip the two. One for the dumper, one for the caller) */
92 for (i
= 0; i
< FrameCount
; i
++)
97 /* If we had a custom frame, make sure we've reached it first */
98 if ((Frame
) && (Frame
[1] == Addr
))
104 /* Skip this entry */
109 if (!KeRosPrintAddress((PVOID
)Addr
)) DbgPrint("<%X>", Addr
);
111 /* Go to the next frame */
115 /* Finish the output */
122 KiInitializeBugCheck(VOID
)
124 PRTL_MESSAGE_RESOURCE_DATA BugCheckData
;
125 LDR_RESOURCE_INFO ResourceInfo
;
126 PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry
;
129 /* Initialize Callbadk Listhead and State */
130 InitializeListHead(&BugcheckCallbackListHead
);
131 InitializeListHead(&BugcheckReasonCallbackListHead
);
133 /* Cache the Bugcheck Message Strings. Prepare the Lookup Data */
134 ResourceInfo
.Type
= 11;
135 ResourceInfo
.Name
= 1;
136 ResourceInfo
.Language
= 9;
139 Status
= LdrFindResource_U((PVOID
)KERNEL_BASE
,
144 /* Make sure it worked */
145 if (NT_SUCCESS(Status
))
147 /* Now actually get a pointer to it */
148 Status
= LdrAccessResource((PVOID
)KERNEL_BASE
,
150 (PVOID
*)&BugCheckData
,
152 if (NT_SUCCESS(Status
)) KiBugCodeMessages
= BugCheckData
;
158 KeGetBugMessageText(IN ULONG BugCheckCode
,
159 OUT PANSI_STRING OutputString OPTIONAL
)
163 ULONG_PTR MessageEntry
;
166 /* Find the message. This code is based on RtlFindMesssage */
167 for (i
= 0; i
< KiBugCodeMessages
->NumberOfBlocks
; i
++)
169 /* Check if the ID Matches */
170 if ((BugCheckCode
>= KiBugCodeMessages
->Blocks
[i
].LowId
) &&
171 (BugCheckCode
<= KiBugCodeMessages
->Blocks
[i
].HighId
))
173 /* Get Offset to Entry */
174 MessageEntry
= KiBugCodeMessages
->Blocks
[i
].OffsetToEntries
+
175 (ULONG_PTR
)KiBugCodeMessages
;
176 IdOffset
= BugCheckCode
- KiBugCodeMessages
->Blocks
[i
].LowId
;
178 /* Get offset to ID */
179 for (i
= 0; i
< IdOffset
; i
++)
181 /* Advance in the Entries */
182 MessageEntry
+= ((PRTL_MESSAGE_RESOURCE_ENTRY
)MessageEntry
)->
186 /* Get the final Code */
187 BugCode
= ((PRTL_MESSAGE_RESOURCE_ENTRY
)MessageEntry
)->Text
;
190 /* Return it in the OutputString */
193 OutputString
->Buffer
= BugCode
;
194 OutputString
->Length
= i
+ 1;
195 OutputString
->MaximumLength
= i
+ 1;
199 /* Direct Output to Screen */
200 InbvDisplayString(BugCode
);
201 InbvDisplayString("\r");
210 KiDoBugCheckCallbacks(VOID
)
212 PKBUGCHECK_CALLBACK_RECORD CurrentRecord
;
213 PLIST_ENTRY ListHead
, NextEntry
, LastEntry
;
216 /* First make sure that the list is Initialized... it might not be */
217 ListHead
= &BugcheckCallbackListHead
;
218 if ((ListHead
->Flink
) && (ListHead
->Blink
))
221 LastEntry
= ListHead
;
222 NextEntry
= ListHead
->Flink
;
223 while (NextEntry
!= ListHead
)
226 CurrentRecord
= CONTAINING_RECORD(NextEntry
,
227 KBUGCHECK_CALLBACK_RECORD
,
231 if (CurrentRecord
->Entry
.Blink
!= LastEntry
) return;
232 Checksum
= (ULONG_PTR
)CurrentRecord
->CallbackRoutine
;
233 Checksum
+= (ULONG_PTR
)CurrentRecord
->Buffer
;
234 Checksum
+= (ULONG_PTR
)CurrentRecord
->Length
;
235 Checksum
+= (ULONG_PTR
)CurrentRecord
->Component
;
237 /* Make sure it's inserted and valitdated */
238 if ((CurrentRecord
->State
== BufferInserted
) &&
239 (CurrentRecord
->Checksum
== Checksum
))
241 /* Call the routine */
242 CurrentRecord
->State
= BufferStarted
;
243 (CurrentRecord
->CallbackRoutine
)(CurrentRecord
->Buffer
,
244 CurrentRecord
->Length
);
245 CurrentRecord
->State
= BufferFinished
;
248 /* Go to the next entry */
249 LastEntry
= NextEntry
;
250 NextEntry
= NextEntry
->Flink
;
257 KiBugCheckDebugBreak(IN ULONG StatusCode
)
259 /* If KDBG isn't connected, freeze the CPU, otherwise, break */
260 if (KdDebuggerNotPresent
) for (;;) Ke386HaltProcessor();
261 DbgBreakPointWithStatus(StatusCode
);
266 KiPcToFileHeader(IN PVOID Eip
,
267 OUT PLDR_DATA_TABLE_ENTRY
*LdrEntry
,
268 IN BOOLEAN DriversOnly
,
269 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 */
329 KeBugCheckUnicodeToAnsi(IN PUNICODE_STRING Unicode
,
337 /* Set length and normalize it */
338 i
= Unicode
->Length
/ sizeof(WCHAR
);
339 i
= min(i
, Length
- 1);
341 /* Set source and destination, and copy */
342 pw
= Unicode
->Buffer
;
344 while (i
--) *p
++ = (CHAR
)*pw
++;
346 /* Null terminate and return */
353 KiDumpParameterImages(IN PCHAR Message
,
354 IN PULONG_PTR Parameters
,
355 IN ULONG ParameterCount
,
356 IN PKE_BUGCHECK_UNICODE_TO_ANSI ConversionRoutine
)
360 PLDR_DATA_TABLE_ENTRY LdrEntry
;
362 PUNICODE_STRING DriverName
;
364 PIMAGE_NT_HEADERS NtHeader
;
366 BOOLEAN FirstRun
= TRUE
;
368 /* Loop parameters */
369 for (i
= 0; i
< ParameterCount
; i
++)
371 /* Get the base for this parameter */
372 ImageBase
= KiPcToFileHeader((PVOID
)Parameters
[i
],
378 /* Driver wasn't found, check for unloaded driver */
379 DriverName
= NULL
; // FIXME: ROS can't
380 if (!DriverName
) continue;
382 /* Convert the driver name */
383 ImageBase
= (PVOID
)Parameters
[i
];
384 ConversionRoutine(DriverName
, AnsiName
, sizeof(AnsiName
));
388 /* Get the NT Headers and Timestamp */
389 NtHeader
= RtlImageNtHeader(LdrEntry
->DllBase
);
390 TimeStamp
= NtHeader
->FileHeader
.TimeDateStamp
;
392 /* Convert the driver name */
393 DriverName
= &LdrEntry
->BaseDllName
;
394 ConversionRoutine(&LdrEntry
->BaseDllName
,
399 /* Format driver name */
401 "%s** %12s - Address %p base at %p, DateStamp %08lx\n",
402 FirstRun
? "\r\n*":"*",
404 (PVOID
)Parameters
[i
],
408 /* Check if we only had one parameter */
409 if (ParameterCount
<= 1)
411 /* Then just save the name */
412 KiBugCheckDriver
= DriverName
;
416 /* Otherwise, display the message */
417 InbvDisplayString(Message
);
427 KiDisplayBlueScreen(IN ULONG MessageId
,
428 IN BOOLEAN IsHardError
,
429 IN PCHAR HardErrCaption OPTIONAL
,
430 IN PCHAR HardErrMessage OPTIONAL
,
435 /* FIXMEs: Use inbv to clear, fill and write to screen. */
437 /* Check if this is a hard error */
440 /* Display caption and message */
441 if (HardErrCaption
) InbvDisplayString(HardErrCaption
);
442 if (HardErrMessage
) InbvDisplayString(HardErrMessage
);
446 /* Begin the display */
447 InbvDisplayString("\r\n");
449 /* Print out initial message */
450 KeGetBugMessageText(BUGCHECK_MESSAGE_INTRO
, NULL
);
451 InbvDisplayString("\r\n\r\n");
453 /* Check if we have a driver */
454 if (KiBugCheckDriver
)
456 /* Print out into to driver name */
457 KeGetBugMessageText(BUGCODE_ID_DRIVER
, NULL
);
459 /* Convert and print out driver name */
460 KeBugCheckUnicodeToAnsi(KiBugCheckDriver
, AnsiName
, sizeof(AnsiName
));
461 InbvDisplayString(" ");
462 InbvDisplayString(AnsiName
);
463 InbvDisplayString("\r\n\r\n");
466 /* Check if this is the generic message */
467 if (MessageId
== BUGCODE_PSS_MESSAGE
)
469 /* It is, so get the bug code string as well */
470 KeGetBugMessageText(KiBugCheckData
[0], NULL
);
471 InbvDisplayString("\r\n\r\n");
474 /* Print second introduction message */
475 KeGetBugMessageText(PSS_MESSAGE_INTRO
, NULL
);
476 InbvDisplayString("\r\n\r\n");
478 /* Get the bug code string */
479 KeGetBugMessageText(MessageId
, NULL
);
480 InbvDisplayString("\r\n\r\n");
482 /* Print message for technical information */
483 KeGetBugMessageText(BUGCHECK_TECH_INFO
, NULL
);
485 /* Show the techincal Data */
487 "\r\n\r\n*** STOP: 0x%08lX (0x%p,0x%p,0x%p,0x%p)\r\n\r\n",
489 (PVOID
)KiBugCheckData
[1],
490 (PVOID
)KiBugCheckData
[2],
491 (PVOID
)KiBugCheckData
[3],
492 (PVOID
)KiBugCheckData
[4]);
493 InbvDisplayString(AnsiName
);
495 /* Check if we have a driver*/
496 if (KiBugCheckDriver
)
498 /* Display technical driver data */
499 InbvDisplayString(Message
);
503 /* Dump parameter information */
504 KiDumpParameterImages(Message
,
505 (PVOID
)&KiBugCheckData
[1],
507 KeBugCheckUnicodeToAnsi
);
513 KeBugCheckWithTf(IN ULONG BugCheckCode
,
514 IN ULONG_PTR BugCheckParameter1
,
515 IN ULONG_PTR BugCheckParameter2
,
516 IN ULONG_PTR BugCheckParameter3
,
517 IN ULONG_PTR BugCheckParameter4
,
518 IN PKTRAP_FRAME TrapFrame
)
520 PKPRCB Prcb
= KeGetCurrentPrcb();
524 BOOLEAN IsSystem
, IsHardError
= FALSE
;
525 PCHAR HardErrCaption
= NULL
, HardErrMessage
= NULL
;
526 PVOID Eip
= NULL
, Memory
;
528 PLDR_DATA_TABLE_ENTRY LdrEntry
;
529 PULONG_PTR HardErrorParameters
;
532 /* Set active bugcheck */
533 KeBugCheckActive
= TRUE
;
534 KiBugCheckDriver
= NULL
;
536 /* Check if this is power failure simulation */
537 if (BugCheckCode
== POWER_FAILURE_SIMULATE
)
539 /* Call the Callbacks and reboot */;
540 KiDoBugCheckCallbacks();
541 HalReturnToFirmware(HalRebootRoutine
);
544 /* Save the IRQL and set hardware trigger */
545 Prcb
->DebuggerSavedIRQL
= KeGetCurrentIrql();
546 InterlockedIncrement((PLONG
)&KiHardwareTrigger
);
548 /* Capture the CPU Context */
549 RtlCaptureContext(&Prcb
->ProcessorState
.ContextFrame
);
550 Context
= Prcb
->ProcessorState
.ContextFrame
;
552 /* FIXME: Call the Watchdog if it's regsitered */
554 /* Check which bugcode this is */
555 switch (BugCheckCode
)
557 /* These bug checks already have detailed messages, keep them */
558 case UNEXPECTED_KERNEL_MODE_TRAP
:
559 case DRIVER_CORRUPTED_EXPOOL
:
560 case ACPI_BIOS_ERROR
:
561 case ACPI_BIOS_FATAL_ERROR
:
562 case THREAD_STUCK_IN_DEVICE_DRIVER
:
564 case FAT_FILE_SYSTEM
:
565 case NO_MORE_SYSTEM_PTES
:
566 case INACCESSIBLE_BOOT_DEVICE
:
567 case KMODE_EXCEPTION_NOT_HANDLED
:
569 /* Keep the same code */
570 MessageId
= BugCheckCode
;
573 /* Check if this is a kernel-mode exception */
574 case KERNEL_MODE_EXCEPTION_NOT_HANDLED
:
576 /* Use the generic text message */
577 MessageId
= KMODE_EXCEPTION_NOT_HANDLED
;
579 /* File-system errors */
580 case NTFS_FILE_SYSTEM
:
582 /* Use the generic message for FAT */
583 MessageId
= FAT_FILE_SYSTEM
;
585 /* Check if this is a coruption of the Mm's Pool */
586 case DRIVER_CORRUPTED_MMPOOL
:
588 /* Use generic corruption message */
589 MessageId
= DRIVER_CORRUPTED_EXPOOL
;
591 /* Check if this is a signature check failure */
592 case STATUS_SYSTEM_IMAGE_BAD_SIGNATURE
:
594 /* Use the generic corruption message */
595 MessageId
= BUGCODE_PSS_MESSAGE_SIGNATURE
;
597 /* All other codes */
600 /* Use the default bugcheck message */
601 MessageId
= BUGCODE_PSS_MESSAGE
;
604 /* Save bugcheck data */
605 KiBugCheckData
[0] = BugCheckCode
;
606 KiBugCheckData
[1] = BugCheckParameter1
;
607 KiBugCheckData
[2] = BugCheckParameter2
;
608 KiBugCheckData
[3] = BugCheckParameter3
;
609 KiBugCheckData
[4] = BugCheckParameter4
;
611 /* Now check what bugcheck this is */
612 switch (BugCheckCode
)
614 /* Invalid access to R/O memory or Unhandled KM Exception */
615 case KERNEL_MODE_EXCEPTION_NOT_HANDLED
:
616 case ATTEMPTED_WRITE_TO_READONLY_MEMORY
:
617 case ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY
:
619 /* Check if we have a trap frame */
622 /* Use parameter 3 as a trap frame, if it exists */
623 if (BugCheckParameter3
) TrapFrame
= (PVOID
)BugCheckParameter3
;
626 /* Check if we got one now and if we need to get EIP */
628 (BugCheckCode
!= KERNEL_MODE_EXCEPTION_NOT_HANDLED
))
631 Eip
= (PVOID
)TrapFrame
->Eip
;
636 case IRQL_NOT_LESS_OR_EQUAL
:
639 * The NT kernel has 3 special sections:
640 * MISYSPTE, POOLMI and POOLCODE. The bug check code can
641 * determine in which of these sections this bugcode happened
642 * and provide a more detailed analysis. For now, we don't.
645 /* Eip is in parameter 4 */
646 Eip
= (PVOID
)BugCheckParameter4
;
648 /* Get the driver base */
649 DriverBase
= KiPcToFileHeader(Eip
, &LdrEntry
, FALSE
, &IsSystem
);
653 * The error happened inside the kernel or HAL.
654 * Get the memory address that was being referenced.
656 Memory
= (PVOID
)BugCheckParameter1
;
658 /* Find to which driver it belongs */
659 DriverBase
= KiPcToFileHeader(Memory
,
665 /* Get the driver name and update the bug code */
666 KiBugCheckDriver
= &LdrEntry
->BaseDllName
;
667 KiBugCheckData
[0] = DRIVER_PORTION_MUST_BE_NONPAGED
;
671 /* Find the driver that unloaded at this address */
672 KiBugCheckDriver
= NULL
; // FIXME: ROS can't locate
674 /* Check if the cause was an unloaded driver */
675 if (KiBugCheckDriver
)
677 /* Update bug check code */
679 SYSTEM_SCAN_AT_RAISED_IRQL_CAUGHT_IMPROPER_DRIVER_UNLOAD
;
685 /* Update the bug check code */
686 KiBugCheckData
[0] = DRIVER_IRQL_NOT_LESS_OR_EQUAL
;
689 /* Clear EIP so we don't look it up later */
694 case FATAL_UNHANDLED_HARD_ERROR
:
696 /* Copy bug check data from hard error */
697 HardErrorParameters
= (PULONG_PTR
)BugCheckParameter2
;
698 KiBugCheckData
[0] = BugCheckParameter1
;
699 KiBugCheckData
[1] = HardErrorParameters
[0];
700 KiBugCheckData
[2] = HardErrorParameters
[1];
701 KiBugCheckData
[3] = HardErrorParameters
[2];
702 KiBugCheckData
[4] = HardErrorParameters
[3];
704 /* Remember that this is hard error and set the caption/message */
706 HardErrCaption
= (PCHAR
)BugCheckParameter3
;
707 HardErrMessage
= (PCHAR
)BugCheckParameter4
;
711 case PAGE_FAULT_IN_NONPAGED_AREA
:
713 /* Assume no driver */
716 /* Check if we have a trap frame */
719 /* We don't, use parameter 3 if possible */
720 if (BugCheckParameter3
) TrapFrame
= (PVOID
)BugCheckParameter3
;
723 /* Check if we have a frame now */
727 Eip
= (PVOID
)TrapFrame
->Eip
;
729 /* Find out if was in the kernel or drivers */
730 DriverBase
= KiPcToFileHeader(Eip
, &LdrEntry
, FALSE
, &IsSystem
);
734 * Now we should check if this happened in:
735 * 1) Special Pool 2) Free Special Pool 3) Session Pool
736 * and update the bugcheck code appropriately.
739 /* Check if we had a driver base */
742 /* Find the driver that unloaded at this address */
743 KiBugCheckDriver
= NULL
; // FIXME: ROS can't locate
745 /* Check if the cause was an unloaded driver */
746 if (KiBugCheckDriver
)
749 DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS
;
754 /* Check if the driver forgot to unlock pages */
755 case DRIVER_LEFT_LOCKED_PAGES_IN_PROCESS
:
757 /* EIP is in parameter 1 */
758 Eip
= (PVOID
)BugCheckParameter1
;
761 /* Check if the driver consumed too many PTEs */
762 case DRIVER_USED_EXCESSIVE_PTES
:
764 /* Driver base is in parameter 1 */
765 DriverBase
= (PVOID
)BugCheckParameter1
;
766 /* FIXME: LdrEntry is uninitialized for god's sake!!!
767 KiBugCheckDriver = &LdrEntry->BaseDllName; */
770 /* Check if the driver has a stuck thread */
771 case THREAD_STUCK_IN_DEVICE_DRIVER
:
773 /* The name is in Parameter 3 */
774 KiBugCheckDriver
= (PVOID
)BugCheckParameter3
;
782 /* Do we have a driver name? */
783 if (KiBugCheckDriver
)
785 /* Convert it to ANSI */
786 KeBugCheckUnicodeToAnsi(KiBugCheckDriver
, AnsiName
, sizeof(AnsiName
));
790 /* Do we have an EIP? */
793 /* Dump image name */
794 KiDumpParameterImages(AnsiName
,
797 KeBugCheckUnicodeToAnsi
);
801 /* FIXME: Check if we need to save the context for KD */
803 /* Check if a debugger is connected */
804 if ((BugCheckCode
!= MANUALLY_INITIATED_CRASH
) && (KdDebuggerEnabled
))
806 /* Crash on the debugger console */
807 DbgPrint("\n*** Fatal System Error: 0x%08lx\n"
808 " (0x%p,0x%p,0x%p,0x%p)\n\n",
815 /* Check if the debugger isn't currently connected */
816 if (!KdDebuggerNotPresent
)
818 /* Check if we have a driver to blame */
819 if (KiBugCheckDriver
)
822 DbgPrint("Driver at fault: %s.\n", AnsiName
);
825 /* Check if this was a hard error */
828 /* Print caption and message */
829 if (HardErrCaption
) DbgPrint(HardErrCaption
);
830 if (HardErrMessage
) DbgPrint(HardErrMessage
);
833 /* Break in the debugger */
834 KiBugCheckDebugBreak(DBG_STATUS_BUGCHECK_FIRST
);
840 * Ok, so debugging is enabled, but KDBG isn't there.
841 * We'll manually dump the stack for the user.
843 KeRosDumpStackFrames(NULL
, 0);
847 /* Switching back to the blue screen so we print messages on it */
848 HalReleaseDisplayOwnership();
850 /* Raise IRQL to HIGH_LEVEL */
851 Ke386DisableInterrupts();
852 KeRaiseIrql(HIGH_LEVEL
, &OldIrql
);
854 /* Unlock the Kernel Adress Space if we own it */
855 if (KernelAddressSpaceLock
.Owner
== KeGetCurrentThread())
857 MmUnlockAddressSpace(MmGetKernelAddressSpace());
860 /* Avoid recursion */
861 if (!InterlockedDecrement((PLONG
)&KeBugCheckCount
))
863 /* Set CPU that is bug checking now */
864 KeBugCheckOwner
= Prcb
->Number
;
867 /* Freeze the other CPUs */
868 for (i
= 0; i
< KeNumberProcessors
; i
++)
870 if (i
!= (LONG
)KeGetCurrentProcessorNumber())
872 /* Send the IPI and give them one second to catch up */
873 KiIpiSendRequest(1 << i
, IPI_FREEZE
);
874 KeStallExecutionProcessor(1000000);
879 /* Display the BSOD */
880 KiDisplayBlueScreen(MessageId
,
886 /* FIXME: Enable debugger if it was pending */
888 /* Print the last line */
889 InbvDisplayString("\r\n");
891 /* Save the context */
892 Prcb
->ProcessorState
.ContextFrame
= Context
;
894 /* FIXME: Support Triage Dump */
896 /* Write the crash dump */
897 MmDumpToPagingFile(KiBugCheckData
[4],
905 /* Increase recursioun count */
906 KeBugCheckOwnerRecursionCount
++;
907 if (KeBugCheckOwnerRecursionCount
== 2)
909 /* Break in the debugger */
910 KiBugCheckDebugBreak(DBG_STATUS_BUGCHECK_SECOND
);
912 else if (KeBugCheckOwnerRecursionCount
> 2)
915 for (;;) Ke386HaltProcessor();
918 /* Call the Callbacks */
919 KiDoBugCheckCallbacks();
921 /* FIXME: Call Watchdog if enabled */
923 /* Attempt to break in the debugger (otherwise halt CPU) */
924 KiBugCheckDebugBreak(DBG_STATUS_BUGCHECK_SECOND
);
927 /* PUBLIC FUNCTIONS **********************************************************/
934 KeDeregisterBugCheckCallback(IN PKBUGCHECK_CALLBACK_RECORD CallbackRecord
)
937 BOOLEAN Status
= FALSE
;
939 /* Raise IRQL to High */
940 KeRaiseIrql(HIGH_LEVEL
, &OldIrql
);
942 /* Check the Current State */
943 if (CallbackRecord
->State
== BufferInserted
)
945 /* Reset state and remove from list */
946 CallbackRecord
->State
= BufferEmpty
;
947 RemoveEntryList(&CallbackRecord
->Entry
);
951 /* Lower IRQL and return */
952 KeLowerIrql(OldIrql
);
961 KeDeregisterBugCheckReasonCallback(
962 IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord
)
965 BOOLEAN Status
= FALSE
;
967 /* Raise IRQL to High */
968 KeRaiseIrql(HIGH_LEVEL
, &OldIrql
);
970 /* Check the Current State */
971 if (CallbackRecord
->State
== BufferInserted
)
973 /* Reset state and remove from list */
974 CallbackRecord
->State
= BufferEmpty
;
975 RemoveEntryList(&CallbackRecord
->Entry
);
979 /* Lower IRQL and return */
980 KeLowerIrql(OldIrql
);
989 KeRegisterBugCheckCallback(IN PKBUGCHECK_CALLBACK_RECORD CallbackRecord
,
990 IN PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine
,
996 BOOLEAN Status
= FALSE
;
998 /* Raise IRQL to High */
999 KeRaiseIrql(HIGH_LEVEL
, &OldIrql
);
1001 /* Check the Current State first so we don't double-register */
1002 if (CallbackRecord
->State
== BufferEmpty
)
1004 /* Set the Callback Settings and insert into the list */
1005 CallbackRecord
->Length
= Length
;
1006 CallbackRecord
->Buffer
= Buffer
;
1007 CallbackRecord
->Component
= Component
;
1008 CallbackRecord
->CallbackRoutine
= CallbackRoutine
;
1009 CallbackRecord
->State
= BufferInserted
;
1010 InsertTailList(&BugcheckCallbackListHead
, &CallbackRecord
->Entry
);
1014 /* Lower IRQL and return */
1015 KeLowerIrql(OldIrql
);
1024 KeRegisterBugCheckReasonCallback(
1025 IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord
,
1026 IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine
,
1027 IN KBUGCHECK_CALLBACK_REASON Reason
,
1028 IN PUCHAR Component
)
1031 BOOLEAN Status
= FALSE
;
1033 /* Raise IRQL to High */
1034 KeRaiseIrql(HIGH_LEVEL
, &OldIrql
);
1036 /* Check the Current State first so we don't double-register */
1037 if (CallbackRecord
->State
== BufferEmpty
)
1039 /* Set the Callback Settings and insert into the list */
1040 CallbackRecord
->Component
= Component
;
1041 CallbackRecord
->CallbackRoutine
= CallbackRoutine
;
1042 CallbackRecord
->State
= BufferInserted
;
1043 CallbackRecord
->Reason
= Reason
;
1044 InsertTailList(&BugcheckReasonCallbackListHead
,
1045 &CallbackRecord
->Entry
);
1049 /* Lower IRQL and return */
1050 KeLowerIrql(OldIrql
);
1059 KeBugCheckEx(IN ULONG BugCheckCode
,
1060 IN ULONG_PTR BugCheckParameter1
,
1061 IN ULONG_PTR BugCheckParameter2
,
1062 IN ULONG_PTR BugCheckParameter3
,
1063 IN ULONG_PTR BugCheckParameter4
)
1065 /* Call the internal API */
1066 KeBugCheckWithTf(BugCheckCode
,
1079 KeBugCheck(ULONG BugCheckCode
)
1081 /* Call the internal API */
1082 KeBugCheckWithTf(BugCheckCode
, 0, 0, 0, 0, NULL
);