Пример #1
0
VOID
KiSaveProcessorState (
    IN PKTRAP_FRAME TrapFrame,
    IN PKEXCEPTION_FRAME ExceptionFrame
    )

/*++

Routine Description:

    This function saves the processor state from the specified exception
    and trap frames, and saves the processor control state.

Arguments:

    TrapFrame - Supplies a pointer to a trap frame.

    ExceptionFrame - Supplies a pointer to an exception frame.

Return Value:

    None.

--*/

{

#if !defined(NT_UP)

    PKPRCB Prcb;

    //
    // Get the address of the current processor block, move the specified
    // register state from specified trap and exception frames to the current
    // processor context structure, and save the processor control state.
    //

    Prcb = KeGetCurrentPrcb();
    Prcb->ProcessorState.ContextFrame.ContextFlags = CONTEXT_FULL;
    KeContextFromKframes(TrapFrame,
                         ExceptionFrame,
                         &Prcb->ProcessorState.ContextFrame);

    KiSaveProcessorControlState(&Prcb->ProcessorState);

#else

    UNREFERENCED_PARAMETER(TrapFrame);
    UNREFERENCED_PARAMETER(ExceptionFrame);

#endif

    return;
}
Пример #2
0
VOID
KiSaveProcessorState (
    IN PKTRAP_FRAME TrapFrame,
    IN PKEXCEPTION_FRAME ExceptionFrame
)

/*++

Routine Description:

    This function moves processor register state from the specified trap
    and exception frames to the processor context structure in the current
    processor block.

Arguments:

    TrapFrame - Supplies a pointer to a trap frame.

    ExceptionFrame - Supplies a pointer to an exception frame.

Return Value:

    None.

--*/

