VOID NTAPI PopShutdownHandler(VOID) { PUCHAR Logo1, Logo2; ULONG i; /* Stop all interrupts */ KeRaiseIrqlToDpcLevel(); _disable(); /* Do we have boot video */ if (InbvIsBootDriverInstalled()) { /* Yes we do, cleanup for shutdown screen */ if (!InbvCheckDisplayOwnership()) InbvAcquireDisplayOwnership(); InbvResetDisplay(); InbvSolidColorFill(0, 0, 639, 479, 0); InbvEnableDisplayString(TRUE); InbvSetScrollRegion(0, 0, 639, 479); /* Display shutdown logo and message */ Logo1 = InbvGetResourceAddress(IDB_SHUTDOWN_MSG); Logo2 = InbvGetResourceAddress(IDB_DEFAULT_LOGO); if ((Logo1) && (Logo2)) { InbvBitBlt(Logo1, 220, 352); InbvBitBlt(Logo2, 222, 111); } } else { /* Do it in text-mode */ for (i = 0; i < 25; i++) InbvDisplayString("\r\n"); InbvDisplayString(" "); InbvDisplayString("The system may be powered off now.\r\n"); } /* Hang the system */ for (;;) HalHaltSystem(); }
VOID KeBugCheckEx ( IN ULONG BugCheckCode, IN ULONG_PTR BugCheckParameter1, IN ULONG_PTR BugCheckParameter2, IN ULONG_PTR BugCheckParameter3, IN ULONG_PTR BugCheckParameter4 ) /*++ Routine Description: This function crashes the system in a controlled manner. Arguments: BugCheckCode - Supplies the reason for the bug check. BugCheckParameter1-4 - Supplies additional bug check information Return Value: None. --*/ { UCHAR Buffer[100]; ULONG_PTR BugCheckParameters[4]; CONTEXT ContextSave; ULONG PssMessage; PCHAR HardErrorCaption; PCHAR HardErrorMessage; KIRQL OldIrql; PKTRAP_FRAME TrapInformation; PVOID ExecutionAddress; PVOID ImageBase; PVOID VirtualAddress; PLDR_DATA_TABLE_ENTRY DataTableEntry; UCHAR AnsiBuffer[32]; PKTHREAD Thread; BOOLEAN InKernelOrHal; BOOLEAN DontCare; #if !defined(NT_UP) ULONG TargetSet; #endif BOOLEAN hardErrorCalled; // // Try to simulate a power failure for Cluster testing // if (BugCheckCode == POWER_FAILURE_SIMULATE) { KiScanBugCheckCallbackList(); HalReturnToFirmware(HalRebootRoutine); } // // Capture the callers context as closely as possible into the debugger's // processor state area of the Prcb. // // N.B. There may be some prologue code that shuffles registers such that // they get destroyed. // #if defined(i386) KiSetHardwareTrigger(); #else KiHardwareTrigger = 1; #endif RtlCaptureContext(&KeGetCurrentPrcb()->ProcessorState.ContextFrame); KiSaveProcessorControlState(&KeGetCurrentPrcb()->ProcessorState); // // This is necessary on machines where the virtual unwind that happens // during KeDumpMachineState() destroys the context record. // ContextSave = KeGetCurrentPrcb()->ProcessorState.ContextFrame; // // If we are called by hard error then we don't want to dump the // processor state on the machine. // // We know that we are called by hard error because the bug check // code will be FATAL_UNHANDLED_HARD_ERROR. If this is so then the // error status passed to harderr is the first parameter, and a pointer // to the parameter array from hard error is passed as the second // argument. // // The third argument is the OemCaption to be printed. // The last argument is the OemMessage to be printed. // if (BugCheckCode == FATAL_UNHANDLED_HARD_ERROR) { PULONG_PTR parameterArray; hardErrorCalled = TRUE; HardErrorCaption = (PCHAR)BugCheckParameter3; HardErrorMessage = (PCHAR)BugCheckParameter4; parameterArray = (PULONG_PTR)BugCheckParameter2; BugCheckCode = (ULONG)BugCheckParameter1; BugCheckParameter1 = parameterArray[0]; BugCheckParameter2 = parameterArray[1]; BugCheckParameter3 = parameterArray[2]; BugCheckParameter4 = parameterArray[3]; } else { hardErrorCalled = FALSE; switch (BugCheckCode) { case IRQL_NOT_LESS_OR_EQUAL: ExecutionAddress = (PVOID)BugCheckParameter4; if (ExecutionAddress >= ExPoolCodeStart && ExecutionAddress < ExPoolCodeEnd) { BugCheckCode = DRIVER_CORRUPTED_EXPOOL; } else if (ExecutionAddress >= MmPoolCodeStart && ExecutionAddress < MmPoolCodeEnd) { BugCheckCode = DRIVER_CORRUPTED_MMPOOL; } else if (ExecutionAddress >= MmPteCodeStart && ExecutionAddress < MmPteCodeEnd) { BugCheckCode = DRIVER_CORRUPTED_SYSPTES; } else { ImageBase = KiPcToFileHeader (ExecutionAddress, &DataTableEntry, FALSE, &InKernelOrHal); if (InKernelOrHal == TRUE) { // // The kernel faulted at raised IRQL. Quite often this // is a driver that has unloaded without deleting its // lookaside lists or other resources. Or its resources // are marked pagable and shouldn't be. Detect both // cases here and identify the offending driver // whenever possible. // VirtualAddress = (PVOID)BugCheckParameter1; ImageBase = KiPcToFileHeader (VirtualAddress, &DataTableEntry, TRUE, &InKernelOrHal); if (ImageBase != NULL) { KiBugCheckDriver = &DataTableEntry->BaseDllName; BugCheckCode = DRIVER_PORTION_MUST_BE_NONPAGED; } else { KiBugCheckDriver = MmLocateUnloadedDriver (VirtualAddress); if (KiBugCheckDriver != NULL) { BugCheckCode = SYSTEM_SCAN_AT_RAISED_IRQL_CAUGHT_IMPROPER_DRIVER_UNLOAD; } } } else { BugCheckCode = DRIVER_IRQL_NOT_LESS_OR_EQUAL; } } break; case ATTEMPTED_WRITE_TO_READONLY_MEMORY: KiBugCheckDriver = NULL; TrapInformation = (PKTRAP_FRAME)BugCheckParameter3; // // Extract the execution address from the trap frame to // identify the component. // if (TrapInformation != NULL) { ExecutionAddress = (PVOID)PROGRAM_COUNTER (TrapInformation); ImageBase = KiPcToFileHeader (ExecutionAddress, &DataTableEntry, TRUE, &InKernelOrHal); if (ImageBase != NULL) { KiBugCheckDriver = &DataTableEntry->BaseDllName; } } break; case DRIVER_LEFT_LOCKED_PAGES_IN_PROCESS: ExecutionAddress = (PVOID)BugCheckParameter1; ImageBase = KiPcToFileHeader (ExecutionAddress, &DataTableEntry, TRUE, &InKernelOrHal); if (ImageBase != NULL) { KiBugCheckDriver = &DataTableEntry->BaseDllName; } else { KiBugCheckDriver = MmLocateUnloadedDriver (ExecutionAddress); } BugCheckParameter4 = (ULONG_PTR)KiBugCheckDriver; break; case DRIVER_USED_EXCESSIVE_PTES: DataTableEntry = (PLDR_DATA_TABLE_ENTRY)BugCheckParameter1; KiBugCheckDriver = &DataTableEntry->BaseDllName; break; case PAGE_FAULT_IN_NONPAGED_AREA: ExecutionAddress = NULL; KiBugCheckDriver = NULL; VirtualAddress = (PVOID)BugCheckParameter1; TrapInformation = (PKTRAP_FRAME)BugCheckParameter3; // // Extract the execution address from the trap frame to // identify the component. // if (TrapInformation != NULL) { ExecutionAddress = (PVOID)PROGRAM_COUNTER (TrapInformation); BugCheckParameter3 = (ULONG_PTR)ExecutionAddress; KiPcToFileHeader (ExecutionAddress, &DataTableEntry, FALSE, &InKernelOrHal); ImageBase = KiPcToFileHeader (ExecutionAddress, &DataTableEntry, TRUE, &DontCare); if (ImageBase != NULL) { KiBugCheckDriver = &DataTableEntry->BaseDllName; } } else { // // No trap frame, so no execution address either. // BugCheckParameter3 = 0; } Thread = KeGetCurrentThread(); if ((VirtualAddress >= MmSpecialPoolStart) && (VirtualAddress < MmSpecialPoolEnd)) { // // Update the bugcheck number so the administrator gets // useful feedback that enabling special pool has enabled // the system to locate the corruptor. // if (MmIsSpecialPoolAddressFree (VirtualAddress) == TRUE) { if (InKernelOrHal == TRUE) { BugCheckCode = PAGE_FAULT_IN_FREED_SPECIAL_POOL; } else { BugCheckCode = DRIVER_PAGE_FAULT_IN_FREED_SPECIAL_POOL; } } else { if (InKernelOrHal == TRUE) { BugCheckCode = PAGE_FAULT_BEYOND_END_OF_ALLOCATION; } else { BugCheckCode = DRIVER_PAGE_FAULT_BEYOND_END_OF_ALLOCATION; } } } else if ((ExecutionAddress == VirtualAddress) && (MmIsHydraAddress (VirtualAddress) == TRUE) && ((Thread->Teb == NULL) || (IS_SYSTEM_ADDRESS(Thread->Teb)))) { // // This is a driver reference to session space from a // worker thread. Since the system process has no session // space this is illegal and the driver must be fixed. // BugCheckCode = TERMINAL_SERVER_DRIVER_MADE_INCORRECT_MEMORY_REFERENCE; } else { KiBugCheckDriver = MmLocateUnloadedDriver (VirtualAddress); if (KiBugCheckDriver != NULL) { BugCheckCode = DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS; } } break; default: break; } } if (KiBugCheckDriver != NULL) { KeBugCheckUnicodeToAnsi (KiBugCheckDriver, AnsiBuffer, sizeof (AnsiBuffer)); } KiBugCheckData[0] = BugCheckCode; KiBugCheckData[1] = BugCheckParameter1; KiBugCheckData[2] = BugCheckParameter2; KiBugCheckData[3] = BugCheckParameter3; KiBugCheckData[4] = BugCheckParameter4; BugCheckParameters[0] = BugCheckParameter1; BugCheckParameters[1] = BugCheckParameter2; BugCheckParameters[2] = BugCheckParameter3; BugCheckParameters[3] = BugCheckParameter4; if (KdPitchDebugger == FALSE ) { KdDebuggerDataBlock.SavedContext = (ULONG_PTR) &ContextSave; } // // If the user manually crashed the machine, skips the DbgPrints and // go to the crashdump. // Trying to do DbgPrint causes us to reeeter the debugger which causes // some problems. // // Otherwise, if the debugger is enabled, print out the information and // stop. // if ((BugCheckCode != MANUALLY_INITIATED_CRASH) && (KdDebuggerEnabled)) { DbgPrint("\n*** Fatal System Error: 0x%08lx\n" " (0x%p,0x%p,0x%p,0x%p)\n\n", BugCheckCode, BugCheckParameter1, BugCheckParameter2, BugCheckParameter3, BugCheckParameter4); // // If the debugger is not actually connected, or the user manually // crashed the machine by typing .crash in the debugger, proceed to // "blue screen" the system. // // The call to DbgPrint above will have set the state of // KdDebuggerNotPresent if the debugger has become disconnected // since the system was booted. // if (KdDebuggerNotPresent == FALSE) { if (KiBugCheckDriver != NULL) { DbgPrint("The %s driver may be at fault.\n", AnsiBuffer); } if (hardErrorCalled != FALSE) { if (HardErrorCaption) { DbgPrint(HardErrorCaption); } if (HardErrorMessage) { DbgPrint(HardErrorMessage); } } KiBugCheckDebugBreak (DBG_STATUS_BUGCHECK_FIRST); } } // // Freeze execution of the system by disabling interrupts and looping. // KiDisableInterrupts(); KeRaiseIrql(HIGH_LEVEL, &OldIrql); // // Don't attempt to display message more than once. // if (InterlockedDecrement (&KeBugCheckCount) == 0) { #if !defined(NT_UP) // // Attempt to get the other processors frozen now, but don't wait // for them to freeze (in case someone is stuck). // TargetSet = KeActiveProcessors & ~KeGetCurrentPrcb()->SetMember; if (TargetSet != 0) { KiIpiSend((KAFFINITY) TargetSet, IPI_FREEZE); // // Give the other processors one second to flush their data caches. // // N.B. This cannot be synchronized since the reason for the bug // may be one of the other processors failed. // KeStallExecutionProcessor(1000 * 1000); } #endif // // Enable InbvDisplayString calls to make it through to bootvid driver. // if (InbvIsBootDriverInstalled()) { InbvAcquireDisplayOwnership(); InbvResetDisplay(); InbvSolidColorFill(0,0,639,479,4); // make the screen blue InbvSetTextColor(15); InbvInstallDisplayStringFilter((INBV_DISPLAY_STRING_FILTER)NULL); InbvEnableDisplayString(TRUE); // enable display string InbvSetScrollRegion(0,0,639,479); // set to use entire screen } if (!hardErrorCalled) { sprintf((char *)Buffer, "\n*** STOP: 0x%08lX (0x%p,0x%p,0x%p,0x%p)\n", BugCheckCode, BugCheckParameter1, BugCheckParameter2, BugCheckParameter3, BugCheckParameter4 ); InbvDisplayString((char *)Buffer); KeGetBugMessageText(BugCheckCode, NULL); InbvDisplayString("\n"); if (KiBugCheckDriver != NULL) { // // Output the driver name. // KeGetBugMessageText(BUGCODE_ID_DRIVER, NULL); InbvDisplayString(AnsiBuffer); InbvDisplayString("\n"); } } else { if (HardErrorCaption) { InbvDisplayString(HardErrorCaption); } if (HardErrorMessage) { InbvDisplayString(HardErrorMessage); } } // // Process the bug check callback list. // KiScanBugCheckCallbackList(); // // If the debugger is not enabled, then dump the machine state and // attempt to enable the debugger. // if (!hardErrorCalled) { KiDumpParameterImages( (char *)Buffer, BugCheckParameters, 4, KeBugCheckUnicodeToAnsi); } if (KdDebuggerEnabled == FALSE && KdPitchDebugger == FALSE ) { KdInitSystem(NULL, FALSE); } else { InbvDisplayString("\n"); } // // Write a crash dump and optionally reboot if the system has been // so configured. // KeGetCurrentPrcb()->ProcessorState.ContextFrame = ContextSave; if (!IoWriteCrashDump(BugCheckCode, BugCheckParameter1, BugCheckParameter2, BugCheckParameter3, BugCheckParameter4, &ContextSave )) { // // If no crashdump take, display the PSS message. // switch ( BugCheckCode ) { case IRQL_NOT_LESS_OR_EQUAL: case DRIVER_IRQL_NOT_LESS_OR_EQUAL: case DRIVER_CORRUPTED_EXPOOL: case DRIVER_CORRUPTED_MMPOOL: case DRIVER_PORTION_MUST_BE_NONPAGED: case SYSTEM_SCAN_AT_RAISED_IRQL_CAUGHT_IMPROPER_DRIVER_UNLOAD: PssMessage = BUGCODE_PSS_MESSAGE_A; break; case KMODE_EXCEPTION_NOT_HANDLED: PssMessage = BUGCODE_PSS_MESSAGE_1E; break; case FAT_FILE_SYSTEM: case NTFS_FILE_SYSTEM: PssMessage = BUGCODE_PSS_MESSAGE_23; break; case DATA_BUS_ERROR: PssMessage = BUGCODE_PSS_MESSAGE_2E; break; case NO_MORE_SYSTEM_PTES: PssMessage = BUGCODE_PSS_MESSAGE_3F; break; case INACCESSIBLE_BOOT_DEVICE: PssMessage = BUGCODE_PSS_MESSAGE_7B; break; case UNEXPECTED_KERNEL_MODE_TRAP: PssMessage = BUGCODE_PSS_MESSAGE_7F; break; case STATUS_SYSTEM_IMAGE_BAD_SIGNATURE: PssMessage = BUGCODE_PSS_MESSAGE_SIGNATURE; break; case ACPI_BIOS_ERROR: PssMessage = BUGCODE_PSS_MESSAGE_A5; break; case ACPI_BIOS_FATAL_ERROR: PssMessage = ACPI_BIOS_FATAL_ERROR; break; default: PssMessage = BUGCODE_PSS_MESSAGE; break; } KeGetBugMessageText(PssMessage, NULL); } } // // Attempt to enter the kernel debugger. // KiBugCheckDebugBreak (DBG_STATUS_BUGCHECK_SECOND); return; }
VOID NTAPI KiDisplayBlueScreen(IN ULONG MessageId, IN BOOLEAN IsHardError, IN PCHAR HardErrCaption OPTIONAL, IN PCHAR HardErrMessage OPTIONAL, IN PCHAR Message) { CHAR AnsiName[75]; /* Check if bootvid is installed */ if (InbvIsBootDriverInstalled()) { /* Acquire ownership and reset the display */ InbvAcquireDisplayOwnership(); InbvResetDisplay(); /* Display blue screen */ InbvSolidColorFill(0, 0, 639, 479, 4); InbvSetTextColor(15); InbvInstallDisplayStringFilter(NULL); InbvEnableDisplayString(TRUE); InbvSetScrollRegion(0, 0, 639, 479); } /* Check if this is a hard error */ if (IsHardError) { /* Display caption and message */ if (HardErrCaption) InbvDisplayString(HardErrCaption); if (HardErrMessage) InbvDisplayString(HardErrMessage); } /* Begin the display */ InbvDisplayString("\r\n"); /* Print out initial message */ KeGetBugMessageText(BUGCHECK_MESSAGE_INTRO, NULL); InbvDisplayString("\r\n\r\n"); /* Check if we have a driver */ if (KiBugCheckDriver) { /* Print out into to driver name */ KeGetBugMessageText(BUGCODE_ID_DRIVER, NULL); /* Convert and print out driver name */ KeBugCheckUnicodeToAnsi(KiBugCheckDriver, AnsiName, sizeof(AnsiName)); InbvDisplayString(" "); InbvDisplayString(AnsiName); InbvDisplayString("\r\n\r\n"); } /* Check if this is the generic message */ if (MessageId == BUGCODE_PSS_MESSAGE) { /* It is, so get the bug code string as well */ KeGetBugMessageText((ULONG)KiBugCheckData[0], NULL); InbvDisplayString("\r\n\r\n"); } /* Print second introduction message */ KeGetBugMessageText(PSS_MESSAGE_INTRO, NULL); InbvDisplayString("\r\n\r\n"); /* Get the bug code string */ KeGetBugMessageText(MessageId, NULL); InbvDisplayString("\r\n\r\n"); /* Print message for technical information */ KeGetBugMessageText(BUGCHECK_TECH_INFO, NULL); /* Show the technical Data */ sprintf(AnsiName, "\r\n\r\n*** STOP: 0x%08lX (0x%p,0x%p,0x%p,0x%p)\r\n\r\n", KiBugCheckData[0], (PVOID)KiBugCheckData[1], (PVOID)KiBugCheckData[2], (PVOID)KiBugCheckData[3], (PVOID)KiBugCheckData[4]); InbvDisplayString(AnsiName); /* Check if we have a driver*/ if (KiBugCheckDriver) { /* Display technical driver data */ InbvDisplayString(Message); } else { /* Dump parameter information */ KiDumpParameterImages(Message, (PVOID)&KiBugCheckData[1], 4, KeBugCheckUnicodeToAnsi); } }