+/*
+ * 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"
+#include "inbv/logo.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 * 10000 /* 20ms */
-
-/** From bootvid/precomp.h **/
-//
-// Bitmap Header
-//
-typedef struct tagBITMAPINFOHEADER
+/*
+ * Enable this define if you want Inbv to use coloured headless mode.
+ */
+// #define INBV_HEADLESS_COLORS
+
+typedef struct _INBV_PROGRESS_STATE
{
- 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)
+ ULONG Floor;
+ ULONG Ceiling;
+ ULONG Bias;
+} INBV_PROGRESS_STATE;
+
+typedef struct _BT_PROGRESS_INDICATOR
{
- UCHAR PaletteBitmapBuffer[sizeof(BITMAPINFOHEADER) + sizeof(_MainPalette)];
- PBITMAPINFOHEADER PaletteBitmap = (PBITMAPINFOHEADER)PaletteBitmapBuffer;
- LPRGBQUAD Palette = (LPRGBQUAD)(PaletteBitmapBuffer + sizeof(BITMAPINFOHEADER));
+ ULONG Count;
+ ULONG Expected;
+ ULONG Percentage;
+} BT_PROGRESS_INDICATOR, *PBT_PROGRESS_INDICATOR;
- ULONG Iteration, Index, ClrUsed;
- LARGE_INTEGER Interval;
+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;
- Interval.QuadPart = -PALETTE_FADE_TIME;
+static BOOLEAN InbvDisplayDebugStrings = FALSE;
+static INBV_DISPLAY_STRING_FILTER InbvDisplayFilter = NULL;
- /* Check if we're installed and we own it */
- if ((InbvBootDriverInstalled) &&
- (InbvDisplayState == INBV_DISPLAY_STATE_OWNED))
- {
- /* Acquire the lock */
- InbvAcquireLock();
+ULONG ProgressBarLeft = 0, ProgressBarTop = 0;
+BOOLEAN ShowProgressBar = FALSE;
+static INBV_PROGRESS_STATE InbvProgressState;
+static BT_PROGRESS_INDICATOR InbvProgressIndicator = {0, 25, 0};
- /*
- * 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);
- }
+static ULONG ResourceCount = 0;
+static PUCHAR ResourceList[1 + IDB_MAX_RESOURCES]; // First entry == NULL, followed by 'ResourceCount' entries.
- VidBitBlt(PaletteBitmapBuffer, 0, 0);
- /* Wait for a bit. */
- KeDelayExecutionThread(KernelMode, FALSE, &Interval);
- }
+/*
+ * Headless terminal text colors
+ */
- /* Release the lock */
- InbvReleaseLock();
+#ifdef INBV_HEADLESS_COLORS
+
+// Conversion table CGA to ANSI color index
+static const UCHAR CGA_TO_ANSI_COLOR_TABLE[16] =
+{
+ 0, // Black
+ 4, // Blue
+ 2, // Green
+ 6, // Cyan
+ 1, // Red
+ 5, // Magenta
+ 3, // Brown/Yellow
+ 7, // Grey/White
+
+ 60, // Bright Black
+ 64, // Bright Blue
+ 62, // Bright Green
+ 66, // Bright Cyan
+ 61, // Bright Red
+ 65, // Bright Magenta
+ 63, // Bright Yellow
+ 67 // Bright Grey (White)
+};
+
+#define CGA_TO_ANSI_COLOR(CgaColor) \
+ CGA_TO_ANSI_COLOR_TABLE[CgaColor & 0x0F]
+
+#endif
+
+// Default colors: text in white, background in black
+static ULONG InbvTerminalTextColor = 37;
+static ULONG InbvTerminalBkgdColor = 40;
- /* Wait for a bit. */
- KeDelayExecutionThread(KernelMode, FALSE, &Interval);
- }
-}
/* 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,
InLoadOrderLinks);
/* Check for a match */
- if ((RtlEqualUnicodeString(&LdrEntry->BaseDllName, &UpString, TRUE)) ||
- (RtlEqualUnicodeString(&LdrEntry->BaseDllName, &MpString, TRUE)))
+ if (RtlEqualUnicodeString(&LdrEntry->BaseDllName, &UpString, TRUE) ||
+ RtlEqualUnicodeString(&LdrEntry->BaseDllName, &MpString, TRUE))
{
/* Break out */
break;
if (NextEntry != ListHead)
{
/* Try to find the resource */
- ResourceInfo.Type = 2; //RT_BITMAP;
+ ResourceInfo.Type = 2; // RT_BITMAP;
ResourceInfo.Name = ResourceId;
ResourceInfo.Language = 0;
Status = LdrFindResource_U(LdrEntry->DllBase,
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 CustomLogo = FALSE;
+ BOOLEAN ResetMode = FALSE; // By default do not reset the video mode
ULONG i;
/* Quit if we're already installed */
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;
+ /* Reset the video mode in case we do not have a custom boot logo */
+ CommandLine = (LoaderBlock->LoadOptions ? _strupr(LoaderBlock->LoadOptions) : NULL);
+ ResetMode = (CommandLine == NULL) || (strstr(CommandLine, "BOOTLOGO") == NULL);
}
/* Initialize the video */
- InbvBootDriverInstalled = VidInitialize(FALSE);
+ InbvBootDriverInstalled = VidInitialize(ResetMode);
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++)
+ ResourceCount = min(Count, RTL_NUMBER_OF(ResourceList) - 1);
+ for (i = 1; i <= ResourceCount; i++)
{
/* Do the lookup */
ResourceList[i] = FindBitmapResource(LoaderBlock, i);
/* 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)
if (InbvDisplayState == INBV_DISPLAY_STATE_OWNED) VidCleanUp();
/* Set the new display state */
- InbvDisplayState = Enable ? INBV_DISPLAY_STATE_OWNED:
+ InbvDisplayState = Enable ? INBV_DISPLAY_STATE_OWNED :
INBV_DISPLAY_STATE_DISABLED;
/* Release the lock */
else
{
/* Set the new display state */
- InbvDisplayState = Enable ? INBV_DISPLAY_STATE_OWNED:
+ InbvDisplayState = Enable ? INBV_DISPLAY_STATE_OWNED :
INBV_DISPLAY_STATE_DISABLED;
}
}
VOID
NTAPI
-InbvSetDisplayOwnership(IN BOOLEAN DisplayOwned)
+InbvSetDisplayOwnership(
+ _In_ BOOLEAN DisplayOwned)
{
/* Set the new display state */
- InbvDisplayState = DisplayOwned ? INBV_DISPLAY_STATE_OWNED:
+ InbvDisplayState = DisplayOwned ? INBV_DISPLAY_STATE_OWNED :
INBV_DISPLAY_STATE_LOST;
}
BOOLEAN
NTAPI
-InbvDisplayString(IN PCHAR String)
+InbvDisplayString(
+ _In_ PCHAR String)
{
/* Make sure we own the display */
if (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)
InbvAcquireLock();
/* Make sure we're installed and display the string */
- if (InbvBootDriverInstalled) VidDisplayString((PUCHAR) String);
+ if (InbvBootDriverInstalled) VidDisplayString((PUCHAR)String);
/* Print the string on the EMS port */
HeadlessDispatch(HeadlessCmdPutString,
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)
InbvResetDisplay(VOID)
{
/* Check if we're installed and we own it */
- if ((InbvBootDriverInstalled) &&
+ if (InbvBootDriverInstalled &&
(InbvDisplayState == INBV_DISPLAY_STATE_OWNED))
{
/* Do the reset */
VOID
NTAPI
-InbvSetScrollRegion(IN ULONG Left,
- IN ULONG Top,
- IN ULONG Width,
- IN ULONG Height)
+InbvSetScrollRegion(
+ _In_ ULONG Left,
+ _In_ ULONG Top,
+ _In_ ULONG Right,
+ _In_ ULONG Bottom)
{
/* Just call bootvid */
- VidSetScrollRegion(Left, Top, Width, Height);
+ VidSetScrollRegion(Left, Top, Right, Bottom);
}
VOID
NTAPI
-InbvSetTextColor(IN ULONG Color)
+InbvSetTextColor(
+ _In_ ULONG Color)
{
- /* FIXME: Headless */
+ HEADLESS_CMD_SET_COLOR HeadlessSetColor;
+
+ /* Set color for EMS port */
+#ifdef INBV_HEADLESS_COLORS
+ InbvTerminalTextColor = 30 + CGA_TO_ANSI_COLOR(Color);
+#else
+ InbvTerminalTextColor = 37;
+#endif
+ HeadlessSetColor.TextColor = InbvTerminalTextColor;
+ HeadlessSetColor.BkgdColor = InbvTerminalBkgdColor;
+ HeadlessDispatch(HeadlessCmdSetColor,
+ &HeadlessSetColor,
+ sizeof(HeadlessSetColor),
+ NULL,
+ NULL);
/* Update the text color */
VidSetTextColor(Color);
VOID
NTAPI
-InbvSolidColorFill(IN ULONG Left,
- IN ULONG Top,
- IN ULONG Width,
- IN ULONG Height,
- IN ULONG Color)
+InbvSolidColorFill(
+ _In_ ULONG Left,
+ _In_ ULONG Top,
+ _In_ ULONG Right,
+ _In_ ULONG Bottom,
+ _In_ ULONG Color)
{
+ HEADLESS_CMD_SET_COLOR HeadlessSetColor;
+
/* Make sure we own it */
if (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)
{
if (InbvBootDriverInstalled)
{
/* Call bootvid */
- VidSolidColorFill(Left, Top, Width, Height, (UCHAR)Color);
+ VidSolidColorFill(Left, Top, Right, Bottom, (UCHAR)Color);
}
- /* FIXME: Headless */
+ /* Set color for EMS port and clear display */
+#ifdef INBV_HEADLESS_COLORS
+ InbvTerminalBkgdColor = 40 + CGA_TO_ANSI_COLOR(Color);
+#else
+ InbvTerminalBkgdColor = 40;
+#endif
+ HeadlessSetColor.TextColor = InbvTerminalTextColor;
+ HeadlessSetColor.BkgdColor = InbvTerminalBkgdColor;
+ HeadlessDispatch(HeadlessCmdSetColor,
+ &HeadlessSetColor,
+ sizeof(HeadlessSetColor),
+ NULL,
+ NULL);
+ HeadlessDispatch(HeadlessCmdClearDisplay,
+ NULL, 0,
+ NULL, NULL);
/* Release the lock */
InbvReleaseLock();
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) &&
+ if (InbvBootDriverInstalled &&
(InbvDisplayState == INBV_DISPLAY_STATE_OWNED))
{
/* Do the blit */
VOID
NTAPI
-InbvBitBlt(IN PUCHAR Buffer,
- IN ULONG X,
- IN ULONG Y)
+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) &&
- (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) &&
+ if (InbvBootDriverInstalled &&
(InbvDisplayState == INBV_DISPLAY_STATE_OWNED))
{
/* Do the blit */
}
}
+/**
+ * @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;
- ProgressBarTop = Top;
+ ProgressBarTop = Top;
/* Enable the progress bar */
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;
}
-NTSTATUS
+/**
+ * @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
-NtDisplayString(IN PUNICODE_STRING DisplayString)
+InbvUpdateProgressBar(
+ _In_ ULONG Percentage)
{
- OEM_STRING OemString;
+ ULONG TotalProgress;
- /* Convert the string to OEM and display it */
- RtlUnicodeStringToOemString(&OemString, DisplayString, TRUE);
- InbvDisplayString(OemString.Buffer);
- RtlFreeOemString(&OemString);
+ /* 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);
- /* Return success */
- return STATUS_SUCCESS;
+ BootAnimTickProgressBar(TotalProgress);
+ }
}
-VOID
+NTSTATUS
NTAPI
-INIT_FUNCTION
-DisplayBootBitmap(IN BOOLEAN TextMode)
+NtDisplayString(IN PUNICODE_STRING DisplayString)
{
- PBITMAPINFOHEADER BitmapInfoHeader;
- LPRGBQUAD Palette;
+ NTSTATUS Status;
+ UNICODE_STRING CapturedString;
+ OEM_STRING OemString;
+ ULONG OemLength;
+ KPROCESSOR_MODE PreviousMode;
- PVOID Header, Band, Text, Screen;
- ROT_BAR_TYPE TempRotBarSelection = RB_UNSPECIFIED;
+ PAGED_CODE();
-#ifdef CORE_6781_resolved
- UCHAR Buffer[64];
-#endif
+ PreviousMode = ExGetPreviousMode();
+
+ /* We require the TCB privilege */
+ if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
+ return STATUS_PRIVILEGE_NOT_HELD;
- /* Check if the system thread has already been created */
- if (SysThreadCreated)
+ /* Capture the string */
+ Status = ProbeAndCaptureUnicodeString(&CapturedString, PreviousMode, DisplayString);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ /* Do not display the string if it is empty */
+ if (CapturedString.Length == 0 || CapturedString.Buffer == NULL)
{
- /* Reset the progress bar */
- InbvAcquireLock();
- RotBarSelection = RB_UNSPECIFIED;
- InbvReleaseLock();
+ Status = STATUS_SUCCESS;
+ goto Quit;
}
- /* Check if this is text mode */
- ShowProgressBar = FALSE;
- if (TextMode)
+ /*
+ * Convert the string since INBV understands only ANSI/OEM. Allocate the
+ * string buffer in non-paged pool because INBV passes it down to BOOTVID.
+ * We cannot perform the allocation using RtlUnicodeStringToOemString()
+ * since its allocator uses PagedPool.
+ */
+ OemLength = RtlUnicodeStringToOemSize(&CapturedString);
+ if (OemLength > MAXUSHORT)
{
- /* 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);
- }
+ Status = STATUS_BUFFER_OVERFLOW;
+ goto Quit;
}
- else
+ RtlInitEmptyAnsiString((PANSI_STRING)&OemString, NULL, (USHORT)OemLength);
+ OemString.Buffer = ExAllocatePoolWithTag(NonPagedPool, OemLength, TAG_OSTR);
+ if (OemString.Buffer == NULL)
{
- /* 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);
-#endif
-
- /* Draw the progress bar bit */
-// if (Bar) InbvBitBlt(Bar, 0, 0);
-
- /* Set filter which will draw text display if needed */
- InbvInstallDisplayStringFilter(DisplayFilter);
+ Status = STATUS_NO_MEMORY;
+ goto Quit;
}
-
- /* Do we have a system thread? */
- if (SysThreadCreated)
+ Status = RtlUnicodeStringToOemString(&OemString, &CapturedString, FALSE);
+ if (!NT_SUCCESS(Status))
{
- /* We do, set the progress bar location */
- InbvAcquireLock();
- RotBarSelection = TempRotBarSelection;
- //InbvRotBarInit();
- InbvReleaseLock();
+ ExFreePoolWithTag(OemString.Buffer, TAG_OSTR);
+ goto Quit;
}
-}
-
-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);
+ /* Display the string */
+ InbvDisplayString(OemString.Buffer);
- DotHack = FALSE;
+ /* Free the string buffer */
+ ExFreePoolWithTag(OemString.Buffer, TAG_OSTR);
- /* Draw text screen */
- DisplayBootBitmap(TRUE);
- }
-}
+ Status = STATUS_SUCCESS;
-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);
- }
+Quit:
+ /* Free the captured string */
+ ReleaseCapturedUnicodeString(&CapturedString, PreviousMode);
- /* Reset progress bar and lock */
- PltRotBarStatus = 3;
- InbvReleaseLock();
+ return Status;
}