{

    PKPRCB Prcb;

    //
    // Get the address of the current processor block and move the
    // specified register state from specified trap and exception
    // frames to the current processor context structure.
    //

    Prcb = KeGetCurrentPrcb();
    Prcb->ProcessorState.ContextFrame.ContextFlags = CONTEXT_FULL |
            CONTEXT_DEBUG_REGISTERS;
    KeContextFromKframes(TrapFrame,
                         ExceptionFrame,
                         &Prcb->ProcessorState.ContextFrame);

    //
    // Save the current processor control state.
    //
    Prcb->ProcessorState.SpecialRegisters.KernelDr6 =
        Prcb->ProcessorState.ContextFrame.Dr6;
    KiSaveProcessorControlState(&Prcb->ProcessorState);
    return;
}
Пример #3
0
VOID
NTAPI
KdpSymbol(IN PSTRING DllPath,
          IN PKD_SYMBOLS_INFO SymbolInfo,
          IN BOOLEAN Unload,
          IN KPROCESSOR_MODE PreviousMode,
          IN PCONTEXT ContextRecord,
          IN PKTRAP_FRAME TrapFrame,
          IN PKEXCEPTION_FRAME ExceptionFrame)
{
    BOOLEAN Enable;
    PKPRCB Prcb = KeGetCurrentPrcb();

    /* Check if we need to do anything */
    if ((PreviousMode != KernelMode) || (KdDebuggerNotPresent)) return;

    /* Enter the debugger */
    Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);

    /* Save the CPU Control State and save the context */
    KiSaveProcessorControlState(&Prcb->ProcessorState);
    RtlCopyMemory(&Prcb->ProcessorState.ContextFrame,
                  ContextRecord,
                  sizeof(CONTEXT));

    /* Report the new state */
    KdpReportLoadSymbolsStateChange(DllPath,
                                    SymbolInfo,
                                    Unload,
                                    &Prcb->ProcessorState.ContextFrame);

    /* Restore the processor state */
    RtlCopyMemory(ContextRecord,
                  &Prcb->ProcessorState.ContextFrame,
                  sizeof(CONTEXT));
    KiRestoreProcessorControlState(&Prcb->ProcessorState);

    /* Exit the debugger and return */
    KdExitDebugger(Enable);
}
Пример #4
0
VOID
NTAPI
KdpCommandString(IN PSTRING NameString,
                 IN PSTRING CommandString,
                 IN KPROCESSOR_MODE PreviousMode,
                 IN PCONTEXT ContextRecord,
                 IN PKTRAP_FRAME TrapFrame,
                 IN PKEXCEPTION_FRAME ExceptionFrame)
{
    BOOLEAN Enable;
    PKPRCB Prcb = KeGetCurrentPrcb();

    /* Check if we need to do anything */
    if ((PreviousMode != KernelMode) || (KdDebuggerNotPresent)) return;

    /* Enter the debugger */
    Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);

    /* Save the CPU Control State and save the context */
    KiSaveProcessorControlState(&Prcb->ProcessorState);
    RtlCopyMemory(&Prcb->ProcessorState.ContextFrame,
                  ContextRecord,
                  sizeof(CONTEXT));

    /* Send the command string to the debugger */
    KdpReportCommandStringStateChange(NameString,
                                      CommandString,
                                      &Prcb->ProcessorState.ContextFrame);

    /* Restore the processor state */
    RtlCopyMemory(ContextRecord,
                  &Prcb->ProcessorState.ContextFrame,
                  sizeof(CONTEXT));
    KiRestoreProcessorControlState(&Prcb->ProcessorState);

    /* Exit the debugger and return */
    KdExitDebugger(Enable);
}
Пример #5
0
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;
}
Пример #6
0
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);
}
Пример #7
0
VOID
NTAPI
INIT_FUNCTION
KiInitializeKernel(IN PKPROCESS InitProcess,
                   IN PKTHREAD InitThread,
                   IN PVOID IdleStack,
                   IN PKPRCB Prcb,
                   IN CCHAR Number,
                   IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
    BOOLEAN NpxPresent;
    ULONG FeatureBits;
    ULONG PageDirectory[2];
    PVOID DpcStack;
    ULONG Vendor[3];

    /* Detect and set the CPU Type */
    KiSetProcessorType();

    /* Check if an FPU is present */
    NpxPresent = KiIsNpxPresent();

    /* Initialize the Power Management Support for this PRCB */
    PoInitializePrcb(Prcb);

    /* Bugcheck if this is a 386 CPU */
    if (Prcb->CpuType == 3) KeBugCheckEx(UNSUPPORTED_PROCESSOR, 0x386, 0, 0, 0);

    /* Get the processor features for the CPU */
    FeatureBits = KiGetFeatureBits();

    /* Set the default NX policy (opt-in) */
    SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_OPTIN;

    /* Check if NPX is always on */
    if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=ALWAYSON"))
    {
        /* Set it always on */
        SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSON;
        FeatureBits |= KF_NX_ENABLED;
    }
    else if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTOUT"))
    {
        /* Set it in opt-out mode */
        SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_OPTOUT;
        FeatureBits |= KF_NX_ENABLED;
    }
    else if ((strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTIN")) ||
             (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE")))
    {
        /* Set the feature bits */
        FeatureBits |= KF_NX_ENABLED;
    }
    else if ((strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=ALWAYSOFF")) ||
             (strstr(KeLoaderBlock->LoadOptions, "EXECUTE")))
    {
        /* Set disabled mode */
        SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSOFF;
        FeatureBits |= KF_NX_DISABLED;
    }

    /* Save feature bits */
    Prcb->FeatureBits = FeatureBits;

    /* Save CPU state */
    KiSaveProcessorControlState(&Prcb->ProcessorState);

    /* Get cache line information for this CPU */
    KiGetCacheInformation();

    /* Initialize spinlocks and DPC data */
    KiInitSpinLocks(Prcb, Number);

    /* Check if this is the Boot CPU */
    if (!Number)
    {
        /* Set Node Data */
        KeNodeBlock[0] = &KiNode0;
        Prcb->ParentNode = KeNodeBlock[0];
        KeNodeBlock[0]->ProcessorMask = Prcb->SetMember;

        /* Set boot-level flags */
        KeI386NpxPresent = NpxPresent;
        KeI386CpuType = Prcb->CpuType;
        KeI386CpuStep = Prcb->CpuStep;
        KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
        KeProcessorLevel = (USHORT)Prcb->CpuType;
        if (Prcb->CpuID) KeProcessorRevision = Prcb->CpuStep;
        KeFeatureBits = FeatureBits;
        KeI386FxsrPresent = (KeFeatureBits & KF_FXSR) ? TRUE : FALSE;
        KeI386XMMIPresent = (KeFeatureBits & KF_XMMI) ? TRUE : FALSE;

        /* Detect 8-byte compare exchange support */
        if (!(KeFeatureBits & KF_CMPXCHG8B))
        {
            /* Copy the vendor string */
            RtlCopyMemory(Vendor, Prcb->VendorString, sizeof(Vendor));

            /* Bugcheck the system. Windows *requires* this */
            KeBugCheckEx(UNSUPPORTED_PROCESSOR,
                         (1 << 24 ) | (Prcb->CpuType << 16) | Prcb->CpuStep,
                         Vendor[0],
                         Vendor[1],
                         Vendor[2]);
        }

        /* Set the current MP Master KPRCB to the Boot PRCB */
        Prcb->MultiThreadSetMaster = Prcb;

        /* Lower to APC_LEVEL */
        KeLowerIrql(APC_LEVEL);

        /* Initialize some spinlocks */
        KeInitializeSpinLock(&KiFreezeExecutionLock);
        KeInitializeSpinLock(&Ki486CompatibilityLock);

        /* Initialize portable parts of the OS */
        KiInitSystem();

        /* Initialize the Idle Process and the Process Listhead */
        InitializeListHead(&KiProcessListHead);
        PageDirectory[0] = 0;
        PageDirectory[1] = 0;
        KeInitializeProcess(InitProcess,
                            0,
                            0xFFFFFFFF,
                            PageDirectory,
                            FALSE);
        InitProcess->QuantumReset = MAXCHAR;
    }
    else
    {
        /* FIXME */
        DPRINT1("SMP Boot support not yet present\n");
    }

    /* Setup the Idle Thread */
    KeInitializeThread(InitProcess,
                       InitThread,
                       NULL,
                       NULL,
                       NULL,
                       NULL,
                       NULL,
                       IdleStack);
    InitThread->NextProcessor = Number;
    InitThread->Priority = HIGH_PRIORITY;
    InitThread->State = Running;
    InitThread->Affinity = 1 << Number;
    InitThread->WaitIrql = DISPATCH_LEVEL;
    InitProcess->ActiveProcessors = 1 << Number;

    /* HACK for MmUpdatePageDir */
    ((PETHREAD)InitThread)->ThreadsProcess = (PEPROCESS)InitProcess;

    /* Set basic CPU Features that user mode can read */
    SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] =
        (KeFeatureBits & KF_MMX) ? TRUE: FALSE;
    SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] =
        (KeFeatureBits & KF_CMPXCHG8B) ? TRUE: FALSE;
    SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] =
        ((KeFeatureBits & KF_FXSR) && (KeFeatureBits & KF_XMMI)) ? TRUE: FALSE;
    SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] =
        ((KeFeatureBits & KF_FXSR) && (KeFeatureBits & KF_XMMI64)) ? TRUE: FALSE;
    SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] =
        (KeFeatureBits & KF_3DNOW) ? TRUE: FALSE;
    SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] =
        (KeFeatureBits & KF_RDTSC) ? TRUE: FALSE;

    /* Set up the thread-related fields in the PRCB */
    Prcb->CurrentThread = InitThread;
    Prcb->NextThread = NULL;
    Prcb->IdleThread = InitThread;

    /* Initialize the Kernel Executive */
    ExpInitializeExecutive(Number, LoaderBlock);

    /* Only do this on the boot CPU */
    if (!Number)
    {
        /* Calculate the time reciprocal */
        KiTimeIncrementReciprocal =
            KiComputeReciprocal(KeMaximumIncrement,
                                &KiTimeIncrementShiftCount);

        /* Update DPC Values in case they got updated by the executive */
        Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
        Prcb->MinimumDpcRate = KiMinimumDpcRate;
        Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;

        /* Allocate the DPC Stack */
        DpcStack = MmCreateKernelStack(FALSE, 0);
        if (!DpcStack) KeBugCheckEx(NO_PAGES_AVAILABLE, 1, 0, 0, 0);
        Prcb->DpcStack = DpcStack;

        /* Allocate the IOPM save area. */
        Ki386IopmSaveArea = ExAllocatePoolWithTag(PagedPool,
                                                  PAGE_SIZE * 2,
                                                  '  eK');
        if (!Ki386IopmSaveArea)
        {
            /* Bugcheck. We need this for V86/VDM support. */
            KeBugCheckEx(NO_PAGES_AVAILABLE, 2, PAGE_SIZE * 2, 0, 0);
        }
    }

    /* Raise to Dispatch */
    KfRaiseIrql(DISPATCH_LEVEL);

    /* Set the Idle Priority to 0. This will jump into Phase 1 */
    KeSetPriorityThread(InitThread, 0);

    /* If there's no thread scheduled, put this CPU in the Idle summary */
    KiAcquirePrcbLock(Prcb);
    if (!Prcb->NextThread) KiIdleSummary |= 1 << Number;
    KiReleasePrcbLock(Prcb);

    /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */
    KfRaiseIrql(HIGH_LEVEL);
    LoaderBlock->Prcb = 0;
}
Пример #8
0
BOOLEAN
NTAPI
KdpReport(IN PKTRAP_FRAME TrapFrame,
          IN PKEXCEPTION_FRAME ExceptionFrame,
          IN PEXCEPTION_RECORD ExceptionRecord,
          IN PCONTEXT ContextRecord,
          IN KPROCESSOR_MODE PreviousMode,
          IN BOOLEAN SecondChanceException)
{
    BOOLEAN Enable, Handled;
    PKPRCB Prcb;
    NTSTATUS ExceptionCode = ExceptionRecord->ExceptionCode;

    /*
     * Determine whether to pass the exception to the debugger.
     * First, check if this is a "debug exception", meaning breakpoint
     * (including debug service), single step and assertion failure exceptions.
     */
    if ((ExceptionCode == STATUS_BREAKPOINT) ||
            (ExceptionCode == STATUS_SINGLE_STEP) ||
            (ExceptionCode == STATUS_ASSERTION_FAILURE))
    {
        /* This is a debug exception; we always pass them to the debugger */
    }
    else if (NtGlobalFlag & FLG_STOP_ON_EXCEPTION)
    {
        /*
         * Not a debug exception, but the stop-on-exception flag is set,
         * meaning the debugger requests that we pass it first chance
         * exceptions. However, some exceptions are always passed to the
         * exception handler first, namely exceptions with a code that isn't
         * an error or warning code, and also exceptions with the special
         * STATUS_PORT_DISCONNECTED code (an error code).
         */
        if ((SecondChanceException == FALSE) &&
                ((ExceptionCode == STATUS_PORT_DISCONNECTED) ||
                 (NT_SUCCESS(ExceptionCode))))
        {
            /* Let the exception handler, if any, try to handle it */
            return FALSE;
        }
    }
    else if (SecondChanceException == FALSE)
    {
        /*
         * This isn't a debug exception and the stop-on-exception flag isn't
         * set, so don't bother
         */
        return FALSE;
    }

    /* Enter the debugger */
    Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);

    /*
     * Get the KPRCB and save the CPU Control State manually instead of
     * using KiSaveProcessorState, since we already have a valid CONTEXT.
     */
    Prcb = KeGetCurrentPrcb();
    KiSaveProcessorControlState(&Prcb->ProcessorState);
    RtlCopyMemory(&Prcb->ProcessorState.ContextFrame,
                  ContextRecord,
                  sizeof(CONTEXT));

    /* Report the new state */
    Handled = KdpReportExceptionStateChange(ExceptionRecord,
                                            &Prcb->ProcessorState.
                                            ContextFrame,
                                            SecondChanceException);

    /* Now restore the processor state, manually again. */
    RtlCopyMemory(ContextRecord,
                  &Prcb->ProcessorState.ContextFrame,
                  sizeof(CONTEXT));
    KiRestoreProcessorControlState(&Prcb->ProcessorState);

    /* Exit the debugger and clear the CTRL-C state */
    KdExitDebugger(Enable);
    KdpControlCPressed = FALSE;
    return Handled;
}