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 KeBugCheckWithTf(IN ULONG BugCheckCode, IN ULONG_PTR BugCheckParameter1, IN ULONG_PTR BugCheckParameter2, IN ULONG_PTR BugCheckParameter3, IN ULONG_PTR BugCheckParameter4, IN PKTRAP_FRAME TrapFrame) { PKPRCB Prcb = KeGetCurrentPrcb(); CONTEXT Context; ULONG MessageId; CHAR AnsiName[128]; BOOLEAN IsSystem, IsHardError = FALSE, Reboot = FALSE; PCHAR HardErrCaption = NULL, HardErrMessage = NULL; PVOID Pc = NULL, Memory; PVOID DriverBase; PLDR_DATA_TABLE_ENTRY LdrEntry; PULONG_PTR HardErrorParameters; KIRQL OldIrql; #ifdef CONFIG_SMP LONG i = 0; #endif /* Set active bugcheck */ KeBugCheckActive = TRUE; KiBugCheckDriver = NULL; /* Check if this is power failure simulation */ if (BugCheckCode == POWER_FAILURE_SIMULATE) { /* Call the Callbacks and reboot */ KiDoBugCheckCallbacks(); HalReturnToFirmware(HalRebootRoutine); } /* Save the IRQL and set hardware trigger */ Prcb->DebuggerSavedIRQL = KeGetCurrentIrql(); InterlockedIncrement((PLONG)&KiHardwareTrigger); /* Capture the CPU Context */ RtlCaptureContext(&Prcb->ProcessorState.ContextFrame); KiSaveProcessorControlState(&Prcb->ProcessorState); Context = Prcb->ProcessorState.ContextFrame; /* FIXME: Call the Watchdog if it's registered */ /* Check which bugcode this is */ switch (BugCheckCode) { /* These bug checks already have detailed messages, keep them */ case UNEXPECTED_KERNEL_MODE_TRAP: case DRIVER_CORRUPTED_EXPOOL: case ACPI_BIOS_ERROR: case ACPI_BIOS_FATAL_ERROR: case THREAD_STUCK_IN_DEVICE_DRIVER: case DATA_BUS_ERROR: case FAT_FILE_SYSTEM: case NO_MORE_SYSTEM_PTES: case INACCESSIBLE_BOOT_DEVICE: /* Keep the same code */ MessageId = BugCheckCode; break; /* Check if this is a kernel-mode exception */ case KERNEL_MODE_EXCEPTION_NOT_HANDLED: case SYSTEM_THREAD_EXCEPTION_NOT_HANDLED: case KMODE_EXCEPTION_NOT_HANDLED: /* Use the generic text message */ MessageId = KMODE_EXCEPTION_NOT_HANDLED; break; /* File-system errors */ case NTFS_FILE_SYSTEM: /* Use the generic message for FAT */ MessageId = FAT_FILE_SYSTEM; break; /* Check if this is a coruption of the Mm's Pool */ case DRIVER_CORRUPTED_MMPOOL: /* Use generic corruption message */ MessageId = DRIVER_CORRUPTED_EXPOOL; break; /* Check if this is a signature check failure */ case STATUS_SYSTEM_IMAGE_BAD_SIGNATURE: /* Use the generic corruption message */ MessageId = BUGCODE_PSS_MESSAGE_SIGNATURE; break; /* All other codes */ default: /* Use the default bugcheck message */ MessageId = BUGCODE_PSS_MESSAGE; break; } /* Save bugcheck data */ KiBugCheckData[0] = BugCheckCode; KiBugCheckData[1] = BugCheckParameter1; KiBugCheckData[2] = BugCheckParameter2; KiBugCheckData[3] = BugCheckParameter3; KiBugCheckData[4] = BugCheckParameter4; /* Now check what bugcheck this is */ switch (BugCheckCode) { /* Invalid access to R/O memory or Unhandled KM Exception */ case KERNEL_MODE_EXCEPTION_NOT_HANDLED: case ATTEMPTED_WRITE_TO_READONLY_MEMORY: case ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY: /* Check if we have a trap frame */ if (!TrapFrame) { /* Use parameter 3 as a trap frame, if it exists */ if (BugCheckParameter3) TrapFrame = (PVOID)BugCheckParameter3; } /* Check if we got one now and if we need to get the Program Counter */ if ((TrapFrame) && (BugCheckCode != KERNEL_MODE_EXCEPTION_NOT_HANDLED)) { /* Get the Program Counter */ Pc = (PVOID)KeGetTrapFramePc(TrapFrame); } break; /* Wrong IRQL */ case IRQL_NOT_LESS_OR_EQUAL: /* * The NT kernel has 3 special sections: * MISYSPTE, POOLMI and POOLCODE. The bug check code can * determine in which of these sections this bugcode happened * and provide a more detailed analysis. For now, we don't. */ /* Program Counter is in parameter 4 */ Pc = (PVOID)BugCheckParameter4; /* Get the driver base */ DriverBase = KiPcToFileHeader(Pc, &LdrEntry, FALSE, &IsSystem); if (IsSystem) { /* * The error happened inside the kernel or HAL. * Get the memory address that was being referenced. */ Memory = (PVOID)BugCheckParameter1; /* Find to which driver it belongs */ DriverBase = KiPcToFileHeader(Memory, &LdrEntry, TRUE, &IsSystem); if (DriverBase) { /* Get the driver name and update the bug code */ KiBugCheckDriver = &LdrEntry->BaseDllName; KiBugCheckData[0] = DRIVER_PORTION_MUST_BE_NONPAGED; } else { /* Find the driver that unloaded at this address */ KiBugCheckDriver = NULL; // FIXME: ROS can't locate /* Check if the cause was an unloaded driver */ if (KiBugCheckDriver) { /* Update bug check code */ KiBugCheckData[0] = SYSTEM_SCAN_AT_RAISED_IRQL_CAUGHT_IMPROPER_DRIVER_UNLOAD; } } } else { /* Update the bug check code */ KiBugCheckData[0] = DRIVER_IRQL_NOT_LESS_OR_EQUAL; } /* Clear Pc so we don't look it up later */ Pc = NULL; break; /* Hard error */ case FATAL_UNHANDLED_HARD_ERROR: /* Copy bug check data from hard error */ HardErrorParameters = (PULONG_PTR)BugCheckParameter2; KiBugCheckData[0] = BugCheckParameter1; KiBugCheckData[1] = HardErrorParameters[0]; KiBugCheckData[2] = HardErrorParameters[1]; KiBugCheckData[3] = HardErrorParameters[2]; KiBugCheckData[4] = HardErrorParameters[3]; /* Remember that this is hard error and set the caption/message */ IsHardError = TRUE; HardErrCaption = (PCHAR)BugCheckParameter3; HardErrMessage = (PCHAR)BugCheckParameter4; break; /* Page fault */ case PAGE_FAULT_IN_NONPAGED_AREA: /* Assume no driver */ DriverBase = NULL; /* Check if we have a trap frame */ if (!TrapFrame) { /* We don't, use parameter 3 if possible */ if (BugCheckParameter3) TrapFrame = (PVOID)BugCheckParameter3; } /* Check if we have a frame now */ if (TrapFrame) { /* Get the Program Counter */ Pc = (PVOID)KeGetTrapFramePc(TrapFrame); KiBugCheckData[3] = (ULONG_PTR)Pc; /* Find out if was in the kernel or drivers */ DriverBase = KiPcToFileHeader(Pc, &LdrEntry, FALSE, &IsSystem); } else { /* Can't blame a driver, assume system */ IsSystem = TRUE; } /* FIXME: Check for session pool in addition to special pool */ /* Special pool has its own bug check codes */ if (MmIsSpecialPoolAddress((PVOID)BugCheckParameter1)) { if (MmIsSpecialPoolAddressFree((PVOID)BugCheckParameter1)) { KiBugCheckData[0] = IsSystem ? PAGE_FAULT_IN_FREED_SPECIAL_POOL : DRIVER_PAGE_FAULT_IN_FREED_SPECIAL_POOL; } else { KiBugCheckData[0] = IsSystem ? PAGE_FAULT_BEYOND_END_OF_ALLOCATION : DRIVER_PAGE_FAULT_BEYOND_END_OF_ALLOCATION; } } else if (!DriverBase) { /* Find the driver that unloaded at this address */ KiBugCheckDriver = NULL; // FIXME: ROS can't locate /* Check if the cause was an unloaded driver */ if (KiBugCheckDriver) { KiBugCheckData[0] = DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS; } } break; /* Check if the driver forgot to unlock pages */ case DRIVER_LEFT_LOCKED_PAGES_IN_PROCESS: /* Program Counter is in parameter 1 */ Pc = (PVOID)BugCheckParameter1; break; /* Check if the driver consumed too many PTEs */ case DRIVER_USED_EXCESSIVE_PTES: /* Loader entry is in parameter 1 */ LdrEntry = (PVOID)BugCheckParameter1; KiBugCheckDriver = &LdrEntry->BaseDllName; break; /* Check if the driver has a stuck thread */ case THREAD_STUCK_IN_DEVICE_DRIVER: /* The name is in Parameter 3 */ KiBugCheckDriver = (PVOID)BugCheckParameter3; break; /* Anything else */ default: break; } /* Do we have a driver name? */ if (KiBugCheckDriver) { /* Convert it to ANSI */ KeBugCheckUnicodeToAnsi(KiBugCheckDriver, AnsiName, sizeof(AnsiName)); } else { /* Do we have a Program Counter? */ if (Pc) { /* Dump image name */ KiDumpParameterImages(AnsiName, (PULONG_PTR)&Pc, 1, KeBugCheckUnicodeToAnsi); } } /* Check if we need to save the context for KD */ #ifdef _WINKD_ if (!KdPitchDebugger) KdDebuggerDataBlock.SavedContext = (ULONG_PTR)&Context; #endif /* Check if a debugger is connected */ if ((BugCheckCode != MANUALLY_INITIATED_CRASH) && (KdDebuggerEnabled)) { /* Crash on the debugger console */ DbgPrint("\n*** Fatal System Error: 0x%08lx\n" " (0x%p,0x%p,0x%p,0x%p)\n\n", KiBugCheckData[0], KiBugCheckData[1], KiBugCheckData[2], KiBugCheckData[3], KiBugCheckData[4]); /* Check if the debugger isn't currently connected */ if (!KdDebuggerNotPresent) { /* Check if we have a driver to blame */ if (KiBugCheckDriver) { /* Dump it */ DbgPrint("Driver at fault: %s.\n", AnsiName); } /* Check if this was a hard error */ if (IsHardError) { /* Print caption and message */ if (HardErrCaption) DbgPrint(HardErrCaption); if (HardErrMessage) DbgPrint(HardErrMessage); } /* Break in the debugger */ KiBugCheckDebugBreak(DBG_STATUS_BUGCHECK_FIRST); } else { /* * ROS HACK. * Ok, so debugging is enabled, but KDBG isn't there. * We'll manually dump the stack for the user. */ KeRosDumpStackFrames(NULL, 0); /* ROS HACK 2: Generate something useful for Bugzilla */ KeRosDumpTriageForBugZillaReport(); } } /* Raise IRQL to HIGH_LEVEL */ _disable(); KeRaiseIrql(HIGH_LEVEL, &OldIrql); /* Avoid recursion */ if (!InterlockedDecrement((PLONG)&KeBugCheckCount)) { #ifdef CONFIG_SMP /* Set CPU that is bug checking now */ KeBugCheckOwner = Prcb->Number; /* Freeze the other CPUs */ for (i = 0; i < KeNumberProcessors; i++) { if (i != (LONG)KeGetCurrentProcessorNumber()) { /* Send the IPI and give them one second to catch up */ KiIpiSend(1 << i, IPI_FREEZE); KeStallExecutionProcessor(1000000); } } #endif /* Display the BSOD */ KiDisplayBlueScreen(MessageId, IsHardError, HardErrCaption, HardErrMessage, AnsiName); /* Check if the debugger is disabled but we can enable it */ if (!(KdDebuggerEnabled) && !(KdPitchDebugger)) { /* Enable it */ #ifdef _WINKD_ KdEnableDebuggerWithLock(FALSE); #endif } else { /* Otherwise, print the last line */ InbvDisplayString("\r\n"); } /* Save the context */ Prcb->ProcessorState.ContextFrame = Context; /* FIXME: Support Triage Dump */ /* FIXME: Write the crash dump */ } else { /* Increase recursion count */ KeBugCheckOwnerRecursionCount++; if (KeBugCheckOwnerRecursionCount == 2) { /* Break in the debugger */ KiBugCheckDebugBreak(DBG_STATUS_BUGCHECK_SECOND); } else if (KeBugCheckOwnerRecursionCount > 2) { /* Halt execution */ while (TRUE); } } /* Call the Callbacks */ KiDoBugCheckCallbacks(); /* FIXME: Call Watchdog if enabled */ /* Check if we have to reboot */ if (Reboot) { /* Unload symbols */ 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 */ ASSERT(FALSE); while (TRUE); }