1136 lines
22 KiB
C
1136 lines
22 KiB
C
/*++
|
||
|
||
Copyright (c) 1990-1998 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
bootvid.c
|
||
|
||
Abstract:
|
||
|
||
This file implements the interface between the kernel, and the
|
||
graphical boot driver.
|
||
|
||
Author:
|
||
|
||
Erick Smith (ericks) Feb. 3, 1998
|
||
|
||
Environment:
|
||
|
||
kernel mode
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "ntos.h"
|
||
#include "ntimage.h"
|
||
#include <zwapi.h>
|
||
#include <ntdddisk.h>
|
||
#include <setupblk.h>
|
||
#include <fsrtl.h>
|
||
#include <ntverp.h>
|
||
|
||
#include "stdlib.h"
|
||
#include "stdio.h"
|
||
#include <string.h>
|
||
|
||
#include <safeboot.h>
|
||
|
||
#include <inbv.h>
|
||
#include <bootvid.h>
|
||
#include <hdlsblk.h>
|
||
#include <hdlsterm.h>
|
||
|
||
#include "anim.h"
|
||
|
||
ULONG InbvTerminalBkgdColor = HEADLESS_TERM_DEFAULT_BKGD_COLOR;
|
||
ULONG InbvTerminalTextColor = HEADLESS_TERM_DEFAULT_TEXT_COLOR;
|
||
|
||
PUCHAR
|
||
FindBitmapResource(
|
||
IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
||
IN ULONG_PTR ResourceIdentifier
|
||
);
|
||
|
||
#if defined(ALLOC_PRAGMA)
|
||
#pragma alloc_text(INIT,InbvIndicateProgress)
|
||
#pragma alloc_text(INIT,InbvDriverInitialize)
|
||
#pragma alloc_text(INIT,FindBitmapResource)
|
||
#endif
|
||
|
||
//
|
||
// System global variable
|
||
//
|
||
|
||
BOOLEAN InbvBootDriverInstalled = FALSE;
|
||
BOOLEAN InbvDisplayDebugStrings = FALSE;
|
||
INBV_DISPLAY_STATE InbvDisplayState = INBV_DISPLAY_STATE_OWNED;
|
||
|
||
KSPIN_LOCK BootDriverLock;
|
||
KIRQL InbvOldIrql;
|
||
|
||
INBV_RESET_DISPLAY_PARAMETERS InbvResetDisplayParameters = NULL;
|
||
INBV_DISPLAY_STRING_FILTER InbvDisplayFilter = NULL;
|
||
|
||
#define MAX_RESOURCES 15
|
||
|
||
ULONG ResourceCount = 0;
|
||
PUCHAR ResourceList[MAX_RESOURCES];
|
||
|
||
ULONG ProgressBarLeft;
|
||
ULONG ProgressBarTop;
|
||
BOOLEAN ShowProgressBar = TRUE;
|
||
|
||
struct _InbvProgressState {
|
||
ULONG Floor;
|
||
ULONG Ceiling;
|
||
ULONG Bias;
|
||
} InbvProgressState;
|
||
|
||
#ifdef ALLOC_DATA_PRAGMA
|
||
#pragma data_seg("INITDATA")
|
||
#endif
|
||
|
||
struct _BT_PROGRESS_INDICATOR {
|
||
ULONG Count;
|
||
ULONG Expected;
|
||
ULONG Percentage;
|
||
} InbvProgressIndicator = { 0, 25, 0 };
|
||
|
||
|
||
#ifdef ALLOC_DATA_PRAGMA
|
||
#pragma data_seg()
|
||
#endif
|
||
|
||
VOID
|
||
InbvAcquireLock(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is an internal function used to grab the boot driver lock. This
|
||
ensures that only one thread will enter the driver code at a time.
|
||
|
||
Notes:
|
||
|
||
You must call ReleaseLock for each call to AcquireLock.
|
||
|
||
--*/
|
||
|
||
{
|
||
KIRQL Irql;
|
||
KIRQL LocalIrql;
|
||
|
||
LocalIrql = KeGetCurrentIrql();
|
||
|
||
if (LocalIrql <= DISPATCH_LEVEL) {
|
||
|
||
while (!KeTestSpinLock(&BootDriverLock))
|
||
;
|
||
KeRaiseIrql(DISPATCH_LEVEL, &Irql);
|
||
LocalIrql = Irql;
|
||
}
|
||
|
||
KiAcquireSpinLock(&BootDriverLock);
|
||
InbvOldIrql = LocalIrql;
|
||
}
|
||
|
||
VOID
|
||
InbvReleaseLock(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine releases the boot driver lock.
|
||
|
||
--*/
|
||
|
||
{
|
||
KIRQL OldIrql = InbvOldIrql;
|
||
|
||
KiReleaseSpinLock(&BootDriverLock);
|
||
|
||
if (OldIrql <= DISPATCH_LEVEL) {
|
||
KeLowerIrql(OldIrql);
|
||
}
|
||
}
|
||
|
||
BOOLEAN
|
||
InbvTestLock(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine allows you to try to acquire the display lock. If it
|
||
can't get the lock right away, it returns failure.
|
||
|
||
Returns:
|
||
|
||
TRUE - If you aqcuired the lock.
|
||
FALSE - If another thread is currently using the boot driver.
|
||
|
||
Notes:
|
||
|
||
You must call InbvReleaseLock if this function returns TRUE!
|
||
|
||
--*/
|
||
|
||
{
|
||
KIRQL Irql;
|
||
|
||
if (KeTryToAcquireSpinLock(&BootDriverLock, &Irql)) {
|
||
InbvOldIrql = Irql;
|
||
return TRUE;
|
||
} else {
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
InbvEnableBootDriver(
|
||
BOOLEAN bEnable
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine allows the kernel to control whether Inbv
|
||
calls make it through to the boot driver, and when they don't.
|
||
|
||
Arguments:
|
||
|
||
bEnable - If TRUE, we will allow Inbv calls to display,
|
||
otherwise we will not.
|
||
|
||
--*/
|
||
|
||
{
|
||
if (InbvBootDriverInstalled) {
|
||
|
||
if (InbvDisplayState < INBV_DISPLAY_STATE_LOST) {
|
||
|
||
//
|
||
// We can only wait for our lock, and execute our clean up code
|
||
// if the driver is installed.
|
||
//
|
||
|
||
InbvAcquireLock();
|
||
|
||
if (InbvDisplayState == INBV_DISPLAY_STATE_OWNED) {
|
||
VidCleanUp();
|
||
}
|
||
|
||
InbvDisplayState = (bEnable ? INBV_DISPLAY_STATE_OWNED : INBV_DISPLAY_STATE_DISABLED);
|
||
InbvReleaseLock();
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// This allow us to set display state before boot driver starts.
|
||
//
|
||
|
||
InbvDisplayState = (bEnable ? INBV_DISPLAY_STATE_OWNED : INBV_DISPLAY_STATE_DISABLED);
|
||
}
|
||
}
|
||
|
||
BOOLEAN
|
||
InbvEnableDisplayString(
|
||
BOOLEAN bEnable
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine allows the kernel to control when HalDisplayString
|
||
calls make it through to the boot driver, and when they don't.
|
||
|
||
Arguments:
|
||
|
||
bEnable - If TRUE, we will allow HalDisplayString calls to display,
|
||
otherwise we will not.
|
||
|
||
Returns:
|
||
|
||
TRUE - If display string were currently being dumped.
|
||
FALSE - otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOLEAN PrevValue = InbvDisplayDebugStrings;
|
||
|
||
InbvDisplayDebugStrings = bEnable;
|
||
|
||
return PrevValue;
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
InbvIsBootDriverInstalled(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine allows a component to determine if the gui boot
|
||
driver is in use.
|
||
|
||
--*/
|
||
|
||
{
|
||
return InbvBootDriverInstalled;
|
||
}
|
||
|
||
BOOLEAN
|
||
InbvResetDisplay(
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine will reset the display from text mode to a
|
||
supported graphics mode.
|
||
|
||
Notes:
|
||
|
||
This routine expects the display to be in text mode when called.
|
||
|
||
--*/
|
||
|
||
{
|
||
if (InbvBootDriverInstalled && (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)) {
|
||
VidResetDisplay(TRUE);
|
||
return TRUE;
|
||
} else {
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
VOID
|
||
InbvScreenToBufferBlt(
|
||
PUCHAR Buffer,
|
||
ULONG x,
|
||
ULONG y,
|
||
ULONG width,
|
||
ULONG height,
|
||
ULONG lDelta
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine allows for copying portions of video memory into system
|
||
memory.
|
||
|
||
Arguments:
|
||
|
||
Buffer - Location in which to place the video image.
|
||
|
||
x, y - X and Y coordinates of top-left corner of image.
|
||
|
||
width, height - The width and height of the image in pixels.
|
||
|
||
lDelta - width of the buffer in bytes
|
||
|
||
Notes:
|
||
|
||
This routine does not automatically acquire the device lock, so
|
||
the caller must call InbvAquireLock or InbvTestLock to acquire
|
||
the device lock.
|
||
|
||
--*/
|
||
|
||
{
|
||
if (InbvBootDriverInstalled && (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)) {
|
||
VidScreenToBufferBlt(Buffer, x, y, width, height, lDelta);
|
||
}
|
||
}
|
||
|
||
VOID
|
||
InbvBufferToScreenBlt(
|
||
PUCHAR Buffer,
|
||
ULONG x,
|
||
ULONG y,
|
||
ULONG width,
|
||
ULONG height,
|
||
ULONG lDelta
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine allows for copying previously saved portions of video
|
||
memory back to the screen.
|
||
|
||
Arguments:
|
||
|
||
Buffer - Location in which to place the video image.
|
||
|
||
x, y - X and Y coordinates of top-left corner of image.
|
||
|
||
width, height - The width and height of the image in pixels.
|
||
|
||
lDelta - width of the buffer in bytes
|
||
|
||
Notes:
|
||
|
||
This routine does not automatically acquire the device lock, so
|
||
the caller must call InbvAquireLock or InbvTestLock to acquire
|
||
the device lock.
|
||
|
||
--*/
|
||
|
||
{
|
||
if (InbvBootDriverInstalled && (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)) {
|
||
VidBufferToScreenBlt(Buffer, x, y, width, height, lDelta);
|
||
}
|
||
}
|
||
|
||
VOID
|
||
InbvBitBlt(
|
||
PUCHAR Buffer,
|
||
ULONG x,
|
||
ULONG y
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine blts the bitmap described in 'Buffer' to the location
|
||
x and y on the screen.
|
||
|
||
Arguments:
|
||
|
||
Buffer - points to a bitmap (in the same format as stored on disk).
|
||
|
||
x, y - the upper left corner at which the bitmap will be drawn.
|
||
|
||
--*/
|
||
|
||
{
|
||
if (InbvBootDriverInstalled && (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)) {
|
||
InbvAcquireLock();
|
||
VidBitBlt(Buffer, x, y);
|
||
InbvReleaseLock();
|
||
}
|
||
}
|
||
|
||
VOID
|
||
InbvSolidColorFill(
|
||
ULONG x1,
|
||
ULONG y1,
|
||
ULONG x2,
|
||
ULONG y2,
|
||
ULONG color
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine fills a rectangular portion of the screen with a
|
||
given color.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG x, y;
|
||
HEADLESS_CMD_SET_COLOR HeadlessCmd;
|
||
|
||
if (InbvBootDriverInstalled && (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)) {
|
||
InbvAcquireLock();
|
||
VidSolidColorFill(x1, y1, x2, y2, color);
|
||
|
||
//
|
||
// Now fill in the area on the terminal
|
||
//
|
||
|
||
//
|
||
// Color comes in as the palette index to the standard windows VGA palette.
|
||
// Convert it.
|
||
//
|
||
switch (color) {
|
||
|
||
case 0:
|
||
InbvTerminalBkgdColor = 40;
|
||
break;
|
||
|
||
case 4:
|
||
InbvTerminalBkgdColor = 44;
|
||
break;
|
||
|
||
default:
|
||
//
|
||
// Guess
|
||
//
|
||
InbvTerminalBkgdColor = color + 40;
|
||
}
|
||
|
||
HeadlessCmd.FgColor = InbvTerminalTextColor;
|
||
HeadlessCmd.BkgColor = InbvTerminalBkgdColor;
|
||
HeadlessDispatch(HeadlessCmdSetColor,
|
||
&HeadlessCmd,
|
||
sizeof(HEADLESS_CMD_SET_COLOR),
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
//
|
||
// All block fills come in as if on VGA (640x480). The terminal is only 24x80
|
||
// so just assume it is full screen reset for now. This works because the only
|
||
// thing enables terminal output is KeBugCheckEx(), which does a full screen fill.
|
||
//
|
||
HeadlessDispatch(HeadlessCmdClearDisplay, NULL, 0, NULL, NULL);
|
||
|
||
InbvReleaseLock();
|
||
}
|
||
}
|
||
|
||
ULONG
|
||
InbvSetTextColor(
|
||
ULONG Color
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Sets the text color used when dislaying text.
|
||
|
||
Arguments:
|
||
|
||
Color - the new text color.
|
||
|
||
Returns:
|
||
|
||
The previous text color.
|
||
|
||
--*/
|
||
|
||
{
|
||
HEADLESS_CMD_SET_COLOR HeadlessCmd;
|
||
|
||
//
|
||
// Color comes in as the palette index to the standard windows VGA palette.
|
||
// Convert it.
|
||
//
|
||
switch (Color) {
|
||
|
||
case 0:
|
||
InbvTerminalBkgdColor = 40;
|
||
break;
|
||
|
||
case 4:
|
||
InbvTerminalTextColor = 44;
|
||
break;
|
||
|
||
default:
|
||
//
|
||
// Guess
|
||
//
|
||
InbvTerminalTextColor = Color + 40;
|
||
}
|
||
|
||
HeadlessCmd.FgColor = InbvTerminalTextColor;
|
||
HeadlessCmd.BkgColor = InbvTerminalBkgdColor;
|
||
HeadlessDispatch(HeadlessCmdSetColor,
|
||
&HeadlessCmd,
|
||
sizeof(HEADLESS_CMD_SET_COLOR),
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
return VidSetTextColor(Color);
|
||
}
|
||
|
||
VOID
|
||
InbvInstallDisplayStringFilter(
|
||
INBV_DISPLAY_STRING_FILTER DisplayFilter
|
||
)
|
||
|
||
/*++
|
||
|
||
--*/
|
||
|
||
{
|
||
InbvDisplayFilter = DisplayFilter;
|
||
}
|
||
|
||
BOOLEAN
|
||
InbvDisplayString(
|
||
PUCHAR Str
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine displays a string on the screen.
|
||
|
||
Arguments:
|
||
|
||
Str - The string to be displayed.
|
||
|
||
--*/
|
||
|
||
{
|
||
PUCHAR *String = &Str;
|
||
|
||
if (InbvBootDriverInstalled && (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)) {
|
||
|
||
if (InbvDisplayDebugStrings) {
|
||
|
||
if (InbvDisplayFilter) {
|
||
InbvDisplayFilter(String);
|
||
}
|
||
|
||
InbvAcquireLock();
|
||
|
||
VidDisplayString(*String);
|
||
|
||
//
|
||
// Since the command structure is exactly a string, we can do this. The
|
||
// ASSERT() will catch if this ever changes. If it does change, then
|
||
// we will need to allocate a structure, or have one pre-allocated, for
|
||
// filling in and copying over the string.
|
||
//
|
||
ASSERT(FIELD_OFFSET(HEADLESS_CMD_PUT_STRING, String) == 0);
|
||
HeadlessDispatch(HeadlessCmdPutString,
|
||
*String,
|
||
strlen(*String) + sizeof('\0'),
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
InbvReleaseLock();
|
||
}
|
||
|
||
return TRUE;
|
||
|
||
} else {
|
||
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
#define PROGRESS_BAR_TICK_WIDTH 9
|
||
#define PROGRESS_BAR_TICK_HEIGHT 8
|
||
#define PROGRESS_BAR_TICKS 18
|
||
#define PROGRESS_BAR_COLOR 11
|
||
|
||
VOID
|
||
InbvSetProgressBarCoordinates(
|
||
ULONG x,
|
||
ULONG y
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sets the upper left coordinate of the progress bar.
|
||
|
||
Arguments:
|
||
|
||
x, y - upper left coordinate of progress bar.
|
||
|
||
--*/
|
||
|
||
{
|
||
ProgressBarLeft = x;
|
||
ProgressBarTop = y;
|
||
ShowProgressBar = TRUE;
|
||
}
|
||
|
||
VOID
|
||
InbvUpdateProgressBar(
|
||
ULONG Percentage
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called by the system during startup to update
|
||
the status bar displayed on the gui boot screen.
|
||
|
||
--*/
|
||
|
||
{
|
||
int i, Ticks;
|
||
|
||
if (ShowProgressBar && InbvBootDriverInstalled && (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)) {
|
||
|
||
//
|
||
// Draw the ticks for the current percentage
|
||
//
|
||
|
||
//
|
||
// The following calculations are biased by 100 do that
|
||
// InbvProgressState.Bias can be expressed as an integer fraction.
|
||
//
|
||
|
||
Ticks = Percentage * InbvProgressState.Bias;
|
||
Ticks += InbvProgressState.Floor;
|
||
Ticks *= PROGRESS_BAR_TICKS;
|
||
Ticks /= 10000;
|
||
|
||
for (i=0; i<Ticks; i++) {
|
||
InbvAcquireLock();
|
||
VidSolidColorFill(ProgressBarLeft + (i * PROGRESS_BAR_TICK_WIDTH),
|
||
ProgressBarTop,
|
||
ProgressBarLeft + ((i + 1) * PROGRESS_BAR_TICK_WIDTH) - 2,
|
||
ProgressBarTop + PROGRESS_BAR_TICK_HEIGHT - 1,
|
||
PROGRESS_BAR_COLOR);
|
||
InbvReleaseLock();
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
VOID
|
||
InbvSetProgressBarSubset(
|
||
ULONG Floor,
|
||
ULONG Ceiling
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Sets floor and ceiling for subsequent calls to InbvUpdateProgressBar.
|
||
While a floor and ceiling are in effect, a caller's 100% is a
|
||
percentage of this range. If floor and ceiling are zero, the
|
||
entire range is used.
|
||
|
||
Arguments:
|
||
|
||
Floor Lower limit of the subset.
|
||
Ceiling Upper limit of the subset.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
ASSERT(Floor < Ceiling);
|
||
ASSERT(Ceiling <= 100);
|
||
|
||
InbvProgressState.Floor = Floor * 100;
|
||
InbvProgressState.Ceiling = Ceiling * 100;
|
||
InbvProgressState.Bias = (Ceiling - Floor);
|
||
}
|
||
|
||
VOID
|
||
InbvIndicateProgress(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called to indicate that progress is being
|
||
made. The number of calls is counted and compared to the
|
||
expected number of calls, the boot progress bar is updated
|
||
apropriately.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG Percentage;
|
||
|
||
InbvProgressIndicator.Count++;
|
||
|
||
//
|
||
// Calculate how far along we think we are.
|
||
//
|
||
|
||
Percentage = (InbvProgressIndicator.Count * 100) /
|
||
InbvProgressIndicator.Expected;
|
||
|
||
//
|
||
// The Expected number of calls can vary from boot to boot
|
||
// but should remain relatively constant. Allow for the
|
||
// possibility we were called more than we expected to be.
|
||
// (The progress bar simply stalls at this point).
|
||
//
|
||
|
||
if (Percentage > 99) {
|
||
Percentage = 99;
|
||
}
|
||
|
||
//
|
||
// See if the progress bar should be updated.
|
||
//
|
||
|
||
if (Percentage != InbvProgressIndicator.Percentage) {
|
||
InbvProgressIndicator.Percentage = Percentage;
|
||
InbvUpdateProgressBar(Percentage);
|
||
}
|
||
}
|
||
|
||
PUCHAR
|
||
FindBitmapResource(
|
||
IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
||
IN ULONG_PTR ResourceIdentifier
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Gets a pointer to the bitmap image compiled into this binary,
|
||
if one exists.
|
||
|
||
Arguments:
|
||
|
||
LoaderBlock - Used in obtaining the bitmap resource
|
||
ResourceIdentifier - Identifier for the resource to return the address for
|
||
|
||
Return Value:
|
||
|
||
Pointer to bitmap resource, if successful. NULL otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
PLIST_ENTRY Entry;
|
||
PKLDR_DATA_TABLE_ENTRY DataTableEntry;
|
||
ULONG_PTR ResourceIdPath[3];
|
||
PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry;
|
||
PUCHAR Bitmap;
|
||
UNICODE_STRING KernelString1;
|
||
UNICODE_STRING KernelString2;
|
||
|
||
RtlInitUnicodeString(&KernelString1, L"NTOSKRNL.EXE");
|
||
RtlInitUnicodeString(&KernelString2, L"NTKRNLMP.EXE");
|
||
|
||
//
|
||
// Find our loader block entry
|
||
//
|
||
|
||
Entry = LoaderBlock->LoadOrderListHead.Flink;
|
||
while (Entry != &LoaderBlock->LoadOrderListHead) {
|
||
|
||
//
|
||
// Get the address of the data table entry for this component.
|
||
//
|
||
|
||
DataTableEntry = CONTAINING_RECORD(Entry,
|
||
KLDR_DATA_TABLE_ENTRY,
|
||
InLoadOrderLinks);
|
||
|
||
//
|
||
// Case-insensitive comparison with "NTOSKRNL.EXE" and "NTKRNLMP.EXE"
|
||
//
|
||
|
||
if (RtlEqualUnicodeString(&DataTableEntry->BaseDllName,
|
||
&KernelString1,
|
||
TRUE) == TRUE) {
|
||
break;
|
||
}
|
||
|
||
if (RtlEqualUnicodeString(&DataTableEntry->BaseDllName,
|
||
&KernelString2,
|
||
TRUE) == TRUE) {
|
||
break;
|
||
}
|
||
|
||
Entry = Entry->Flink;
|
||
}
|
||
|
||
//
|
||
// If we couldn't find ntoskrnl in the loader list, give up
|
||
//
|
||
|
||
if (Entry == &LoaderBlock->LoadOrderListHead) {
|
||
return NULL;
|
||
}
|
||
|
||
ResourceIdPath[0] = 2; // RT_BITMAP = 2
|
||
ResourceIdPath[1] = ResourceIdentifier;
|
||
ResourceIdPath[2] = 0; // ??
|
||
|
||
Status = LdrFindResource_U( DataTableEntry->DllBase,
|
||
ResourceIdPath,
|
||
3,
|
||
(VOID *) &ResourceDataEntry );
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
return NULL;
|
||
}
|
||
|
||
Status = LdrAccessResource( DataTableEntry->DllBase,
|
||
ResourceDataEntry,
|
||
&Bitmap,
|
||
NULL );
|
||
if (!NT_SUCCESS(Status)) {
|
||
return NULL;
|
||
}
|
||
|
||
return Bitmap;
|
||
}
|
||
|
||
PUCHAR
|
||
InbvGetResourceAddress(
|
||
IN ULONG ResourceNumber
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine returns the cached resources address for a given
|
||
resource.
|
||
|
||
--*/
|
||
|
||
{
|
||
if (ResourceNumber <= ResourceCount) {
|
||
return ResourceList[ResourceNumber-1];
|
||
} else {
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
BOOLEAN
|
||
InbvDriverInitialize(
|
||
IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
||
ULONG Count
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine will call into the graphical boot driver and give the
|
||
driver a chance to initialize. At this point, the boot driver
|
||
should determine whether it can run on the hardware in the machine.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG i;
|
||
ULONG_PTR p;
|
||
PCHAR Options;
|
||
BOOLEAN DispModeChange = FALSE;
|
||
|
||
//
|
||
// Only do this once.
|
||
//
|
||
|
||
if (InbvBootDriverInstalled == TRUE) {
|
||
return TRUE;
|
||
}
|
||
|
||
KeInitializeSpinLock(&BootDriverLock);
|
||
|
||
if (InbvDisplayState == INBV_DISPLAY_STATE_OWNED) {
|
||
|
||
Options = LoaderBlock->LoadOptions ? _strupr(LoaderBlock->LoadOptions) : NULL;
|
||
|
||
if (Options) {
|
||
DispModeChange = (BOOLEAN)(strstr(Options, "BOOTLOGO") == NULL);
|
||
} else {
|
||
DispModeChange = TRUE;
|
||
}
|
||
}
|
||
|
||
InbvBootDriverInstalled = VidInitialize(DispModeChange);
|
||
|
||
if (InbvBootDriverInstalled == FALSE) {
|
||
return FALSE;
|
||
}
|
||
|
||
ResourceCount = Count;
|
||
|
||
for (i=1; i<=Count; i++) {
|
||
p = (ULONG_PTR) i;
|
||
ResourceList[i-1] = FindBitmapResource(LoaderBlock, p);
|
||
}
|
||
|
||
//
|
||
// Set prograss bar to full range.
|
||
//
|
||
|
||
InbvSetProgressBarSubset(0, 100);
|
||
|
||
return InbvBootDriverInstalled;
|
||
}
|
||
|
||
VOID
|
||
InbvNotifyDisplayOwnershipLost(
|
||
INBV_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called by the hal when the hal looses
|
||
display ownership. At this point win32k.sys has taken
|
||
over.
|
||
|
||
--*/
|
||
|
||
{
|
||
if (InbvBootDriverInstalled) {
|
||
|
||
//
|
||
// We can only wait for our lock, and execute our clean up code
|
||
// if the driver is installed and we still own the display.
|
||
//
|
||
|
||
InbvAcquireLock();
|
||
if (InbvDisplayState != INBV_DISPLAY_STATE_LOST) {
|
||
VidCleanUp();
|
||
}
|
||
InbvDisplayState = INBV_DISPLAY_STATE_LOST;
|
||
InbvResetDisplayParameters = ResetDisplayParameters;
|
||
InbvReleaseLock();
|
||
|
||
} else {
|
||
|
||
InbvDisplayState = INBV_DISPLAY_STATE_LOST;
|
||
InbvResetDisplayParameters = ResetDisplayParameters;
|
||
}
|
||
}
|
||
|
||
VOID
|
||
InbvAcquireDisplayOwnership(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Allows the kernel to reaquire ownership of the display.
|
||
|
||
--*/
|
||
|
||
{
|
||
if (InbvResetDisplayParameters && (InbvDisplayState == INBV_DISPLAY_STATE_LOST)) {
|
||
InbvResetDisplayParameters(80,50);
|
||
}
|
||
|
||
InbvDisplayState = INBV_DISPLAY_STATE_OWNED;
|
||
}
|
||
|
||
VOID
|
||
InbvSetDisplayOwnership(
|
||
BOOLEAN DisplayOwned
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine allows the kernel to set a display state. This is useful
|
||
after a hibernate. At this point win32k will reacquire display ownership
|
||
but will not tell us.
|
||
|
||
Arguments:
|
||
|
||
Whether the display is owned or not.
|
||
|
||
--*/
|
||
|
||
{
|
||
if (DisplayOwned) {
|
||
InbvDisplayState = INBV_DISPLAY_STATE_OWNED;
|
||
} else {
|
||
InbvDisplayState = INBV_DISPLAY_STATE_LOST;
|
||
}
|
||
}
|
||
|
||
BOOLEAN
|
||
InbvCheckDisplayOwnership(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Indicates whether the Hal owns the display.
|
||
|
||
--*/
|
||
|
||
{
|
||
return (InbvDisplayState != INBV_DISPLAY_STATE_LOST);
|
||
}
|
||
|
||
INBV_DISPLAY_STATE
|
||
InbvGetDisplayState(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Indicates whether the Hal owns the display.
|
||
|
||
--*/
|
||
|
||
{
|
||
return InbvDisplayState;
|
||
}
|
||
|
||
VOID
|
||
InbvSetScrollRegion(
|
||
ULONG x1,
|
||
ULONG y1,
|
||
ULONG x2,
|
||
ULONG y2
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Control what portions of the screen are used for text.
|
||
|
||
Arguments:
|
||
|
||
Lines - number of lines of text.
|
||
|
||
--*/
|
||
|
||
{
|
||
VidSetScrollRegion(x1, y1, x2, y2);
|
||
}
|