https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c322610f6e1a407f3bf2c…
commit c322610f6e1a407f3bf2c2a915ab2526b6b9f91d
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Mon Feb 14 02:28:53 2022 +0100
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Mon Feb 21 02:53:54 2022 +0100
[FREELDR] Improve progress bar support, adapted from Inbv.
- Improve accuracy/progression smoothness when loading drivers.
- Allow changing text and percentage independently.
---
boot/freeldr/freeldr/disk/ramdisk.c | 18 +--
boot/freeldr/freeldr/include/ui.h | 95 +++++++++++++--
boot/freeldr/freeldr/include/ui/minitui.h | 16 ++-
boot/freeldr/freeldr/include/ui/noui.h | 19 ++-
boot/freeldr/freeldr/include/ui/tui.h | 22 +---
boot/freeldr/freeldr/linuxboot.c | 6 +-
boot/freeldr/freeldr/ntldr/setupldr.c | 4 +-
boot/freeldr/freeldr/ntldr/winldr.c | 27 +++--
boot/freeldr/freeldr/ntldr/winldr.h | 2 +
boot/freeldr/freeldr/ui/directui.c | 31 -----
boot/freeldr/freeldr/ui/minitui.c | 133 ++++++++++++--------
boot/freeldr/freeldr/ui/noui.c | 23 +++-
boot/freeldr/freeldr/ui/tui.c | 135 +++++++++++++++------
boot/freeldr/freeldr/ui/ui.c | 195 ++++++++++++++++++++++++------
14 files changed, 500 insertions(+), 226 deletions(-)
diff --git a/boot/freeldr/freeldr/disk/ramdisk.c b/boot/freeldr/freeldr/disk/ramdisk.c
index 58f8a37d528..6306cad88be 100644
--- a/boot/freeldr/freeldr/disk/ramdisk.c
+++ b/boot/freeldr/freeldr/disk/ramdisk.c
@@ -111,13 +111,12 @@ RamDiskLoadVirtualFile(
ULONG RamFileId;
ULONG ChunkSize, Count;
ULONGLONG TotalRead;
- PCHAR MsgBuffer = "Loading RamDisk...";
ULONG PercentPerChunk, Percent;
FILEINFORMATION Information;
LARGE_INTEGER Position;
/* Display progress */
- UiDrawProgressBarCenter(1, 100, MsgBuffer);
+ UiDrawProgressBarCenter("Loading RamDisk...");
/* Try opening the Ramdisk file */
Status = FsOpenFile(FileName, DefaultPath, OpenReadOnly, &RamFileId);
@@ -135,8 +134,8 @@ RamDiskLoadVirtualFile(
/* FIXME: For now, limit RAM disks to 4GB */
if (Information.EndingAddress.HighPart != 0)
{
- UiMessageBox("RAM disk too big.");
ArcClose(RamFileId);
+ UiMessageBox("RAM disk too big.");
return ENOMEM;
}
RamDiskFileSize = Information.EndingAddress.QuadPart;
@@ -145,20 +144,22 @@ RamDiskLoadVirtualFile(
/* Allocate memory for it */
ChunkSize = 8 * 1024 * 1024;
if (RamDiskFileSize < ChunkSize)
- Percent = PercentPerChunk = 0;
+ PercentPerChunk = 0;
else
- Percent = PercentPerChunk = 100 / (RamDiskFileSize / ChunkSize);
+ PercentPerChunk = 100 * ChunkSize / RamDiskFileSize;
RamDiskBase = MmAllocateMemoryWithType(RamDiskFileSize, LoaderXIPRom);
if (!RamDiskBase)
{
- UiMessageBox("Failed to allocate memory for RAM disk.");
+ RamDiskFileSize = 0;
ArcClose(RamFileId);
+ UiMessageBox("Failed to allocate memory for RAM disk.");
return ENOMEM;
}
/*
* Read it in chunks
*/
+ Percent = 0;
for (TotalRead = 0; TotalRead < RamDiskFileSize; TotalRead += ChunkSize)
{
/* Check if we're at the last chunk */
@@ -168,8 +169,8 @@ RamDiskLoadVirtualFile(
ChunkSize = (ULONG)(RamDiskFileSize - TotalRead);
}
- /* Draw progress */
- UiDrawProgressBarCenter(Percent, 100, MsgBuffer);
+ /* Update progress */
+ UiUpdateProgressBar(Percent, NULL);
Percent += PercentPerChunk;
/* Copy the contents */
@@ -194,6 +195,7 @@ RamDiskLoadVirtualFile(
return ((Status != ESUCCESS) ? Status : EIO);
}
}
+ UiUpdateProgressBar(100, NULL);
ArcClose(RamFileId);
diff --git a/boot/freeldr/freeldr/include/ui.h b/boot/freeldr/freeldr/include/ui.h
index 4308b95c0f4..938192e19b8 100644
--- a/boot/freeldr/freeldr/include/ui.h
+++ b/boot/freeldr/freeldr/include/ui.h
@@ -95,12 +95,74 @@ VOID UiInfoBox(PCSTR MessageText); //
Displays a i
VOID UiMessageBox(PCSTR Format, ...); // Displays a message box
on the screen with an ok button
VOID UiMessageBoxCritical(PCSTR MessageText); // Displays a message box
on the screen with an ok button using no system resources
+
+/* Loading Progress-Bar Functions ********************************************/
+
+/*
+ * Loading progress bar, based on the one from NTOS Inbv.
+ * Supports progress within sub-ranges, used when loading
+ * with an unknown number of steps.
+ */
+typedef struct _UI_PROGRESS_BAR
+{
+ // UI_PROGRESS_STATE
+ struct
+ {
+ ULONG Floor;
+ // ULONG Ceiling;
+ ULONG Bias;
+ } State;
+
+ // BT_PROGRESS_INDICATOR
+ struct
+ {
+ ULONG Count;
+ ULONG Expected;
+ ULONG Percentage;
+ } Indicator;
+
+ ULONG Left;
+ ULONG Top;
+ ULONG Right;
+ ULONG Bottom;
+ // ULONG Width; // == Right - Left + 1;
+ BOOLEAN Show;
+} UI_PROGRESS_BAR, *PUI_PROGRESS_BAR;
+
+extern UI_PROGRESS_BAR UiProgressBar;
+
+VOID
+UiInitProgressBar(
+ _In_ ULONG Left,
+ _In_ ULONG Top,
+ _In_ ULONG Right,
+ _In_ ULONG Bottom,
+ _In_ PCSTR ProgressText);
+
+/* Indicate loading progress without any specific number of steps */
+VOID
+UiIndicateProgress(VOID);
+
+/* Set a progress loading percentage range */
+VOID
+UiSetProgressBarSubset(
+ _In_ ULONG Floor,
+ _In_ ULONG Ceiling);
+
+/* Update the loading progress percentage within a selected range */
+VOID
+UiUpdateProgressBar(
+ _In_ ULONG Percentage,
+ _In_opt_ PCSTR ProgressText);
+
+VOID
+UiSetProgressBarText(
+ _In_ PCSTR ProgressText);
+
/* Draws the progress bar showing nPos percent filled */
VOID
UiDrawProgressBarCenter(
- _In_ ULONG Position,
- _In_ ULONG Range,
- _Inout_z_ PSTR ProgressText);
+ _In_ PCSTR ProgressText);
/* Draws the progress bar showing nPos percent filled */
VOID
@@ -109,9 +171,8 @@ UiDrawProgressBar(
_In_ ULONG Top,
_In_ ULONG Right,
_In_ ULONG Bottom,
- _In_ ULONG Position,
- _In_ ULONG Range,
- _Inout_z_ PSTR ProgressText);
+ _In_ PCSTR ProgressText);
+
// Displays all the message boxes in a given section.
VOID
@@ -123,14 +184,11 @@ UiShowMessageBoxesInArgv(
IN ULONG Argc,
IN PCHAR Argv[]);
-VOID UiEscapeString(PCHAR String); // Processes a string
and changes all occurrences of "\n" to '\n'
BOOLEAN UiEditBox(PCSTR MessageText, PCHAR EditTextBuffer, ULONG Length);
UCHAR UiTextToColor(PCSTR ColorText); // Converts the text
color into it's equivalent color value
UCHAR UiTextToFillStyle(PCSTR FillStyleText); // Converts the text fill
into it's equivalent fill value
-VOID UiTruncateStringEllipsis(PCHAR StringText, ULONG MaxChars); // Truncates a
string to MaxChars by adding an ellipsis on the end '...'
-
VOID UiFadeInBackdrop(VOID); // Draws the backdrop
and fades the screen in
VOID UiFadeOut(VOID); // Fades the screen out
@@ -200,8 +258,23 @@ typedef struct tagUIVTBL
VOID (*UpdateDateTime)(VOID);
VOID (*MessageBox)(PCSTR MessageText);
VOID (*MessageBoxCritical)(PCSTR MessageText);
- VOID (*DrawProgressBarCenter)(ULONG Position, ULONG Range, PCHAR ProgressText);
- VOID (*DrawProgressBar)(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, ULONG
Position, ULONG Range, PCHAR ProgressText);
+
+ VOID (*DrawProgressBarCenter)(
+ _In_ PCSTR ProgressText);
+
+ VOID (*DrawProgressBar)(
+ _In_ ULONG Left,
+ _In_ ULONG Top,
+ _In_ ULONG Right,
+ _In_ ULONG Bottom,
+ _In_ PCSTR ProgressText);
+
+ VOID (*SetProgressBarText)(
+ _In_ PCSTR ProgressText);
+
+ VOID (*TickProgressBar)(
+ _In_ ULONG SubPercentTimes100);
+
BOOLEAN (*EditBox)(PCSTR MessageText, PCHAR EditTextBuffer, ULONG Length);
UCHAR (*TextToColor)(PCSTR ColorText);
UCHAR (*TextToFillStyle)(PCSTR FillStyleText);
diff --git a/boot/freeldr/freeldr/include/ui/minitui.h
b/boot/freeldr/freeldr/include/ui/minitui.h
index 4a710cd8b6f..6db89b41cc0 100644
--- a/boot/freeldr/freeldr/include/ui/minitui.h
+++ b/boot/freeldr/freeldr/include/ui/minitui.h
@@ -13,12 +13,18 @@
VOID MiniTuiDrawBackdrop(VOID);
VOID MiniTuiDrawStatusText(PCSTR StatusText);
+VOID
+MiniTuiSetProgressBarText(
+ _In_ PCSTR ProgressText);
+
+VOID
+MiniTuiTickProgressBar(
+ _In_ ULONG SubPercentTimes100);
+
/* Draws the progress bar showing nPos percent filled */
VOID
MiniTuiDrawProgressBarCenter(
- _In_ ULONG Position,
- _In_ ULONG Range,
- _Inout_z_ PSTR ProgressText);
+ _In_ PCSTR ProgressText);
/* Draws the progress bar showing nPos percent filled */
VOID
@@ -27,9 +33,7 @@ MiniTuiDrawProgressBar(
_In_ ULONG Top,
_In_ ULONG Right,
_In_ ULONG Bottom,
- _In_ ULONG Position,
- _In_ ULONG Range,
- _Inout_z_ PSTR ProgressText);
+ _In_ PCSTR ProgressText);
/* Menu Functions ************************************************************/
diff --git a/boot/freeldr/freeldr/include/ui/noui.h
b/boot/freeldr/freeldr/include/ui/noui.h
index dca5db172e0..72eca1a9298 100644
--- a/boot/freeldr/freeldr/include/ui/noui.h
+++ b/boot/freeldr/freeldr/include/ui/noui.h
@@ -50,12 +50,20 @@ VOID NoUiUpdateDateTime(VOID);
VOID NoUiMessageBox(PCSTR MessageText);
VOID NoUiMessageBoxCritical(PCSTR MessageText);
+/* Loading Progress-Bar Functions ********************************************/
+
+VOID
+NoUiSetProgressBarText(
+ _In_ PCSTR ProgressText);
+
+VOID
+NoUiTickProgressBar(
+ _In_ ULONG SubPercentTimes100);
+
/* Draws the progress bar showing nPos percent filled */
VOID
NoUiDrawProgressBarCenter(
- _In_ ULONG Position,
- _In_ ULONG Range,
- _Inout_z_ PSTR ProgressText);
+ _In_ PCSTR ProgressText);
/* Draws the progress bar showing nPos percent filled */
VOID
@@ -64,9 +72,8 @@ NoUiDrawProgressBar(
_In_ ULONG Top,
_In_ ULONG Right,
_In_ ULONG Bottom,
- _In_ ULONG Position,
- _In_ ULONG Range,
- _Inout_z_ PSTR ProgressText);
+ _In_ PCSTR ProgressText);
+
BOOLEAN NoUiEditBox(PCSTR MessageText, PCHAR EditTextBuffer, ULONG Length);
UCHAR NoUiTextToColor(PCSTR ColorText);
diff --git a/boot/freeldr/freeldr/include/ui/tui.h
b/boot/freeldr/freeldr/include/ui/tui.h
index 27918f47bd7..b952a06822d 100644
--- a/boot/freeldr/freeldr/include/ui/tui.h
+++ b/boot/freeldr/freeldr/include/ui/tui.h
@@ -25,6 +25,10 @@ INT
TuiPrintf(
_In_ PCSTR Format, ...);
+VOID
+TuiTruncateStringEllipsis(
+ _Inout_z_ PSTR StringText,
+ _In_ ULONG MaxChars);
#define TUI_TITLE_BOX_CHAR_HEIGHT 5
@@ -72,24 +76,6 @@ VOID TuiRestoreScreen(PUCHAR Buffer); //
Restores the
VOID TuiMessageBox(PCSTR MessageText); // Displays a message
box on the screen with an ok button
VOID TuiMessageBoxCritical(PCSTR MessageText); // Displays a message
box on the screen with an ok button using no system resources
-/* Draws the progress bar showing nPos percent filled */
-VOID
-TuiDrawProgressBarCenter(
- _In_ ULONG Position,
- _In_ ULONG Range,
- _Inout_z_ PSTR ProgressText);
-
-/* Draws the progress bar showing nPos percent filled */
-VOID
-TuiDrawProgressBar(
- _In_ ULONG Left,
- _In_ ULONG Top,
- _In_ ULONG Right,
- _In_ ULONG Bottom,
- _In_ ULONG Position,
- _In_ ULONG Range,
- _Inout_z_ PSTR ProgressText);
-
BOOLEAN TuiEditBox(PCSTR MessageText, PCHAR EditTextBuffer, ULONG Length);
UCHAR TuiTextToColor(PCSTR ColorText); // Converts the text
color into it's equivalent color value
UCHAR TuiTextToFillStyle(PCSTR FillStyleText); // Converts the text
fill into it's equivalent fill value
diff --git a/boot/freeldr/freeldr/linuxboot.c b/boot/freeldr/freeldr/linuxboot.c
index fae1f8da6a2..5375aafe796 100644
--- a/boot/freeldr/freeldr/linuxboot.c
+++ b/boot/freeldr/freeldr/linuxboot.c
@@ -107,7 +107,7 @@ LoadAndBootLinux(
UiDrawBackdrop();
UiDrawStatusText(LinuxBootDescription);
- UiDrawProgressBarCenter(0, 100, LinuxBootDescription);
+ UiDrawProgressBarCenter(LinuxBootDescription);
/* Find all the message box settings and run them */
UiShowMessageBoxesInArgv(Argc, Argv);
@@ -445,7 +445,7 @@ static BOOLEAN LinuxReadKernel(ULONG LinuxKernelFile)
BytesLoaded += LINUX_READ_CHUNK_SIZE;
LoadAddress = (PVOID)((ULONG_PTR)LoadAddress + LINUX_READ_CHUNK_SIZE);
- UiDrawProgressBarCenter(BytesLoaded, LinuxKernelSize + LinuxInitrdSize,
LinuxBootDescription);
+ UiUpdateProgressBar(BytesLoaded * 100 / (LinuxKernelSize + LinuxInitrdSize),
NULL);
}
return TRUE;
@@ -540,7 +540,7 @@ static BOOLEAN LinuxReadInitrd(ULONG LinuxInitrdFile)
BytesLoaded += LINUX_READ_CHUNK_SIZE;
LinuxInitrdLoadAddress = (PVOID)((ULONG_PTR)LinuxInitrdLoadAddress +
LINUX_READ_CHUNK_SIZE);
- UiDrawProgressBarCenter(BytesLoaded + LinuxKernelSize, LinuxInitrdSize +
LinuxKernelSize, LinuxBootDescription);
+ UiUpdateProgressBar((BytesLoaded + LinuxKernelSize) * 100 / (LinuxInitrdSize +
LinuxKernelSize), NULL);
}
return TRUE;
diff --git a/boot/freeldr/freeldr/ntldr/setupldr.c
b/boot/freeldr/freeldr/ntldr/setupldr.c
index 2deaf6ce5ba..f7a330be2fd 100644
--- a/boot/freeldr/freeldr/ntldr/setupldr.c
+++ b/boot/freeldr/freeldr/ntldr/setupldr.c
@@ -493,7 +493,7 @@ LoadReactOSSetup(
/* Let the user know we started loading */
UiDrawBackdrop();
UiDrawStatusText("Setup is loading...");
- UiDrawProgressBarCenter(1, 100, "Loading ReactOS Setup...");
+ UiDrawProgressBarCenter("Loading ReactOS Setup...");
/* Retrieve the system path */
*BootPath = ANSI_NULL;
@@ -743,7 +743,7 @@ LoadReactOSSetup(
SetupBlock->Flags = SETUPLDR_TEXT_MODE;
/* Load the "setupreg.hiv" setup system hive */
- if (!SosEnabled) UiDrawProgressBarCenter(15, 100, "Loading setup system
hive...");
+ UiUpdateProgressBar(15, "Loading setup system hive...");
Success = WinLdrInitSystemHive(LoaderBlock, BootPath, TRUE);
TRACE("Setup SYSTEM hive %s\n", (Success ? "loaded" : "not
loaded"));
/* Bail out if failure */
diff --git a/boot/freeldr/freeldr/ntldr/winldr.c b/boot/freeldr/freeldr/ntldr/winldr.c
index 317d59a35bd..5b06bef6e0f 100644
--- a/boot/freeldr/freeldr/ntldr/winldr.c
+++ b/boot/freeldr/freeldr/ntldr/winldr.c
@@ -66,7 +66,8 @@ NtLdrOutputLoadMsg(
RtlStringCbPrintfA(ProgressString, sizeof(ProgressString),
"Loading %s...",
(Description ? Description : FileName));
- // UiDrawProgressBarCenter(1, 100, ProgressString);
+ // UiSetProgressBarText(ProgressString);
+ // UiIndicateProgress();
UiDrawStatusText(ProgressString);
}
}
@@ -379,12 +380,12 @@ WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock,
// Paths are relative (FIXME: Are they always relative?)
// Load it
+ UiIndicateProgress();
Success = WinLdrLoadDeviceDriver(&LoaderBlock->LoadOrderListHead,
BootPath,
&BootDriver->FilePath,
0,
&BootDriver->LdrEntry);
-
if (Success)
{
// Convert the RegistryPath and DTE addresses to VA since we are not going to
use it anymore
@@ -503,7 +504,7 @@ LoadModule(
PVOID BaseAddress;
RtlStringCbPrintfA(ProgressString, sizeof(ProgressString), "Loading %s...",
File);
- if (!SosEnabled) UiDrawProgressBarCenter(Percentage, 100, ProgressString);
+ UiUpdateProgressBar(Percentage, ProgressString);
RtlStringCbCopyA(FullFileName, sizeof(FullFileName), Path);
RtlStringCbCatA(FullFileName, sizeof(FullFileName), File);
@@ -609,7 +610,7 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
/* Load the HAL */
HalBase = LoadModule(LoaderBlock, DirPath, HalFileName,
- "hal.dll", LoaderHalCode, &HalDTE, 45);
+ "hal.dll", LoaderHalCode, &HalDTE, 35);
if (!HalBase)
{
ERR("LoadModule('%s') failed\n", HalFileName);
@@ -684,7 +685,7 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
/* Load the KD DLL. Override its base DLL name to the default
"KDCOM.DLL". */
KdDllBase = LoadModule(LoaderBlock, DirPath, KdDllName,
- "kdcom.dll", LoaderSystemCode, &KdDllDTE,
60);
+ "kdcom.dll", LoaderSystemCode, &KdDllDTE,
40);
if (!KdDllBase)
{
/* If we failed to load a custom KD DLL, fall back to the standard one */
@@ -697,7 +698,7 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
RtlStringCbCopyA(KdDllName, sizeof(KdDllName), "kdcom.dll");
KdDllBase = LoadModule(LoaderBlock, DirPath, KdDllName,
- "kdcom.dll", LoaderSystemCode,
&KdDllDTE, 60);
+ "kdcom.dll", LoaderSystemCode,
&KdDllDTE, 40);
}
if (!KdDllBase)
@@ -939,7 +940,7 @@ LoadAndBootWindows(
/* Let the user know we started loading */
UiDrawBackdrop();
UiDrawStatusText("Loading...");
- UiDrawProgressBarCenter(1, 100, "Loading NT...");
+ UiDrawProgressBarCenter("Loading NT...");
/* Retrieve the system path */
*BootPath = ANSI_NULL;
@@ -1043,7 +1044,7 @@ LoadAndBootWindows(
AllocateAndInitLPB(OperatingSystemVersion, &LoaderBlock);
/* Load the system hive */
- if (!SosEnabled) UiDrawProgressBarCenter(15, 100, "Loading system
hive...");
+ UiUpdateProgressBar(15, "Loading system hive...");
Success = WinLdrInitSystemHive(LoaderBlock, BootPath, FALSE);
TRACE("SYSTEM hive %s\n", (Success ? "loaded" : "not
loaded"));
/* Bail out if failure */
@@ -1101,7 +1102,7 @@ LoadAndBootWindowsCommon(
SystemRoot = strstr(BootPath, "\\");
/* Detect hardware */
- if (!SosEnabled) UiDrawProgressBarCenter(20, 100, "Detecting
hardware...");
+ UiUpdateProgressBar(20, "Detecting hardware...");
LoaderBlock->ConfigurationRoot = MachHwDetect();
/* Initialize the PE loader import-DLL callback, so that we can obtain
@@ -1130,11 +1131,15 @@ LoadAndBootWindowsCommon(
**** WE HAVE NOW REACHED THE POINT OF NO RETURN !!
****/
+ UiSetProgressBarSubset(40, 90); // NTOS goes from 25 to 75%
+
/* Load boot drivers */
- if (!SosEnabled) UiDrawProgressBarCenter(100, 100, "Loading boot
drivers...");
+ UiSetProgressBarText("Loading boot drivers...");
Success = WinLdrLoadBootDrivers(LoaderBlock, BootPath);
TRACE("Boot drivers loading %s\n", Success ? "successful" :
"failed");
+ UiSetProgressBarSubset(0, 100);
+
/* Reset the PE loader import-DLL callback */
PeLdrImportDllLoadCallback = NULL;
@@ -1145,6 +1150,8 @@ LoadAndBootWindowsCommon(
BootPath,
OperatingSystemVersion);
+ UiUpdateProgressBar(100, NULL);
+
/* Save entry-point pointer and Loader block VAs */
KiSystemStartup = (KERNEL_ENTRY_POINT)KernelDTE->EntryPoint;
LoaderBlockVA = PaToVa(LoaderBlock);
diff --git a/boot/freeldr/freeldr/ntldr/winldr.h b/boot/freeldr/freeldr/ntldr/winldr.h
index 03cc68f88c7..38598e29f85 100644
--- a/boot/freeldr/freeldr/ntldr/winldr.h
+++ b/boot/freeldr/freeldr/ntldr/winldr.h
@@ -88,6 +88,8 @@ UiResetForSOS(VOID)
UiVtbl = MiniTuiVtbl;
UiVtbl.Initialize();
#endif
+ /* Disable the progress bar */
+ UiProgressBar.Show = FALSE;
}
VOID
diff --git a/boot/freeldr/freeldr/ui/directui.c b/boot/freeldr/freeldr/ui/directui.c
index dbd2ed41902..68d67777190 100644
--- a/boot/freeldr/freeldr/ui/directui.c
+++ b/boot/freeldr/freeldr/ui/directui.c
@@ -111,28 +111,6 @@ UiMessageBoxCritical(IN PCSTR MessageText)
TuiPrintf(MessageText);
}
-VOID
-UiDrawProgressBarCenter(
- _In_ ULONG Position,
- _In_ ULONG Range,
- _Inout_z_ PSTR ProgressText)
-{
- MiniTuiDrawProgressBarCenter(Position, Range, ProgressText);
-}
-
-VOID
-UiDrawProgressBar(
- _In_ ULONG Left,
- _In_ ULONG Top,
- _In_ ULONG Right,
- _In_ ULONG Bottom,
- _In_ ULONG Position,
- _In_ ULONG Range,
- _Inout_z_ PSTR ProgressText)
-{
- MiniTuiDrawProgressBar(Left, Top, Right, Bottom, Position, Range, ProgressText);
-}
-
VOID
UiShowMessageBoxesInSection(
IN ULONG_PTR SectionId)
@@ -148,15 +126,6 @@ UiShowMessageBoxesInArgv(
return;
}
-VOID
-UiTruncateStringEllipsis(IN PCHAR StringText,
- IN ULONG MaxChars)
-{
- /* If it's too large, just add some ellipsis past the maximum */
- if (strlen(StringText) > MaxChars)
- strcpy(&StringText[MaxChars - 3], "...");
-}
-
VOID
UiDrawMenu(
_In_ PUI_MENU_INFO MenuInfo)
diff --git a/boot/freeldr/freeldr/ui/minitui.c b/boot/freeldr/freeldr/ui/minitui.c
index 373605a8b1b..ae2ae004fa3 100644
--- a/boot/freeldr/freeldr/ui/minitui.c
+++ b/boot/freeldr/freeldr/ui/minitui.c
@@ -31,11 +31,85 @@ VOID MiniTuiDrawStatusText(PCSTR StatusText)
#endif // _M_ARM
+/*static*/ VOID
+MiniTuiSetProgressBarText(
+ _In_ PCSTR ProgressText)
+{
+ ULONG ProgressBarWidth;
+ CHAR ProgressString[256];
+
+ /* Make sure the progress bar is enabled */
+ ASSERT(UiProgressBar.Show);
+
+ /* Calculate the width of the bar proper */
+ ProgressBarWidth = UiProgressBar.Right - UiProgressBar.Left + 1;
+
+ /* First make sure the progress bar text fits */
+ RtlStringCbCopyA(ProgressString, sizeof(ProgressString), ProgressText);
+ TuiTruncateStringEllipsis(ProgressString, ProgressBarWidth);
+
+ /* Clear the text area */
+ TuiFillArea(UiProgressBar.Left, UiProgressBar.Top,
+ UiProgressBar.Right,
+#ifdef NTLDR_PROGRESSBAR
+ UiProgressBar.Bottom - 1,
+#else // BTMGR_PROGRESSBAR
+ UiProgressBar.Bottom - 2, // One empty line between text and bar.
+#endif
+ ' ', ATTR(UiTextColor, UiMenuBgColor));
+
+ /* Draw the "Loading..." text */
+ TuiDrawCenteredText(UiProgressBar.Left, UiProgressBar.Top,
+ UiProgressBar.Right,
+#ifdef NTLDR_PROGRESSBAR
+ UiProgressBar.Bottom - 1,
+#else // BTMGR_PROGRESSBAR
+ UiProgressBar.Bottom - 2, // One empty line between text and
bar.
+#endif
+ ProgressString, ATTR(UiTextColor, UiMenuBgColor));
+}
+
+/*static*/ VOID
+MiniTuiTickProgressBar(
+ _In_ ULONG SubPercentTimes100)
+{
+ ULONG ProgressBarWidth;
+ ULONG FillCount;
+
+ /* Make sure the progress bar is enabled */
+ ASSERT(UiProgressBar.Show);
+
+ ASSERT(SubPercentTimes100 <= (100 * 100));
+
+ /* Calculate the width of the bar proper */
+ ProgressBarWidth = UiProgressBar.Right - UiProgressBar.Left + 1;
+
+ /* Compute fill count */
+ // FillCount = (ProgressBarWidth * Position) / Range;
+ FillCount = ProgressBarWidth * SubPercentTimes100 / (100 * 100);
+
+ /* Fill the progress bar */
+ /* Draw the percent complete -- Use the fill character */
+ if (FillCount > 0)
+ {
+ TuiFillArea(UiProgressBar.Left, UiProgressBar.Bottom,
+ UiProgressBar.Left + FillCount - 1, UiProgressBar.Bottom,
+ '\xDB', ATTR(UiTextColor, UiMenuBgColor));
+ }
+ /* Fill the remaining with blanks */
+ TuiFillArea(UiProgressBar.Left + FillCount, UiProgressBar.Bottom,
+ UiProgressBar.Right, UiProgressBar.Bottom,
+ ' ', ATTR(UiTextColor, UiMenuBgColor));
+
+#ifndef _M_ARM
+ TuiUpdateDateTime();
+ VideoCopyOffScreenBufferToVRAM();
+#endif
+}
+
VOID
MiniTuiDrawProgressBarCenter(
- _In_ ULONG Position,
- _In_ ULONG Range,
- _Inout_z_ PSTR ProgressText)
+ _In_ PCSTR ProgressText)
{
ULONG Left, Top, Right, Bottom, Width, Height;
@@ -55,7 +129,7 @@ MiniTuiDrawProgressBarCenter(
Bottom = Top + Height - 1;
/* Draw the progress bar */
- MiniTuiDrawProgressBar(Left, Top, Right, Bottom, Position, Range, ProgressText);
+ MiniTuiDrawProgressBar(Left, Top, Right, Bottom, ProgressText);
}
VOID
@@ -64,54 +138,9 @@ MiniTuiDrawProgressBar(
_In_ ULONG Top,
_In_ ULONG Right,
_In_ ULONG Bottom,
- _In_ ULONG Position,
- _In_ ULONG Range,
- _Inout_z_ PSTR ProgressText)
+ _In_ PCSTR ProgressText)
{
- ULONG ProgressBarWidth, i;
-
- /* Calculate the width of the bar proper */
- ProgressBarWidth = Right - Left + 1;
-
- /* Clip the position */
- if (Position > Range)
- Position = Range;
-
- /* First make sure the progress bar text fits */
- UiTruncateStringEllipsis(ProgressText, ProgressBarWidth);
-
- /* Clear the text area */
- TuiFillArea(Left, Top, Right,
-#ifdef NTLDR_PROGRESSBAR
- Bottom - 1,
-#else // BTMGR_PROGRESSBAR
- Bottom - 2, // One empty line between text and bar.
-#endif
- ' ', ATTR(UiTextColor, UiMenuBgColor));
-
- /* Draw the "Loading..." text */
- TuiDrawCenteredText(Left, Top, Right,
-#ifdef NTLDR_PROGRESSBAR
- Bottom - 1,
-#else // BTMGR_PROGRESSBAR
- Bottom - 2, // One empty line between text and bar.
-#endif
- ProgressText, ATTR(UiTextColor, UiMenuBgColor));
-
- /* Draw the percent complete -- Use the fill character */
- for (i = 0; i < (Position * ProgressBarWidth) / Range; i++)
- {
- TuiDrawText(Left + i, Bottom,
- "\xDB", ATTR(UiTextColor, UiMenuBgColor));
- }
- /* Fill the remaining with blanks */
- TuiFillArea(Left + i, Bottom, Right, Bottom,
- ' ', ATTR(UiTextColor, UiMenuBgColor));
-
-#ifndef _M_ARM
- TuiUpdateDateTime();
- VideoCopyOffScreenBufferToVRAM();
-#endif
+ UiInitProgressBar(Left, Top, Right, Bottom, ProgressText);
}
VOID
@@ -192,6 +221,8 @@ const UIVTBL MiniTuiVtbl =
TuiMessageBoxCritical,
MiniTuiDrawProgressBarCenter,
MiniTuiDrawProgressBar,
+ MiniTuiSetProgressBarText,
+ MiniTuiTickProgressBar,
TuiEditBox,
TuiTextToColor,
TuiTextToFillStyle,
diff --git a/boot/freeldr/freeldr/ui/noui.c b/boot/freeldr/freeldr/ui/noui.c
index 5e083dd8be0..5bc33d70e69 100644
--- a/boot/freeldr/freeldr/ui/noui.c
+++ b/boot/freeldr/freeldr/ui/noui.c
@@ -100,11 +100,23 @@ VOID NoUiMessageBoxCritical(PCSTR MessageText)
MachConsGetCh();
}
+/* Loading Progress-Bar Functions ********************************************/
+
+VOID
+NoUiSetProgressBarText(
+ _In_ PCSTR ProgressText)
+{
+}
+
+VOID
+NoUiTickProgressBar(
+ _In_ ULONG SubPercentTimes100)
+{
+}
+
VOID
NoUiDrawProgressBarCenter(
- _In_ ULONG Position,
- _In_ ULONG Range,
- _Inout_z_ PSTR ProgressText)
+ _In_ PCSTR ProgressText)
{
}
@@ -114,12 +126,11 @@ NoUiDrawProgressBar(
_In_ ULONG Top,
_In_ ULONG Right,
_In_ ULONG Bottom,
- _In_ ULONG Position,
- _In_ ULONG Range,
- _Inout_z_ PSTR ProgressText)
+ _In_ PCSTR ProgressText)
{
}
+
BOOLEAN NoUiEditBox(PCSTR MessageText, PCHAR EditTextBuffer, ULONG Length)
{
return FALSE;
diff --git a/boot/freeldr/freeldr/ui/tui.c b/boot/freeldr/freeldr/ui/tui.c
index bcf510ed7c8..3950f93df2d 100644
--- a/boot/freeldr/freeldr/ui/tui.c
+++ b/boot/freeldr/freeldr/ui/tui.c
@@ -53,6 +53,16 @@ TuiPrintf(
return Length;
}
+VOID
+TuiTruncateStringEllipsis(
+ _Inout_z_ PSTR StringText,
+ _In_ ULONG MaxChars)
+{
+ /* If it's too large, just add some ellipsis past the maximum */
+ if (strlen(StringText) > MaxChars)
+ strcpy(&StringText[MaxChars - 3], "...");
+}
+
/*
* DrawText()
* Displays a string on a single screen line.
@@ -690,11 +700,83 @@ VOID TuiMessageBoxCritical(PCSTR MessageText)
}
}
-VOID
+static VOID
+TuiSetProgressBarText(
+ _In_ PCSTR ProgressText)
+{
+ ULONG ProgressBarWidth;
+ CHAR ProgressString[256];
+
+ /* Make sure the progress bar is enabled */
+ ASSERT(UiProgressBar.Show);
+
+ /* Calculate the width of the bar proper */
+ ProgressBarWidth = UiProgressBar.Right - UiProgressBar.Left + 1;
+
+ /* First make sure the progress bar text fits */
+ RtlStringCbCopyA(ProgressString, sizeof(ProgressString), ProgressText);
+ TuiTruncateStringEllipsis(ProgressString, ProgressBarWidth);
+
+ /* Clear the text area */
+ TuiFillArea(UiProgressBar.Left, UiProgressBar.Top,
+ UiProgressBar.Right, UiProgressBar.Bottom - 1,
+ ' ', ATTR(UiTextColor, UiMenuBgColor));
+
+ /* Draw the "Loading..." text */
+ TuiDrawCenteredText(UiProgressBar.Left, UiProgressBar.Top,
+ UiProgressBar.Right, UiProgressBar.Bottom - 1,
+ ProgressString, ATTR(UiTextColor, UiMenuBgColor));
+}
+
+static VOID
+TuiTickProgressBar(
+ _In_ ULONG SubPercentTimes100)
+{
+ ULONG ProgressBarWidth;
+ ULONG FillCount;
+
+ /* Make sure the progress bar is enabled */
+ ASSERT(UiProgressBar.Show);
+
+ ASSERT(SubPercentTimes100 <= (100 * 100));
+
+ /* Calculate the width of the bar proper */
+ ProgressBarWidth = UiProgressBar.Right - UiProgressBar.Left + 1;
+
+ /* Compute fill count */
+ // FillCount = (ProgressBarWidth * Position) / Range;
+ FillCount = ProgressBarWidth * SubPercentTimes100 / (100 * 100);
+
+ /* Fill the progress bar */
+ /* Draw the percent complete -- Use the fill character */
+ if (FillCount > 0)
+ {
+ TuiFillArea(UiProgressBar.Left, UiProgressBar.Bottom,
+ UiProgressBar.Left + FillCount - 1, UiProgressBar.Bottom,
+ '\xDB', ATTR(UiTextColor, UiMenuBgColor));
+ }
+ /* Fill the remaining with shadow blanks */
+ TuiFillArea(UiProgressBar.Left + FillCount, UiProgressBar.Bottom,
+ UiProgressBar.Right, UiProgressBar.Bottom,
+ '\xB2', ATTR(UiTextColor, UiMenuBgColor));
+
+#ifndef _M_ARM
+ TuiUpdateDateTime();
+ VideoCopyOffScreenBufferToVRAM();
+#endif
+}
+
+static VOID
+TuiDrawProgressBar(
+ _In_ ULONG Left,
+ _In_ ULONG Top,
+ _In_ ULONG Right,
+ _In_ ULONG Bottom,
+ _In_ PCSTR ProgressText);
+
+static VOID
TuiDrawProgressBarCenter(
- _In_ ULONG Position,
- _In_ ULONG Range,
- _Inout_z_ PSTR ProgressText)
+ _In_ PCSTR ProgressText)
{
ULONG Left, Top, Right, Bottom, Width, Height;
@@ -713,23 +795,21 @@ TuiDrawProgressBarCenter(
Bottom += 1;
/* Draw the progress bar */
- TuiDrawProgressBar(Left, Top, Right, Bottom, Position, Range, ProgressText);
+ TuiDrawProgressBar(Left, Top, Right, Bottom, ProgressText);
}
-VOID
+static VOID
TuiDrawProgressBar(
_In_ ULONG Left,
_In_ ULONG Top,
_In_ ULONG Right,
_In_ ULONG Bottom,
- _In_ ULONG Position,
- _In_ ULONG Range,
- _Inout_z_ PSTR ProgressText)
+ _In_ PCSTR ProgressText)
{
- ULONG ProgressBarWidth, i;
-
/* Draw the box */
- TuiDrawBox(Left, Top, Right, Bottom, VERT, HORZ, TRUE, TRUE, ATTR(UiMenuFgColor,
UiMenuBgColor));
+ TuiDrawBox(Left, Top, Right, Bottom,
+ VERT, HORZ, TRUE, TRUE,
+ ATTR(UiMenuFgColor, UiMenuBgColor));
/* Exclude the box margins */
Left += 2;
@@ -737,34 +817,7 @@ TuiDrawProgressBar(
Top += 1;
Bottom -= 1;
- /* Calculate the width of the bar proper */
- ProgressBarWidth = Right - Left + 1;
-
- /* Clip the position */
- if (Position > Range)
- Position = Range;
-
- /* First make sure the progress bar text fits */
- UiTruncateStringEllipsis(ProgressText, ProgressBarWidth);
-
- /* Draw the "Loading..." text */
- TuiDrawCenteredText(Left, Top, Right, Bottom - 1,
- ProgressText, ATTR(UiTextColor, UiMenuBgColor));
-
- /* Draw the percent complete -- Use the fill character */
- for (i = 0; i < (Position * ProgressBarWidth) / Range; i++)
- {
- TuiDrawText(Left + i, Bottom,
- "\xDB", ATTR(UiTextColor, UiMenuBgColor));
- }
- /* Fill the remaining with shadow blanks */
- TuiFillArea(Left + i, Bottom, Right, Bottom,
- '\xB2', ATTR(UiTextColor, UiMenuBgColor));
-
-#ifndef _M_ARM
- TuiUpdateDateTime();
- VideoCopyOffScreenBufferToVRAM();
-#endif
+ UiInitProgressBar(Left, Top, Right, Bottom, ProgressText);
}
UCHAR TuiTextToColor(PCSTR ColorText)
@@ -1135,6 +1188,8 @@ const UIVTBL TuiVtbl =
TuiMessageBoxCritical,
TuiDrawProgressBarCenter,
TuiDrawProgressBar,
+ TuiSetProgressBarText,
+ TuiTickProgressBar,
TuiEditBox,
TuiTextToColor,
TuiTextToFillStyle,
diff --git a/boot/freeldr/freeldr/ui/ui.c b/boot/freeldr/freeldr/ui/ui.c
index b2a08f27c9f..7d13d81ef16 100644
--- a/boot/freeldr/freeldr/ui/ui.c
+++ b/boot/freeldr/freeldr/ui/ui.c
@@ -16,13 +16,14 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef _M_ARM
#include <freeldr.h>
#include <debug.h>
DBG_DEFAULT_CHANNEL(UI);
+#ifndef _M_ARM
+
#define TAG_UI_TEXT 'xTiU'
ULONG UiScreenWidth; // Screen Width
@@ -55,6 +56,17 @@ CHAR UiTimeText[260] = "[Time Remaining: ] ";
const CHAR UiMonthNames[12][15] = { "January ", "February ",
"March ", "April ", "May ", "June ", "July
", "August ", "September ", "October ", "November
", "December " };
+#endif // _M_ARM
+
+/*
+ * Loading progress bar, based on the NTOS Inbv one.
+ * Supports progress within sub-ranges, used when loading
+ * with an unknown number of steps.
+ */
+UI_PROGRESS_BAR UiProgressBar = {{0}};
+
+#ifndef _M_ARM
+
UIVTBL UiVtbl =
{
NoUiInitialize,
@@ -72,6 +84,8 @@ UIVTBL UiVtbl =
NoUiMessageBoxCritical,
NoUiDrawProgressBarCenter,
NoUiDrawProgressBar,
+ NoUiSetProgressBarText,
+ NoUiTickProgressBar,
NoUiEditBox,
NoUiTextToColor,
NoUiTextToFillStyle,
@@ -369,13 +383,128 @@ UCHAR UiTextToFillStyle(PCSTR FillStyleText)
return UiVtbl.TextToFillStyle(FillStyleText);
}
+#endif // _M_ARM
+
+VOID
+UiInitProgressBar(
+ _In_ ULONG Left,
+ _In_ ULONG Top,
+ _In_ ULONG Right,
+ _In_ ULONG Bottom,
+ _In_ PCSTR ProgressText)
+{
+ /* Progress bar area */
+ UiProgressBar.Left = Left;
+ UiProgressBar.Top = Top;
+ UiProgressBar.Right = Right;
+ UiProgressBar.Bottom = Bottom;
+ // UiProgressBar.Width = Right - Left + 1;
+
+ /* Set the progress bar ranges */
+ UiSetProgressBarSubset(0, 100);
+ UiProgressBar.Indicator.Count = 0;
+ UiProgressBar.Indicator.Expected = 25;
+ UiProgressBar.Indicator.Percentage = 0;
+
+ /* Enable the progress bar */
+ UiProgressBar.Show = TRUE;
+
+ /* Initial drawing: set the "Loading..." text and the original position */
+#ifndef _M_ARM
+ UiVtbl.SetProgressBarText(ProgressText);
+ UiVtbl.TickProgressBar(0);
+#else
+ MiniTuiSetProgressBarText(ProgressText);
+ MiniTuiTickProgressBar(0);
+#endif
+}
+
+VOID
+UiIndicateProgress(VOID)
+{
+ ULONG Percentage;
+
+ /* Increase progress */
+ UiProgressBar.Indicator.Count++;
+
+ /* Compute the new percentage - Don't go over 100% */
+ Percentage = 100 * UiProgressBar.Indicator.Count /
+ UiProgressBar.Indicator.Expected;
+ Percentage = min(Percentage, 99);
+
+ if (Percentage != UiProgressBar.Indicator.Percentage)
+ {
+ /* Percentage has changed, update the progress bar */
+ UiProgressBar.Indicator.Percentage = Percentage;
+ UiUpdateProgressBar(Percentage, NULL);
+ }
+}
+
+VOID
+UiSetProgressBarSubset(
+ _In_ ULONG Floor,
+ _In_ ULONG Ceiling)
+{
+ /* Sanity checks */
+ ASSERT(Floor < Ceiling);
+ ASSERT(Ceiling <= 100);
+
+ /* Update the progress bar state */
+ UiProgressBar.State.Floor = Floor * 100;
+ // UiProgressBar.State.Ceiling = Ceiling * 100;
+ UiProgressBar.State.Bias = Ceiling - Floor;
+}
+
+VOID
+UiUpdateProgressBar(
+ _In_ ULONG Percentage,
+ _In_opt_ PCSTR ProgressText)
+{
+ ULONG TotalProgress;
+
+ /* Make sure the progress bar is enabled */
+ if (!UiProgressBar.Show)
+ return;
+
+ /* Set the progress text if specified */
+ if (ProgressText)
+ UiSetProgressBarText(ProgressText);
+
+ /* Compute the total progress and tick the progress bar */
+ TotalProgress = UiProgressBar.State.Floor + (Percentage * UiProgressBar.State.Bias);
+ // TotalProgress /= (100 * 100);
+
+#ifndef _M_ARM
+ UiVtbl.TickProgressBar(TotalProgress);
+#else
+ MiniTuiTickProgressBar(TotalProgress);
+#endif
+}
+
+VOID
+UiSetProgressBarText(
+ _In_ PCSTR ProgressText)
+{
+ /* Make sure the progress bar is enabled */
+ if (!UiProgressBar.Show)
+ return;
+
+#ifndef _M_ARM
+ UiVtbl.SetProgressBarText(ProgressText);
+#else
+ MiniTuiSetProgressBarText(ProgressText);
+#endif
+}
+
VOID
UiDrawProgressBarCenter(
- _In_ ULONG Position,
- _In_ ULONG Range,
- _Inout_z_ PSTR ProgressText)
+ _In_ PCSTR ProgressText)
{
- UiVtbl.DrawProgressBarCenter(Position, Range, ProgressText);
+#ifndef _M_ARM
+ UiVtbl.DrawProgressBarCenter(ProgressText);
+#else
+ MiniTuiDrawProgressBarCenter(ProgressText);
+#endif
}
VOID
@@ -384,11 +513,34 @@ UiDrawProgressBar(
_In_ ULONG Top,
_In_ ULONG Right,
_In_ ULONG Bottom,
- _In_ ULONG Position,
- _In_ ULONG Range,
- _Inout_z_ PSTR ProgressText)
+ _In_ PCSTR ProgressText)
{
- UiVtbl.DrawProgressBar(Left, Top, Right, Bottom, Position, Range, ProgressText);
+#ifndef _M_ARM
+ UiVtbl.DrawProgressBar(Left, Top, Right, Bottom, ProgressText);
+#else
+ MiniTuiDrawProgressBar(Left, Top, Right, Bottom, ProgressText);
+#endif
+}
+
+#ifndef _M_ARM
+
+static VOID
+UiEscapeString(PCHAR String)
+{
+ ULONG Idx;
+
+ for (Idx=0; Idx<strlen(String); Idx++)
+ {
+ // Escape the new line characters
+ if (String[Idx] == '\\' && String[Idx+1] == 'n')
+ {
+ // Escape the character
+ String[Idx] = '\n';
+
+ // Move the rest of the string up
+ strcpy(&String[Idx+1], &String[Idx+2]);
+ }
+ }
}
VOID
@@ -472,31 +624,6 @@ UiShowMessageBoxesInArgv(
}
}
-VOID UiEscapeString(PCHAR String)
-{
- ULONG Idx;
-
- for (Idx=0; Idx<strlen(String); Idx++)
- {
- // Escape the new line characters
- if (String[Idx] == '\\' && String[Idx+1] == 'n')
- {
- // Escape the character
- String[Idx] = '\n';
-
- // Move the rest of the string up
- strcpy(&String[Idx+1], &String[Idx+2]);
- }
- }
-}
-
-VOID UiTruncateStringEllipsis(PCHAR StringText, ULONG MaxChars)
-{
- /* If it's too large, just add some ellipsis past the maximum */
- if (strlen(StringText) > MaxChars)
- strcpy(&StringText[MaxChars - 3], "...");
-}
-
BOOLEAN
UiDisplayMenu(
IN PCSTR MenuHeader,