https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c322610f6e1a407f3bf2c2...
commit c322610f6e1a407f3bf2c2a915ab2526b6b9f91d Author: Hermès Bélusca-Maïto hermes.belusca-maito@reactos.org AuthorDate: Mon Feb 14 02:28:53 2022 +0100 Commit: Hermès Bélusca-Maïto hermes.belusca-maito@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,