/*
- * FreeLoader
- *
- * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
- * Copyright (C) 2006 Aleksey Bragin <aleksey@reactos.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * PROJECT: FreeLoader
+ * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Windows-compatible NT OS Loader.
+ * COPYRIGHT: Copyright 2006-2019 Aleksey Bragin <aleksey@reactos.org>
*/
#include <freeldr.h>
+#include <ndk/ldrtypes.h>
#include "winldr.h"
#include "registry.h"
-#include <ndk/ldrtypes.h>
-
#include <debug.h>
DBG_DEFAULT_CHANNEL(WINDOWS);
// Init "phase 1"
VOID
WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
- LPCSTR Options,
- LPCSTR SystemRoot,
- LPCSTR BootPath,
+ PCSTR Options,
+ PCSTR SystemRoot,
+ PCSTR BootPath,
USHORT VersionToBoot)
{
/* Examples of correct options and paths */
//CHAR SystemRoot[] = "\\WINNT\\";
//CHAR ArcBoot[] = "multi(0)disk(0)rdisk(0)partition(1)";
- LPSTR LoadOptions, NewLoadOptions;
+ PSTR LoadOptions, NewLoadOptions;
CHAR HalPath[] = "\\";
- CHAR ArcBoot[256];
- CHAR MiscFiles[256];
+ CHAR ArcBoot[MAX_PATH+1];
+ CHAR MiscFiles[MAX_PATH+1];
ULONG i;
ULONG_PTR PathSeparator;
PLOADER_PARAMETER_EXTENSION Extension;
/* Construct SystemRoot and ArcBoot from SystemPath */
PathSeparator = strstr(BootPath, "\\") - BootPath;
- strncpy(ArcBoot, BootPath, PathSeparator);
- ArcBoot[PathSeparator] = ANSI_NULL;
+ RtlStringCbCopyNA(ArcBoot, sizeof(ArcBoot), BootPath, PathSeparator);
- TRACE("ArcBoot: %s\n", ArcBoot);
- TRACE("SystemRoot: %s\n", SystemRoot);
- TRACE("Options: %s\n", Options);
+ TRACE("ArcBoot: '%s'\n", ArcBoot);
+ TRACE("SystemRoot: '%s'\n", SystemRoot);
+ TRACE("Options: '%s'\n", Options);
- /* Fill Arc BootDevice */
+ /* Fill ARC BootDevice */
LoaderBlock->ArcBootDeviceName = WinLdrSystemBlock->ArcBootDeviceName;
- strncpy(LoaderBlock->ArcBootDeviceName, ArcBoot, MAX_PATH);
+ RtlStringCbCopyA(LoaderBlock->ArcBootDeviceName, sizeof(WinLdrSystemBlock->ArcBootDeviceName), ArcBoot);
LoaderBlock->ArcBootDeviceName = PaToVa(LoaderBlock->ArcBootDeviceName);
- /* Fill Arc HalDevice, it matches ArcBoot path */
+//
+// IMPROVE!!
+// SetupBlock->ArcSetupDeviceName must be the path to the setup **SOURCE**,
+// and not the setup boot path. Indeed they may differ!!
+//
+ /* If we have a setup block, adjust also its ARC path */
+ if (LoaderBlock->SetupLdrBlock)
+ {
+ PSETUP_LOADER_BLOCK SetupBlock = LoaderBlock->SetupLdrBlock;
+
+ /* Matches ArcBoot path */
+ SetupBlock->ArcSetupDeviceName = WinLdrSystemBlock->ArcBootDeviceName;
+ SetupBlock->ArcSetupDeviceName = PaToVa(SetupBlock->ArcSetupDeviceName);
+
+ /* Note: LoaderBlock->SetupLdrBlock is PaToVa'ed at the end of this function */
+ }
+
+ /* Fill ARC HalDevice, it matches ArcBoot path */
LoaderBlock->ArcHalDeviceName = WinLdrSystemBlock->ArcBootDeviceName;
LoaderBlock->ArcHalDeviceName = PaToVa(LoaderBlock->ArcHalDeviceName);
/* Fill SystemRoot */
LoaderBlock->NtBootPathName = WinLdrSystemBlock->NtBootPathName;
- strncpy(LoaderBlock->NtBootPathName, SystemRoot, MAX_PATH);
+ RtlStringCbCopyA(LoaderBlock->NtBootPathName, sizeof(WinLdrSystemBlock->NtBootPathName), SystemRoot);
LoaderBlock->NtBootPathName = PaToVa(LoaderBlock->NtBootPathName);
/* Fill NtHalPathName */
LoaderBlock->NtHalPathName = WinLdrSystemBlock->NtHalPathName;
- strncpy(LoaderBlock->NtHalPathName, HalPath, MAX_PATH);
+ RtlStringCbCopyA(LoaderBlock->NtHalPathName, sizeof(WinLdrSystemBlock->NtHalPathName), HalPath);
LoaderBlock->NtHalPathName = PaToVa(LoaderBlock->NtHalPathName);
- /* Fill LoadOptions and strip the '/' commutator symbol in front of each option */
+ /* Fill LoadOptions and strip the '/' switch symbol in front of each option */
NewLoadOptions = LoadOptions = LoaderBlock->LoadOptions = WinLdrSystemBlock->LoadOptions;
- strncpy(LoaderBlock->LoadOptions, Options, MAX_OPTIONS_LENGTH);
+ RtlStringCbCopyA(LoaderBlock->LoadOptions, sizeof(WinLdrSystemBlock->LoadOptions), Options);
do
{
LoaderBlock->LoadOptions = PaToVa(LoaderBlock->LoadOptions);
- /* Arc devices */
+ /* ARC devices */
LoaderBlock->ArcDiskInformation = &WinLdrSystemBlock->ArcDiskInformation;
InitializeListHead(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead);
}
#endif
/* Load drivers database */
- strcpy(MiscFiles, BootPath);
- strcat(MiscFiles, "AppPatch\\drvmain.sdb");
+ RtlStringCbCopyA(MiscFiles, sizeof(MiscFiles), BootPath);
+ RtlStringCbCatA(MiscFiles, sizeof(MiscFiles), "AppPatch\\drvmain.sdb");
Extension->DrvDBImage = PaToVa(WinLdrLoadModule(MiscFiles,
&Extension->DrvDBSize,
LoaderRegistryData));
static BOOLEAN
WinLdrLoadDeviceDriver(PLIST_ENTRY LoadOrderListHead,
- LPCSTR BootPath,
+ PCSTR BootPath,
PUNICODE_STRING FilePath,
ULONG Flags,
PLDR_DATA_TABLE_ENTRY *DriverDTE)
PVOID DriverBase = NULL;
// Separate the path to file name and directory path
- _snprintf(DriverPath, sizeof(DriverPath), "%wZ", FilePath);
+ RtlStringCbPrintfA(DriverPath, sizeof(DriverPath), "%wZ", FilePath);
DriverNamePos = strrchr(DriverPath, '\\');
if (DriverNamePos != NULL)
{
// Copy the name
- strcpy(DllName, DriverNamePos+1);
+ RtlStringCbCopyA(DllName, sizeof(DllName), DriverNamePos+1);
// Cut out the name from the path
- *(DriverNamePos+1) = 0;
+ *(DriverNamePos+1) = ANSI_NULL;
}
else
{
// There is no directory in the path
- strcpy(DllName, DriverPath);
- DriverPath[0] = ANSI_NULL;
+ RtlStringCbCopyA(DllName, sizeof(DllName), DriverPath);
+ *DriverPath = ANSI_NULL;
}
- TRACE("DriverPath: %s, DllName: %s, LPB\n", DriverPath, DllName);
+ TRACE("DriverPath: '%s', DllName: '%s', LPB\n", DriverPath, DllName);
// Check if driver is already loaded
Success = WinLdrCheckForLoadedDll(LoadOrderListHead, DllName, DriverDTE);
}
// It's not loaded, we have to load it
- _snprintf(FullPath, sizeof(FullPath), "%s%wZ", BootPath, FilePath);
+ RtlStringCbPrintfA(FullPath, sizeof(FullPath), "%s%wZ", BootPath, FilePath);
Success = WinLdrLoadImage(FullPath, LoaderBootDriver, &DriverBase);
if (!Success)
return FALSE;
(*DriverDTE)->Flags |= Flags;
// Look for any dependencies it may have, and load them too
- sprintf(FullPath,"%s%s", BootPath, DriverPath);
+ RtlStringCbPrintfA(FullPath, sizeof(FullPath), "%s%s", BootPath, DriverPath);
Success = WinLdrScanImportDescriptorTable(LoadOrderListHead, FullPath, *DriverDTE);
if (!Success)
{
BOOLEAN
WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock,
- LPCSTR BootPath)
+ PCSTR BootPath)
{
PLIST_ENTRY NextBd;
PBOOT_DRIVER_LIST_ENTRY BootDriver;
PVOID
WinLdrLoadModule(PCSTR ModuleName,
- ULONG *Size,
+ PULONG Size,
TYPE_OF_MEMORY MemoryType)
{
ULONG FileId;
/* Inform user we are loading files */
//UiDrawBackdrop();
- //sprintf(ProgressString, "Loading %s...", FileName);
+ //RtlStringCbPrintfA(ProgressString, sizeof(ProgressString), "Loading %s...", FileName);
//UiDrawProgressBarCenter(1, 100, ProgressString);
TRACE("Loading module %s\n", ModuleName);
if (Status != ESUCCESS)
{
/* In case of errors, we just return, without complaining to the user */
+ WARN("Error while opening '%s', Status: %u\n", ModuleName, Status);
return NULL;
}
ArcClose(FileId);
if (Status != ESUCCESS)
{
+ WARN("Error while reading '%s', Status: %u\n", ModuleName, Status);
return NULL;
}
PVOID BaseAddress = NULL;
UiDrawBackdrop();
- sprintf(ProgressString, "Loading %s...", File);
+ RtlStringCbPrintfA(ProgressString, sizeof(ProgressString), "Loading %s...", File);
UiDrawProgressBarCenter(Percentage, 100, ProgressString);
- strcpy(FullFileName, Path);
- strcat(FullFileName, File);
+ RtlStringCbCopyA(FullFileName, sizeof(FullFileName), Path);
+ RtlStringCbCatA(FullFileName, sizeof(FullFileName), File);
Success = WinLdrLoadImage(FullFileName, MemoryType, &BaseAddress);
if (!Success)
if (!KernelDTE) return FALSE;
/* Initialize SystemRoot\System32 path */
- strcpy(DirPath, BootPath);
- strcat(DirPath, "system32\\");
+ RtlStringCbCopyA(DirPath, sizeof(DirPath), BootPath);
+ RtlStringCbCatA(DirPath, sizeof(DirPath), "system32\\");
//
// TODO: Parse also the separate INI values "Kernel=" and "Hal="
//
/* Default KERNEL and HAL file names */
- strcpy(KernelFileName, "ntoskrnl.exe");
- strcpy(HalFileName , "hal.dll");
+ RtlStringCbCopyA(KernelFileName, sizeof(KernelFileName), "ntoskrnl.exe");
+ RtlStringCbCopyA(HalFileName , sizeof(HalFileName) , "hal.dll");
/* Find any /KERNEL= or /HAL= switch in the boot options */
Options = BootOptions;
/* Skip possible initial whitespace */
Options += strspn(Options, " \t");
- /* Check whether a new commutator starts and it is either KERNEL or HAL */
+ /* Check whether a new option starts and it is either KERNEL or HAL */
if (*Options != '/' || (++Options,
!(_strnicmp(Options, "KERNEL=", 7) == 0 ||
_strnicmp(Options, "HAL=", 4) == 0)) )
break;
}
- /* We have found either KERNEL or HAL commutator */
+ /* We have found either KERNEL or HAL options */
if (_strnicmp(Options, "KERNEL=", 7) == 0)
{
Options += 7; i -= 7;
- strncpy(KernelFileName, Options, i);
- KernelFileName[i] = ANSI_NULL;
+ RtlStringCbCopyNA(KernelFileName, sizeof(KernelFileName), Options, i);
_strupr(KernelFileName);
}
else if (_strnicmp(Options, "HAL=", 4) == 0)
{
Options += 4; i -= 4;
- strncpy(HalFileName, Options, i);
- HalFileName[i] = ANSI_NULL;
+ RtlStringCbCopyNA(HalFileName, sizeof(HalFileName), Options, i);
_strupr(HalFileName);
}
}
/* Skip possible initial whitespace */
Options += strspn(Options, " \t");
- /* Check whether a new commutator starts and it is the DEBUGPORT one */
+ /* Check whether a new option starts and it is the DEBUGPORT one */
if (*Options != '/' || _strnicmp(++Options, "DEBUGPORT=", 10) != 0)
{
/* Search for another whitespace */
}
else
{
- /* We found the DEBUGPORT commutator. Move to the port name. */
+ /* We found the DEBUGPORT option. Move to the port name. */
Options += 10;
break;
}
if (Options)
{
/*
- * We have found the DEBUGPORT commutator. Parse the port name.
+ * We have found the DEBUGPORT option. Parse the port name.
* Format: /DEBUGPORT=COM1 or /DEBUGPORT=FILE:\Device\HarddiskX\PartitionY\debug.log or /DEBUGPORT=FOO
* If we only have /DEBUGPORT= (i.e. without any port name), defaults it to "COM".
*/
- strcpy(KdTransportDllName, "KD");
+ RtlStringCbCopyA(KdTransportDllName, sizeof(KdTransportDllName), "KD");
if (_strnicmp(Options, "COM", 3) == 0 && '0' <= Options[3] && Options[3] <= '9')
{
- strncat(KdTransportDllName, Options, 3);
+ RtlStringCbCatNA(KdTransportDllName, sizeof(KdTransportDllName), Options, 3);
}
else
{
size_t i = strcspn(Options, " \t:"); /* Skip valid separators: whitespace or colon */
if (i == 0)
- strcat(KdTransportDllName, "COM");
+ RtlStringCbCatA(KdTransportDllName, sizeof(KdTransportDllName), "COM");
else
- strncat(KdTransportDllName, Options, i);
+ RtlStringCbCatNA(KdTransportDllName, sizeof(KdTransportDllName), Options, i);
}
- strcat(KdTransportDllName, ".DLL");
+ RtlStringCbCatA(KdTransportDllName, sizeof(KdTransportDllName), ".DLL");
_strupr(KdTransportDllName);
/*
return Success;
}
-VOID
-LoadAndBootWindows(IN OperatingSystemItem* OperatingSystem,
- IN USHORT OperatingSystemVersion)
+ARC_STATUS
+LoadAndBootWindows(
+ IN ULONG Argc,
+ IN PCHAR Argv[],
+ IN PCHAR Envp[])
{
- ULONG_PTR SectionId;
- PCSTR SectionName = OperatingSystem->SystemPartition;
- CHAR SettingsValue[80];
- BOOLEAN HasSection;
- CHAR BootPath[MAX_PATH];
- CHAR FileName[MAX_PATH];
- CHAR BootOptions[256];
+ PCSTR ArgValue;
PCHAR File;
BOOLEAN Success;
+ USHORT OperatingSystemVersion;
PLOADER_PARAMETER_BLOCK LoaderBlock;
+ CHAR BootPath[MAX_PATH];
+ CHAR FileName[MAX_PATH];
+ CHAR BootOptions[256];
- /* Get OS setting value */
- SettingsValue[0] = ANSI_NULL;
- IniOpenSection("Operating Systems", &SectionId);
- IniReadSettingByName(SectionId, SectionName, SettingsValue, sizeof(SettingsValue));
+ ArgValue = GetArgumentValue(Argc, Argv, "BootType");
+ if (!ArgValue)
+ {
+ ERR("No 'BootType' value, aborting!\n");
+ return EINVAL;
+ }
- /* Open the operating system section specified in the .ini file */
- HasSection = IniOpenSection(SectionName, &SectionId);
+ if (_stricmp(ArgValue, "Windows") == 0 ||
+ _stricmp(ArgValue, "Windows2003") == 0)
+ {
+ OperatingSystemVersion = _WIN32_WINNT_WS03;
+ }
+ else if (_stricmp(ArgValue, "WindowsNT40") == 0)
+ {
+ OperatingSystemVersion = _WIN32_WINNT_NT4;
+ }
+ else
+ {
+ ERR("Unknown 'BootType' value '%s', aborting!\n", ArgValue);
+ return EINVAL;
+ }
UiDrawBackdrop();
UiDrawProgressBarCenter(1, 100, "Loading NT...");
- /* Read the system path is set in the .ini file */
- if (!HasSection ||
- !IniReadSettingByName(SectionId, "SystemPath", BootPath, sizeof(BootPath)))
- {
- strcpy(BootPath, SectionName);
- }
+ /* Retrieve the system path */
+ *BootPath = ANSI_NULL;
+ ArgValue = GetArgumentValue(Argc, Argv, "SystemPath");
+ if (ArgValue)
+ RtlStringCbCopyA(BootPath, sizeof(BootPath), ArgValue);
/*
* Check whether BootPath is a full path
if (strrchr(BootPath, ')') == NULL)
{
/* Temporarily save the boot path */
- strcpy(FileName, BootPath);
+ RtlStringCbCopyA(FileName, sizeof(FileName), BootPath);
/* This is not a full path. Use the current (i.e. boot) device. */
MachDiskGetBootPath(BootPath, sizeof(BootPath));
/* Append a path separator if needed */
- if (FileName[0] != '\\' && FileName[0] != '/')
- strcat(BootPath, "\\");
+ if (*FileName != '\\' && *FileName != '/')
+ RtlStringCbCatA(BootPath, sizeof(BootPath), "\\");
/* Append the remaining path */
- strcat(BootPath, FileName);
+ RtlStringCbCatA(BootPath, sizeof(BootPath), FileName);
}
/* Append a backslash if needed */
- if ((BootPath[0] == 0) || BootPath[strlen(BootPath) - 1] != '\\')
- strcat(BootPath, "\\");
+ if (!*BootPath || BootPath[strlen(BootPath) - 1] != '\\')
+ RtlStringCbCatA(BootPath, sizeof(BootPath), "\\");
- /* Read booting options */
- if (!HasSection || !IniReadSettingByName(SectionId, "Options", BootOptions, sizeof(BootOptions)))
- {
- /* Get options after the title */
- PCSTR p = SettingsValue;
- while (*p == ' ' || *p == '"')
- p++;
- while (*p != '\0' && *p != '"')
- p++;
- strcpy(BootOptions, p);
- TRACE("BootOptions: '%s'\n", BootOptions);
- }
+ TRACE("BootPath: '%s'\n", BootPath);
+
+ /* Retrieve the boot options */
+ *BootOptions = ANSI_NULL;
+ ArgValue = GetArgumentValue(Argc, Argv, "Options");
+ if (ArgValue)
+ RtlStringCbCopyA(BootOptions, sizeof(BootOptions), ArgValue);
/* Append boot-time options */
AppendBootTimeOptions(BootOptions);
+ TRACE("BootOptions: '%s'\n", BootOptions);
+
/* Check if a ramdisk file was given */
File = strstr(BootOptions, "/RDPATH=");
if (File)
{
/* Copy the file name and everything else after it */
- strcpy(FileName, File + 8);
+ RtlStringCbCopyA(FileName, sizeof(FileName), File + 8);
/* Null-terminate */
*strstr(FileName, " ") = ANSI_NULL;
if (!RamDiskLoadVirtualFile(FileName))
{
UiMessageBox("Failed to load RAM disk file %s", FileName);
- return;
+ return ENOENT;
}
}
/* Let user know we started loading */
//UiDrawStatusText("Loading...");
- TRACE("BootPath: '%s'\n", BootPath);
-
/* Allocate and minimalist-initialize LPB */
AllocateAndInitLPB(&LoaderBlock);
TRACE("SYSTEM hive %s\n", (Success ? "loaded" : "not loaded"));
/* Bail out if failure */
if (!Success)
- return;
+ return ENOEXEC;
/* Load NLS data, OEM font, and prepare boot drivers list */
Success = WinLdrScanSystemHive(LoaderBlock, BootPath);
TRACE("SYSTEM hive %s\n", (Success ? "scanned" : "not scanned"));
/* Bail out if failure */
if (!Success)
- return;
+ return ENOEXEC;
/* Finish loading */
- LoadAndBootWindowsCommon(OperatingSystemVersion,
- LoaderBlock,
- BootOptions,
- BootPath,
- FALSE);
+ return LoadAndBootWindowsCommon(OperatingSystemVersion,
+ LoaderBlock,
+ BootOptions,
+ BootPath,
+ FALSE);
}
-VOID
+ARC_STATUS
LoadAndBootWindowsCommon(
USHORT OperatingSystemVersion,
PLOADER_PARAMETER_BLOCK LoaderBlock,
- LPCSTR BootOptions,
- LPCSTR BootPath,
+ PCSTR BootOptions,
+ PCSTR BootPath,
BOOLEAN Setup)
{
PLOADER_PARAMETER_BLOCK LoaderBlockVA;
BOOLEAN Success;
PLDR_DATA_TABLE_ENTRY KernelDTE;
KERNEL_ENTRY_POINT KiSystemStartup;
- LPCSTR SystemRoot;
+ PCSTR SystemRoot;
+
TRACE("LoadAndBootWindowsCommon()\n");
#ifdef _M_IX86
if (!Success)
{
UiMessageBox("Error loading NTOS core.");
- return;
+ return ENOEXEC;
}
/* Load boot drivers */
Success = WinLdrLoadBootDrivers(LoaderBlock, BootPath);
TRACE("Boot drivers loading %s\n", Success ? "successful" : "failed");
+ /* Cleanup ini file */
+ IniCleanup();
+
/* Initialize Phase 1 - no drivers loading anymore */
WinLdrInitializePhase1(LoaderBlock,
BootOptions,
LoaderBlockVA = PaToVa(LoaderBlock);
/* "Stop all motors", change videomode */
- MachPrepareForReactOS(Setup);
-
- /* Cleanup ini file */
- IniCleanup();
+ MachPrepareForReactOS();
/* Debugging... */
//DumpMemoryAllocMap();
/* Pass control */
(*KiSystemStartup)(LoaderBlockVA);
+ return ESUCCESS;
}
VOID