+/*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: BSD - See COPYING.ARM in the top level directory
+ * PURPOSE: Boot Video Driver support
+ * COPYRIGHT: Copyright 2007 Alex Ionescu (alex.ionescu@reactos.org)
+ * Copyright 2010 Aleksey Bragin (aleksey@reactos.org)
+ * Copyright 2015-2022 Hermès Bélusca-Maïto
+ */
+
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
-#define NDEBUG
-#include <debug.h>
-#include "bootvid/bootvid.h"
-
-#ifndef TAG_OSTR
-#define TAG_OSTR 'RTSO'
-#endif
+#include "inbv/logo.h"
/* GLOBALS *******************************************************************/
*/
// #define INBV_HEADLESS_COLORS
-/*
- * ReactOS uses the same boot screen for all the products.
- * Also it doesn't use a parallel system thread for the
- * rotating "progress" bar.
- */
-
-/*
- * Enable this define when ReactOS will have different SKUs
- * (Workstation, Server, Storage Server, Cluster Server, etc...).
- */
-// #define REACTOS_SKUS
+typedef struct _INBV_PROGRESS_STATE
+{
+ ULONG Floor;
+ ULONG Ceiling;
+ ULONG Bias;
+} INBV_PROGRESS_STATE;
-/*
- * Enable this define when Inbv will support rotating progress bar.
- */
-#define INBV_ROTBAR_IMPLEMENTED
+typedef struct _BT_PROGRESS_INDICATOR
+{
+ ULONG Count;
+ ULONG Expected;
+ ULONG Percentage;
+} BT_PROGRESS_INDICATOR, *PBT_PROGRESS_INDICATOR;
static KSPIN_LOCK BootDriverLock;
static KIRQL InbvOldIrql;
static INBV_DISPLAY_STATE InbvDisplayState = INBV_DISPLAY_STATE_DISABLED;
BOOLEAN InbvBootDriverInstalled = FALSE;
+static INBV_RESET_DISPLAY_PARAMETERS InbvResetDisplayParameters = NULL;
+
static BOOLEAN InbvDisplayDebugStrings = FALSE;
static INBV_DISPLAY_STRING_FILTER InbvDisplayFilter = NULL;
-static ULONG ProgressBarLeft = 0, ProgressBarTop = 0;
-static BOOLEAN ShowProgressBar = FALSE;
+
+ULONG ProgressBarLeft = 0, ProgressBarTop = 0;
+BOOLEAN ShowProgressBar = FALSE;
static INBV_PROGRESS_STATE InbvProgressState;
static BT_PROGRESS_INDICATOR InbvProgressIndicator = {0, 25, 0};
-static INBV_RESET_DISPLAY_PARAMETERS InbvResetDisplayParameters = NULL;
-static ULONG ResourceCount = 0;
-static PUCHAR ResourceList[1 + IDB_MAX_RESOURCE]; // First entry == NULL, followed by 'ResourceCount' entries.
-
-#ifdef INBV_ROTBAR_IMPLEMENTED
-/*
- * Change this to modify progress bar behaviour
- */
-#define ROT_BAR_DEFAULT_MODE RB_PROGRESS_BAR
-/*
- * Values for PltRotBarStatus:
- * - PltRotBarStatus == 1, do palette fading-in (done elsewhere in ReactOS);
- * - PltRotBarStatus == 2, do rotation bar animation;
- * - PltRotBarStatus == 3, stop the animation thread.
- * - Any other value is ignored and the animation thread continues to run.
- */
-typedef enum _ROT_BAR_STATUS
-{
- RBS_FADEIN = 1,
- RBS_ANIMATE,
- RBS_STOP_ANIMATE,
- RBS_STATUS_MAX
-} ROT_BAR_STATUS;
-
-static BOOLEAN RotBarThreadActive = FALSE;
-static ROT_BAR_TYPE RotBarSelection = RB_UNSPECIFIED;
-static ROT_BAR_STATUS PltRotBarStatus = 0;
-static UCHAR RotBarBuffer[24 * 9];
-static UCHAR RotLineBuffer[640 * 6];
-#endif
+static ULONG ResourceCount = 0;
+static PUCHAR ResourceList[1 + IDB_MAX_RESOURCES]; // First entry == NULL, followed by 'ResourceCount' entries.
/*
static ULONG InbvTerminalBkgdColor = 40;
-/* 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) /* 20 ms */
-
-/** 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
-BootLogoFadeIn(VOID)
-{
- UCHAR PaletteBitmapBuffer[sizeof(BITMAPINFOHEADER) + sizeof(MainPalette)];
- PBITMAPINFOHEADER PaletteBitmap = (PBITMAPINFOHEADER)PaletteBitmapBuffer;
- LPRGBQUAD Palette = (LPRGBQUAD)(PaletteBitmapBuffer + sizeof(BITMAPINFOHEADER));
- ULONG Iteration, Index, ClrUsed;
-
- LARGE_INTEGER Delay;
- Delay.QuadPart = - (PALETTE_FADE_TIME * 10);
-
- /* Check if we are installed and we own the display */
- if (!InbvBootDriverInstalled ||
- (InbvDisplayState != INBV_DISPLAY_STATE_OWNED))
- {
- return;
- }
-
- /*
- * Build a bitmap containing the fade-in palette. The palette entries
- * are then processed in a loop and set using VidBitBlt function.
- */
- ClrUsed = RTL_NUMBER_OF(MainPalette);
- 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);
- }
-
- /* Do the animation */
- InbvAcquireLock();
- VidBitBlt(PaletteBitmapBuffer, 0, 0);
- InbvReleaseLock();
-
- /* Wait for a bit */
- KeDelayExecutionThread(KernelMode, FALSE, &Delay);
- }
-}
-
/* FUNCTIONS *****************************************************************/
+CODE_SEG("INIT")
+static
PVOID
-NTAPI
-INIT_FUNCTION
-FindBitmapResource(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
- IN ULONG ResourceId)
+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");
/* Loop the driver list */
ListHead = &LoaderBlock->LoadOrderListHead;
- NextEntry = ListHead->Flink;
- while (NextEntry != ListHead)
+ for (NextEntry = ListHead->Flink;
+ NextEntry != ListHead;
+ NextEntry = NextEntry->Flink)
{
/* Get the entry */
LdrEntry = CONTAINING_RECORD(NextEntry,
return Data;
}
+PUCHAR
+NTAPI
+InbvGetResourceAddress(
+ _In_ ULONG ResourceNumber)
+{
+ /* Validate the resource number */
+ if (ResourceNumber > ResourceCount) return NULL;
+
+ /* Return the address */
+ return ResourceList[ResourceNumber];
+}
+
+CODE_SEG("INIT")
BOOLEAN
NTAPI
-INIT_FUNCTION
-InbvDriverInitialize(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
- IN ULONG Count)
+InbvDriverInitialize(
+ _In_ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ _In_ ULONG Count)
{
PCHAR CommandLine;
BOOLEAN ResetMode = FALSE; // By default do not reset the video mode
/* Set the progress bar ranges */
InbvSetProgressBarSubset(0, 100);
+
+ // BootAnimInitialize(LoaderBlock, Count);
}
/* Return install state */
VOID
NTAPI
-INIT_FUNCTION
-InbvEnableBootDriver(IN BOOLEAN Enable)
+InbvEnableBootDriver(
+ _In_ BOOLEAN Enable)
{
/* Check if we're installed */
if (InbvBootDriverInstalled)
VOID
NTAPI
-InbvSetDisplayOwnership(IN BOOLEAN DisplayOwned)
+InbvSetDisplayOwnership(
+ _In_ BOOLEAN DisplayOwned)
{
/* Set the new display state */
InbvDisplayState = DisplayOwned ? INBV_DISPLAY_STATE_OWNED :
BOOLEAN
NTAPI
-InbvDisplayString(IN PCHAR String)
+InbvDisplayString(
+ _In_ PCHAR String)
{
/* Make sure we own the display */
if (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)
BOOLEAN
NTAPI
-InbvEnableDisplayString(IN BOOLEAN Enable)
+InbvEnableDisplayString(
+ _In_ BOOLEAN Enable)
{
BOOLEAN OldSetting;
VOID
NTAPI
-InbvInstallDisplayStringFilter(IN INBV_DISPLAY_STRING_FILTER Filter)
+InbvInstallDisplayStringFilter(
+ _In_ INBV_DISPLAY_STRING_FILTER DisplayFilter)
{
/* Save the filter */
- InbvDisplayFilter = Filter;
+ InbvDisplayFilter = DisplayFilter;
}
BOOLEAN
VOID
NTAPI
-InbvNotifyDisplayOwnershipLost(IN INBV_RESET_DISPLAY_PARAMETERS Callback)
+InbvNotifyDisplayOwnershipLost(
+ _In_ INBV_RESET_DISPLAY_PARAMETERS Callback)
{
/* Check if we're installed */
if (InbvBootDriverInstalled)
VOID
NTAPI
-InbvSetScrollRegion(IN ULONG Left,
- IN ULONG Top,
- IN ULONG Right,
- IN ULONG Bottom)
+InbvSetScrollRegion(
+ _In_ ULONG Left,
+ _In_ ULONG Top,
+ _In_ ULONG Right,
+ _In_ ULONG Bottom)
{
/* Just call bootvid */
VidSetScrollRegion(Left, Top, Right, Bottom);
VOID
NTAPI
-InbvSetTextColor(IN ULONG Color)
+InbvSetTextColor(
+ _In_ ULONG Color)
{
HEADLESS_CMD_SET_COLOR HeadlessSetColor;
VOID
NTAPI
-InbvSolidColorFill(IN ULONG Left,
- IN ULONG Top,
- IN ULONG Right,
- IN ULONG Bottom,
- IN ULONG Color)
+InbvSolidColorFill(
+ _In_ ULONG Left,
+ _In_ ULONG Top,
+ _In_ ULONG Right,
+ _In_ ULONG Bottom,
+ _In_ ULONG Color)
{
HEADLESS_CMD_SET_COLOR HeadlessSetColor;
VOID
NTAPI
-INIT_FUNCTION
-InbvUpdateProgressBar(IN ULONG Progress)
+InbvBitBlt(
+ _In_ PUCHAR Buffer,
+ _In_ ULONG X,
+ _In_ ULONG Y)
{
- ULONG FillCount, BoundedProgress;
-
- /* Make sure the progress bar is enabled, that we own and are installed */
- if (ShowProgressBar &&
- InbvBootDriverInstalled &&
+ /* Check if we're installed and we own it */
+ if (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);
+ /* Do the blit */
+ VidBitBlt(Buffer, X, Y);
/* 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)
+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 &&
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)
+InbvScreenToBufferBlt(
+ _Out_ 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 &&
}
}
+/**
+ * @brief
+ * Sets the screen coordinates of the loading progress bar and enable it.
+ *
+ * @param[in] Left
+ * @param[in] Top
+ * The left/top coordinates.
+ *
+ * @return None.
+ **/
VOID
NTAPI
-InbvSetProgressBarCoordinates(IN ULONG Left,
- IN ULONG Top)
+InbvSetProgressBarCoordinates(
+ _In_ ULONG Left,
+ _In_ ULONG Top)
{
/* Update the coordinates */
ProgressBarLeft = Left;
ShowProgressBar = TRUE;
}
+/**
+ * @brief
+ * Gives some progress feedback, without specifying any explicit number
+ * of progress steps or percentage.
+ * The corresponding percentage is derived from the progress indicator's
+ * current count, capped to the number of expected calls to be made to
+ * this function (default: 25, see @b InbvProgressIndicator.Expected).
+ *
+ * @return None.
+ **/
+CODE_SEG("INIT")
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);
+ /* Compute the new percentage - Don't go over 100% */
+ Percentage = 100 * InbvProgressIndicator.Count /
+ InbvProgressIndicator.Expected;
+ Percentage = min(Percentage, 99);
+
if (Percentage != InbvProgressIndicator.Percentage)
{
- /* Percentage has moved, update the progress bar */
+ /* Percentage has changed, update the progress bar */
InbvProgressIndicator.Percentage = Percentage;
InbvUpdateProgressBar(Percentage);
}
}
-PUCHAR
+/**
+ * @brief
+ * Specifies a progress percentage sub-range.
+ * Further calls to InbvIndicateProgress() or InbvUpdateProgressBar()
+ * will update the progress percentage relative to this sub-range.
+ * In particular, the percentage provided to InbvUpdateProgressBar()
+ * is relative to this sub-range.
+ *
+ * @param[in] Floor
+ * The lower bound percentage of the sub-range (default: 0).
+ *
+ * @param[in] Ceiling
+ * The upper bound percentage of the sub-range (default: 100).
+ *
+ * @return None.
+ **/
+VOID
NTAPI
-InbvGetResourceAddress(IN ULONG ResourceNumber)
+InbvSetProgressBarSubset(
+ _In_ ULONG Floor,
+ _In_ ULONG Ceiling)
{
- /* Validate the resource number */
- if (ResourceNumber > ResourceCount) return NULL;
+ /* Sanity checks */
+ ASSERT(Floor < Ceiling);
+ ASSERT(Ceiling <= 100);
- /* Return the address */
- return ResourceList[ResourceNumber];
+ /* Update the progress bar state */
+ InbvProgressState.Floor = Floor * 100;
+ InbvProgressState.Ceiling = Ceiling * 100;
+ InbvProgressState.Bias = Ceiling - Floor;
+}
+
+/**
+ * @brief
+ * Updates the progress bar percentage, relative to the current
+ * percentage sub-range previously set by InbvSetProgressBarSubset().
+ *
+ * @param[in] Percentage
+ * The progress percentage, relative to the current sub-range.
+ *
+ * @return None.
+ **/
+VOID
+NTAPI
+InbvUpdateProgressBar(
+ _In_ ULONG Percentage)
+{
+ ULONG TotalProgress;
+
+ /* Make sure the progress bar is enabled, that we own and are installed */
+ if (ShowProgressBar &&
+ InbvBootDriverInstalled &&
+ (InbvDisplayState == INBV_DISPLAY_STATE_OWNED))
+ {
+ /* Compute the total progress and tick the progress bar */
+ TotalProgress = InbvProgressState.Floor + (Percentage * InbvProgressState.Bias);
+ // TotalProgress /= (100 * 100);
+
+ BootAnimTickProgressBar(TotalProgress);
+ }
}
NTSTATUS
Status = STATUS_NO_MEMORY;
goto Quit;
}
- RtlUnicodeStringToOemString(&OemString, &CapturedString, FALSE);
+ Status = RtlUnicodeStringToOemString(&OemString, &CapturedString, FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePoolWithTag(OemString.Buffer, TAG_OSTR);
+ goto Quit;
+ }
/* Display the string */
InbvDisplayString(OemString.Buffer);
return Status;
}
-
-#ifdef INBV_ROTBAR_IMPLEMENTED
-static
-VOID
-NTAPI
-InbvRotationThread(
- _In_ PVOID Context)
-{
- ULONG X, Y, Index, Total;
- LARGE_INTEGER Delay = {{0}};
-
- InbvAcquireLock();
- if (RotBarSelection == RB_SQUARE_CELLS)
- {
- Index = 0;
- }
- else
- {
- Index = 32;
- }
- X = ProgressBarLeft + 2;
- Y = ProgressBarTop + 2;
- InbvReleaseLock();
-
- while (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)
- {
- /* Wait for a bit */
- KeDelayExecutionThread(KernelMode, FALSE, &Delay);
-
- InbvAcquireLock();
-
- /* Unknown unexpected command */
- ASSERT(PltRotBarStatus < RBS_STATUS_MAX);
-
- if (PltRotBarStatus == RBS_STOP_ANIMATE)
- {
- /* Stop the thread */
- InbvReleaseLock();
- break;
- }
-
- if (RotBarSelection == RB_SQUARE_CELLS)
- {
- Delay.QuadPart = -800000; // 80 ms
- Total = 18;
- Index %= Total;
-
- if (Index >= 3)
- {
- /* Fill previous bar position */
- VidSolidColorFill(X + ((Index - 3) * 8), Y, (X + ((Index - 3) * 8)) + 8 - 1, Y + 9 - 1, 0);
- }
- if (Index < Total - 1)
- {
- /* Draw the progress bar bit */
- if (Index < 2)
- {
- /* Appearing from the left */
- VidBufferToScreenBlt(RotBarBuffer + 8 * (2 - Index) / 2, X, Y, 22 - 8 * (2 - Index), 9, 24);
- }
- else if (Index >= Total - 3)
- {
- /* Hiding to the right */
- VidBufferToScreenBlt(RotBarBuffer, X + ((Index - 2) * 8), Y, 22 - 8 * (4 - (Total - Index)), 9, 24);
- }
- else
- {
- VidBufferToScreenBlt(RotBarBuffer, X + ((Index - 2) * 8), Y, 22, 9, 24);
- }
- }
- Index++;
- }
- else if (RotBarSelection == RB_PROGRESS_BAR)
- {
- Delay.QuadPart = -600000; // 60 ms
- Total = 640;
- Index %= Total;
-
- /* Right part */
- VidBufferToScreenBlt(RotLineBuffer, Index, 474, 640 - Index, 6, 640);
- if (Index > 0)
- {
- /* Left part */
- VidBufferToScreenBlt(RotLineBuffer + (640 - Index) / 2, 0, 474, Index - 2, 6, 640);
- }
- Index += 32;
- }
-
- InbvReleaseLock();
- }
-
- PsTerminateSystemThread(STATUS_SUCCESS);
-}
-
-VOID
-NTAPI
-INIT_FUNCTION
-InbvRotBarInit(VOID)
-{
- PltRotBarStatus = RBS_FADEIN;
- /* Perform other initialization if needed */
-}
-#endif
-
-VOID
-NTAPI
-INIT_FUNCTION
-DisplayBootBitmap(IN BOOLEAN TextMode)
-{
- PVOID Header = NULL, Footer = NULL, Screen = NULL;
-
-#ifdef INBV_ROTBAR_IMPLEMENTED
- UCHAR Buffer[24 * 9];
- PVOID Bar = NULL, LineBmp = NULL;
- ROT_BAR_TYPE TempRotBarSelection = RB_UNSPECIFIED;
- NTSTATUS Status;
- HANDLE ThreadHandle = NULL;
-#endif
-
-#ifdef REACTOS_SKUS
- PVOID Text = NULL;
-#endif
-
-#ifdef INBV_ROTBAR_IMPLEMENTED
- /* Check if the animation thread has already been created */
- if (RotBarThreadActive)
- {
- /* Yes, just reset the progress bar but keep the thread alive */
- InbvAcquireLock();
- RotBarSelection = RB_UNSPECIFIED;
- InbvReleaseLock();
- }
-#endif
-
- ShowProgressBar = FALSE;
-
- /* Check if this is text mode */
- if (TextMode)
- {
- /* Check the type of the OS: workstation or server */
- if (SharedUserData->NtProductType == NtProductWinNt)
- {
- /* Workstation; set colors */
- InbvSetTextColor(15);
- InbvSolidColorFill(0, 0, 639, 479, 7);
- InbvSolidColorFill(0, 421, 639, 479, 1);
-
- /* Get resources */
- Header = InbvGetResourceAddress(IDB_WKSTA_HEADER);
- Footer = InbvGetResourceAddress(IDB_WKSTA_FOOTER);
- }
- else
- {
- /* Server; set colors */
- InbvSetTextColor(14);
- InbvSolidColorFill(0, 0, 639, 479, 6);
- InbvSolidColorFill(0, 421, 639, 479, 1);
-
- /* Get resources */
- Header = InbvGetResourceAddress(IDB_SERVER_HEADER);
- Footer = InbvGetResourceAddress(IDB_SERVER_FOOTER);
- }
-
- /* Set the scrolling region */
- InbvSetScrollRegion(32, 80, 631, 400);
-
- /* Make sure we have resources */
- if (Header && Footer)
- {
- /* BitBlt them on the screen */
- InbvBitBlt(Footer, 0, 419);
- InbvBitBlt(Header, 0, 0);
- }
- }
- else
- {
- /* Is the boot driver installed? */
- if (!InbvBootDriverInstalled) return;
-
- /* Load the standard boot screen */
- Screen = InbvGetResourceAddress(IDB_BOOT_SCREEN);
-
-#ifdef REACTOS_SKUS
- Text = NULL;
- if (SharedUserData->NtProductType == NtProductWinNt)
- {
-#ifdef INBV_ROTBAR_IMPLEMENTED
- /* Workstation product, use appropriate status bar color */
- Bar = InbvGetResourceAddress(IDB_BAR_WKSTA);
-#endif
- }
- 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);
- }
-
-#ifdef INBV_ROTBAR_IMPLEMENTED
- /* Server product, use appropriate status bar color */
- Bar = InbvGetResourceAddress(IDB_BAR_SERVER);
-#endif
- }
-#else
- /* Use default status bar */
- Bar = InbvGetResourceAddress(IDB_BAR_WKSTA);
-#endif
-
- /* Make sure we have a logo */
- if (Screen)
- {
- PBITMAPINFOHEADER BitmapInfoHeader;
- LPRGBQUAD Palette;
-
- /*
- * Save the main image palette and replace it with black palette,
- * so that 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);
-
-#ifdef INBV_ROTBAR_IMPLEMENTED
- /* Choose progress bar */
- TempRotBarSelection = ROT_BAR_DEFAULT_MODE;
-#endif
-
- /* Set progress bar coordinates and display it */
- InbvSetProgressBarCoordinates(259, 352);
-
-#ifdef REACTOS_SKUS
- /* 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 REACTOS_SKUS
- /* Draw the SKU text if it exits */
- if (Text) InbvBitBlt(Text, 180, 121);
-#endif
-
-#ifdef INBV_ROTBAR_IMPLEMENTED
- if (Bar)
- {
- /* Save previous screen pixels to buffer */
- InbvScreenToBufferBlt(Buffer, 0, 0, 22, 9, 24);
- /* Draw the progress bar bit */
- InbvBitBlt(Bar, 0, 0);
- /* Store it in global buffer */
- InbvScreenToBufferBlt(RotBarBuffer, 0, 0, 22, 9, 24);
- /* Restore screen pixels */
- InbvBufferToScreenBlt(Buffer, 0, 0, 22, 9, 24);
- }
-
- /*
- * Add a rotating bottom horizontal bar when using a progress bar,
- * to show that ReactOS can be still alive when the bar does not
- * appear to progress.
- */
- if (TempRotBarSelection == RB_PROGRESS_BAR)
- {
- LineBmp = InbvGetResourceAddress(IDB_ROTATING_LINE);
- if (LineBmp)
- {
- /* Draw the line and store it in global buffer */
- InbvBitBlt(LineBmp, 0, 474);
- InbvScreenToBufferBlt(RotLineBuffer, 0, 474, 640, 6, 640);
- }
- }
- else
- {
- /* Hide the simple progress bar if not used */
- ShowProgressBar = FALSE;
- }
-#endif
-
- /* Display the boot logo and fade it in */
- BootLogoFadeIn();
-
-#ifdef INBV_ROTBAR_IMPLEMENTED
- if (!RotBarThreadActive && TempRotBarSelection != RB_UNSPECIFIED)
- {
- /* Start the animation thread */
- Status = PsCreateSystemThread(&ThreadHandle,
- 0,
- NULL,
- NULL,
- NULL,
- InbvRotationThread,
- NULL);
- if (NT_SUCCESS(Status))
- {
- /* The thread has started, close the handle as we don't need it */
- RotBarThreadActive = TRUE;
- ObCloseHandle(ThreadHandle, KernelMode);
- }
- }
-#endif
-
- /* Set filter which will draw text display if needed */
- InbvInstallDisplayStringFilter(DisplayFilter);
- }
-
-#ifdef INBV_ROTBAR_IMPLEMENTED
- /* Do we have the animation thread? */
- if (RotBarThreadActive)
- {
- /* We do, initialize the progress bar */
- InbvAcquireLock();
- RotBarSelection = TempRotBarSelection;
- InbvRotBarInit();
- InbvReleaseLock();
-
- // FIXME: This was added to allow animation start before the processor hangs
- if (TempRotBarSelection != RB_UNSPECIFIED)
- {
- LARGE_INTEGER Delay;
- Delay.QuadPart = -3000000; // 300 ms
- KeDelayExecutionThread(KernelMode, FALSE, &Delay);
- }
- }
-#endif
-}
-
-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 */
-#ifdef INBV_ROTBAR_IMPLEMENTED
- PltRotBarStatus = RBS_STOP_ANIMATE;
- RotBarThreadActive = FALSE;
-#endif
- InbvReleaseLock();
-}