[FREELDR:NTLDR] Implement support for the SOS option.

CORE-9023, CORE-18033

- Reset the UI to a minimal one in SOS mode.

- In SOS mode, a trace of loaded files is displayed on the screen,
  instead of the usual progress bar.

- Add a callback to the PE loader to notify when imported DLLs are
  loaded for a main image. This allows getting an accurate SOS trace.
This commit is contained in:
Hermès Bélusca-Maïto
2022-01-07 15:39:25 +01:00
parent cfbec70e04
commit f6a13d452c
7 changed files with 123 additions and 27 deletions

View File

@@ -18,6 +18,14 @@
#pragma once
/* Optional user-provided callback used by the PE loader
* when it loads DLLs imported by a main image. */
typedef VOID
(NTAPI *PELDR_IMPORTDLL_LOAD_CALLBACK)(
_In_ PCSTR FileName);
extern PELDR_IMPORTDLL_LOAD_CALLBACK PeLdrImportDllLoadCallback;
BOOLEAN
PeLdrLoadImage(
IN PCHAR FileName,

View File

@@ -23,6 +23,11 @@
#include <debug.h>
DBG_DEFAULT_CHANNEL(PELOADER);
/* GLOBALS *******************************************************************/
PELDR_IMPORTDLL_LOAD_CALLBACK PeLdrImportDllLoadCallback = NULL;
/* PRIVATE FUNCTIONS *********************************************************/
/* DllName - physical, UnicodeString->Buffer - virtual */
@@ -356,6 +361,9 @@ PeLdrpLoadAndScanReferencedDll(
TRACE("Loading referenced DLL: %s\n", FullDllName);
if (PeLdrImportDllLoadCallback)
PeLdrImportDllLoadCallback(FullDllName);
/* Load the image */
Success = PeLdrLoadImage(FullDllName, LoaderBootDriver, &BasePA);
if (!Success)
@@ -722,7 +730,7 @@ PeLdrLoadImage(
LARGE_INTEGER Position;
ULONG i, BytesRead;
TRACE("PeLdrLoadImage(%s, %ld, *)\n", FileName, MemoryType);
TRACE("PeLdrLoadImage(%s, %ld)\n", FileName, MemoryType);
/* Open the image file */
Status = ArcOpen((PSTR)FileName, OpenReadOnly, &FileId);

View File

@@ -254,7 +254,7 @@ static
VOID
MempAllocatePTE(ULONG Entry, PHARDWARE_PTE *PhysicalPT, PHARDWARE_PTE *KernelPT)
{
//Print(L"Creating PDE Entry %X\n", Entry);
//TRACE("Creating PDE Entry %X\n", Entry);
// Identity mapping
*PhysicalPT = (PHARDWARE_PTE)&PhysicalPageTablesBuffer[PhysicalPageTables*MM_PAGE_SIZE];
@@ -297,7 +297,7 @@ MempSetupPaging(IN PFN_NUMBER StartPage,
// We cannot map this as it requires more than 1 PDE
// and in fact it's not possible at all ;)
//
//Print(L"skipping...\n");
//TRACE("skipping...\n");
return TRUE;
}

View File

@@ -490,6 +490,7 @@ LoadReactOSSetup(
return EINVAL;
}
/* Let the user know we started loading */
UiDrawBackdrop();
UiDrawStatusText("Setup is loading...");
UiDrawProgressBarCenter(1, 100, "Loading ReactOS Setup...");
@@ -726,6 +727,11 @@ LoadReactOSSetup(
TRACE("BootOptions: '%s'\n", BootOptions);
/* Handle the SOS option */
SosEnabled = !!NtLdrGetOption(BootOptions, "SOS");
if (SosEnabled)
UiResetForSOS();
/* Allocate and minimally-initialize the Loader Parameter Block */
AllocateAndInitLPB(_WIN32_WINNT_WS03, &LoaderBlock);
@@ -737,7 +743,7 @@ LoadReactOSSetup(
SetupBlock->Flags = SETUPLDR_TEXT_MODE;
/* Load the "setupreg.hiv" setup system hive */
UiDrawProgressBarCenter(15, 100, "Loading setup system hive...");
if (!SosEnabled) UiDrawProgressBarCenter(15, 100, "Loading setup system hive...");
Success = WinLdrInitSystemHive(LoaderBlock, BootPath, TRUE);
TRACE("Setup SYSTEM hive %s\n", (Success ? "loaded" : "not loaded"));
/* Bail out if failure */

View File

@@ -39,6 +39,38 @@ BOOLEAN NoexecuteEnabled = FALSE;
// debug stuff
VOID DumpMemoryAllocMap(VOID);
/* PE loader import-DLL loading callback */
static VOID
NTAPI
NtLdrImportDllLoadCallback(
_In_ PCSTR FileName)
{
NtLdrOutputLoadMsg(FileName, NULL);
}
VOID
NtLdrOutputLoadMsg(
_In_ PCSTR FileName,
_In_opt_ PCSTR Description)
{
if (SosEnabled)
{
printf(" %s\n", FileName);
TRACE("Loading: %s\n", FileName);
}
else
{
/* Inform the user we load a file */
CHAR ProgressString[256];
RtlStringCbPrintfA(ProgressString, sizeof(ProgressString),
"Loading %s...",
(Description ? Description : FileName));
// UiDrawProgressBarCenter(1, 100, ProgressString);
UiDrawStatusText(ProgressString);
}
}
// Init "phase 0"
VOID
AllocateAndInitLPB(
@@ -288,6 +320,8 @@ WinLdrLoadDeviceDriver(PLIST_ENTRY LoadOrderListHead,
// It's not loaded, we have to load it
RtlStringCbPrintfA(FullPath, sizeof(FullPath), "%s%wZ", BootPath, FilePath);
NtLdrOutputLoadMsg(FullPath, NULL);
Success = PeLdrLoadImage(FullPath, LoaderBootDriver, &DriverBase);
if (!Success)
return FALSE;
@@ -379,16 +413,10 @@ WinLdrLoadModule(PCSTR ModuleName,
ARC_STATUS Status;
ULONG BytesRead;
//CHAR ProgressString[256];
/* Inform user we are loading files */
//RtlStringCbPrintfA(ProgressString, sizeof(ProgressString), "Loading %s...", FileName);
//UiDrawProgressBarCenter(1, 100, ProgressString);
TRACE("Loading module %s\n", ModuleName);
*Size = 0;
/* Open the image file */
NtLdrOutputLoadMsg(ModuleName, NULL);
Status = ArcOpen((PSTR)ModuleName, OpenReadOnly, &FileId);
if (Status != ESUCCESS)
{
@@ -467,11 +495,12 @@ LoadModule(
PVOID BaseAddress = NULL;
RtlStringCbPrintfA(ProgressString, sizeof(ProgressString), "Loading %s...", File);
UiDrawProgressBarCenter(Percentage, 100, ProgressString);
if (!SosEnabled) UiDrawProgressBarCenter(Percentage, 100, ProgressString);
RtlStringCbCopyA(FullFileName, sizeof(FullFileName), Path);
RtlStringCbCatA(FullFileName, sizeof(FullFileName), File);
NtLdrOutputLoadMsg(FullFileName, NULL);
Success = PeLdrLoadImage(FullFileName, MemoryType, &BaseAddress);
if (!Success)
{
@@ -620,12 +649,6 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
FIXME("LoadWindowsCore: 3GB - TRUE (not implemented)\n");
VirtualBias = TRUE;
}
if (NtLdrGetOption(BootOptions, "SOS"))
{
/* We found the SOS option. */
FIXME("LoadWindowsCore: SOS - TRUE (not implemented)\n");
SosEnabled = TRUE;
}
if (OperatingSystemVersion > _WIN32_WINNT_NT4)
{
@@ -813,7 +836,9 @@ LoadAndBootWindows(
return EINVAL;
}
/* Let the user know we started loading */
UiDrawBackdrop();
UiDrawStatusText("Loading...");
UiDrawProgressBarCenter(1, 100, "Loading NT...");
/* Retrieve the system path */
@@ -909,14 +934,16 @@ LoadAndBootWindows(
}
}
/* Let user know we started loading */
//UiDrawStatusText("Loading...");
/* Handle the SOS option */
SosEnabled = !!NtLdrGetOption(BootOptions, "SOS");
if (SosEnabled)
UiResetForSOS();
/* Allocate and minimally-initialize the Loader Parameter Block */
AllocateAndInitLPB(OperatingSystemVersion, &LoaderBlock);
/* Load the system hive */
UiDrawProgressBarCenter(15, 100, "Loading system hive...");
if (!SosEnabled) UiDrawProgressBarCenter(15, 100, "Loading system hive...");
Success = WinLdrInitSystemHive(LoaderBlock, BootPath, FALSE);
TRACE("SYSTEM hive %s\n", (Success ? "loaded" : "not loaded"));
/* Bail out if failure */
@@ -974,9 +1001,13 @@ LoadAndBootWindowsCommon(
SystemRoot = strstr(BootPath, "\\");
/* Detect hardware */
UiDrawProgressBarCenter(20, 100, "Detecting hardware...");
if (!SosEnabled) UiDrawProgressBarCenter(20, 100, "Detecting hardware...");
LoaderBlock->ConfigurationRoot = MachHwDetect();
/* Initialize the PE loader import-DLL callback, so that we can obtain
* feedback (for example during SOS) on the PE images that get loaded. */
PeLdrImportDllLoadCallback = NtLdrImportDllLoadCallback;
/* Load the operating system core: the Kernel, the HAL and the Kernel Debugger Transport DLL */
Success = LoadWindowsCore(OperatingSystemVersion,
LoaderBlock,
@@ -985,17 +1016,27 @@ LoadAndBootWindowsCommon(
&KernelDTE);
if (!Success)
{
/* Reset the PE loader import-DLL callback */
PeLdrImportDllLoadCallback = NULL;
UiMessageBox("Error loading NTOS core.");
return ENOEXEC;
}
/* Cleanup INI file */
IniCleanup();
/****
**** WE HAVE NOW REACHED THE POINT OF NO RETURN !!
****/
/* Load boot drivers */
UiDrawProgressBarCenter(100, 100, "Loading boot drivers...");
if (!SosEnabled) UiDrawProgressBarCenter(100, 100, "Loading boot drivers...");
Success = WinLdrLoadBootDrivers(LoaderBlock, BootPath);
TRACE("Boot drivers loading %s\n", Success ? "successful" : "failed");
/* Cleanup ini file */
IniCleanup();
/* Reset the PE loader import-DLL callback */
PeLdrImportDllLoadCallback = NULL;
/* Initialize Phase 1 - no drivers loading anymore */
WinLdrInitializePhase1(LoaderBlock,

View File

@@ -73,6 +73,28 @@ VOID ConvertConfigToVA(PCONFIGURATION_COMPONENT_DATA Start);
// winldr.c
extern BOOLEAN SosEnabled;
FORCEINLINE
VOID
UiResetForSOS(VOID)
{
#ifdef _M_ARM
/* Re-initialize the UI */
UiInitialize(TRUE);
#else
/* Reset the UI and switch to MiniTui */
UiVtbl.UnInitialize();
UiVtbl = MiniTuiVtbl;
UiVtbl.Initialize();
#endif
}
VOID
NtLdrOutputLoadMsg(
_In_ PCSTR FileName,
_In_opt_ PCSTR Description);
PVOID WinLdrLoadModule(PCSTR ModuleName, PULONG Size,
TYPE_OF_MEMORY MemoryType);

View File

@@ -50,6 +50,7 @@ WinLdrLoadSystemHive(
RtlStringCbCopyA(FullHiveName, sizeof(FullHiveName), DirectoryPath);
RtlStringCbCatA(FullHiveName, sizeof(FullHiveName), HiveName);
NtLdrOutputLoadMsg(FullHiveName, NULL);
Status = ArcOpen(FullHiveName, OpenReadOnly, &FileId);
if (Status != ESUCCESS)
{
@@ -330,6 +331,8 @@ WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
/* Open file with ANSI and store its size */
RtlStringCbCopyA(FileName, sizeof(FileName), DirectoryPath);
RtlStringCbCatA(FileName, sizeof(FileName), AnsiFileName);
NtLdrOutputLoadMsg(FileName, NULL);
Status = ArcOpen(FileName, OpenReadOnly, &FileId);
if (Status != ESUCCESS)
{
@@ -351,9 +354,10 @@ WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
}
else
{
//Print(L"Loading %s...\n", Filename);
RtlStringCbCopyA(FileName, sizeof(FileName), DirectoryPath);
RtlStringCbCatA(FileName, sizeof(FileName), OemFileName);
NtLdrOutputLoadMsg(FileName, NULL);
Status = ArcOpen(FileName, OpenReadOnly, &FileId);
if (Status != ESUCCESS)
{
@@ -370,9 +374,10 @@ WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
TRACE("OemFileSize: %d\n", OemFileSize);
/* And finally open the language codepage file and store its length */
//Print(L"Loading %s...\n", Filename);
RtlStringCbCopyA(FileName, sizeof(FileName), DirectoryPath);
RtlStringCbCatA(FileName, sizeof(FileName), LanguageFileName);
NtLdrOutputLoadMsg(FileName, NULL);
Status = ArcOpen(FileName, OpenReadOnly, &FileId);
if (Status != ESUCCESS)
{
@@ -415,6 +420,8 @@ WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
/* Now actually read the data into memory, starting with Ansi file */
RtlStringCbCopyA(FileName, sizeof(FileName), DirectoryPath);
RtlStringCbCatA(FileName, sizeof(FileName), AnsiFileName);
NtLdrOutputLoadMsg(FileName, NULL);
Status = ArcOpen(FileName, OpenReadOnly, &FileId);
if (Status != ESUCCESS)
{
@@ -435,6 +442,8 @@ WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
{
RtlStringCbCopyA(FileName, sizeof(FileName), DirectoryPath);
RtlStringCbCatA(FileName, sizeof(FileName), OemFileName);
NtLdrOutputLoadMsg(FileName, NULL);
Status = ArcOpen(FileName, OpenReadOnly, &FileId);
if (Status != ESUCCESS)
{
@@ -454,6 +463,8 @@ WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
/* Finally the language file */
RtlStringCbCopyA(FileName, sizeof(FileName), DirectoryPath);
RtlStringCbCatA(FileName, sizeof(FileName), LanguageFileName);
NtLdrOutputLoadMsg(FileName, NULL);
Status = ArcOpen(FileName, OpenReadOnly, &FileId);
if (Status != ESUCCESS)
{