[freeldr] Never suppose that buffer in UNICODE_STRING is null terminated. Fixes some...
[reactos.git] / reactos / boot / freeldr / freeldr / windows / winldr.c
index 76622ee..f3f7cd1 100644 (file)
@@ -14,9 +14,9 @@
  *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  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.
  */
 
 #include <freeldr.h>
@@ -37,6 +37,7 @@ extern char reactos_arc_strings[32][256];
 
 extern BOOLEAN UseRealHeap;
 extern ULONG LoaderPagesSpanned;
+extern BOOLEAN AcpiPresent;
 
 BOOLEAN
 WinLdrCheckForLoadedDll(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
@@ -196,6 +197,13 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
        Extension->MinorVersion = VersionToBoot & 0xFF;
        Extension->Profile.Status = 2;
 
+       /* Check if ACPI is present */
+       if (AcpiPresent)
+       {
+               /* See KiRosFrldrLpbToNtLpb for details */
+               Extension->AcpiTable = (PVOID)1;
+       }
+
        /* Load drivers database */
        strcpy(MiscFiles, BootPath);
        strcat(MiscFiles, "AppPatch\\drvmain.sdb");
@@ -224,7 +232,7 @@ WinLdrLoadDeviceDriver(PLOADER_PARAMETER_BLOCK LoaderBlock,
        PVOID DriverBase;
 
        // Separate the path to file name and directory path
-       sprintf(DriverPath, "%S", FilePath->Buffer);
+       snprintf(DriverPath, sizeof(DriverPath), "%wZ", FilePath);
        DriverNamePos = strrchr(DriverPath, '\\');
        if (DriverNamePos != NULL)
        {
@@ -253,7 +261,7 @@ WinLdrLoadDeviceDriver(PLOADER_PARAMETER_BLOCK LoaderBlock,
        }
 
        // It's not loaded, we have to load it
-       sprintf(FullPath,"%s%S", BootPath, FilePath->Buffer);
+       snprintf(FullPath, sizeof(FullPath), "%s%wZ", BootPath, FilePath);
        Status = WinLdrLoadImage(FullPath, LoaderBootDriver, &DriverBase);
        if (!Status)
                return FALSE;
@@ -316,6 +324,7 @@ WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock,
 
                // Convert the RegistryPath and DTE addresses to VA since we are not going to use it anymore
                BootDriver->RegistryPath.Buffer = PaToVa(BootDriver->RegistryPath.Buffer);
+               BootDriver->FilePath.Buffer = PaToVa(BootDriver->FilePath.Buffer);
                BootDriver->LdrEntry = PaToVa(BootDriver->LdrEntry);
 
                NextBd = BootDriver->Link.Flink;
@@ -383,18 +392,41 @@ PVOID WinLdrLoadModule(PCSTR ModuleName, ULONG *Size,
 }
 
 
+USHORT
+WinLdrDetectVersion()
+{
+       LONG rc;
+       FRLDRHKEY hKey;
+
+       rc = RegOpenKey(
+               NULL,
+               L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server",
+               &hKey);
+       if (rc != ERROR_SUCCESS)
+       {
+               // Key doesn't exist; assume NT 4.0
+               return _WIN32_WINNT_NT4;
+       }
+
+       // We may here want to read the value of ProductVersion
+       return _WIN32_WINNT_WS03;
+}
+
+
 VOID
-LoadAndBootWindows(PCSTR OperatingSystemName, USHORT OperatingSystemVersion)
+LoadAndBootWindows(PCSTR OperatingSystemName,
+                   PSTR SettingsValue,
+                   USHORT OperatingSystemVersion)
 {
-       CHAR  MsgBuffer[256];
-       CHAR  FullPath[MAX_PATH], SystemRoot[MAX_PATH], BootPath[MAX_PATH];
+       BOOLEAN HasSection;
+       char  FullPath[MAX_PATH], SystemRoot[MAX_PATH], BootPath[MAX_PATH];
        CHAR  FileName[MAX_PATH];
        CHAR  BootOptions[256];
        PCHAR File;
        PCHAR PathSeparator;
        PVOID NtosBase = NULL, HalBase = NULL, KdComBase = NULL;
        BOOLEAN Status;
-       ULONG SectionId;
+       ULONG_PTR SectionId;
        PLOADER_PARAMETER_BLOCK LoaderBlock, LoaderBlockVA;
        KERNEL_ENTRY_POINT KiSystemStartup;
        PLDR_DATA_TABLE_ENTRY KernelDTE, HalDTE, KdComDTE = NULL;
@@ -403,27 +435,18 @@ LoadAndBootWindows(PCSTR OperatingSystemName, USHORT OperatingSystemVersion)
        ULONG PcrBasePage=0;
        ULONG TssBasePage=0;
 
-       //sprintf(MsgBuffer,"Booting Microsoft(R) Windows(R) OS version '%04x' is not implemented yet", OperatingSystemVersion);
-       //UiMessageBox(MsgBuffer);
-
        // Open the operating system section
        // specified in the .ini file
-       if (!IniOpenSection(OperatingSystemName, &SectionId))
-       {
-               sprintf(MsgBuffer,"Operating System section '%s' not found in freeldr.ini", OperatingSystemName);
-               UiMessageBox(MsgBuffer);
-               return;
-       }
+       HasSection = IniOpenSection(OperatingSystemName, &SectionId);
 
        UiDrawBackdrop();
        UiDrawStatusText("Detecting Hardware...");
-       UiDrawProgressBarCenter(1, 100, "Loading Windows...");
+       UiDrawProgressBarCenter(1, 100, "Loading NT...");
 
-       /* Make sure the system path is set in the .ini file */
-       if (!IniReadSettingByName(SectionId, "SystemPath", FullPath, sizeof(FullPath)))
+       /* Read the system path is set in the .ini file */
+       if (!HasSection || !IniReadSettingByName(SectionId, "SystemPath", FullPath, sizeof(FullPath)))
        {
-               UiMessageBox("System path not specified for selected operating system.");
-               return;
+               strcpy(FullPath, OperatingSystemName);
        }
 
        /* Special case for LiveCD */
@@ -440,10 +463,16 @@ LoadAndBootWindows(PCSTR OperatingSystemName, USHORT OperatingSystemVersion)
        strcat(SystemRoot, "\\");
 
        /* Read booting options */
-       if (!IniReadSettingByName(SectionId, "Options", BootOptions, sizeof(BootOptions)))
+       if (!HasSection || !IniReadSettingByName(SectionId, "Options", BootOptions, sizeof(BootOptions)))
        {
-               /* Nothing read, make the string empty */
-               strcpy(BootOptions, "");
+               /* Get options after the title */
+               const CHAR*p = SettingsValue;
+               while (*p == ' ' || *p == '"')
+                       p++;
+               while (*p != '\0' && *p != '"')
+                       p++;
+               strcpy(BootOptions, p);
+               DPRINTM(DPRINT_WINDOWS,"BootOptions: '%s'\n", BootOptions);
        }
 
        //
@@ -486,6 +515,13 @@ LoadAndBootWindows(PCSTR OperatingSystemName, USHORT OperatingSystemVersion)
        UseRealHeap = TRUE;
        LoaderBlock->ConfigurationRoot = MachHwDetect();
 
+       /* Load Hive */
+       Status = WinLdrInitSystemHive(LoaderBlock, BootPath);
+       DPRINTM(DPRINT_WINDOWS, "SYSTEM hive loaded with status %d\n", Status);
+
+       if (OperatingSystemVersion == 0)
+               OperatingSystemVersion = WinLdrDetectVersion();
+
        /* Load kernel */
        strcpy(FileName, BootPath);
        strcat(FileName, "SYSTEM32\\NTOSKRNL.EXE");
@@ -526,9 +562,9 @@ LoadAndBootWindows(PCSTR OperatingSystemName, USHORT OperatingSystemVersion)
        if (KdComDTE)
                WinLdrScanImportDescriptorTable(LoaderBlock, FileName, KdComDTE);
 
-       /* Load Hive, and then NLS data, OEM font, and prepare boot drivers list */
-       Status = WinLdrLoadAndScanSystemHive(LoaderBlock, BootPath);
-       DPRINTM(DPRINT_WINDOWS, "SYSTEM hive loaded and scanned with status %d\n", Status);
+       /* Load NLS data, OEM font, and prepare boot drivers list */
+       Status = WinLdrScanSystemHive(LoaderBlock, BootPath);
+       DPRINTM(DPRINT_WINDOWS, "SYSTEM hive scanned with status %d\n", Status);
 
        /* Load boot drivers */
        Status = WinLdrLoadBootDrivers(LoaderBlock, BootPath);
@@ -557,7 +593,7 @@ LoadAndBootWindows(PCSTR OperatingSystemName, USHORT OperatingSystemVersion)
        WinLdrTurnOnPaging(LoaderBlock, PcrBasePage, TssBasePage, GdtIdt);
 
        /* Save final value of LoaderPagesSpanned */
-       LoaderBlock->Extension->LoaderPagesSpanned = LoaderPagesSpanned;
+       LoaderBlockVA->Extension->LoaderPagesSpanned = LoaderPagesSpanned;
 
        DPRINTM(DPRINT_WINDOWS, "Hello from paged mode, KiSystemStartup %p, LoaderBlockVA %p!\n",
                KiSystemStartup, LoaderBlockVA);