[SETUPLIB] Add a new module "bldrsup.c" (WIP) where I place all the NT boot loaders...
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Thu, 25 May 2017 23:52:50 +0000 (23:52 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 3 Jun 2018 20:12:43 +0000 (22:12 +0200)
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
base/setup/lib/bldrsup.c [new file with mode: 0644]
base/setup/lib/bldrsup.h [new file with mode: 0644]
base/setup/lib/osdetect.c

index 6d687de..819ecf3 100644 (file)
@@ -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 (file)
index 0000000..493c522
--- /dev/null
@@ -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 (file)
index 0000000..a0965e8
--- /dev/null
@@ -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 */
index a803910..20611bd 100644 (file)
@@ -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 */