[NTOS:INBV] Code refactoring: Move all the boot animation-specific code out of inbv.c and into the new bootanim.c file.

- inbv.c now only contains the Inbv-specific API and nothing else.

- It will make easier for people to write their own boot themes & animations,
  by just copying/adapting the bootanim.c file (and the resources).

- Add SAL annotations.

- All INBV progress bar functions (except for InbvIndicateProgress())
  should not be INIT-only functions, since they can be (not yet in ROS)
  used at later times -- namely, for feedback during hibernation.
This commit is contained in:
Hermès Bélusca-Maïto 2022-02-13 20:57:12 +01:00
parent 17bd71b570
commit f7e8214b55
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
7 changed files with 362 additions and 1682 deletions

View file

@ -11,6 +11,8 @@
#include <ntoskrnl.h> #include <ntoskrnl.h>
#include <reactos/buildno.h> #include <reactos/buildno.h>
#include "inbv/logo.h"
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>

View file

@ -1,10 +1,17 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Boot Theme & Animation
* COPYRIGHT: Copyright 2007 Alex Ionescu (alex.ionescu@reactos.org)
* Copyright 2007 Hervé Poussineau (hpoussin@reactos.org)
* Copyright 2012-2022 Hermès Bélusca-Maïto
* Copyright 2017-2018 Stanislav Motylkov
* Copyright 2019-2020 Yaroslav Kibysh
*/
/* INCLUDES ******************************************************************/ /* INCLUDES ******************************************************************/
#include <ntoskrnl.h> #include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
#include "inbv/logo.h" #include "inbv/logo.h"
/* See also mm/ARM3/miarm.h */ /* See also mm/ARM3/miarm.h */
@ -13,35 +20,14 @@
/* GLOBALS *******************************************************************/ /* GLOBALS *******************************************************************/
/*
* Enable this define if you want Inbv to use coloured headless mode.
*/
// #define INBV_HEADLESS_COLORS
/* /*
* ReactOS uses the same boot screen for all the products. * ReactOS uses the same boot screen for all the products.
*/ *
/*
* Enable this define when ReactOS will have different SKUs * Enable this define when ReactOS will have different SKUs
* (Workstation, Server, Storage Server, Cluster Server, etc...). * (Workstation, Server, Storage Server, Cluster Server, etc...).
*/ */
// #define REACTOS_SKUS // #define REACTOS_SKUS
typedef struct _INBV_PROGRESS_STATE
{
ULONG Floor;
ULONG Ceiling;
ULONG Bias;
} INBV_PROGRESS_STATE;
typedef struct _BT_PROGRESS_INDICATOR
{
ULONG Count;
ULONG Expected;
ULONG Percentage;
} BT_PROGRESS_INDICATOR, *PBT_PROGRESS_INDICATOR;
typedef enum _ROT_BAR_TYPE typedef enum _ROT_BAR_TYPE
{ {
RB_UNSPECIFIED, RB_UNSPECIFIED,
@ -71,20 +57,8 @@ typedef enum _BBLT_HORZ_ALIGNMENT
*/ */
#define INBV_ROTBAR_IMPLEMENTED #define INBV_ROTBAR_IMPLEMENTED
static KSPIN_LOCK BootDriverLock; extern ULONG ProgressBarLeft, ProgressBarTop;
static KIRQL InbvOldIrql; extern BOOLEAN ShowProgressBar;
static INBV_DISPLAY_STATE InbvDisplayState = INBV_DISPLAY_STATE_DISABLED;
BOOLEAN InbvBootDriverInstalled = FALSE;
static BOOLEAN InbvDisplayDebugStrings = FALSE;
static INBV_DISPLAY_STRING_FILTER InbvDisplayFilter = NULL;
static ULONG ProgressBarLeft = 0, ProgressBarTop = 0;
static ULONG ProgressBarWidth = 0, ProgressBarHeight = 0;
static 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 #ifdef INBV_ROTBAR_IMPLEMENTED
/* /*
@ -115,47 +89,9 @@ static UCHAR RotLineBuffer[SCREEN_WIDTH * 6];
#endif #endif
/* /* FADE-IN FUNCTION **********************************************************/
* Headless terminal text colors
*/
#ifdef INBV_HEADLESS_COLORS /** From include/psdk/wingdi.h and bootvid/precomp.h **/
// 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;
/* FADING FUNCTION ***********************************************************/
/** From include/psdk/wingdi.h **/
typedef struct tagRGBQUAD typedef struct tagRGBQUAD
{ {
UCHAR rgbBlue; UCHAR rgbBlue;
@ -163,14 +99,7 @@ typedef struct tagRGBQUAD
UCHAR rgbRed; UCHAR rgbRed;
UCHAR rgbReserved; UCHAR rgbReserved;
} RGBQUAD, *LPRGBQUAD; } RGBQUAD, *LPRGBQUAD;
/*******************************/
static RGBQUAD MainPalette[16];
#define PALETTE_FADE_STEPS 12
#define PALETTE_FADE_TIME (15 * 1000) /* 15 ms */
/** From bootvid/precomp.h **/
// //
// Bitmap Header // Bitmap Header
// //
@ -188,13 +117,12 @@ typedef struct tagBITMAPINFOHEADER
ULONG biClrUsed; ULONG biClrUsed;
ULONG biClrImportant; ULONG biClrImportant;
} BITMAPINFOHEADER, *PBITMAPINFOHEADER; } BITMAPINFOHEADER, *PBITMAPINFOHEADER;
/****************************/ /*******************************/
// static RGBQUAD MainPalette[16];
// Needed prototypes
// #define PALETTE_FADE_STEPS 12
VOID NTAPI InbvAcquireLock(VOID); #define PALETTE_FADE_TIME (15 * 1000) /* 15 ms */
VOID NTAPI InbvReleaseLock(VOID);
static VOID static VOID
BootLogoFadeIn(VOID) BootLogoFadeIn(VOID)
@ -209,7 +137,7 @@ BootLogoFadeIn(VOID)
/* Check if we are installed and we own the display */ /* Check if we are installed and we own the display */
if (!InbvBootDriverInstalled || if (!InbvBootDriverInstalled ||
(InbvDisplayState != INBV_DISPLAY_STATE_OWNED)) (InbvGetDisplayState() != INBV_DISPLAY_STATE_OWNED))
{ {
return; return;
} }
@ -341,97 +269,19 @@ BitBltAligned(
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
CODE_SEG("INIT")
PVOID
NTAPI
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;
}
CODE_SEG("INIT") CODE_SEG("INIT")
BOOLEAN BOOLEAN
NTAPI NTAPI
InbvDriverInitialize(IN PLOADER_PARAMETER_BLOCK LoaderBlock, BootAnimInitialize(
IN ULONG Count) _In_ PLOADER_PARAMETER_BLOCK LoaderBlock,
_In_ ULONG Count)
{ {
PCHAR CommandLine; #if 0
BOOLEAN ResetMode = FALSE; // By default do not reset the video mode
ULONG i; ULONG i;
/* Quit if we're already installed */ /* Quit if we're already installed */
if (InbvBootDriverInstalled) return TRUE; if (InbvBootDriverInstalled) return TRUE;
/* Initialize the lock and check the current display state */
KeInitializeSpinLock(&BootDriverLock);
if (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)
{
/* 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(ResetMode);
if (InbvBootDriverInstalled)
{
/* Find bitmap resources in the kernel */ /* Find bitmap resources in the kernel */
ResourceCount = min(Count, RTL_NUMBER_OF(ResourceList) - 1); ResourceCount = min(Count, RTL_NUMBER_OF(ResourceList) - 1);
for (i = 1; i <= ResourceCount; i++) for (i = 1; i <= ResourceCount; i++)
@ -442,340 +292,35 @@ InbvDriverInitialize(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
/* Set the progress bar ranges */ /* Set the progress bar ranges */
InbvSetProgressBarSubset(0, 100); InbvSetProgressBarSubset(0, 100);
} #endif
/* Return install state */ /* 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
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; 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 Right,
IN ULONG Bottom)
{
/* Just call bootvid */
VidSetScrollRegion(Left, Top, Right, Bottom);
}
VOID
NTAPI
InbvSetTextColor(IN ULONG Color)
{
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 Right,
IN ULONG Bottom,
IN ULONG Color)
{
HEADLESS_CMD_SET_COLOR HeadlessSetColor;
/* 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, Right, Bottom, (UCHAR)Color);
}
/* 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();
}
}
/** /**
* @brief * @brief
* Updates the progress bar percentage, relative to the current * Ticks the progress bar. Used by InbvUpdateProgressBar() and related.
* percentage sub-range previously set by InbvSetProgressBarSubset().
* *
* @param[in] Percentage * @param[in] SubPercentTimes100
* The progress percentage, relative to the current sub-range. * The progress percentage, scaled up by 100.
* *
* @return None. * @return None.
**/ **/
CODE_SEG("INIT")
VOID VOID
NTAPI NTAPI
InbvUpdateProgressBar( BootAnimTickProgressBar(
_In_ ULONG Percentage) _In_ ULONG SubPercentTimes100)
{ {
ULONG TotalProgress, FillCount; ULONG FillCount;
/* Make sure the progress bar is enabled, that we own and are installed */ /* Make sure the progress bar is enabled, that we own and are installed */
if (ShowProgressBar && ASSERT(ShowProgressBar &&
InbvBootDriverInstalled && InbvBootDriverInstalled &&
(InbvDisplayState == INBV_DISPLAY_STATE_OWNED)) (InbvGetDisplayState() == INBV_DISPLAY_STATE_OWNED));
{
/* Compute fill count */ /* Compute fill count */
TotalProgress = InbvProgressState.Floor + (Percentage * InbvProgressState.Bias); FillCount = VID_PROGRESS_BAR_WIDTH * SubPercentTimes100 / (100 * 100);
FillCount = ProgressBarWidth * TotalProgress / (100 * 100);
/* Acquire the lock */ /* Acquire the lock */
InbvAcquireLock(); InbvAcquireLock();
@ -784,252 +329,12 @@ InbvUpdateProgressBar(
VidSolidColorFill(ProgressBarLeft, VidSolidColorFill(ProgressBarLeft,
ProgressBarTop, ProgressBarTop,
ProgressBarLeft + FillCount, ProgressBarLeft + FillCount,
ProgressBarTop + ProgressBarHeight, ProgressBarTop + VID_PROGRESS_BAR_HEIGHT,
BV_COLOR_WHITE); BV_COLOR_WHITE);
/* Release the lock */ /* Release the lock */
InbvReleaseLock(); 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(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))
{
/* Do the blit */
VidScreenToBufferBlt(Buffer, X, Y, Width, Height, Delta);
}
}
/**
* @brief
* Sets the screen coordinates of the loading progress bar and enable it.
*
* @param[in] Left
* @param[in] Top
* The left/top coordinates.
*
* (ReactOS-specific)
* @param[in] Width
* @param[in] Height
* The width/height of the progress bar.
*
* @return None.
**/
CODE_SEG("INIT")
VOID
NTAPI
InbvSetProgressBarCoordinates(
_In_ ULONG Left,
_In_ ULONG Top,
_In_ ULONG Width,
_In_ ULONG Height)
{
/* Update the coordinates */
ProgressBarLeft = Left;
ProgressBarTop = Top;
ProgressBarWidth = Width;
ProgressBarHeight = Height;
/* Enable the progress bar */
ShowProgressBar = TRUE;
}
/**
* @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.
**/
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 - Floor;
}
/**
* @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
InbvIndicateProgress(VOID)
{
ULONG Percentage;
/* Increase progress */
InbvProgressIndicator.Count++;
/* 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 changed, 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)
{
NTSTATUS Status;
UNICODE_STRING CapturedString;
OEM_STRING OemString;
ULONG OemLength;
KPROCESSOR_MODE PreviousMode;
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
/* We require the TCB privilege */
if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
return STATUS_PRIVILEGE_NOT_HELD;
/* 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)
{
Status = STATUS_SUCCESS;
goto Quit;
}
/*
* 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)
{
Status = STATUS_BUFFER_OVERFLOW;
goto Quit;
}
RtlInitEmptyAnsiString((PANSI_STRING)&OemString, NULL, (USHORT)OemLength);
OemString.Buffer = ExAllocatePoolWithTag(NonPagedPool, OemLength, TAG_OSTR);
if (OemString.Buffer == NULL)
{
Status = STATUS_NO_MEMORY;
goto Quit;
}
Status = RtlUnicodeStringToOemString(&OemString, &CapturedString, FALSE);
if (!NT_SUCCESS(Status))
{
ExFreePoolWithTag(OemString.Buffer, TAG_OSTR);
goto Quit;
}
/* Display the string */
InbvDisplayString(OemString.Buffer);
/* Free the string buffer */
ExFreePoolWithTag(OemString.Buffer, TAG_OSTR);
Status = STATUS_SUCCESS;
Quit:
/* Free the captured string */
ReleaseCapturedUnicodeString(&CapturedString, PreviousMode);
return Status;
}
#ifdef INBV_ROTBAR_IMPLEMENTED #ifdef INBV_ROTBAR_IMPLEMENTED
static static
@ -1054,7 +359,7 @@ InbvRotationThread(
Y = ProgressBarTop + 2; Y = ProgressBarTop + 2;
InbvReleaseLock(); InbvReleaseLock();
while (InbvDisplayState == INBV_DISPLAY_STATE_OWNED) while (InbvGetDisplayState() == INBV_DISPLAY_STATE_OWNED)
{ {
/* Wait for a bit */ /* Wait for a bit */
KeDelayExecutionThread(KernelMode, FALSE, &Delay); KeDelayExecutionThread(KernelMode, FALSE, &Delay);
@ -1135,9 +440,36 @@ InbvRotBarInit(VOID)
#endif #endif
CODE_SEG("INIT") CODE_SEG("INIT")
static
VOID VOID
NTAPI NTAPI
DisplayBootBitmap(IN BOOLEAN TextMode) DisplayFilter(
_Inout_ PCHAR* String)
{
/* Windows hack to skip first dots displayed by AUTOCHK */
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);
}
}
CODE_SEG("INIT")
VOID
NTAPI
DisplayBootBitmap(
_In_ BOOLEAN TextMode)
{ {
PVOID BootCopy = NULL, BootProgress = NULL, BootLogo = NULL, Header = NULL, Footer = NULL; PVOID BootCopy = NULL, BootProgress = NULL, BootLogo = NULL, Header = NULL, Footer = NULL;
@ -1296,9 +628,7 @@ DisplayBootBitmap(IN BOOLEAN TextMode)
/* Set progress bar coordinates and display it */ /* Set progress bar coordinates and display it */
InbvSetProgressBarCoordinates(VID_PROGRESS_BAR_LEFT, InbvSetProgressBarCoordinates(VID_PROGRESS_BAR_LEFT,
VID_PROGRESS_BAR_TOP, VID_PROGRESS_BAR_TOP);
VID_PROGRESS_BAR_WIDTH,
VID_PROGRESS_BAR_HEIGHT);
#ifdef REACTOS_SKUS #ifdef REACTOS_SKUS
/* Check for non-workstation products */ /* Check for non-workstation products */
@ -1418,30 +748,6 @@ DisplayBootBitmap(IN BOOLEAN TextMode)
#endif #endif
} }
CODE_SEG("INIT")
VOID
NTAPI
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);
}
}
CODE_SEG("INIT") CODE_SEG("INIT")
VOID VOID
NTAPI NTAPI

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,10 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Boot Theme & Animation header
* COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
*/
#pragma once #pragma once
// //
@ -32,3 +39,36 @@
#define VID_SKU_TEXT_TOP 121 #define VID_SKU_TEXT_TOP 121
#define VID_FOOTER_BG_TOP (SCREEN_HEIGHT - 59) #define VID_FOOTER_BG_TOP (SCREEN_HEIGHT - 59)
//
// Boot Splash-Screen Functions
//
CODE_SEG("INIT")
BOOLEAN
NTAPI
BootAnimInitialize(
_In_ PLOADER_PARAMETER_BLOCK LoaderBlock,
_In_ ULONG Count);
VOID
NTAPI
BootAnimTickProgressBar(
_In_ ULONG SubPercentTimes100);
CODE_SEG("INIT")
VOID
NTAPI
InbvRotBarInit(VOID);
CODE_SEG("INIT")
VOID
NTAPI
DisplayBootBitmap(
_In_ BOOLEAN TextMode);
CODE_SEG("INIT")
VOID
NTAPI
FinalizeBootLogo(VOID);

View file

@ -1,6 +1,14 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: BSD - See COPYING.ARM in the top level directory
* PURPOSE: Boot Video Driver support header
* COPYRIGHT: Copyright 2007 Alex Ionescu (alex.ionescu@reactos.org)
* Copyright 2019-2022 Hermès Bélusca-Maïto
*/
#pragma once #pragma once
// Native definitions from BOOTVID (Boot Video Driver). /* Native definitions from BOOTVID (Boot Video Driver) */
#include "bootvid/bootvid.h" #include "bootvid/bootvid.h"
// //
@ -10,35 +18,78 @@ CODE_SEG("INIT")
BOOLEAN BOOLEAN
NTAPI NTAPI
InbvDriverInitialize( InbvDriverInitialize(
IN PLOADER_PARAMETER_BLOCK LoaderBlock, _In_ PLOADER_PARAMETER_BLOCK LoaderBlock,
IN ULONG Count _In_ ULONG Count
); );
extern BOOLEAN InbvBootDriverInstalled; extern BOOLEAN InbvBootDriverInstalled;
INBV_DISPLAY_STATE
NTAPI
InbvGetDisplayState(VOID);
VOID
NTAPI
InbvAcquireLock(VOID);
VOID
NTAPI
InbvReleaseLock(VOID);
PUCHAR PUCHAR
NTAPI NTAPI
InbvGetResourceAddress( InbvGetResourceAddress(
IN ULONG ResourceNumber _In_ ULONG ResourceNumber
);
//
// Display Functions
//
VOID
NTAPI
InbvBitBlt(
_In_ PUCHAR Buffer,
_In_ ULONG X,
_In_ ULONG Y
); );
VOID VOID
NTAPI NTAPI
InbvBitBlt( InbvBufferToScreenBlt(
IN PUCHAR Buffer, _In_ PUCHAR Buffer,
IN ULONG X, _In_ ULONG X,
IN ULONG Y _In_ ULONG Y,
_In_ ULONG Width,
_In_ ULONG Height,
_In_ ULONG Delta
);
VOID
NTAPI
InbvScreenToBufferBlt(
_Out_ PUCHAR Buffer,
_In_ ULONG X,
_In_ ULONG Y,
_In_ ULONG Width,
_In_ ULONG Height,
_In_ ULONG Delta
); );
// //
// Progress-Bar Functions // Progress-Bar Functions
// //
VOID
NTAPI
InbvSetProgressBarCoordinates(
_In_ ULONG Left,
_In_ ULONG Top
);
CODE_SEG("INIT") CODE_SEG("INIT")
VOID VOID
NTAPI NTAPI
InbvIndicateProgress(VOID); InbvIndicateProgress(VOID);
CODE_SEG("INIT")
VOID VOID
NTAPI NTAPI
InbvSetProgressBarSubset( InbvSetProgressBarSubset(
@ -46,44 +97,12 @@ InbvSetProgressBarSubset(
_In_ ULONG Ceiling _In_ ULONG Ceiling
); );
CODE_SEG("INIT")
VOID VOID
NTAPI NTAPI
InbvUpdateProgressBar( InbvUpdateProgressBar(
_In_ ULONG Percentage _In_ ULONG Percentage
); );
//
// Boot Splash-Screen Functions
//
CODE_SEG("INIT")
VOID
NTAPI
InbvRotBarInit(
VOID
);
CODE_SEG("INIT")
VOID
NTAPI
DisplayBootBitmap(
IN BOOLEAN TextMode
);
CODE_SEG("INIT")
VOID
NTAPI
DisplayFilter(
IN PCHAR *String
);
CODE_SEG("INIT")
VOID
NTAPI
FinalizeBootLogo(
VOID
);
// //
// Headless Terminal Support Functions // Headless Terminal Support Functions
// //

View file

@ -124,6 +124,7 @@ list(APPEND SOURCE
${REACTOS_SOURCE_DIR}/ntoskrnl/fstub/fstubex.c ${REACTOS_SOURCE_DIR}/ntoskrnl/fstub/fstubex.c
${REACTOS_SOURCE_DIR}/ntoskrnl/fstub/halstub.c ${REACTOS_SOURCE_DIR}/ntoskrnl/fstub/halstub.c
${REACTOS_SOURCE_DIR}/ntoskrnl/fstub/translate.c ${REACTOS_SOURCE_DIR}/ntoskrnl/fstub/translate.c
${REACTOS_SOURCE_DIR}/ntoskrnl/inbv/bootanim.c
${REACTOS_SOURCE_DIR}/ntoskrnl/inbv/inbv.c ${REACTOS_SOURCE_DIR}/ntoskrnl/inbv/inbv.c
${REACTOS_SOURCE_DIR}/ntoskrnl/inbv/inbvport.c ${REACTOS_SOURCE_DIR}/ntoskrnl/inbv/inbvport.c
${REACTOS_SOURCE_DIR}/ntoskrnl/io/iomgr/adapter.c ${REACTOS_SOURCE_DIR}/ntoskrnl/io/iomgr/adapter.c

View file

@ -41,14 +41,14 @@ typedef enum _INBV_DISPLAY_STATE
typedef typedef
BOOLEAN BOOLEAN
(NTAPI *INBV_RESET_DISPLAY_PARAMETERS)( (NTAPI *INBV_RESET_DISPLAY_PARAMETERS)(
ULONG Cols, _In_ ULONG Cols,
ULONG Rows _In_ ULONG Rows
); );
typedef typedef
VOID VOID
(NTAPI *INBV_DISPLAY_STRING_FILTER)( (NTAPI *INBV_DISPLAY_STRING_FILTER)(
PCHAR *Str _Inout_ PCHAR* String
); );
#endif #endif