mirror of
https://github.com/reactos/reactos.git
synced 2024-08-26 21:28:48 +00:00
878 lines
22 KiB
C
878 lines
22 KiB
C
/* INCLUDES ******************************************************************/
|
|
|
|
#include <ntoskrnl.h>
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
#include "bootvid/bootvid.h"
|
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
KSPIN_LOCK BootDriverLock;
|
|
KIRQL InbvOldIrql;
|
|
INBV_DISPLAY_STATE InbvDisplayState;
|
|
BOOLEAN InbvBootDriverInstalled = FALSE;
|
|
BOOLEAN InbvDisplayDebugStrings = FALSE;
|
|
INBV_DISPLAY_STRING_FILTER InbvDisplayFilter;
|
|
ULONG ProgressBarLeft, ProgressBarTop;
|
|
BOOLEAN ShowProgressBar = FALSE;
|
|
INBV_PROGRESS_STATE InbvProgressState;
|
|
INBV_RESET_DISPLAY_PARAMETERS InbvResetDisplayParameters;
|
|
ULONG ResourceCount;
|
|
PUCHAR ResourceList[64];
|
|
BOOLEAN SysThreadCreated = FALSE;
|
|
ROT_BAR_TYPE RotBarSelection;
|
|
ULONG PltRotBarStatus;
|
|
BT_PROGRESS_INDICATOR InbvProgressIndicator = {0, 25, 0};
|
|
|
|
/* FADING FUNCTION ***********************************************************/
|
|
|
|
/** From include/psdk/wingdi.h **/
|
|
typedef struct tagRGBQUAD
|
|
{
|
|
UCHAR rgbBlue;
|
|
UCHAR rgbGreen;
|
|
UCHAR rgbRed;
|
|
UCHAR rgbReserved;
|
|
} RGBQUAD,*LPRGBQUAD;
|
|
/*******************************/
|
|
|
|
static RGBQUAD _MainPalette[16];
|
|
|
|
#define PALETTE_FADE_STEPS 15
|
|
#define PALETTE_FADE_TIME 20 * 1000 /* 20ms */
|
|
|
|
/** From bootvid/precomp.h **/
|
|
//
|
|
// Bitmap Header
|
|
//
|
|
typedef struct tagBITMAPINFOHEADER
|
|
{
|
|
ULONG biSize;
|
|
LONG biWidth;
|
|
LONG biHeight;
|
|
USHORT biPlanes;
|
|
USHORT biBitCount;
|
|
ULONG biCompression;
|
|
ULONG biSizeImage;
|
|
LONG biXPelsPerMeter;
|
|
LONG biYPelsPerMeter;
|
|
ULONG biClrUsed;
|
|
ULONG biClrImportant;
|
|
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
|
|
/****************************/
|
|
|
|
//
|
|
// Needed prototypes
|
|
//
|
|
VOID NTAPI InbvAcquireLock(VOID);
|
|
VOID NTAPI InbvReleaseLock(VOID);
|
|
|
|
static VOID
|
|
NTAPI
|
|
BootImageFadeIn(VOID)
|
|
{
|
|
UCHAR PaletteBitmapBuffer[sizeof(BITMAPINFOHEADER) + sizeof(_MainPalette)];
|
|
PBITMAPINFOHEADER PaletteBitmap = (PBITMAPINFOHEADER)PaletteBitmapBuffer;
|
|
LPRGBQUAD Palette = (LPRGBQUAD)(PaletteBitmapBuffer + sizeof(BITMAPINFOHEADER));
|
|
|
|
ULONG Iteration, Index, ClrUsed;
|
|
|
|
/* Check if we're installed and we own it */
|
|
if ((InbvBootDriverInstalled) &&
|
|
(InbvDisplayState == INBV_DISPLAY_STATE_OWNED))
|
|
{
|
|
/* Acquire the lock */
|
|
InbvAcquireLock();
|
|
|
|
/*
|
|
* Build a bitmap containing the fade in palette. The palette entries
|
|
* are then processed in a loop and set using VidBitBlt function.
|
|
*/
|
|
ClrUsed = sizeof(_MainPalette) / sizeof(_MainPalette[0]);
|
|
RtlZeroMemory(PaletteBitmap, sizeof(BITMAPINFOHEADER));
|
|
PaletteBitmap->biSize = sizeof(BITMAPINFOHEADER);
|
|
PaletteBitmap->biBitCount = 4;
|
|
PaletteBitmap->biClrUsed = ClrUsed;
|
|
|
|
/*
|
|
* Main animation loop.
|
|
*/
|
|
for (Iteration = 0; Iteration <= PALETTE_FADE_STEPS; ++Iteration)
|
|
{
|
|
for (Index = 0; Index < ClrUsed; Index++)
|
|
{
|
|
Palette[Index].rgbRed = (UCHAR)
|
|
(_MainPalette[Index].rgbRed * Iteration / PALETTE_FADE_STEPS);
|
|
Palette[Index].rgbGreen = (UCHAR)
|
|
(_MainPalette[Index].rgbGreen * Iteration / PALETTE_FADE_STEPS);
|
|
Palette[Index].rgbBlue = (UCHAR)
|
|
(_MainPalette[Index].rgbBlue * Iteration / PALETTE_FADE_STEPS);
|
|
}
|
|
|
|
VidBitBlt(PaletteBitmapBuffer, 0, 0);
|
|
|
|
/* Wait for a bit. */
|
|
KeStallExecutionProcessor(PALETTE_FADE_TIME);
|
|
}
|
|
|
|
/* Release the lock */
|
|
InbvReleaseLock();
|
|
|
|
/* Wait for a bit. */
|
|
KeStallExecutionProcessor(PALETTE_FADE_TIME);
|
|
}
|
|
}
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
PVOID
|
|
NTAPI
|
|
INIT_FUNCTION
|
|
FindBitmapResource(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
|
IN ULONG ResourceId)
|
|
{
|
|
UNICODE_STRING UpString = RTL_CONSTANT_STRING(L"ntoskrnl.exe");
|
|
UNICODE_STRING MpString = RTL_CONSTANT_STRING(L"ntkrnlmp.exe");
|
|
PLIST_ENTRY NextEntry, ListHead;
|
|
PLDR_DATA_TABLE_ENTRY LdrEntry;
|
|
PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry;
|
|
LDR_RESOURCE_INFO ResourceInfo;
|
|
NTSTATUS Status;
|
|
PVOID Data = NULL;
|
|
|
|
/* Loop the driver list */
|
|
ListHead = &LoaderBlock->LoadOrderListHead;
|
|
NextEntry = ListHead->Flink;
|
|
while (NextEntry != ListHead)
|
|
{
|
|
/* Get the entry */
|
|
LdrEntry = CONTAINING_RECORD(NextEntry,
|
|
LDR_DATA_TABLE_ENTRY,
|
|
InLoadOrderLinks);
|
|
|
|
/* Check for a match */
|
|
if ((RtlEqualUnicodeString(&LdrEntry->BaseDllName, &UpString, TRUE)) ||
|
|
(RtlEqualUnicodeString(&LdrEntry->BaseDllName, &MpString, TRUE)))
|
|
{
|
|
/* Break out */
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Check if we found it */
|
|
if (NextEntry != ListHead)
|
|
{
|
|
/* Try to find the resource */
|
|
ResourceInfo.Type = 2; //RT_BITMAP;
|
|
ResourceInfo.Name = ResourceId;
|
|
ResourceInfo.Language = 0;
|
|
Status = LdrFindResource_U(LdrEntry->DllBase,
|
|
&ResourceInfo,
|
|
RESOURCE_DATA_LEVEL,
|
|
&ResourceDataEntry);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* Access the resource */
|
|
ULONG Size = 0;
|
|
Status = LdrAccessResource(LdrEntry->DllBase,
|
|
ResourceDataEntry,
|
|
&Data,
|
|
&Size);
|
|
if ((Data) && (ResourceId < 3))
|
|
{
|
|
KiBugCheckData[4] ^= RtlComputeCrc32(0, Data, Size);
|
|
}
|
|
if (!NT_SUCCESS(Status)) Data = NULL;
|
|
}
|
|
}
|
|
|
|
/* Return the pointer */
|
|
return Data;
|
|
}
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
INIT_FUNCTION
|
|
InbvDriverInitialize(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
|
IN ULONG Count)
|
|
{
|
|
PCHAR CommandLine;
|
|
BOOLEAN CustomLogo = FALSE;
|
|
ULONG i;
|
|
|
|
/* Quit if we're already installed */
|
|
if (InbvBootDriverInstalled) return TRUE;
|
|
|
|
/* Initialize the lock and check the current display state */
|
|
KeInitializeSpinLock(&BootDriverLock);
|
|
if (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)
|
|
{
|
|
/* Check if we have a custom boot logo */
|
|
CommandLine = _strupr(LoaderBlock->LoadOptions);
|
|
CustomLogo = strstr(CommandLine, "BOOTLOGO") ? TRUE: FALSE;
|
|
}
|
|
|
|
/* Initialize the video */
|
|
InbvBootDriverInstalled = VidInitialize(FALSE);
|
|
if (InbvBootDriverInstalled)
|
|
{
|
|
/* Now reset the display, but only if there's a custom boot logo */
|
|
VidResetDisplay(CustomLogo);
|
|
|
|
/* Find bitmap resources in the kernel */
|
|
ResourceCount = min(IDB_CLUSTER_SERVER, Count);
|
|
for (i = 1; i <= Count; i++)
|
|
{
|
|
/* Do the lookup */
|
|
ResourceList[i] = FindBitmapResource(LoaderBlock, i);
|
|
}
|
|
|
|
/* Set the progress bar ranges */
|
|
InbvSetProgressBarSubset(0, 100);
|
|
}
|
|
|
|
/* Return install state */
|
|
return InbvBootDriverInstalled;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
InbvAcquireLock(VOID)
|
|
{
|
|
KIRQL OldIrql;
|
|
|
|
/* Check if we're at dispatch level or lower */
|
|
OldIrql = KeGetCurrentIrql();
|
|
if (OldIrql <= DISPATCH_LEVEL)
|
|
{
|
|
/* Loop until the lock is free */
|
|
while (!KeTestSpinLock(&BootDriverLock));
|
|
|
|
/* Raise IRQL to dispatch level */
|
|
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
|
}
|
|
|
|
/* Acquire the lock */
|
|
KiAcquireSpinLock(&BootDriverLock);
|
|
InbvOldIrql = OldIrql;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
InbvReleaseLock(VOID)
|
|
{
|
|
KIRQL OldIrql;
|
|
|
|
/* Capture the old IRQL */
|
|
OldIrql = InbvOldIrql;
|
|
|
|
/* Release the driver lock */
|
|
KiReleaseSpinLock(&BootDriverLock);
|
|
|
|
/* If we were at dispatch level or lower, restore the old IRQL */
|
|
if (InbvOldIrql <= DISPATCH_LEVEL) KeLowerIrql(OldIrql);
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
INIT_FUNCTION
|
|
InbvEnableBootDriver(IN BOOLEAN Enable)
|
|
{
|
|
/* Check if we're installed */
|
|
if (InbvBootDriverInstalled)
|
|
{
|
|
/* Check for lost state */
|
|
if (InbvDisplayState >= INBV_DISPLAY_STATE_LOST) return;
|
|
|
|
/* Acquire the lock */
|
|
InbvAcquireLock();
|
|
|
|
/* Cleanup the screen if we own it */
|
|
if (InbvDisplayState == INBV_DISPLAY_STATE_OWNED) VidCleanUp();
|
|
|
|
/* Set the new display state */
|
|
InbvDisplayState = Enable ? INBV_DISPLAY_STATE_OWNED:
|
|
INBV_DISPLAY_STATE_DISABLED;
|
|
|
|
/* Release the lock */
|
|
InbvReleaseLock();
|
|
}
|
|
else
|
|
{
|
|
/* Set the new display state */
|
|
InbvDisplayState = Enable ? INBV_DISPLAY_STATE_OWNED:
|
|
INBV_DISPLAY_STATE_DISABLED;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
InbvAcquireDisplayOwnership(VOID)
|
|
{
|
|
/* Check if we have a callback and we're just acquiring it now */
|
|
if ((InbvResetDisplayParameters) &&
|
|
(InbvDisplayState == INBV_DISPLAY_STATE_LOST))
|
|
{
|
|
/* Call the callback */
|
|
InbvResetDisplayParameters(80, 50);
|
|
}
|
|
|
|
/* Acquire the display */
|
|
InbvDisplayState = INBV_DISPLAY_STATE_OWNED;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
InbvSetDisplayOwnership(IN BOOLEAN DisplayOwned)
|
|
{
|
|
/* Set the new display state */
|
|
InbvDisplayState = DisplayOwned ? INBV_DISPLAY_STATE_OWNED:
|
|
INBV_DISPLAY_STATE_LOST;
|
|
}
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
InbvCheckDisplayOwnership(VOID)
|
|
{
|
|
/* Return if we own it or not */
|
|
return InbvDisplayState != INBV_DISPLAY_STATE_LOST;
|
|
}
|
|
|
|
INBV_DISPLAY_STATE
|
|
NTAPI
|
|
InbvGetDisplayState(VOID)
|
|
{
|
|
/* Return the actual state */
|
|
return InbvDisplayState;
|
|
}
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
InbvDisplayString(IN PCHAR String)
|
|
{
|
|
/* Make sure we own the display */
|
|
if (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)
|
|
{
|
|
/* If we're not allowed, return success anyway */
|
|
if (!InbvDisplayDebugStrings) return TRUE;
|
|
|
|
/* Check if a filter is installed */
|
|
if (InbvDisplayFilter) InbvDisplayFilter(&String);
|
|
|
|
/* Acquire the lock */
|
|
InbvAcquireLock();
|
|
|
|
/* Make sure we're installed and display the string */
|
|
if (InbvBootDriverInstalled) VidDisplayString((PUCHAR) String);
|
|
|
|
/* Print the string on the EMS port */
|
|
HeadlessDispatch(HeadlessCmdPutString,
|
|
String,
|
|
strlen(String) + sizeof(ANSI_NULL),
|
|
NULL,
|
|
NULL);
|
|
|
|
/* Release the lock */
|
|
InbvReleaseLock();
|
|
|
|
/* All done */
|
|
return TRUE;
|
|
}
|
|
|
|
/* We don't own it, fail */
|
|
return FALSE;
|
|
}
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
InbvEnableDisplayString(IN BOOLEAN Enable)
|
|
{
|
|
BOOLEAN OldSetting;
|
|
|
|
/* Get the old setting */
|
|
OldSetting = InbvDisplayDebugStrings;
|
|
|
|
/* Update it */
|
|
InbvDisplayDebugStrings = Enable;
|
|
|
|
/* Return the old setting */
|
|
return OldSetting;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
InbvInstallDisplayStringFilter(IN INBV_DISPLAY_STRING_FILTER Filter)
|
|
{
|
|
/* Save the filter */
|
|
InbvDisplayFilter = Filter;
|
|
}
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
InbvIsBootDriverInstalled(VOID)
|
|
{
|
|
/* Return driver state */
|
|
return InbvBootDriverInstalled;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
InbvNotifyDisplayOwnershipLost(IN INBV_RESET_DISPLAY_PARAMETERS Callback)
|
|
{
|
|
/* Check if we're installed */
|
|
if (InbvBootDriverInstalled)
|
|
{
|
|
/* Acquire the lock and cleanup if we own the screen */
|
|
InbvAcquireLock();
|
|
if (InbvDisplayState != INBV_DISPLAY_STATE_LOST) VidCleanUp();
|
|
|
|
/* Set the reset callback and display state */
|
|
InbvResetDisplayParameters = Callback;
|
|
InbvDisplayState = INBV_DISPLAY_STATE_LOST;
|
|
|
|
/* Release the lock */
|
|
InbvReleaseLock();
|
|
}
|
|
else
|
|
{
|
|
/* Set the reset callback and display state */
|
|
InbvResetDisplayParameters = Callback;
|
|
InbvDisplayState = INBV_DISPLAY_STATE_LOST;
|
|
}
|
|
}
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
InbvResetDisplay(VOID)
|
|
{
|
|
/* Check if we're installed and we own it */
|
|
if ((InbvBootDriverInstalled) &&
|
|
(InbvDisplayState == INBV_DISPLAY_STATE_OWNED))
|
|
{
|
|
/* Do the reset */
|
|
VidResetDisplay(TRUE);
|
|
return TRUE;
|
|
}
|
|
|
|
/* Nothing to reset */
|
|
return FALSE;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
InbvSetScrollRegion(IN ULONG Left,
|
|
IN ULONG Top,
|
|
IN ULONG Width,
|
|
IN ULONG Height)
|
|
{
|
|
/* Just call bootvid */
|
|
VidSetScrollRegion(Left, Top, Width, Height);
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
InbvSetTextColor(IN ULONG Color)
|
|
{
|
|
/* FIXME: Headless */
|
|
|
|
/* Update the text color */
|
|
VidSetTextColor(Color);
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
InbvSolidColorFill(IN ULONG Left,
|
|
IN ULONG Top,
|
|
IN ULONG Width,
|
|
IN ULONG Height,
|
|
IN ULONG Color)
|
|
{
|
|
/* Make sure we own it */
|
|
if (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)
|
|
{
|
|
/* Acquire the lock */
|
|
InbvAcquireLock();
|
|
|
|
/* Check if we're installed */
|
|
if (InbvBootDriverInstalled)
|
|
{
|
|
/* Call bootvid */
|
|
VidSolidColorFill(Left, Top, Width, Height, (UCHAR)Color);
|
|
}
|
|
|
|
/* FIXME: Headless */
|
|
|
|
/* Release the lock */
|
|
InbvReleaseLock();
|
|
}
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
INIT_FUNCTION
|
|
InbvUpdateProgressBar(IN ULONG Progress)
|
|
{
|
|
ULONG FillCount, BoundedProgress;
|
|
|
|
/* Make sure the progress bar is enabled, that we own and are installed */
|
|
if ((ShowProgressBar) &&
|
|
(InbvBootDriverInstalled) &&
|
|
(InbvDisplayState == INBV_DISPLAY_STATE_OWNED))
|
|
{
|
|
/* Compute fill count */
|
|
BoundedProgress = (InbvProgressState.Floor / 100) + Progress;
|
|
FillCount = 121 * (InbvProgressState.Bias * BoundedProgress) / 1000000;
|
|
|
|
/* Acquire the lock */
|
|
InbvAcquireLock();
|
|
|
|
/* Fill the progress bar */
|
|
VidSolidColorFill(ProgressBarLeft,
|
|
ProgressBarTop,
|
|
ProgressBarLeft + FillCount,
|
|
ProgressBarTop + 12,
|
|
15);
|
|
|
|
/* Release the lock */
|
|
InbvReleaseLock();
|
|
}
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
InbvBufferToScreenBlt(IN PUCHAR Buffer,
|
|
IN ULONG X,
|
|
IN ULONG Y,
|
|
IN ULONG Width,
|
|
IN ULONG Height,
|
|
IN ULONG Delta)
|
|
{
|
|
/* Check if we're installed and we own it */
|
|
if ((InbvBootDriverInstalled) &&
|
|
(InbvDisplayState == INBV_DISPLAY_STATE_OWNED))
|
|
{
|
|
/* Do the blit */
|
|
VidBufferToScreenBlt(Buffer, X, Y, Width, Height, Delta);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
InbvBitBlt(IN PUCHAR Buffer,
|
|
IN ULONG X,
|
|
IN ULONG Y)
|
|
{
|
|
/* Check if we're installed and we own it */
|
|
if ((InbvBootDriverInstalled) &&
|
|
(InbvDisplayState == INBV_DISPLAY_STATE_OWNED))
|
|
{
|
|
/* Acquire the lock */
|
|
InbvAcquireLock();
|
|
|
|
/* Do the blit */
|
|
VidBitBlt(Buffer, X, Y);
|
|
|
|
/* Release the lock */
|
|
InbvReleaseLock();
|
|
}
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
InbvScreenToBufferBlt(IN PUCHAR Buffer,
|
|
IN ULONG X,
|
|
IN ULONG Y,
|
|
IN ULONG Width,
|
|
IN ULONG Height,
|
|
IN ULONG Delta)
|
|
{
|
|
/* Check if we're installed and we own it */
|
|
if ((InbvBootDriverInstalled) &&
|
|
(InbvDisplayState == INBV_DISPLAY_STATE_OWNED))
|
|
{
|
|
/* Do the blit */
|
|
VidScreenToBufferBlt(Buffer, X, Y, Width, Height, Delta);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
InbvSetProgressBarCoordinates(IN ULONG Left,
|
|
IN ULONG Top)
|
|
{
|
|
/* Update the coordinates */
|
|
ProgressBarLeft = Left;
|
|
ProgressBarTop = Top;
|
|
|
|
/* Enable the progress bar */
|
|
ShowProgressBar = TRUE;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
InbvSetProgressBarSubset(IN ULONG Floor,
|
|
IN ULONG Ceiling)
|
|
{
|
|
/* Sanity checks */
|
|
ASSERT(Floor < Ceiling);
|
|
ASSERT(Ceiling <= 100);
|
|
|
|
/* Update the progress bar state */
|
|
InbvProgressState.Floor = Floor * 100;
|
|
InbvProgressState.Ceiling = Ceiling * 100;
|
|
InbvProgressState.Bias = (Ceiling * 100) - Floor;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
INIT_FUNCTION
|
|
InbvIndicateProgress(VOID)
|
|
{
|
|
ULONG Percentage;
|
|
|
|
/* Increase progress */
|
|
InbvProgressIndicator.Count++;
|
|
|
|
/* Compute new percentage */
|
|
Percentage = min(100 * InbvProgressIndicator.Count /
|
|
InbvProgressIndicator.Expected,
|
|
99);
|
|
if (Percentage != InbvProgressIndicator.Percentage)
|
|
{
|
|
/* Percentage has moved, update the progress bar */
|
|
InbvProgressIndicator.Percentage = Percentage;
|
|
InbvUpdateProgressBar(Percentage);
|
|
}
|
|
}
|
|
|
|
PUCHAR
|
|
NTAPI
|
|
InbvGetResourceAddress(IN ULONG ResourceNumber)
|
|
{
|
|
/* Validate the resource number */
|
|
if (ResourceNumber > ResourceCount) return NULL;
|
|
|
|
/* Return the address */
|
|
return ResourceList[ResourceNumber--];
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
NtDisplayString(IN PUNICODE_STRING DisplayString)
|
|
{
|
|
OEM_STRING OemString;
|
|
|
|
/* Convert the string to OEM and display it */
|
|
RtlUnicodeStringToOemString(&OemString, DisplayString, TRUE);
|
|
InbvDisplayString(OemString.Buffer);
|
|
RtlFreeOemString(&OemString);
|
|
|
|
/* Return success */
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
INIT_FUNCTION
|
|
DisplayFilter(PCHAR *String)
|
|
{
|
|
/* Windows hack to skip first dots */
|
|
static BOOLEAN DotHack = TRUE;
|
|
|
|
/* If "." is given set *String to empty string */
|
|
if(DotHack && strcmp(*String, ".") == 0)
|
|
*String = "";
|
|
|
|
if(**String)
|
|
{
|
|
/* Remove the filter */
|
|
InbvInstallDisplayStringFilter(NULL);
|
|
|
|
DotHack = FALSE;
|
|
|
|
/* Draw text screen */
|
|
DisplayBootBitmap(TRUE);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
INIT_FUNCTION
|
|
FinalizeBootLogo(VOID)
|
|
{
|
|
/* Acquire lock and check the display state */
|
|
InbvAcquireLock();
|
|
if (InbvGetDisplayState() == INBV_DISPLAY_STATE_OWNED)
|
|
{
|
|
/* Clear the screen */
|
|
VidSolidColorFill(0, 0, 639, 479, 0);
|
|
}
|
|
|
|
/* Reset progress bar and lock */
|
|
PltRotBarStatus = 3;
|
|
InbvReleaseLock();
|
|
}
|