https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6681fb8af5eec6ac2897a…
commit 6681fb8af5eec6ac2897a3e4bde973992fa9456c
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Thu May 25 23:52:50 2017 +0000
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Sun Jun 3 22:12:43 2018 +0200
[SETUPLIB] Add a new module "bldrsup.c" (WIP) where I place all the NT boot
loaders (i.e. ntldr, freeldr, and possibly bootmgr in the future) management functions.
So far we only have:
- a function FindNTOSBootLoader() that detects the existence of a given boot loader;
- a function EnumerateNTOSBootEntries() (and corresponding helpers) that enumerate the
different boot entries in the configuration file(s) for a given boot loader, and for each
entry, calls a user-provided callback.
Only supported at the moment: ntldr and freeldr.
Doing that allows me to simplify large portions of the NT-OS detection code so that it
becomes more bootloader-agnostic, and this will help me for simplifying some parts of
usetup/bootsup.c too, later...
svn path=/branches/setup_improvements/; revision=74661
---
base/setup/lib/CMakeLists.txt | 1 +
base/setup/lib/bldrsup.c | 352 ++++++++++++++++++++++++++++
base/setup/lib/bldrsup.h | 59 +++++
base/setup/lib/osdetect.c | 523 ++++++++++++------------------------------
4 files changed, 556 insertions(+), 379 deletions(-)
diff --git a/base/setup/lib/CMakeLists.txt b/base/setup/lib/CMakeLists.txt
index 6d687deb1a..819ecf34bd 100644
--- a/base/setup/lib/CMakeLists.txt
+++ b/base/setup/lib/CMakeLists.txt
@@ -1,6 +1,7 @@
list(APPEND SOURCE
arcname.c
+ bldrsup.c
filesup.c
fsutil.c
genlist.c
diff --git a/base/setup/lib/bldrsup.c b/base/setup/lib/bldrsup.c
new file mode 100644
index 0000000000..493c52237e
--- /dev/null
+++ b/base/setup/lib/bldrsup.c
@@ -0,0 +1,352 @@
+/*
+ * PROJECT: ReactOS Setup Library
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: NT 5.x family (MS Windows <= 2003, and ReactOS)
+ * boot loaders management.
+ * COPYRIGHT: Copyright 2017-2018 Hermes Belusca-Maito
+ */
+
+// TODO: Add support for NT 6.x family! (detection + BCD manipulation).
+
+/* INCLUDES *****************************************************************/
+
+#include "precomp.h"
+
+#include "bldrsup.h"
+#include "filesup.h"
+#include "inicache.h"
+
+#define NDEBUG
+#include <debug.h>
+
+
+/* GLOBALS ******************************************************************/
+
+typedef struct _NTOS_BOOT_LOADER_FILES
+{
+ NTOS_BOOT_LOADER_TYPE Type;
+ PCWSTR LoaderExecutable;
+ PCWSTR LoaderConfigurationFile;
+ // EnumerateInstallations;
+} NTOS_BOOT_LOADER_FILES, *PNTOS_BOOT_LOADER_FILES;
+
+// Question 1: What if config file is optional?
+// Question 2: What if many config files are possible?
+NTOS_BOOT_LOADER_FILES NtosBootLoaders[] =
+{
+ {FreeLdr, L"freeldr.sys", L"freeldr.ini"},
+ {NtLdr , L"ntldr" , L"boot.ini"}, // FIXME: What about
osloader.exe, etc...?
+// {NtLdr , L"setupldr" , L"txtsetup.sif"}, // FIXME
+// {BootMgr, L"bootmgr" , L"BCD"}
+};
+
+
+/* FUNCTIONS ****************************************************************/
+
+//
+// We need, for each type of bootloader (FreeLdr, NtLdr, Bootmgr):
+// 1. A function that detects its presence and its version;
+// 2. A function that opens/closes its corresponding configuration file;
+// 3. A function that adds a new boot entry. Note that for the first two BLDRs
+// this is a .INI file, while in the latter case this is a registry hive...
+//
+
+NTSTATUS
+FindNTOSBootLoader( // By handle
+ IN HANDLE PartitionHandle, // OPTIONAL
+ IN NTOS_BOOT_LOADER_TYPE Type,
+ OUT PULONG Version OPTIONAL)
+// OUT PHANDLE ConfigFileHande OPTIONAL ????
+{
+ // UINT i;
+
+ if (Type >= BldrTypeMax)
+ return STATUS_INVALID_PARAMETER;
+
+ // FIXME: Unused for now, but should be used later!!
+ *Version = 0;
+ // TODO: Check for BLDR version ONLY if Version != NULL
+
+ /* Check whether the loader executable exists */
+ if (!DoesFileExist(PartitionHandle, NtosBootLoaders[Type].LoaderExecutable))
+ {
+ /* The loader does not exist, continue with another one */
+ // DPRINT1("Loader executable '%S' does not exist, continue with
another one...\n", NtosBootLoaders[Type].LoaderExecutable);
+ DPRINT1("Loader executable '%S' does not exist\n",
NtosBootLoaders[Type].LoaderExecutable);
+ return STATUS_NOT_FOUND;
+ }
+
+ /* Check whether the loader configuration file exists */
+ if (!DoesFileExist(PartitionHandle, NtosBootLoaders[Type].LoaderConfigurationFile))
+ {
+ /* The loader does not exist, continue with another one */
+ // FIXME: Consider it might be optional??
+ // DPRINT1("Loader configuration file '%S' does not exist, continue
with another one...\n", NtosBootLoaders[Type].LoaderConfigurationFile);
+ DPRINT1("Loader configuration file '%S' does not exist\n",
NtosBootLoaders[Type].LoaderConfigurationFile);
+ return STATUS_NOT_FOUND;
+ }
+
+#if 0
+ /* Check whether the loader configuration file exists */
+ Status = OpenAndMapFile(PartitionHandle,
NtosBootLoaders[Type].LoaderConfigurationFile,
+ &FileHandle, &SectionHandle, &ViewBase,
&FileSize);
+ if (!NT_SUCCESS(Status))
+ {
+ /* The loader does not exist, continue with another one */
+ // FIXME: Consider it might be optional??
+ DPRINT1("Loader configuration file '%S' does not exist, continue
with another one...\n", NtosBootLoaders[Type].LoaderConfigurationFile);
+ return STATUS_NOT_FOUND;
+ }
+#endif
+
+ return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS
+FreeLdrEnumerateBootEntries(
+ IN PCHAR FileBuffer,
+ IN ULONG FileLength,
+// IN ULONG Flags, // Determine which data to retrieve
+ IN PENUM_BOOT_ENTRIES_ROUTINE EnumBootEntriesRoutine,
+ IN PVOID Parameter OPTIONAL)
+{
+ NTSTATUS Status;
+ PINICACHE IniCache;
+ PINICACHEITERATOR Iterator;
+ PINICACHESECTION IniSection, OsIniSection;
+ PWCHAR SectionName, KeyData;
+/**/NTOS_BOOT_ENTRY xxBootEntry;/**/
+ PNTOS_BOOT_ENTRY BootEntry = &xxBootEntry;
+ UNICODE_STRING InstallName;
+
+ /* Open an *existing* FreeLdr.ini configuration file */
+ Status = IniCacheLoadFromMemory(&IniCache, FileBuffer, FileLength, FALSE);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ /* Get the "Operating Systems" section */
+ IniSection = IniCacheGetSection(IniCache, L"Operating Systems");
+ if (IniSection == NULL)
+ {
+ IniCacheDestroy(IniCache);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /* Enumerate all the valid installations */
+ Iterator = IniCacheFindFirstValue(IniSection, &SectionName, &KeyData);
+ if (!Iterator) goto Quit;
+ do
+ {
+ // FIXME: Poor-man quotes removal (improvement over
bootsup.c:UpdateFreeLoaderIni).
+ if (KeyData[0] == L'"')
+ {
+ /* Quoted name, copy up to the closing quote */
+ PWCHAR Begin = &KeyData[1];
+ PWCHAR End = wcschr(Begin, L'"');
+ if (!End)
+ End = Begin + wcslen(Begin);
+ RtlInitEmptyUnicodeString(&InstallName, Begin, (ULONG_PTR)End -
(ULONG_PTR)Begin);
+ InstallName.Length = InstallName.MaximumLength;
+ }
+ else
+ {
+ /* Non-quoted name, copy everything */
+ RtlInitUnicodeString(&InstallName, KeyData);
+ }
+
+ DPRINT1("Boot entry '%wZ' in OS section '%S'\n",
&InstallName, SectionName);
+
+ /* Search for an existing ReactOS entry */
+ OsIniSection = IniCacheGetSection(IniCache, SectionName);
+ if (!OsIniSection)
+ continue;
+
+ /* Check for supported boot type "Windows2003" */
+ Status = IniCacheGetKey(OsIniSection, L"BootType", &KeyData);
+ if (NT_SUCCESS(Status))
+ {
+ // TODO: What to do with "Windows" ; "WindowsNT40" ;
"ReactOSSetup" ?
+ if ((KeyData == NULL) ||
+ ( (_wcsicmp(KeyData, L"Windows2003") != 0) &&
+ (_wcsicmp(KeyData, L"\"Windows2003\"") != 0) ))
+ {
+ /* This is not a ReactOS entry */
+ continue;
+ }
+ }
+ else
+ {
+ /* Certainly not a ReactOS installation */
+ continue;
+ }
+
+ /* BootType is Windows2003. Now check its SystemPath. */
+ Status = IniCacheGetKey(OsIniSection, L"SystemPath", &KeyData);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1(" A Win2k3 install '%wZ' without an ARC
path?!\n", &InstallName);
+ continue;
+ }
+
+ DPRINT1(" Found a candidate Win2k3 install '%wZ' with ARC path
'%S'\n", &InstallName, KeyData);
+ // KeyData == SystemRoot;
+
+ BootEntry->FriendlyName = &InstallName;
+ BootEntry->OsLoadPath = KeyData;
+ /* Unused stuff (for now...) */
+ BootEntry->BootFilePath = NULL;
+ BootEntry->OsOptions = NULL;
+ BootEntry->OsLoadOptions = NULL;
+
+ Status = EnumBootEntriesRoutine(FreeLdr, BootEntry, Parameter);
+ // TODO: Stop enumeration if !NT_SUCCESS(Status);
+ }
+ while (IniCacheFindNextValue(Iterator, &SectionName, &KeyData));
+
+ IniCacheFindClose(Iterator);
+
+Quit:
+ IniCacheDestroy(IniCache);
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+NtLdrEnumerateBootEntries(
+ IN PCHAR FileBuffer,
+ IN ULONG FileLength,
+// IN ULONG Flags, // Determine which data to retrieve
+ IN PENUM_BOOT_ENTRIES_ROUTINE EnumBootEntriesRoutine,
+ IN PVOID Parameter OPTIONAL)
+{
+ NTSTATUS Status;
+ PINICACHE IniCache;
+ PINICACHEITERATOR Iterator;
+ PINICACHESECTION IniSection;
+ PWCHAR SectionName, KeyData;
+/**/NTOS_BOOT_ENTRY xxBootEntry;/**/
+ PNTOS_BOOT_ENTRY BootEntry = &xxBootEntry;
+ UNICODE_STRING InstallName;
+
+ /* Open an *existing* boot.ini configuration file */
+ Status = IniCacheLoadFromMemory(&IniCache, FileBuffer, FileLength, FALSE);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ /* Get the "Operating Systems" section */
+ IniSection = IniCacheGetSection(IniCache, L"operating systems");
+ if (IniSection == NULL)
+ {
+ IniCacheDestroy(IniCache);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /* Enumerate all the valid installations */
+ Iterator = IniCacheFindFirstValue(IniSection, &SectionName, &KeyData);
+ if (!Iterator) goto Quit;
+ do
+ {
+ // FIXME: Poor-man quotes removal (improvement over
bootsup.c:UpdateFreeLoaderIni).
+ if (KeyData[0] == L'"')
+ {
+ /* Quoted name, copy up to the closing quote */
+ PWCHAR Begin = &KeyData[1];
+ PWCHAR End = wcschr(Begin, L'"');
+ if (!End)
+ End = Begin + wcslen(Begin);
+ RtlInitEmptyUnicodeString(&InstallName, Begin, (ULONG_PTR)End -
(ULONG_PTR)Begin);
+ InstallName.Length = InstallName.MaximumLength;
+ }
+ else
+ {
+ /* Non-quoted name, copy everything */
+ RtlInitUnicodeString(&InstallName, KeyData);
+ }
+
+ DPRINT1("Boot entry '%wZ' in OS section '%S'\n",
&InstallName, SectionName);
+
+ DPRINT1(" Found a Win2k3 install '%wZ' with ARC path
'%S'\n", &InstallName, SectionName);
+ // SectionName == SystemRoot;
+
+ BootEntry->FriendlyName = &InstallName;
+ BootEntry->OsLoadPath = SectionName;
+ /* Unused stuff (for now...) */
+ BootEntry->BootFilePath = NULL;
+ BootEntry->OsOptions = NULL;
+ BootEntry->OsLoadOptions = NULL;
+
+ Status = EnumBootEntriesRoutine(NtLdr, BootEntry, Parameter);
+ // TODO: Stop enumeration if !NT_SUCCESS(Status);
+ }
+ while (IniCacheFindNextValue(Iterator, &SectionName, &KeyData));
+
+ IniCacheFindClose(Iterator);
+
+Quit:
+ IniCacheDestroy(IniCache);
+ return STATUS_SUCCESS;
+}
+
+
+// This function may be viewed as being similar to ntos:NtEnumerateBootEntries().
+NTSTATUS
+EnumerateNTOSBootEntries(
+ IN HANDLE PartitionHandle, // OPTIONAL
+ IN NTOS_BOOT_LOADER_TYPE Type,
+// IN ULONG Flags, // Determine which data to retrieve
+ IN PENUM_BOOT_ENTRIES_ROUTINE EnumBootEntriesRoutine,
+ IN PVOID Parameter OPTIONAL)
+{
+ NTSTATUS Status;
+ HANDLE FileHandle;
+ HANDLE SectionHandle;
+ // SIZE_T ViewSize;
+ ULONG FileSize;
+ PVOID ViewBase;
+
+ /*
+ * NOTE: Currently we open & map the loader configuration file without
+ * further tests. It's OK as long as we only deal with FreeLdr's freeldr.ini
+ * and NTLDR's boot.ini files. But as soon as we'll implement support for
+ * BOOTMGR detection, the "configuration file" will be the BCD registry
+ * hive and then, we'll have instead to mount the hive & open it.
+ */
+
+ /* Check whether the loader configuration file exists */
+ Status = OpenAndMapFile(PartitionHandle,
NtosBootLoaders[Type].LoaderConfigurationFile,
+ &FileHandle, &SectionHandle, &ViewBase,
&FileSize);
+ if (!NT_SUCCESS(Status))
+ {
+ /* The loader does not exist, continue with another one */
+ // FIXME: Consider it might be optional??
+ // DPRINT1("Loader configuration file '%S' does not exist, continue
with another one...\n", NtosBootLoaders[Type].LoaderConfigurationFile);
+ DPRINT1("Loader configuration file '%S' does not exist\n",
NtosBootLoaders[Type].LoaderConfigurationFile);
+ return Status;
+ }
+
+ /* The loader configuration file exists, interpret it to find valid installations */
+ switch (NtosBootLoaders[Type].Type)
+ {
+ case FreeLdr:
+ Status = FreeLdrEnumerateBootEntries(ViewBase, FileSize, /* Flags, */
+ EnumBootEntriesRoutine, Parameter);
+ break;
+
+ case NtLdr:
+ Status = NtLdrEnumerateBootEntries(ViewBase, FileSize, /* Flags, */
+ EnumBootEntriesRoutine, Parameter);
+ break;
+
+ default:
+ DPRINT1("Loader type %d is currently unsupported!\n",
NtosBootLoaders[Type].Type);
+ Status = STATUS_SUCCESS;
+ }
+
+ /* Finally, unmap and close the file */
+ UnMapFile(SectionHandle, ViewBase);
+ NtClose(FileHandle);
+
+ return Status;
+}
+
+/* EOF */
diff --git a/base/setup/lib/bldrsup.h b/base/setup/lib/bldrsup.h
new file mode 100644
index 0000000000..a0965e88e9
--- /dev/null
+++ b/base/setup/lib/bldrsup.h
@@ -0,0 +1,59 @@
+/*
+ * PROJECT: ReactOS Setup Library
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: NT 5.x family (MS Windows <= 2003, and ReactOS)
+ * boot loaders management.
+ * COPYRIGHT: Copyright 2017-2018 Hermes Belusca-Maito
+ */
+
+// TODO: Add support for NT 6.x family! (detection + BCD manipulation).
+
+#pragma once
+
+typedef enum _NTOS_BOOT_LOADER_TYPE
+{
+ FreeLdr, // ReactOS' FreeLoader
+ NtLdr, // Windows <= 2k3 NT "FlexBoot" OS Loader NTLDR
+// BootMgr, // Vista+ BCD-oriented BOOTMGR
+ BldrTypeMax
+} NTOS_BOOT_LOADER_TYPE;
+
+/*
+ * This structure is inspired from the EFI boot entry structures
+ * BOOT_ENTRY, BOOT_OPTIONS and FILE_PATH that are defined in ndk/iotypes.h .
+ */
+typedef struct _NTOS_BOOT_ENTRY
+{
+ // ULONG Version; // We might use the ntldr version here?? Or the
"BootType" as in freeldr?
+ // ULONG Length;
+ // ULONG Id; // Boot entry number (position) in the list
+/** PCWSTR FriendlyName; // Human-readable boot entry description **/
+ PUNICODE_STRING FriendlyName;
+ PCWSTR BootFilePath; // Path to e.g. osloader.exe, or winload.efi
+ PCWSTR OsLoadPath; // The OS SystemRoot path
+ PCWSTR OsOptions;
+ PCWSTR OsLoadOptions;
+} NTOS_BOOT_ENTRY, *PNTOS_BOOT_ENTRY;
+
+
+typedef NTSTATUS
+(NTAPI *PENUM_BOOT_ENTRIES_ROUTINE)(
+ IN NTOS_BOOT_LOADER_TYPE Type,
+ IN PNTOS_BOOT_ENTRY BootEntry,
+ IN PVOID Parameter OPTIONAL);
+
+
+NTSTATUS
+FindNTOSBootLoader( // By handle
+ IN HANDLE PartitionHandle, // OPTIONAL
+ IN NTOS_BOOT_LOADER_TYPE Type,
+ OUT PULONG Version);
+
+NTSTATUS
+EnumerateNTOSBootEntries(
+ IN HANDLE PartitionHandle, // OPTIONAL
+ IN NTOS_BOOT_LOADER_TYPE Type,
+ IN PENUM_BOOT_ENTRIES_ROUTINE EnumBootEntriesRoutine,
+ IN PVOID Parameter OPTIONAL);
+
+/* EOF */
diff --git a/base/setup/lib/osdetect.c b/base/setup/lib/osdetect.c
index a803910fc1..20611bdc02 100644
--- a/base/setup/lib/osdetect.c
+++ b/base/setup/lib/osdetect.c
@@ -12,9 +12,9 @@
#include "ntverrsrc.h"
// #include "arcname.h"
+#include "bldrsup.h"
#include "filesup.h"
#include "genlist.h"
-#include "inicache.h"
#include "partlist.h"
#include "arcname.h"
#include "osdetect.h"
@@ -78,31 +78,6 @@ BOOL IsWindowsOS(VOID)
#endif
-typedef enum _NTOS_BOOT_LOADER_TYPE
-{
- FreeLdr, // ReactOS' FreeLDR
- NtLdr, // Windows <= 2k3 NTLDR
-// BootMgr, // Vista+ BCD-oriented BOOTMGR
-} NTOS_BOOT_LOADER_TYPE;
-
-typedef struct _NTOS_BOOT_LOADER_FILES
-{
- NTOS_BOOT_LOADER_TYPE Type;
- PCWSTR LoaderExecutable;
- PCWSTR LoaderConfigurationFile;
- // EnumerateInstallations;
-} NTOS_BOOT_LOADER_FILES, *PNTOS_BOOT_LOADER_FILES;
-
-// Question 1: What if config file is optional?
-// Question 2: What if many config files are possible?
-NTOS_BOOT_LOADER_FILES NtosBootLoaders[] =
-{
- {FreeLdr, L"freeldr.sys", L"freeldr.ini"},
- {NtLdr , L"ntldr" , L"boot.ini"},
- {NtLdr , L"setupldr" , L"txtsetup.sif"},
-// {BootMgr, L"bootmgr" , ???}
-};
-
static BOOLEAN
IsValidNTOSInstallation_UStr(
@@ -130,339 +105,146 @@ AddNTOSInstallation(
IN PPARTENTRY PartEntry OPTIONAL,
IN PCWSTR InstallationName);
+typedef struct _ENUM_INSTALLS_DATA
+{
+ IN OUT PGENERIC_LIST List;
+ IN PPARTLIST PartList;
+ // IN PPARTENTRY PartEntry;
+} ENUM_INSTALLS_DATA, *PENUM_INSTALLS_DATA;
+
+// PENUM_BOOT_ENTRIES_ROUTINE
static NTSTATUS
-FreeLdrEnumerateInstallations(
- IN OUT PGENERIC_LIST List,
- IN PPARTLIST PartList,
- // IN PPARTENTRY PartEntry,
- IN PCHAR FileBuffer,
- IN ULONG FileLength)
+NTAPI
+EnumerateInstallations(
+ IN NTOS_BOOT_LOADER_TYPE Type,
+ IN PNTOS_BOOT_ENTRY BootEntry,
+ IN PVOID Parameter OPTIONAL)
{
- NTSTATUS Status;
- PINICACHE IniCache;
- PINICACHEITERATOR Iterator;
- PINICACHESECTION IniSection, OsIniSection;
- PWCHAR SectionName, KeyData;
- UNICODE_STRING InstallName;
+ PENUM_INSTALLS_DATA Data = (PENUM_INSTALLS_DATA)Parameter;
PNTOS_INSTALLATION NtOsInstall;
UNICODE_STRING SystemRootPath;
WCHAR SystemRoot[MAX_PATH];
WCHAR InstallNameW[MAX_PATH];
- /* Open an *existing* FreeLdr.ini configuration file */
- Status = IniCacheLoadFromMemory(&IniCache, FileBuffer, FileLength, FALSE);
- if (!NT_SUCCESS(Status))
- return Status;
+ ULONG DiskNumber = 0, PartitionNumber = 0;
+ PCWSTR PathComponent = NULL;
+ PDISKENTRY DiskEntry = NULL;
+ PPARTENTRY PartEntry = NULL;
- /* Get the "Operating Systems" section */
- IniSection = IniCacheGetSection(IniCache, L"Operating Systems");
- if (IniSection == NULL)
- {
- IniCacheDestroy(IniCache);
- return STATUS_UNSUCCESSFUL;
- }
+ /* We have a boot entry */
- /* Enumerate all the valid installations */
- Iterator = IniCacheFindFirstValue(IniSection, &SectionName, &KeyData);
- if (!Iterator) goto Quit;
- do
- {
- // FIXME: Poor-man quotes removal (improvement over
bootsup.c:UpdateFreeLoaderIni).
- if (KeyData[0] == L'"')
- {
- /* Quoted name, copy up to the closing quote */
- PWCHAR Begin = &KeyData[1];
- PWCHAR End = wcschr(Begin, L'"');
- if (!End)
- End = Begin + wcslen(Begin);
- RtlInitEmptyUnicodeString(&InstallName, Begin, (ULONG_PTR)End -
(ULONG_PTR)Begin);
- InstallName.Length = InstallName.MaximumLength;
- }
- else
- {
- /* Non-quoted name, copy everything */
- RtlInitUnicodeString(&InstallName, KeyData);
- }
-
- DPRINT1("Possible installation '%wZ' in OS section
'%S'\n", &InstallName, SectionName);
-
- /* Search for an existing ReactOS entry */
- OsIniSection = IniCacheGetSection(IniCache, SectionName);
- if (!OsIniSection)
- continue;
+ UNICODE_STRING InstallName;
+ // /**/RtlInitUnicodeString(&InstallName, BootEntry->FriendlyName);/**/
+ InstallName = *BootEntry->FriendlyName;
+#if 0
+ if (Type == FreeLdr)
+ {
/* Check for supported boot type "Windows2003" */
- Status = IniCacheGetKey(OsIniSection, L"BootType", &KeyData);
- if (NT_SUCCESS(Status))
- {
- // TODO: What to do with "Windows" ; "WindowsNT40" ;
"ReactOSSetup" ?
- if ((KeyData == NULL) ||
- ( (_wcsicmp(KeyData, L"Windows2003") != 0) &&
- (_wcsicmp(KeyData, L"\"Windows2003\"") != 0) ))
- {
- /* This is not a ReactOS entry */
- continue;
- }
- }
- else
- {
- /* Certainly not a ReactOS installation */
- continue;
- }
-
- /* BootType is Windows2003. Now check SystemPath. */
- Status = IniCacheGetKey(OsIniSection, L"SystemPath", &KeyData);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1(" A Win2k3 install '%wZ' without an ARC
path?!\n", &InstallName);
- continue;
- }
- DPRINT1(" Found a candidate Win2k3 install '%wZ' with ARC path
'%S'\n", &InstallName, KeyData);
-
- // TODO: Normalize the ARC path.
-
- /*
- * Check whether we already have an installation with this ARC path.
- * If this is the case, stop there.
- */
- NtOsInstall = FindExistingNTOSInstall(List, KeyData, NULL);
- if (NtOsInstall)
- {
- DPRINT1(" An NTOS installation with name \"%S\" already
exists in SystemRoot '%wZ'\n",
- NtOsInstall->InstallationName,
&NtOsInstall->SystemArcPath);
- continue;
- }
-
- /*
- * Convert the ARC path into an NT path, from which we will deduce
- * the real disk drive & partition on which the candidate installation
- * resides, as well verifying whether it is indeed an NTOS installation.
- */
- RtlInitEmptyUnicodeString(&SystemRootPath, SystemRoot, sizeof(SystemRoot));
- if (!ArcPathToNtPath(&SystemRootPath, KeyData, PartList))
+ // TODO: What to do with "Windows" ; "WindowsNT40" ;
"ReactOSSetup" ?
+ if ((BootType == NULL) ||
+ ( (_wcsicmp(BootType, L"Windows2003") != 0) &&
+ (_wcsicmp(BootType, L"\"Windows2003\"") != 0) ))
{
- DPRINT1("ArcPathToNtPath(%S) failed, skip the installation.\n",
KeyData);
- continue;
- }
-
- DPRINT1("ArcPathToNtPath() succeeded: '%S' -->
'%wZ'\n", KeyData, &SystemRootPath);
-
- /*
- * Check whether we already have an installation with this NT path.
- * If this is the case, stop there.
- */
- NtOsInstall = FindExistingNTOSInstall(List, NULL /*KeyData*/,
&SystemRootPath);
- if (NtOsInstall)
- {
- DPRINT1(" An NTOS installation with name \"%S\" already
exists in SystemRoot '%wZ'\n",
- NtOsInstall->InstallationName,
&NtOsInstall->SystemNtPath);
- continue;
- }
-
- /* Set SystemRootPath */
- DPRINT1("FreeLdrEnumerateInstallations: SystemRootPath:
'%wZ'\n", &SystemRootPath);
-
- if (IsValidNTOSInstallation_UStr(&SystemRootPath))
- {
- ULONG DiskNumber = 0, PartitionNumber = 0;
- PCWSTR PathComponent = NULL;
- PDISKENTRY DiskEntry = NULL;
- PPARTENTRY PartEntry = NULL;
-
- DPRINT1("Found a valid NTOS installation in SystemRoot ARC path
'%S', NT path '%wZ'\n", KeyData, &SystemRootPath);
-
- /* From the NT path, compute the disk, partition and path components */
- if (NtPathToDiskPartComponents(SystemRootPath.Buffer, &DiskNumber,
&PartitionNumber, &PathComponent))
- {
- DPRINT1("SystemRootPath = '%wZ' points to disk #%d,
partition #%d, path '%S'\n",
- &SystemRootPath, DiskNumber, PartitionNumber,
PathComponent);
-
- /* Retrieve the corresponding disk and partition */
- if (!GetDiskOrPartition(PartList, DiskNumber, PartitionNumber,
&DiskEntry, &PartEntry))
- DPRINT1("GetDiskOrPartition(disk #%d, partition #%d)
failed\n", DiskNumber, PartitionNumber);
- }
- else
- {
- DPRINT1("NtPathToDiskPartComponents(%wZ) failed\n",
&SystemRootPath);
- }
-
- if (PartEntry && PartEntry->DriveLetter)
- {
- /* We have retrieved a partition that is mounted */
- StringCchPrintfW(InstallNameW, ARRAYSIZE(InstallNameW), L"%C:%s
\"%wZ\"",
- PartEntry->DriveLetter, PathComponent,
&InstallName);
- }
- else
- {
- /* We failed somewhere, just show the NT path */
- StringCchPrintfW(InstallNameW, ARRAYSIZE(InstallNameW), L"%wZ
\"%wZ\"",
- &SystemRootPath, &InstallName);
- }
- AddNTOSInstallation(List, KeyData, &SystemRootPath, PathComponent,
- DiskNumber, PartitionNumber, PartEntry,
- InstallNameW);
+ /* This is not a ReactOS entry */
+ /* Certainly not a ReactOS installation */
+ return STATUS_SUCCESS;
}
}
- while (IniCacheFindNextValue(Iterator, &SectionName, &KeyData));
-
- IniCacheFindClose(Iterator);
-
-Quit:
- IniCacheDestroy(IniCache);
- return STATUS_SUCCESS;
-}
-
-static NTSTATUS
-NtLdrEnumerateInstallations(
- IN OUT PGENERIC_LIST List,
- IN PPARTLIST PartList,
- // IN PPARTENTRY PartEntry,
- IN PCHAR FileBuffer,
- IN ULONG FileLength)
-{
- NTSTATUS Status;
- PINICACHE IniCache;
- PINICACHEITERATOR Iterator;
- PINICACHESECTION IniSection;
- PWCHAR SectionName, KeyData;
- UNICODE_STRING InstallName;
+#endif
- PNTOS_INSTALLATION NtOsInstall;
- UNICODE_STRING SystemRootPath;
- WCHAR SystemRoot[MAX_PATH];
- WCHAR InstallNameW[MAX_PATH];
+ DPRINT1(" Found a candidate Win2k3 install '%wZ' with ARC path
'%S'\n",
+ &InstallName, BootEntry->OsLoadPath);
+ // DPRINT1(" Found a Win2k3 install '%wZ' with ARC path
'%S'\n",
+ // &InstallName, BootEntry->OsLoadPath);
- /* Open an *existing* FreeLdr.ini configuration file */
- Status = IniCacheLoadFromMemory(&IniCache, FileBuffer, FileLength, FALSE);
- if (!NT_SUCCESS(Status))
- return Status;
+ // TODO: Normalize the ARC path.
- /* Get the "Operating Systems" section */
- IniSection = IniCacheGetSection(IniCache, L"operating systems");
- if (IniSection == NULL)
+ /*
+ * Check whether we already have an installation with this ARC path.
+ * If this is the case, stop there.
+ */
+ NtOsInstall = FindExistingNTOSInstall(Data->List, BootEntry->OsLoadPath,
NULL);
+ if (NtOsInstall)
{
- IniCacheDestroy(IniCache);
- return STATUS_UNSUCCESSFUL;
+ DPRINT1(" An NTOS installation with name \"%S\" already exists
in SystemRoot '%wZ'\n",
+ NtOsInstall->InstallationName, &NtOsInstall->SystemArcPath);
+ return STATUS_SUCCESS;
}
- /* Enumerate all the valid installations */
- Iterator = IniCacheFindFirstValue(IniSection, &SectionName, &KeyData);
- if (!Iterator) goto Quit;
- do
+ /*
+ * Convert the ARC path into an NT path, from which we will deduce
+ * the real disk drive & partition on which the candidate installation
+ * resides, as well verifying whether it is indeed an NTOS installation.
+ */
+ RtlInitEmptyUnicodeString(&SystemRootPath, SystemRoot, sizeof(SystemRoot));
+ if (!ArcPathToNtPath(&SystemRootPath, BootEntry->OsLoadPath,
Data->PartList))
{
- // FIXME: Poor-man quotes removal (improvement over
bootsup.c:UpdateFreeLoaderIni).
- if (KeyData[0] == L'"')
- {
- /* Quoted name, copy up to the closing quote */
- PWCHAR Begin = &KeyData[1];
- PWCHAR End = wcschr(Begin, L'"');
- if (!End)
- End = Begin + wcslen(Begin);
- RtlInitEmptyUnicodeString(&InstallName, Begin, (ULONG_PTR)End -
(ULONG_PTR)Begin);
- InstallName.Length = InstallName.MaximumLength;
- }
- else
- {
- /* Non-quoted name, copy everything */
- RtlInitUnicodeString(&InstallName, KeyData);
- }
-
- DPRINT1("Possible installation '%wZ' with ARC path
'%S'\n", &InstallName, SectionName);
-
- DPRINT1(" Found a Win2k3 install '%wZ' with ARC path
'%S'\n", &InstallName, SectionName);
+ DPRINT1("ArcPathToNtPath(%S) failed, skip the installation.\n",
BootEntry->OsLoadPath);
+ return STATUS_SUCCESS;
+ }
- // TODO: Normalize the ARC path.
+ DPRINT1("ArcPathToNtPath() succeeded: '%S' -->
'%wZ'\n",
+ BootEntry->OsLoadPath, &SystemRootPath);
- /*
- * Check whether we already have an installation with this ARC path.
- * If this is the case, stop there.
- */
- NtOsInstall = FindExistingNTOSInstall(List, SectionName, NULL);
- if (NtOsInstall)
- {
- DPRINT1(" An NTOS installation with name \"%S\" already
exists in SystemRoot '%wZ'\n",
- NtOsInstall->InstallationName,
&NtOsInstall->SystemArcPath);
- continue;
- }
+ /*
+ * Check whether we already have an installation with this NT path.
+ * If this is the case, stop there.
+ */
+ NtOsInstall = FindExistingNTOSInstall(Data->List, NULL
/*BootEntry->OsLoadPath*/, &SystemRootPath);
+ if (NtOsInstall)
+ {
+ DPRINT1(" An NTOS installation with name \"%S\" already exists
in SystemRoot '%wZ'\n",
+ NtOsInstall->InstallationName, &NtOsInstall->SystemNtPath);
+ return STATUS_SUCCESS;
+ }
- /*
- * Convert the ARC path into an NT path, from which we will deduce
- * the real disk drive & partition on which the candidate installation
- * resides, as well verifying whether it is indeed an NTOS installation.
- */
- RtlInitEmptyUnicodeString(&SystemRootPath, SystemRoot, sizeof(SystemRoot));
- if (!ArcPathToNtPath(&SystemRootPath, SectionName, PartList))
- {
- DPRINT1("ArcPathToNtPath(%S) failed, skip the installation.\n",
SectionName);
- continue;
- }
+ DPRINT1("EnumerateInstallations: SystemRootPath: '%wZ'\n",
&SystemRootPath);
- DPRINT1("ArcPathToNtPath() succeeded: '%S' -->
'%wZ'\n", SectionName, &SystemRootPath);
+ /* Check if this is a valid NTOS installation; stop there if it isn't one */
+ if (!IsValidNTOSInstallation_UStr(&SystemRootPath))
+ return STATUS_SUCCESS;
- /*
- * Check whether we already have an installation with this NT path.
- * If this is the case, stop there.
- */
- NtOsInstall = FindExistingNTOSInstall(List, NULL /*SectionName*/,
&SystemRootPath);
- if (NtOsInstall)
- {
- DPRINT1(" An NTOS installation with name \"%S\" already
exists in SystemRoot '%wZ'\n",
- NtOsInstall->InstallationName,
&NtOsInstall->SystemNtPath);
- continue;
- }
+ DPRINT1("Found a valid NTOS installation in SystemRoot ARC path '%S', NT
path '%wZ'\n",
+ BootEntry->OsLoadPath, &SystemRootPath);
- /* Set SystemRootPath */
- DPRINT1("NtLdrEnumerateInstallations: SystemRootPath: '%wZ'\n",
&SystemRootPath);
+ /* From the NT path, compute the disk, partition and path components */
+ if (NtPathToDiskPartComponents(SystemRootPath.Buffer, &DiskNumber,
&PartitionNumber, &PathComponent))
+ {
+ DPRINT1("SystemRootPath = '%wZ' points to disk #%d, partition #%d,
path '%S'\n",
+ &SystemRootPath, DiskNumber, PartitionNumber, PathComponent);
- if (IsValidNTOSInstallation_UStr(&SystemRootPath))
+ /* Retrieve the corresponding disk and partition */
+ if (!GetDiskOrPartition(Data->PartList, DiskNumber, PartitionNumber,
&DiskEntry, &PartEntry))
{
- ULONG DiskNumber = 0, PartitionNumber = 0;
- PCWSTR PathComponent = NULL;
- PDISKENTRY DiskEntry = NULL;
- PPARTENTRY PartEntry = NULL;
-
- DPRINT1("Found a valid NTOS installation in SystemRoot ARC path
'%S', NT path '%wZ'\n", SectionName, &SystemRootPath);
-
- /* From the NT path, compute the disk, partition and path components */
- if (NtPathToDiskPartComponents(SystemRootPath.Buffer, &DiskNumber,
&PartitionNumber, &PathComponent))
- {
- DPRINT1("SystemRootPath = '%wZ' points to disk #%d,
partition #%d, path '%S'\n",
- &SystemRootPath, DiskNumber, PartitionNumber,
PathComponent);
-
- /* Retrieve the corresponding disk and partition */
- if (!GetDiskOrPartition(PartList, DiskNumber, PartitionNumber,
&DiskEntry, &PartEntry))
- DPRINT1("GetDiskOrPartition(disk #%d, partition #%d)
failed\n", DiskNumber, PartitionNumber);
- }
- else
- {
- DPRINT1("NtPathToDiskPartComponents(%wZ) failed\n",
&SystemRootPath);
- }
-
- if (PartEntry && PartEntry->DriveLetter)
- {
- /* We have retrieved a partition that is mounted */
- StringCchPrintfW(InstallNameW, ARRAYSIZE(InstallNameW), L"%C:%s
\"%wZ\"",
- PartEntry->DriveLetter, PathComponent,
&InstallName);
- }
- else
- {
- /* We failed somewhere, just show the NT path */
- StringCchPrintfW(InstallNameW, ARRAYSIZE(InstallNameW), L"%wZ
\"%wZ\"",
- &SystemRootPath, &InstallName);
- }
- AddNTOSInstallation(List, SectionName, &SystemRootPath, PathComponent,
- DiskNumber, PartitionNumber, PartEntry,
- InstallNameW);
+ DPRINT1("GetDiskOrPartition(disk #%d, partition #%d) failed\n",
+ DiskNumber, PartitionNumber);
}
}
- while (IniCacheFindNextValue(Iterator, &SectionName, &KeyData));
+ else
+ {
+ DPRINT1("NtPathToDiskPartComponents(%wZ) failed\n",
&SystemRootPath);
+ }
- IniCacheFindClose(Iterator);
+ if (PartEntry && PartEntry->DriveLetter)
+ {
+ /* We have retrieved a partition that is mounted */
+ StringCchPrintfW(InstallNameW, ARRAYSIZE(InstallNameW), L"%C:%s
\"%wZ\"",
+ PartEntry->DriveLetter, PathComponent, &InstallName);
+ }
+ else
+ {
+ /* We failed somewhere, just show the NT path */
+ StringCchPrintfW(InstallNameW, ARRAYSIZE(InstallNameW), L"%wZ
\"%wZ\"",
+ &SystemRootPath, &InstallName);
+ }
+ AddNTOSInstallation(Data->List, BootEntry->OsLoadPath,
+ &SystemRootPath, PathComponent,
+ DiskNumber, PartitionNumber, PartEntry,
+ InstallNameW);
-Quit:
- IniCacheDestroy(IniCache);
return STATUS_SUCCESS;
}
@@ -599,28 +381,32 @@ IsValidNTOSInstallationByHandle(
IN HANDLE SystemRootDirectory)
{
BOOLEAN Success = FALSE;
+ PCWSTR PathName;
USHORT i;
UNICODE_STRING VendorName;
WCHAR VendorNameBuffer[MAX_PATH];
/* Check for the existence of \SystemRoot\System32 */
- if (!DoesPathExist(SystemRootDirectory, L"System32\\"))
+ PathName = L"System32\\";
+ if (!DoesPathExist(SystemRootDirectory, PathName))
{
- // DPRINT1("Failed to open directory '%wZ', Status 0x%08lx\n",
&FileName, Status);
+ // DPRINT1("Failed to open directory '%S', Status 0x%08lx\n",
PathName, Status);
return FALSE;
}
/* Check for the existence of \SystemRoot\System32\drivers */
- if (!DoesPathExist(SystemRootDirectory, L"System32\\drivers\\"))
+ PathName = L"System32\\drivers\\";
+ if (!DoesPathExist(SystemRootDirectory, PathName))
{
- // DPRINT1("Failed to open directory '%wZ', Status 0x%08lx\n",
&FileName, Status);
+ // DPRINT1("Failed to open directory '%S', Status 0x%08lx\n",
PathName, Status);
return FALSE;
}
/* Check for the existence of \SystemRoot\System32\config */
- if (!DoesPathExist(SystemRootDirectory, L"System32\\config\\"))
+ PathName = L"System32\\config\\";
+ if (!DoesPathExist(SystemRootDirectory, PathName))
{
- // DPRINT1("Failed to open directory '%wZ', Status 0x%08lx\n",
&FileName, Status);
+ // DPRINT1("Failed to open directory '%S', Status 0x%08lx\n",
PathName, Status);
return FALSE;
}
@@ -629,14 +415,16 @@ IsValidNTOSInstallationByHandle(
* Check for the existence of SYSTEM and SOFTWARE hives in
\SystemRoot\System32\config
* (but we don't check here whether they are actually valid).
*/
- if (!DoesFileExist(SystemRootDirectory, L"System32\\config\\SYSTEM"))
+ PathName = L"System32\\config\\SYSTEM";
+ if (!DoesFileExist(SystemRootDirectory, PathName))
{
- // DPRINT1("Failed to open file '%wZ', Status 0x%08lx\n",
&FileName, Status);
+ // DPRINT1("Failed to open file '%S', Status 0x%08lx\n",
PathName, Status);
return FALSE;
}
- if (!DoesFileExist(SystemRootDirectory, L"System32\\config\\SOFTWARE"))
+ PathName = L"System32\\config\\SOFTWARE";
+ if (!DoesFileExist(SystemRootDirectory, PathName))
{
- // DPRINT1("Failed to open file '%wZ', Status 0x%08lx\n",
&FileName, Status);
+ // DPRINT1("Failed to open file '%S', Status 0x%08lx\n",
PathName, Status);
return FALSE;
}
#endif
@@ -644,9 +432,10 @@ IsValidNTOSInstallationByHandle(
RtlInitEmptyUnicodeString(&VendorName, VendorNameBuffer,
sizeof(VendorNameBuffer));
/* Check for the existence of \SystemRoot\System32\ntoskrnl.exe and retrieves its
vendor name */
- Success = CheckForValidPEAndVendor(SystemRootDirectory,
L"System32\\ntoskrnl.exe", &VendorName);
+ PathName = L"System32\\ntoskrnl.exe";
+ Success = CheckForValidPEAndVendor(SystemRootDirectory, PathName, &VendorName);
if (!Success)
- DPRINT1("Kernel file ntoskrnl.exe is either not a PE file, or does not have
any vendor?\n");
+ DPRINT1("Kernel executable '%S' is either not a PE file, or does not
have any vendor?\n", PathName);
/* The kernel gives the OS its flavour */
if (Success)
@@ -666,9 +455,10 @@ IsValidNTOSInstallationByHandle(
/* OPTIONAL: Check for the existence of \SystemRoot\System32\ntkrnlpa.exe */
/* Check for the existence of \SystemRoot\System32\ntdll.dll and retrieves its vendor
name */
- Success = CheckForValidPEAndVendor(SystemRootDirectory,
L"System32\\ntdll.dll", &VendorName);
+ PathName = L"System32\\ntdll.dll";
+ Success = CheckForValidPEAndVendor(SystemRootDirectory, PathName, &VendorName);
if (!Success)
- DPRINT1("User-mode file ntdll.dll is either not a PE file, or does not have
any vendor?\n");
+ DPRINT1("User-mode DLL '%S' is either not a PE file, or does not
have any vendor?\n", PathName);
if (Success)
{
for (i = 0; i < ARRAYSIZE(KnownVendors); ++i)
@@ -676,7 +466,7 @@ IsValidNTOSInstallationByHandle(
if (!!FindSubStrI(VendorName.Buffer, KnownVendors[i]))
{
/* We have found a correct vendor combination */
- DPRINT1("IsValidNTOSInstallation: The user-mode file ntdll.dll is
from %S\n", KnownVendors[i]);
+ DPRINT1("IsValidNTOSInstallation: The user-mode DLL '%S' is
from %S\n", PathName, KnownVendors[i]);
break;
}
}
@@ -876,15 +666,13 @@ FindNTOSInstallations(
NTSTATUS Status;
ULONG DiskNumber = PartEntry->DiskEntry->DiskNumber;
ULONG PartitionNumber = PartEntry->PartitionNumber;
- HANDLE PartitionHandle, FileHandle;
+ HANDLE PartitionHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
UNICODE_STRING PartitionRootPath;
- UINT i;
- HANDLE SectionHandle;
- // SIZE_T ViewSize;
- ULONG FileSize;
- PVOID ViewBase;
+ NTOS_BOOT_LOADER_TYPE Type;
+ ENUM_INSTALLS_DATA Data;
+ ULONG Version;
WCHAR PathBuffer[MAX_PATH];
/* Set PartitionRootPath */
@@ -912,49 +700,26 @@ FindNTOSInstallations(
return;
}
+ Data.List = List;
+ Data.PartList = PartList;
+
/* Try to see whether we recognize some NT boot loaders */
- for (i = 0; i < ARRAYSIZE(NtosBootLoaders); ++i)
+ for (Type = FreeLdr; Type < BldrTypeMax; ++Type)
{
- /* Check whether the loader executable exists */
- if (!DoesFileExist(PartitionHandle, NtosBootLoaders[i].LoaderExecutable))
- {
- /* The loader does not exist, continue with another one */
- DPRINT1("Loader executable '%S' does not exist, continue with
another one...\n", NtosBootLoaders[i].LoaderExecutable);
- continue;
- }
-
- /* Check whether the loader configuration file exists */
- Status = OpenAndMapFile(PartitionHandle,
NtosBootLoaders[i].LoaderConfigurationFile,
- &FileHandle, &SectionHandle, &ViewBase,
&FileSize);
+ Status = FindNTOSBootLoader(PartitionHandle, Type, &Version);
if (!NT_SUCCESS(Status))
{
/* The loader does not exist, continue with another one */
- // FIXME: Consider it might be optional??
- DPRINT1("Loader configuration file '%S' does not exist, continue
with another one...\n", NtosBootLoaders[i].LoaderConfigurationFile);
+ DPRINT1("Loader type '%d' does not exist, or an error happened
(Status 0x%08lx), continue with another one...\n",
+ Type, Status);
continue;
}
- /* The loader configuration file exists, interpret it to find valid installations
*/
- DPRINT1("Analyse the OS installations inside '%S' in disk #%d,
partition #%d\n",
- NtosBootLoaders[i].LoaderConfigurationFile, DiskNumber,
PartitionNumber);
- switch (NtosBootLoaders[i].Type)
- {
- case FreeLdr:
- Status = FreeLdrEnumerateInstallations(List, PartList, ViewBase, FileSize);
- break;
-
- case NtLdr:
- Status = NtLdrEnumerateInstallations(List, PartList, ViewBase, FileSize);
- break;
-
- default:
- DPRINT1("Loader type %d is currently unsupported!\n",
NtosBootLoaders[i].Type);
- Status = STATUS_SUCCESS;
- }
+ /* The loader exists, try to enumerate its boot entries */
+ DPRINT1("Analyse the OS installations for loader type '%d' in disk
#%d, partition #%d\n",
+ Type, DiskNumber, PartitionNumber);
- /* Finally, unmap and close the file */
- UnMapFile(SectionHandle, ViewBase);
- NtClose(FileHandle);
+ EnumerateNTOSBootEntries(PartitionHandle, Type, EnumerateInstallations,
&Data);
}
/* Close the partition */