[FREELDR] Minor fixes.
[reactos.git] / boot / freeldr / freeldr / ntldr / winldr.c
index e563188..b114adb 100644 (file)
@@ -1,30 +1,15 @@
 /*
- *  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);
 
@@ -75,9 +60,9 @@ AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock)
 // 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 */
@@ -86,45 +71,61 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
     //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
     {
@@ -136,7 +137,7 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
 
     LoaderBlock->LoadOptions = PaToVa(LoaderBlock->LoadOptions);
 
-    /* Arc devices */
+    /* ARC devices */
     LoaderBlock->ArcDiskInformation = &WinLdrSystemBlock->ArcDiskInformation;
     InitializeListHead(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead);
 
@@ -205,8 +206,8 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
     }
 #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));
@@ -222,7 +223,7 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
 
 static BOOLEAN
 WinLdrLoadDeviceDriver(PLIST_ENTRY LoadOrderListHead,
-                       LPCSTR BootPath,
+                       PCSTR BootPath,
                        PUNICODE_STRING FilePath,
                        ULONG Flags,
                        PLDR_DATA_TABLE_ENTRY *DriverDTE)
@@ -235,24 +236,24 @@ WinLdrLoadDeviceDriver(PLIST_ENTRY LoadOrderListHead,
     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);
@@ -263,7 +264,7 @@ WinLdrLoadDeviceDriver(PLIST_ENTRY LoadOrderListHead,
     }
 
     // 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;
@@ -280,7 +281,7 @@ WinLdrLoadDeviceDriver(PLIST_ENTRY LoadOrderListHead,
     (*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)
     {
@@ -293,7 +294,7 @@ WinLdrLoadDeviceDriver(PLIST_ENTRY LoadOrderListHead,
 
 BOOLEAN
 WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock,
-                      LPCSTR BootPath)
+                      PCSTR BootPath)
 {
     PLIST_ENTRY NextBd;
     PBOOT_DRIVER_LIST_ENTRY BootDriver;
@@ -345,7 +346,7 @@ WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock,
 
 PVOID
 WinLdrLoadModule(PCSTR ModuleName,
-                 ULONG *Size,
+                 PULONG Size,
                  TYPE_OF_MEMORY MemoryType)
 {
     ULONG FileId;
@@ -359,7 +360,7 @@ WinLdrLoadModule(PCSTR ModuleName,
 
     /* 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);
@@ -370,6 +371,7 @@ WinLdrLoadModule(PCSTR 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;
     }
 
@@ -396,6 +398,7 @@ WinLdrLoadModule(PCSTR ModuleName,
     ArcClose(FileId);
     if (Status != ESUCCESS)
     {
+        WARN("Error while reading '%s', Status: %u\n", ModuleName, Status);
         return NULL;
     }
 
@@ -441,11 +444,11 @@ LoadModule(
     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)
@@ -488,16 +491,16 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
     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;
@@ -506,7 +509,7 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
         /* 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)) )
@@ -524,19 +527,17 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
                 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);
             }
         }
@@ -589,7 +590,7 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
             /* 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 */
@@ -598,7 +599,7 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
             }
             else
             {
-                /* We found the DEBUGPORT commutator. Move to the port name. */
+                /* We found the DEBUGPORT option. Move to the port name. */
                 Options += 10;
                 break;
             }
@@ -607,24 +608,24 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
         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);
 
             /*
@@ -646,38 +647,51 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
     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
@@ -688,45 +702,42 @@ LoadAndBootWindows(IN OperatingSystemItem* OperatingSystem,
     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;
@@ -735,15 +746,13 @@ LoadAndBootWindows(IN OperatingSystemItem* OperatingSystem,
         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);
 
@@ -754,36 +763,37 @@ LoadAndBootWindows(IN OperatingSystemItem* OperatingSystem,
     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
@@ -811,7 +821,7 @@ LoadAndBootWindowsCommon(
     if (!Success)
     {
         UiMessageBox("Error loading NTOS core.");
-        return;
+        return ENOEXEC;
     }
 
     /* Load boot drivers */
@@ -820,6 +830,9 @@ LoadAndBootWindowsCommon(
     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,
@@ -832,10 +845,7 @@ LoadAndBootWindowsCommon(
     LoaderBlockVA = PaToVa(LoaderBlock);
 
     /* "Stop all motors", change videomode */
-    MachPrepareForReactOS(Setup);
-
-    /* Cleanup ini file */
-    IniCleanup();
+    MachPrepareForReactOS();
 
     /* Debugging... */
     //DumpMemoryAllocMap();
@@ -866,6 +876,7 @@ LoadAndBootWindowsCommon(
 
     /* Pass control */
     (*KiSystemStartup)(LoaderBlockVA);
+    return ESUCCESS;
 }
 
 VOID