Ejemplo n.º 1
1
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();
}
Ejemplo n.º 2
1
VOID
NTAPI
INIT_FUNCTION
DisplayBootBitmap(IN BOOLEAN TextMode)
{
    PBITMAPINFOHEADER BitmapInfoHeader;
    LPRGBQUAD Palette;

    PVOID Header, Band, Text, Screen;
    ROT_BAR_TYPE TempRotBarSelection = RB_UNSPECIFIED;

#ifdef CORE_6781_resolved
    UCHAR Buffer[64];
#endif

    /* Check if the system thread has already been created */
    if (SysThreadCreated)
    {
        /* Reset the progress bar */
        InbvAcquireLock();
        RotBarSelection = RB_UNSPECIFIED;
        InbvReleaseLock();
    }

    /* Check if this is text mode */
    ShowProgressBar = FALSE;
    if (TextMode)
    {
        /* Check if this is a server OS */
        if (SharedUserData->NtProductType == NtProductWinNt)
        {
            /* It's not, set workstation settings */
            InbvSetTextColor(15);
            InbvSolidColorFill(0, 0, 639, 479, 7);
            InbvSolidColorFill(0, 421, 639, 479, 1);

            /* Get resources */
            Header = InbvGetResourceAddress(IDB_LOGO_HEADER);
            Band = InbvGetResourceAddress(IDB_LOGO_BAND);
        }
        else
        {
            /* Set server settings */
            InbvSetTextColor(14);
            InbvSolidColorFill(0, 0, 639, 479, 6);
            InbvSolidColorFill(0, 421, 639, 479, 1);

            /* Get resources */
            Header = InbvGetResourceAddress(IDB_SERVER_HEADER);
            Band = InbvGetResourceAddress(IDB_SERVER_BAND);
        }

        /* Set the scrolling region */
        InbvSetScrollRegion(32, 80, 631, 400);

        /* Make sure we have resources */
        if ((Header) && (Band))
        {
            /* BitBlt them on the screen */
            InbvBitBlt(Band, 0, 419);
            InbvBitBlt(Header, 0, 0);
        }
    }
    else
    {
        /* Is the boot driver installed? */
        Text = NULL;
        if (!InbvBootDriverInstalled) return;

        /* Load the standard boot screen */
        Screen = InbvGetResourceAddress(IDB_BOOT_LOGO);
        if (SharedUserData->NtProductType == NtProductWinNt)
        {
            /* Workstation product, display appropriate status bar color */
            InbvGetResourceAddress(IDB_BAR_PRO);
        }
        else
        {
            /* Display correct branding based on server suite */
            if (ExVerifySuite(StorageServer))
            {
                /* Storage Server Edition */
                Text = InbvGetResourceAddress(IDB_STORAGE_SERVER);
            }
            else if (ExVerifySuite(ComputeServer))
            {
                /* Compute Cluster Edition */
                Text = InbvGetResourceAddress(IDB_CLUSTER_SERVER);
            }
            else
            {
                /* Normal edition */
                Text = InbvGetResourceAddress(IDB_SERVER_LOGO);
            }

            /* Server product, display appropriate status bar color */
            InbvGetResourceAddress(IDB_BAR_SERVER);
        }

        /* Make sure we had a logo */
        if (Screen)
        {
            /* Choose progress bar */
            TempRotBarSelection = RB_SQUARE_CELLS;

            /*
             * Save the main image palette and replace it with black palette, so
             * we can do fade in effect later.
             */
            BitmapInfoHeader = (PBITMAPINFOHEADER)Screen;
            Palette = (LPRGBQUAD)((PUCHAR)Screen + BitmapInfoHeader->biSize);
            RtlCopyMemory(_MainPalette, Palette, sizeof(_MainPalette));
            RtlZeroMemory(Palette, sizeof(_MainPalette));

            /* Blit the background */
            InbvBitBlt(Screen, 0, 0);

            /* Set progress bar coordinates and display it */
            InbvSetProgressBarCoordinates(257, 352);

            /* Display the boot logo and fade it in */
            BootImageFadeIn();

#ifdef CORE_6781_resolved
            /* Check for non-workstation products */
            if (SharedUserData->NtProductType != NtProductWinNt)
            {
                /* Overwrite part of the logo for a server product */
                InbvScreenToBufferBlt(Buffer, 413, 237, 7, 7, 8);
                InbvSolidColorFill(418, 230, 454, 256, 0);
                InbvBufferToScreenBlt(Buffer, 413, 237, 7, 7, 8);

                /* In setup mode, you haven't selected a SKU yet */
                if (ExpInTextModeSetup) Text = NULL;
            }
#endif
        }

#ifdef CORE_6781_resolved
        /* Draw the SKU text if it exits */
        if (Text) InbvBitBlt(Text, 180, 121);
#else
        DBG_UNREFERENCED_LOCAL_VARIABLE(Text);
#endif

        /* Draw the progress bar bit */
//      if (Bar) InbvBitBlt(Bar, 0, 0);

        /* Set filter which will draw text display if needed */
        InbvInstallDisplayStringFilter(DisplayFilter);
    }

    /* Do we have a system thread? */
    if (SysThreadCreated)
    {
        /* We do, set the progress bar location */
        InbvAcquireLock();
        RotBarSelection = TempRotBarSelection;
        //InbvRotBarInit();
        InbvReleaseLock();
    }
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
Archivo: bug.c Proyecto: RPG-7/reactos
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);
    }
}