2017-05-13 16:13:19 +00:00
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
* operating systems detection code.
|
|
|
|
* COPYRIGHT: Copyright 2017-2018 Hermes Belusca-Maito
|
|
|
|
*/
|
|
|
|
|
2017-05-23 11:39:12 +00:00
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
|
|
|
|
#include "ntverrsrc.h"
|
|
|
|
// #include "arcname.h"
|
2017-05-25 23:52:50 +00:00
|
|
|
#include "bldrsup.h"
|
2017-05-23 11:39:12 +00:00
|
|
|
#include "filesup.h"
|
|
|
|
#include "genlist.h"
|
|
|
|
#include "partlist.h"
|
|
|
|
#include "arcname.h"
|
|
|
|
#include "osdetect.h"
|
2017-05-13 16:13:19 +00:00
|
|
|
|
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
|
|
|
|
/* GLOBALS ******************************************************************/
|
|
|
|
|
|
|
|
/* Language-independent Vendor strings */
|
2017-12-29 18:37:28 +00:00
|
|
|
static const PCWSTR KnownVendors[] = { VENDOR_REACTOS, VENDOR_MICROSOFT };
|
2017-05-13 16:13:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
|
2017-05-22 01:19:08 +00:00
|
|
|
static BOOLEAN
|
|
|
|
IsValidNTOSInstallation(
|
2017-12-29 18:37:28 +00:00
|
|
|
IN PUNICODE_STRING SystemRootPath,
|
2018-01-28 22:32:52 +00:00
|
|
|
OUT PUSHORT Machine OPTIONAL,
|
2017-12-29 18:37:28 +00:00
|
|
|
OUT PUNICODE_STRING VendorName OPTIONAL);
|
2017-05-22 01:19:08 +00:00
|
|
|
|
2017-05-22 22:59:11 +00:00
|
|
|
static PNTOS_INSTALLATION
|
|
|
|
FindExistingNTOSInstall(
|
|
|
|
IN PGENERIC_LIST List,
|
|
|
|
IN PCWSTR SystemRootArcPath OPTIONAL,
|
|
|
|
IN PUNICODE_STRING SystemRootNtPath OPTIONAL // or PCWSTR ?
|
|
|
|
);
|
|
|
|
|
2017-05-22 01:19:08 +00:00
|
|
|
static PNTOS_INSTALLATION
|
|
|
|
AddNTOSInstallation(
|
|
|
|
IN PGENERIC_LIST List,
|
2017-12-29 18:37:28 +00:00
|
|
|
IN PCWSTR InstallationName,
|
2018-01-28 22:32:52 +00:00
|
|
|
IN USHORT Machine,
|
2017-12-29 18:37:28 +00:00
|
|
|
IN PCWSTR VendorName,
|
2017-05-22 22:59:11 +00:00
|
|
|
IN PCWSTR SystemRootArcPath,
|
|
|
|
IN PUNICODE_STRING SystemRootNtPath, // or PCWSTR ?
|
|
|
|
IN PCWSTR PathComponent, // Pointer inside SystemRootNtPath buffer
|
2017-05-22 01:19:08 +00:00
|
|
|
IN ULONG DiskNumber,
|
|
|
|
IN ULONG PartitionNumber,
|
2017-12-29 18:37:28 +00:00
|
|
|
IN PPARTENTRY PartEntry OPTIONAL);
|
2017-05-22 01:19:08 +00:00
|
|
|
|
2017-05-25 23:52:50 +00:00
|
|
|
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
|
2017-05-22 01:19:08 +00:00
|
|
|
static NTSTATUS
|
2017-05-25 23:52:50 +00:00
|
|
|
NTAPI
|
|
|
|
EnumerateInstallations(
|
2017-06-08 17:30:23 +00:00
|
|
|
IN BOOT_STORE_TYPE Type,
|
|
|
|
IN PBOOT_STORE_ENTRY BootEntry,
|
2017-05-25 23:52:50 +00:00
|
|
|
IN PVOID Parameter OPTIONAL)
|
2017-05-13 16:13:19 +00:00
|
|
|
{
|
2017-05-25 23:52:50 +00:00
|
|
|
PENUM_INSTALLS_DATA Data = (PENUM_INSTALLS_DATA)Parameter;
|
2017-06-08 02:20:33 +00:00
|
|
|
PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
|
2017-05-22 22:59:11 +00:00
|
|
|
PNTOS_INSTALLATION NtOsInstall;
|
2017-05-13 16:13:19 +00:00
|
|
|
|
2017-05-25 23:52:50 +00:00
|
|
|
ULONG DiskNumber = 0, PartitionNumber = 0;
|
|
|
|
PCWSTR PathComponent = NULL;
|
|
|
|
PDISKENTRY DiskEntry = NULL;
|
|
|
|
PPARTENTRY PartEntry = NULL;
|
2017-05-13 16:13:19 +00:00
|
|
|
|
2017-12-29 18:37:28 +00:00
|
|
|
UNICODE_STRING SystemRootPath;
|
|
|
|
WCHAR SystemRoot[MAX_PATH];
|
|
|
|
|
2018-01-28 22:32:52 +00:00
|
|
|
USHORT Machine;
|
2017-12-29 18:37:28 +00:00
|
|
|
UNICODE_STRING VendorName;
|
|
|
|
WCHAR VendorNameBuffer[MAX_PATH];
|
|
|
|
|
|
|
|
|
2017-05-25 23:52:50 +00:00
|
|
|
/* We have a boot entry */
|
2017-05-13 16:13:19 +00:00
|
|
|
|
[SETUPLIB] Introduce a lot of (Work in progress) functions to manipulate boot entries from different boot "stores".
This concerns so far, only freeldr.ini and to an extent, boot.ini, but planning in the future to add support for registry-oriented BCD
as well as possibly direct (u)EFI entries, using the corresponding NT functions.
This code is so far only used in osdetect.c, but will be soon used by usetup's bootsup.c (note that some helper functions: CreateCommonFreeLdrSections()
and (Un)protectBootIni() are already taken from it and used in bldrsup.c).
- In EnumerateNTOSBootEntries(), continue enumerating the boot entries until the user callback returns an status code that is not successful.
- Remove some old code from osdetect.c; use directly BootEntry->FriendlyName when building the display names of the available installations, since now
BootEntry->FriendlyName is a PCWSTR (and not a UNICODE_STRING anymore).
svn path=/branches/setup_improvements/; revision=74943
[SETUPLIB] Make the NTOS_BOOT_ENTRY structure more generic, so that it can wrap around either actual NTOS boot entry options, or FreeLdr-like boot-sector options.
In a sense, the NTOS_BOOT_ENTRY structure now looks much more like the NT structure "BOOT_ENTRY".
- Adapt the code in bldrsup.c to these modifications, and re-enable FreeLdr-like boot-sector-file support code that was commented out.
More code cleanup will follow later.
svn path=/branches/setup_improvements/; revision=74952
2017-06-07 15:58:44 +00:00
|
|
|
/* Check for supported boot type "Windows2003" */
|
2017-06-08 02:20:33 +00:00
|
|
|
if (BootEntry->OsOptionsLength < sizeof(NTOS_OPTIONS) ||
|
|
|
|
RtlCompareMemory(&BootEntry->OsOptions /* Signature */,
|
|
|
|
NTOS_OPTIONS_SIGNATURE,
|
|
|
|
RTL_FIELD_SIZE(NTOS_OPTIONS, Signature)) !=
|
|
|
|
RTL_FIELD_SIZE(NTOS_OPTIONS, Signature))
|
2017-05-25 23:52:50 +00:00
|
|
|
{
|
[SETUPLIB] Introduce a lot of (Work in progress) functions to manipulate boot entries from different boot "stores".
This concerns so far, only freeldr.ini and to an extent, boot.ini, but planning in the future to add support for registry-oriented BCD
as well as possibly direct (u)EFI entries, using the corresponding NT functions.
This code is so far only used in osdetect.c, but will be soon used by usetup's bootsup.c (note that some helper functions: CreateCommonFreeLdrSections()
and (Un)protectBootIni() are already taken from it and used in bldrsup.c).
- In EnumerateNTOSBootEntries(), continue enumerating the boot entries until the user callback returns an status code that is not successful.
- Remove some old code from osdetect.c; use directly BootEntry->FriendlyName when building the display names of the available installations, since now
BootEntry->FriendlyName is a PCWSTR (and not a UNICODE_STRING anymore).
svn path=/branches/setup_improvements/; revision=74943
[SETUPLIB] Make the NTOS_BOOT_ENTRY structure more generic, so that it can wrap around either actual NTOS boot entry options, or FreeLdr-like boot-sector options.
In a sense, the NTOS_BOOT_ENTRY structure now looks much more like the NT structure "BOOT_ENTRY".
- Adapt the code in bldrsup.c to these modifications, and re-enable FreeLdr-like boot-sector-file support code that was commented out.
More code cleanup will follow later.
svn path=/branches/setup_improvements/; revision=74952
2017-06-07 15:58:44 +00:00
|
|
|
/* This is not a ReactOS entry */
|
2018-10-28 22:33:29 +00:00
|
|
|
// DPRINT(" An installation '%S' of unsupported type '%S'\n",
|
|
|
|
// BootEntry->FriendlyName, BootEntry->Version ? BootEntry->Version : L"n/a");
|
|
|
|
DPRINT(" An installation '%S' of unsupported type %lu\n",
|
|
|
|
BootEntry->FriendlyName, BootEntry->OsOptionsLength);
|
[SETUPLIB] Introduce a lot of (Work in progress) functions to manipulate boot entries from different boot "stores".
This concerns so far, only freeldr.ini and to an extent, boot.ini, but planning in the future to add support for registry-oriented BCD
as well as possibly direct (u)EFI entries, using the corresponding NT functions.
This code is so far only used in osdetect.c, but will be soon used by usetup's bootsup.c (note that some helper functions: CreateCommonFreeLdrSections()
and (Un)protectBootIni() are already taken from it and used in bldrsup.c).
- In EnumerateNTOSBootEntries(), continue enumerating the boot entries until the user callback returns an status code that is not successful.
- Remove some old code from osdetect.c; use directly BootEntry->FriendlyName when building the display names of the available installations, since now
BootEntry->FriendlyName is a PCWSTR (and not a UNICODE_STRING anymore).
svn path=/branches/setup_improvements/; revision=74943
[SETUPLIB] Make the NTOS_BOOT_ENTRY structure more generic, so that it can wrap around either actual NTOS boot entry options, or FreeLdr-like boot-sector options.
In a sense, the NTOS_BOOT_ENTRY structure now looks much more like the NT structure "BOOT_ENTRY".
- Adapt the code in bldrsup.c to these modifications, and re-enable FreeLdr-like boot-sector-file support code that was commented out.
More code cleanup will follow later.
svn path=/branches/setup_improvements/; revision=74952
2017-06-07 15:58:44 +00:00
|
|
|
/* Continue the enumeration */
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
2017-05-13 16:13:19 +00:00
|
|
|
|
2017-06-08 02:20:33 +00:00
|
|
|
/* BootType is Windows2003, now check OsLoadPath */
|
|
|
|
if (!Options->OsLoadPath || !*Options->OsLoadPath)
|
[SETUPLIB] Introduce a lot of (Work in progress) functions to manipulate boot entries from different boot "stores".
This concerns so far, only freeldr.ini and to an extent, boot.ini, but planning in the future to add support for registry-oriented BCD
as well as possibly direct (u)EFI entries, using the corresponding NT functions.
This code is so far only used in osdetect.c, but will be soon used by usetup's bootsup.c (note that some helper functions: CreateCommonFreeLdrSections()
and (Un)protectBootIni() are already taken from it and used in bldrsup.c).
- In EnumerateNTOSBootEntries(), continue enumerating the boot entries until the user callback returns an status code that is not successful.
- Remove some old code from osdetect.c; use directly BootEntry->FriendlyName when building the display names of the available installations, since now
BootEntry->FriendlyName is a PCWSTR (and not a UNICODE_STRING anymore).
svn path=/branches/setup_improvements/; revision=74943
[SETUPLIB] Make the NTOS_BOOT_ENTRY structure more generic, so that it can wrap around either actual NTOS boot entry options, or FreeLdr-like boot-sector options.
In a sense, the NTOS_BOOT_ENTRY structure now looks much more like the NT structure "BOOT_ENTRY".
- Adapt the code in bldrsup.c to these modifications, and re-enable FreeLdr-like boot-sector-file support code that was commented out.
More code cleanup will follow later.
svn path=/branches/setup_improvements/; revision=74952
2017-06-07 15:58:44 +00:00
|
|
|
{
|
|
|
|
/* Certainly not a ReactOS installation */
|
|
|
|
DPRINT1(" A Win2k3 install '%S' without an ARC path?!\n", BootEntry->FriendlyName);
|
|
|
|
/* Continue the enumeration */
|
|
|
|
return STATUS_SUCCESS;
|
2017-05-13 16:13:19 +00:00
|
|
|
}
|
2017-05-22 22:59:11 +00:00
|
|
|
|
2018-10-28 22:33:29 +00:00
|
|
|
DPRINT(" Found a candidate Win2k3 install '%S' with ARC path '%S'\n",
|
|
|
|
BootEntry->FriendlyName, Options->OsLoadPath);
|
|
|
|
// DPRINT(" Found a Win2k3 install '%S' with ARC path '%S'\n",
|
|
|
|
// BootEntry->FriendlyName, Options->OsLoadPath);
|
2017-05-13 16:13:19 +00:00
|
|
|
|
2017-05-25 23:52:50 +00:00
|
|
|
// TODO: Normalize the ARC path.
|
2017-05-22 01:19:08 +00:00
|
|
|
|
2017-05-25 23:52:50 +00:00
|
|
|
/*
|
|
|
|
* Check whether we already have an installation with this ARC path.
|
|
|
|
* If this is the case, stop there.
|
|
|
|
*/
|
2017-06-08 02:20:33 +00:00
|
|
|
NtOsInstall = FindExistingNTOSInstall(Data->List, Options->OsLoadPath, NULL);
|
2017-05-25 23:52:50 +00:00
|
|
|
if (NtOsInstall)
|
2017-05-22 01:19:08 +00:00
|
|
|
{
|
2018-10-28 22:33:29 +00:00
|
|
|
DPRINT(" An NTOS installation with name \"%S\" from vendor \"%S\" already exists in SystemRoot '%wZ'\n",
|
|
|
|
NtOsInstall->InstallationName, NtOsInstall->VendorName, &NtOsInstall->SystemArcPath);
|
2017-05-31 01:11:05 +00:00
|
|
|
/* Continue the enumeration */
|
2017-05-25 23:52:50 +00:00
|
|
|
return STATUS_SUCCESS;
|
2017-05-22 01:19:08 +00:00
|
|
|
}
|
|
|
|
|
2017-05-25 23:52:50 +00:00
|
|
|
/*
|
|
|
|
* 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));
|
2017-06-08 02:20:33 +00:00
|
|
|
if (!ArcPathToNtPath(&SystemRootPath, Options->OsLoadPath, Data->PartList))
|
2017-05-22 01:19:08 +00:00
|
|
|
{
|
2017-06-08 02:20:33 +00:00
|
|
|
DPRINT1("ArcPathToNtPath(%S) failed, skip the installation.\n", Options->OsLoadPath);
|
2017-05-31 01:11:05 +00:00
|
|
|
/* Continue the enumeration */
|
2017-05-25 23:52:50 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
2017-05-22 01:19:08 +00:00
|
|
|
|
2018-10-28 22:33:29 +00:00
|
|
|
DPRINT("ArcPathToNtPath() succeeded: '%S' --> '%wZ'\n",
|
|
|
|
Options->OsLoadPath, &SystemRootPath);
|
2017-05-22 01:19:08 +00:00
|
|
|
|
2017-05-25 23:52:50 +00:00
|
|
|
/*
|
|
|
|
* Check whether we already have an installation with this NT path.
|
|
|
|
* If this is the case, stop there.
|
|
|
|
*/
|
2017-06-08 02:20:33 +00:00
|
|
|
NtOsInstall = FindExistingNTOSInstall(Data->List, NULL /*Options->OsLoadPath*/, &SystemRootPath);
|
2017-05-25 23:52:50 +00:00
|
|
|
if (NtOsInstall)
|
|
|
|
{
|
2017-12-29 18:37:28 +00:00
|
|
|
DPRINT1(" An NTOS installation with name \"%S\" from vendor \"%S\" already exists in SystemRoot '%wZ'\n",
|
|
|
|
NtOsInstall->InstallationName, NtOsInstall->VendorName, &NtOsInstall->SystemNtPath);
|
2017-05-31 01:11:05 +00:00
|
|
|
/* Continue the enumeration */
|
2017-05-25 23:52:50 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
2017-05-22 01:19:08 +00:00
|
|
|
|
2018-10-28 22:33:29 +00:00
|
|
|
DPRINT("EnumerateInstallations: SystemRootPath: '%wZ'\n", &SystemRootPath);
|
2017-05-22 01:19:08 +00:00
|
|
|
|
2017-05-25 23:52:50 +00:00
|
|
|
/* Check if this is a valid NTOS installation; stop there if it isn't one */
|
2017-12-29 18:37:28 +00:00
|
|
|
RtlInitEmptyUnicodeString(&VendorName, VendorNameBuffer, sizeof(VendorNameBuffer));
|
2018-01-28 22:32:52 +00:00
|
|
|
if (!IsValidNTOSInstallation(&SystemRootPath, &Machine, &VendorName))
|
2017-05-31 01:11:05 +00:00
|
|
|
{
|
|
|
|
/* Continue the enumeration */
|
2017-05-25 23:52:50 +00:00
|
|
|
return STATUS_SUCCESS;
|
2017-05-31 01:11:05 +00:00
|
|
|
}
|
2017-05-22 01:19:08 +00:00
|
|
|
|
2018-10-28 22:33:29 +00:00
|
|
|
DPRINT("Found a valid NTOS installation in SystemRoot ARC path '%S', NT path '%wZ'\n",
|
|
|
|
Options->OsLoadPath, &SystemRootPath);
|
2017-05-22 01:19:08 +00:00
|
|
|
|
2017-05-25 23:52:50 +00:00
|
|
|
/* From the NT path, compute the disk, partition and path components */
|
|
|
|
if (NtPathToDiskPartComponents(SystemRootPath.Buffer, &DiskNumber, &PartitionNumber, &PathComponent))
|
|
|
|
{
|
2018-10-28 22:33:29 +00:00
|
|
|
DPRINT("SystemRootPath = '%wZ' points to disk #%d, partition #%d, path '%S'\n",
|
|
|
|
&SystemRootPath, DiskNumber, PartitionNumber, PathComponent);
|
2017-05-22 01:19:08 +00:00
|
|
|
|
2017-05-25 23:52:50 +00:00
|
|
|
/* Retrieve the corresponding disk and partition */
|
|
|
|
if (!GetDiskOrPartition(Data->PartList, DiskNumber, PartitionNumber, &DiskEntry, &PartEntry))
|
2017-05-22 01:19:08 +00:00
|
|
|
{
|
2017-05-25 23:52:50 +00:00
|
|
|
DPRINT1("GetDiskOrPartition(disk #%d, partition #%d) failed\n",
|
|
|
|
DiskNumber, PartitionNumber);
|
2017-05-22 01:19:08 +00:00
|
|
|
}
|
|
|
|
}
|
2017-05-25 23:52:50 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT1("NtPathToDiskPartComponents(%wZ) failed\n", &SystemRootPath);
|
|
|
|
}
|
2017-05-22 01:19:08 +00:00
|
|
|
|
2017-05-31 01:11:05 +00:00
|
|
|
/* Add the discovered NTOS installation into the list */
|
2017-12-29 18:37:28 +00:00
|
|
|
AddNTOSInstallation(Data->List,
|
|
|
|
BootEntry->FriendlyName,
|
2018-01-28 22:32:52 +00:00
|
|
|
Machine,
|
2017-12-29 18:37:28 +00:00
|
|
|
VendorName.Buffer, // FIXME: What if it's not NULL-terminated?
|
|
|
|
Options->OsLoadPath,
|
2017-05-25 23:52:50 +00:00
|
|
|
&SystemRootPath, PathComponent,
|
2017-12-29 18:37:28 +00:00
|
|
|
DiskNumber, PartitionNumber, PartEntry);
|
2017-05-22 01:19:08 +00:00
|
|
|
|
2017-05-31 01:11:05 +00:00
|
|
|
/* Continue the enumeration */
|
2017-05-22 01:19:08 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
2017-05-13 16:13:19 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* FindSubStrI(PCWSTR str, PCWSTR strSearch) :
|
|
|
|
* Searches for a sub-string 'strSearch' inside 'str', similarly to what
|
|
|
|
* wcsstr(str, strSearch) does, but ignores the case during the comparisons.
|
|
|
|
*/
|
2017-05-22 22:59:11 +00:00
|
|
|
PCWSTR FindSubStrI(PCWSTR str, PCWSTR strSearch)
|
2017-05-13 16:13:19 +00:00
|
|
|
{
|
2017-05-22 22:59:11 +00:00
|
|
|
PCWSTR cp = str;
|
|
|
|
PCWSTR s1, s2;
|
2017-05-13 16:13:19 +00:00
|
|
|
|
|
|
|
if (!*strSearch)
|
2017-05-22 22:59:11 +00:00
|
|
|
return str;
|
2017-05-13 16:13:19 +00:00
|
|
|
|
|
|
|
while (*cp)
|
|
|
|
{
|
|
|
|
s1 = cp;
|
2017-05-22 22:59:11 +00:00
|
|
|
s2 = strSearch;
|
2017-05-13 16:13:19 +00:00
|
|
|
|
|
|
|
while (*s1 && *s2 && (towupper(*s1) == towupper(*s2)))
|
|
|
|
++s1, ++s2;
|
|
|
|
|
|
|
|
if (!*s2)
|
|
|
|
return cp;
|
|
|
|
|
|
|
|
++cp;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOLEAN
|
|
|
|
CheckForValidPEAndVendor(
|
|
|
|
IN HANDLE RootDirectory OPTIONAL,
|
2017-05-24 16:37:49 +00:00
|
|
|
IN PCWSTR PathNameToFile,
|
2018-01-28 22:32:52 +00:00
|
|
|
OUT PUSHORT Machine,
|
|
|
|
OUT PUNICODE_STRING VendorName)
|
2017-05-13 16:13:19 +00:00
|
|
|
{
|
|
|
|
BOOLEAN Success = FALSE;
|
|
|
|
NTSTATUS Status;
|
|
|
|
HANDLE FileHandle, SectionHandle;
|
|
|
|
// SIZE_T ViewSize;
|
|
|
|
PVOID ViewBase;
|
2018-01-28 22:32:52 +00:00
|
|
|
PIMAGE_NT_HEADERS NtHeader;
|
2017-05-13 16:13:19 +00:00
|
|
|
PVOID VersionBuffer = NULL; // Read-only
|
|
|
|
PVOID pvData = NULL;
|
|
|
|
UINT BufLen = 0;
|
|
|
|
|
2017-05-22 01:19:08 +00:00
|
|
|
if (VendorName->MaximumLength < sizeof(UNICODE_NULL))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
*VendorName->Buffer = UNICODE_NULL;
|
|
|
|
VendorName->Length = 0;
|
|
|
|
|
2017-05-24 16:37:49 +00:00
|
|
|
Status = OpenAndMapFile(RootDirectory, PathNameToFile,
|
2017-05-31 01:11:05 +00:00
|
|
|
&FileHandle, &SectionHandle, &ViewBase,
|
|
|
|
NULL, FALSE);
|
2017-05-13 16:13:19 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2017-05-24 16:37:49 +00:00
|
|
|
DPRINT1("Failed to open and map file '%S', Status 0x%08lx\n", PathNameToFile, Status);
|
2017-05-13 16:13:19 +00:00
|
|
|
return FALSE; // Status;
|
|
|
|
}
|
|
|
|
|
2018-01-28 22:32:52 +00:00
|
|
|
/* Make sure it's a valid NT PE file */
|
|
|
|
NtHeader = RtlImageNtHeader(ViewBase);
|
|
|
|
if (!NtHeader)
|
2017-05-13 16:13:19 +00:00
|
|
|
{
|
2018-01-28 22:32:52 +00:00
|
|
|
DPRINT1("File '%S' does not seem to be a valid NT PE file, bail out\n", PathNameToFile);
|
2017-05-13 16:13:19 +00:00
|
|
|
Status = STATUS_INVALID_IMAGE_FORMAT;
|
2017-08-23 12:20:15 +00:00
|
|
|
goto UnmapCloseFile;
|
2017-05-13 16:13:19 +00:00
|
|
|
}
|
|
|
|
|
2018-01-28 22:32:52 +00:00
|
|
|
/* Retrieve the target architecture of this PE module */
|
|
|
|
*Machine = NtHeader->FileHeader.Machine;
|
|
|
|
|
2017-05-13 16:13:19 +00:00
|
|
|
/*
|
|
|
|
* Search for a valid executable version and vendor.
|
|
|
|
* NOTE: The module is loaded as a data file, it should be marked as such.
|
|
|
|
*/
|
|
|
|
Status = NtGetVersionResource((PVOID)((ULONG_PTR)ViewBase | 1), &VersionBuffer, NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2017-05-24 16:37:49 +00:00
|
|
|
DPRINT1("Failed to get version resource for file '%S', Status 0x%08lx\n", PathNameToFile, Status);
|
2017-08-23 12:20:15 +00:00
|
|
|
goto UnmapCloseFile;
|
2017-05-13 16:13:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Status = NtVerQueryValue(VersionBuffer, L"\\VarFileInfo\\Translation", &pvData, &BufLen);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
USHORT wCodePage = 0, wLangID = 0;
|
|
|
|
WCHAR FileInfo[MAX_PATH];
|
|
|
|
|
|
|
|
wCodePage = LOWORD(*(ULONG*)pvData);
|
|
|
|
wLangID = HIWORD(*(ULONG*)pvData);
|
|
|
|
|
[SETUPLIB] Introduce a lot of (Work in progress) functions to manipulate boot entries from different boot "stores".
This concerns so far, only freeldr.ini and to an extent, boot.ini, but planning in the future to add support for registry-oriented BCD
as well as possibly direct (u)EFI entries, using the corresponding NT functions.
This code is so far only used in osdetect.c, but will be soon used by usetup's bootsup.c (note that some helper functions: CreateCommonFreeLdrSections()
and (Un)protectBootIni() are already taken from it and used in bldrsup.c).
- In EnumerateNTOSBootEntries(), continue enumerating the boot entries until the user callback returns an status code that is not successful.
- Remove some old code from osdetect.c; use directly BootEntry->FriendlyName when building the display names of the available installations, since now
BootEntry->FriendlyName is a PCWSTR (and not a UNICODE_STRING anymore).
svn path=/branches/setup_improvements/; revision=74943
[SETUPLIB] Make the NTOS_BOOT_ENTRY structure more generic, so that it can wrap around either actual NTOS boot entry options, or FreeLdr-like boot-sector options.
In a sense, the NTOS_BOOT_ENTRY structure now looks much more like the NT structure "BOOT_ENTRY".
- Adapt the code in bldrsup.c to these modifications, and re-enable FreeLdr-like boot-sector-file support code that was commented out.
More code cleanup will follow later.
svn path=/branches/setup_improvements/; revision=74952
2017-06-07 15:58:44 +00:00
|
|
|
RtlStringCchPrintfW(FileInfo, ARRAYSIZE(FileInfo),
|
|
|
|
L"StringFileInfo\\%04X%04X\\CompanyName",
|
|
|
|
wCodePage, wLangID);
|
2017-05-13 16:13:19 +00:00
|
|
|
|
|
|
|
Status = NtVerQueryValue(VersionBuffer, FileInfo, &pvData, &BufLen);
|
2017-05-22 01:19:08 +00:00
|
|
|
|
|
|
|
/* Fixup the Status in case pvData is NULL */
|
|
|
|
if (NT_SUCCESS(Status) && !pvData)
|
|
|
|
Status = STATUS_NOT_FOUND;
|
|
|
|
|
|
|
|
if (NT_SUCCESS(Status) /*&& pvData*/)
|
2017-05-13 16:13:19 +00:00
|
|
|
{
|
|
|
|
/* BufLen includes the NULL terminator count */
|
2018-10-28 22:33:29 +00:00
|
|
|
DPRINT("Found version vendor: \"%S\" for file '%S'\n", pvData, PathNameToFile);
|
2017-05-13 16:13:19 +00:00
|
|
|
|
[SETUPLIB] Introduce a lot of (Work in progress) functions to manipulate boot entries from different boot "stores".
This concerns so far, only freeldr.ini and to an extent, boot.ini, but planning in the future to add support for registry-oriented BCD
as well as possibly direct (u)EFI entries, using the corresponding NT functions.
This code is so far only used in osdetect.c, but will be soon used by usetup's bootsup.c (note that some helper functions: CreateCommonFreeLdrSections()
and (Un)protectBootIni() are already taken from it and used in bldrsup.c).
- In EnumerateNTOSBootEntries(), continue enumerating the boot entries until the user callback returns an status code that is not successful.
- Remove some old code from osdetect.c; use directly BootEntry->FriendlyName when building the display names of the available installations, since now
BootEntry->FriendlyName is a PCWSTR (and not a UNICODE_STRING anymore).
svn path=/branches/setup_improvements/; revision=74943
[SETUPLIB] Make the NTOS_BOOT_ENTRY structure more generic, so that it can wrap around either actual NTOS boot entry options, or FreeLdr-like boot-sector options.
In a sense, the NTOS_BOOT_ENTRY structure now looks much more like the NT structure "BOOT_ENTRY".
- Adapt the code in bldrsup.c to these modifications, and re-enable FreeLdr-like boot-sector-file support code that was commented out.
More code cleanup will follow later.
svn path=/branches/setup_improvements/; revision=74952
2017-06-07 15:58:44 +00:00
|
|
|
RtlStringCbCopyNW(VendorName->Buffer, VendorName->MaximumLength,
|
|
|
|
pvData, BufLen * sizeof(WCHAR));
|
2021-06-29 16:50:15 +00:00
|
|
|
VendorName->Length = (USHORT)wcslen(VendorName->Buffer) * sizeof(WCHAR);
|
2017-05-13 16:13:19 +00:00
|
|
|
|
2017-05-22 01:19:08 +00:00
|
|
|
Success = TRUE;
|
2017-05-13 16:13:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-22 01:19:08 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2018-10-28 22:33:29 +00:00
|
|
|
DPRINT("No version vendor found for file '%S'\n", PathNameToFile);
|
2017-05-22 01:19:08 +00:00
|
|
|
|
2017-08-23 12:20:15 +00:00
|
|
|
UnmapCloseFile:
|
2017-05-13 16:13:19 +00:00
|
|
|
/* Finally, unmap and close the file */
|
2017-08-23 12:20:15 +00:00
|
|
|
UnMapAndCloseFile(FileHandle, SectionHandle, ViewBase);
|
2017-05-13 16:13:19 +00:00
|
|
|
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
2017-05-22 01:19:08 +00:00
|
|
|
//
|
|
|
|
// TODO: Instead of returning TRUE/FALSE, it would be nice to return
|
|
|
|
// a flag indicating:
|
|
|
|
// - whether the installation is actually valid;
|
|
|
|
// - if it's broken or not (aka. needs for repair, or just upgrading).
|
|
|
|
//
|
2017-05-13 16:13:19 +00:00
|
|
|
static BOOLEAN
|
2017-05-24 16:37:49 +00:00
|
|
|
IsValidNTOSInstallationByHandle(
|
2017-12-29 18:37:28 +00:00
|
|
|
IN HANDLE SystemRootDirectory,
|
2018-01-28 22:32:52 +00:00
|
|
|
OUT PUSHORT Machine OPTIONAL,
|
2017-12-29 18:37:28 +00:00
|
|
|
OUT PUNICODE_STRING VendorName OPTIONAL)
|
2017-05-13 16:13:19 +00:00
|
|
|
{
|
|
|
|
BOOLEAN Success = FALSE;
|
2017-05-25 23:52:50 +00:00
|
|
|
PCWSTR PathName;
|
2017-05-13 16:13:19 +00:00
|
|
|
USHORT i;
|
2018-01-28 22:32:52 +00:00
|
|
|
USHORT LocalMachine;
|
2017-12-29 18:37:28 +00:00
|
|
|
UNICODE_STRING LocalVendorName;
|
2017-05-24 16:37:49 +00:00
|
|
|
WCHAR VendorNameBuffer[MAX_PATH];
|
2017-05-13 16:13:19 +00:00
|
|
|
|
2017-12-29 18:37:28 +00:00
|
|
|
/* Check for VendorName validity */
|
|
|
|
if (VendorName->MaximumLength < sizeof(UNICODE_NULL))
|
|
|
|
{
|
|
|
|
/* Don't use it, invalidate the pointer */
|
|
|
|
VendorName = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Zero it out */
|
|
|
|
*VendorName->Buffer = UNICODE_NULL;
|
|
|
|
VendorName->Length = 0;
|
|
|
|
}
|
|
|
|
|
2017-05-13 16:13:19 +00:00
|
|
|
/* Check for the existence of \SystemRoot\System32 */
|
2017-05-25 23:52:50 +00:00
|
|
|
PathName = L"System32\\";
|
2017-08-21 19:41:40 +00:00
|
|
|
if (!DoesDirExist(SystemRootDirectory, PathName))
|
2017-05-13 16:13:19 +00:00
|
|
|
{
|
2017-05-25 23:52:50 +00:00
|
|
|
// DPRINT1("Failed to open directory '%S', Status 0x%08lx\n", PathName, Status);
|
2017-05-13 16:13:19 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for the existence of \SystemRoot\System32\drivers */
|
2017-05-25 23:52:50 +00:00
|
|
|
PathName = L"System32\\drivers\\";
|
2017-08-21 19:41:40 +00:00
|
|
|
if (!DoesDirExist(SystemRootDirectory, PathName))
|
2017-05-13 16:13:19 +00:00
|
|
|
{
|
2017-05-25 23:52:50 +00:00
|
|
|
// DPRINT1("Failed to open directory '%S', Status 0x%08lx\n", PathName, Status);
|
2017-05-13 16:13:19 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for the existence of \SystemRoot\System32\config */
|
2017-05-25 23:52:50 +00:00
|
|
|
PathName = L"System32\\config\\";
|
2017-08-21 19:41:40 +00:00
|
|
|
if (!DoesDirExist(SystemRootDirectory, PathName))
|
2017-05-13 16:13:19 +00:00
|
|
|
{
|
2017-05-25 23:52:50 +00:00
|
|
|
// DPRINT1("Failed to open directory '%S', Status 0x%08lx\n", PathName, Status);
|
2017-05-13 16:13:19 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
/*
|
|
|
|
* Check for the existence of SYSTEM and SOFTWARE hives in \SystemRoot\System32\config
|
|
|
|
* (but we don't check here whether they are actually valid).
|
|
|
|
*/
|
2017-05-25 23:52:50 +00:00
|
|
|
PathName = L"System32\\config\\SYSTEM";
|
|
|
|
if (!DoesFileExist(SystemRootDirectory, PathName))
|
2017-05-13 16:13:19 +00:00
|
|
|
{
|
2017-05-25 23:52:50 +00:00
|
|
|
// DPRINT1("Failed to open file '%S', Status 0x%08lx\n", PathName, Status);
|
2017-05-13 16:13:19 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2017-05-25 23:52:50 +00:00
|
|
|
PathName = L"System32\\config\\SOFTWARE";
|
|
|
|
if (!DoesFileExist(SystemRootDirectory, PathName))
|
2017-05-13 16:13:19 +00:00
|
|
|
{
|
2017-05-25 23:52:50 +00:00
|
|
|
// DPRINT1("Failed to open file '%S', Status 0x%08lx\n", PathName, Status);
|
2017-05-13 16:13:19 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-12-29 18:37:28 +00:00
|
|
|
RtlInitEmptyUnicodeString(&LocalVendorName, VendorNameBuffer, sizeof(VendorNameBuffer));
|
2017-05-13 16:13:19 +00:00
|
|
|
|
2017-05-22 01:19:08 +00:00
|
|
|
/* Check for the existence of \SystemRoot\System32\ntoskrnl.exe and retrieves its vendor name */
|
2017-05-25 23:52:50 +00:00
|
|
|
PathName = L"System32\\ntoskrnl.exe";
|
2018-01-28 22:32:52 +00:00
|
|
|
Success = CheckForValidPEAndVendor(SystemRootDirectory, PathName, &LocalMachine, &LocalVendorName);
|
2017-05-22 01:19:08 +00:00
|
|
|
if (!Success)
|
2017-05-25 23:52:50 +00:00
|
|
|
DPRINT1("Kernel executable '%S' is either not a PE file, or does not have any vendor?\n", PathName);
|
2017-05-13 16:13:19 +00:00
|
|
|
|
2018-01-28 22:32:52 +00:00
|
|
|
/*
|
|
|
|
* The kernel gives the OS its flavour. If we failed due to the absence of
|
|
|
|
* ntoskrnl.exe this might be due to the fact this particular installation
|
|
|
|
* uses a custom kernel that has a different name, overridden in the boot
|
|
|
|
* parameters. We then rely on the existence of ntdll.dll, which cannot be
|
|
|
|
* renamed on a valid NT system.
|
|
|
|
*/
|
2017-05-22 01:19:08 +00:00
|
|
|
if (Success)
|
|
|
|
{
|
|
|
|
for (i = 0; i < ARRAYSIZE(KnownVendors); ++i)
|
|
|
|
{
|
2017-12-29 18:37:28 +00:00
|
|
|
Success = !!FindSubStrI(LocalVendorName.Buffer, KnownVendors[i]);
|
2017-05-22 01:19:08 +00:00
|
|
|
if (Success)
|
|
|
|
{
|
|
|
|
/* We have found a correct vendor combination */
|
2018-10-28 22:33:29 +00:00
|
|
|
DPRINT("IsValidNTOSInstallation: We've got an NTOS installation from %S !\n", KnownVendors[i]);
|
2017-05-22 01:19:08 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2017-05-13 16:13:19 +00:00
|
|
|
|
2018-01-28 22:32:52 +00:00
|
|
|
/* Return the target architecture */
|
|
|
|
if (Machine)
|
|
|
|
{
|
|
|
|
/* Copy the value and invalidate the pointer */
|
|
|
|
*Machine = LocalMachine;
|
|
|
|
Machine = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the vendor name */
|
|
|
|
if (VendorName)
|
|
|
|
{
|
|
|
|
/* Copy the string and invalidate the pointer */
|
|
|
|
RtlCopyUnicodeString(VendorName, &LocalVendorName);
|
|
|
|
VendorName = NULL;
|
|
|
|
}
|
2017-12-29 18:37:28 +00:00
|
|
|
}
|
|
|
|
|
2017-05-22 01:19:08 +00:00
|
|
|
/* OPTIONAL: Check for the existence of \SystemRoot\System32\ntkrnlpa.exe */
|
|
|
|
|
|
|
|
/* Check for the existence of \SystemRoot\System32\ntdll.dll and retrieves its vendor name */
|
2017-05-25 23:52:50 +00:00
|
|
|
PathName = L"System32\\ntdll.dll";
|
2018-01-28 22:32:52 +00:00
|
|
|
Success = CheckForValidPEAndVendor(SystemRootDirectory, PathName, &LocalMachine, &LocalVendorName);
|
2017-05-22 01:19:08 +00:00
|
|
|
if (!Success)
|
2017-05-25 23:52:50 +00:00
|
|
|
DPRINT1("User-mode DLL '%S' is either not a PE file, or does not have any vendor?\n", PathName);
|
2018-01-28 22:32:52 +00:00
|
|
|
|
2017-05-22 01:19:08 +00:00
|
|
|
if (Success)
|
|
|
|
{
|
|
|
|
for (i = 0; i < ARRAYSIZE(KnownVendors); ++i)
|
|
|
|
{
|
2017-12-29 18:37:28 +00:00
|
|
|
if (!!FindSubStrI(LocalVendorName.Buffer, KnownVendors[i]))
|
2017-05-22 01:19:08 +00:00
|
|
|
{
|
|
|
|
/* We have found a correct vendor combination */
|
2018-10-28 22:33:29 +00:00
|
|
|
DPRINT("IsValidNTOSInstallation: The user-mode DLL '%S' is from %S\n", PathName, KnownVendors[i]);
|
2017-05-22 01:19:08 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2017-05-13 16:13:19 +00:00
|
|
|
|
2018-01-28 22:32:52 +00:00
|
|
|
/* Return the target architecture if not already obtained */
|
|
|
|
if (Machine)
|
|
|
|
{
|
|
|
|
/* Copy the value and invalidate the pointer */
|
|
|
|
*Machine = LocalMachine;
|
|
|
|
Machine = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the vendor name if not already obtained */
|
|
|
|
if (VendorName)
|
|
|
|
{
|
|
|
|
/* Copy the string and invalidate the pointer */
|
|
|
|
RtlCopyUnicodeString(VendorName, &LocalVendorName);
|
|
|
|
VendorName = NULL;
|
|
|
|
}
|
2017-12-29 18:37:28 +00:00
|
|
|
}
|
|
|
|
|
2017-05-13 16:13:19 +00:00
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
2017-05-24 16:37:49 +00:00
|
|
|
static BOOLEAN
|
2017-12-29 18:37:28 +00:00
|
|
|
IsValidNTOSInstallation(
|
|
|
|
IN PUNICODE_STRING SystemRootPath,
|
2018-01-28 22:32:52 +00:00
|
|
|
OUT PUSHORT Machine,
|
2017-12-29 18:37:28 +00:00
|
|
|
OUT PUNICODE_STRING VendorName OPTIONAL)
|
2017-05-24 16:37:49 +00:00
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
HANDLE SystemRootDirectory;
|
|
|
|
BOOLEAN Success;
|
|
|
|
|
|
|
|
/* Open SystemRootPath */
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
SystemRootPath,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
Status = NtOpenFile(&SystemRootDirectory,
|
[SETUPLIB] Introduce a lot of (Work in progress) functions to manipulate boot entries from different boot "stores".
This concerns so far, only freeldr.ini and to an extent, boot.ini, but planning in the future to add support for registry-oriented BCD
as well as possibly direct (u)EFI entries, using the corresponding NT functions.
This code is so far only used in osdetect.c, but will be soon used by usetup's bootsup.c (note that some helper functions: CreateCommonFreeLdrSections()
and (Un)protectBootIni() are already taken from it and used in bldrsup.c).
- In EnumerateNTOSBootEntries(), continue enumerating the boot entries until the user callback returns an status code that is not successful.
- Remove some old code from osdetect.c; use directly BootEntry->FriendlyName when building the display names of the available installations, since now
BootEntry->FriendlyName is a PCWSTR (and not a UNICODE_STRING anymore).
svn path=/branches/setup_improvements/; revision=74943
[SETUPLIB] Make the NTOS_BOOT_ENTRY structure more generic, so that it can wrap around either actual NTOS boot entry options, or FreeLdr-like boot-sector options.
In a sense, the NTOS_BOOT_ENTRY structure now looks much more like the NT structure "BOOT_ENTRY".
- Adapt the code in bldrsup.c to these modifications, and re-enable FreeLdr-like boot-sector-file support code that was commented out.
More code cleanup will follow later.
svn path=/branches/setup_improvements/; revision=74952
2017-06-07 15:58:44 +00:00
|
|
|
FILE_LIST_DIRECTORY | FILE_TRAVERSE | SYNCHRONIZE,
|
2017-05-24 16:37:49 +00:00
|
|
|
&ObjectAttributes,
|
|
|
|
&IoStatusBlock,
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
|
|
FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to open SystemRoot '%wZ', Status 0x%08lx\n", SystemRootPath, Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2018-01-28 22:32:52 +00:00
|
|
|
Success = IsValidNTOSInstallationByHandle(SystemRootDirectory,
|
|
|
|
Machine, VendorName);
|
2017-05-24 16:37:49 +00:00
|
|
|
|
|
|
|
/* Done! */
|
|
|
|
NtClose(SystemRootDirectory);
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
2018-10-28 22:33:29 +00:00
|
|
|
#ifndef NDEBUG
|
2017-05-13 16:13:19 +00:00
|
|
|
static VOID
|
2017-05-22 01:19:08 +00:00
|
|
|
DumpNTOSInstalls(
|
2017-05-13 16:13:19 +00:00
|
|
|
IN PGENERIC_LIST List)
|
|
|
|
{
|
|
|
|
PGENERIC_LIST_ENTRY Entry;
|
|
|
|
PNTOS_INSTALLATION NtOsInstall;
|
|
|
|
ULONG NtOsInstallsCount = GetNumberOfListEntries(List);
|
|
|
|
|
2018-10-28 22:33:29 +00:00
|
|
|
DPRINT("There %s %d installation%s detected:\n",
|
|
|
|
NtOsInstallsCount >= 2 ? "are" : "is",
|
|
|
|
NtOsInstallsCount,
|
|
|
|
NtOsInstallsCount >= 2 ? "s" : "");
|
2017-05-13 16:13:19 +00:00
|
|
|
|
2017-12-29 18:37:28 +00:00
|
|
|
for (Entry = GetFirstListEntry(List); Entry; Entry = GetNextListEntry(Entry))
|
2017-05-13 16:13:19 +00:00
|
|
|
{
|
2017-12-29 18:37:28 +00:00
|
|
|
NtOsInstall = (PNTOS_INSTALLATION)GetListEntryData(Entry);
|
2017-05-13 16:13:19 +00:00
|
|
|
|
2018-10-28 22:33:29 +00:00
|
|
|
DPRINT(" On disk #%d, partition #%d: Installation \"%S\" in SystemRoot '%wZ'\n",
|
|
|
|
NtOsInstall->DiskNumber, NtOsInstall->PartitionNumber,
|
|
|
|
NtOsInstall->InstallationName, &NtOsInstall->SystemNtPath);
|
2017-05-13 16:13:19 +00:00
|
|
|
}
|
|
|
|
|
2018-10-28 22:33:29 +00:00
|
|
|
DPRINT("Done.\n");
|
2017-05-13 16:13:19 +00:00
|
|
|
}
|
2018-10-28 22:33:29 +00:00
|
|
|
#endif
|
2017-05-13 16:13:19 +00:00
|
|
|
|
|
|
|
static PNTOS_INSTALLATION
|
|
|
|
FindExistingNTOSInstall(
|
|
|
|
IN PGENERIC_LIST List,
|
2017-05-22 22:59:11 +00:00
|
|
|
IN PCWSTR SystemRootArcPath OPTIONAL,
|
|
|
|
IN PUNICODE_STRING SystemRootNtPath OPTIONAL // or PCWSTR ?
|
|
|
|
)
|
2017-05-13 16:13:19 +00:00
|
|
|
{
|
|
|
|
PGENERIC_LIST_ENTRY Entry;
|
|
|
|
PNTOS_INSTALLATION NtOsInstall;
|
2017-05-22 22:59:11 +00:00
|
|
|
UNICODE_STRING SystemArcPath;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We search either via ARC path or NT path.
|
|
|
|
* If both pointers are NULL then we fail straight away.
|
|
|
|
*/
|
|
|
|
if (!SystemRootArcPath && !SystemRootNtPath)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
RtlInitUnicodeString(&SystemArcPath, SystemRootArcPath);
|
2017-05-13 16:13:19 +00:00
|
|
|
|
2017-12-29 18:37:28 +00:00
|
|
|
for (Entry = GetFirstListEntry(List); Entry; Entry = GetNextListEntry(Entry))
|
2017-05-13 16:13:19 +00:00
|
|
|
{
|
2017-12-29 18:37:28 +00:00
|
|
|
NtOsInstall = (PNTOS_INSTALLATION)GetListEntryData(Entry);
|
2017-05-13 16:13:19 +00:00
|
|
|
|
2017-05-22 22:59:11 +00:00
|
|
|
/*
|
|
|
|
* Note that if both ARC paths are equal, then the corresponding
|
|
|
|
* NT paths must be the same. However, two ARC paths may be different
|
|
|
|
* but resolve into the same NT path.
|
|
|
|
*/
|
|
|
|
if ( (SystemRootArcPath &&
|
|
|
|
RtlEqualUnicodeString(&NtOsInstall->SystemArcPath,
|
|
|
|
&SystemArcPath, TRUE)) ||
|
|
|
|
(SystemRootNtPath &&
|
|
|
|
RtlEqualUnicodeString(&NtOsInstall->SystemNtPath,
|
|
|
|
SystemRootNtPath, TRUE)) )
|
2017-05-13 16:13:19 +00:00
|
|
|
{
|
|
|
|
/* Found it! */
|
|
|
|
return NtOsInstall;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PNTOS_INSTALLATION
|
|
|
|
AddNTOSInstallation(
|
|
|
|
IN PGENERIC_LIST List,
|
2017-12-29 18:37:28 +00:00
|
|
|
IN PCWSTR InstallationName,
|
2018-01-28 22:32:52 +00:00
|
|
|
IN USHORT Machine,
|
2017-12-29 18:37:28 +00:00
|
|
|
IN PCWSTR VendorName,
|
2017-05-22 22:59:11 +00:00
|
|
|
IN PCWSTR SystemRootArcPath,
|
|
|
|
IN PUNICODE_STRING SystemRootNtPath, // or PCWSTR ?
|
|
|
|
IN PCWSTR PathComponent, // Pointer inside SystemRootNtPath buffer
|
2017-05-13 16:13:19 +00:00
|
|
|
IN ULONG DiskNumber,
|
|
|
|
IN ULONG PartitionNumber,
|
2017-12-29 18:37:28 +00:00
|
|
|
IN PPARTENTRY PartEntry OPTIONAL)
|
2017-05-13 16:13:19 +00:00
|
|
|
{
|
|
|
|
PNTOS_INSTALLATION NtOsInstall;
|
2017-05-22 22:59:11 +00:00
|
|
|
SIZE_T ArcPathLength, NtPathLength;
|
2017-05-13 16:13:19 +00:00
|
|
|
|
|
|
|
/* Is there already any installation with these settings? */
|
2017-05-22 22:59:11 +00:00
|
|
|
NtOsInstall = FindExistingNTOSInstall(List, SystemRootArcPath, SystemRootNtPath);
|
2017-05-13 16:13:19 +00:00
|
|
|
if (NtOsInstall)
|
|
|
|
{
|
2017-12-29 18:37:28 +00:00
|
|
|
DPRINT1("An NTOS installation with name \"%S\" from vendor \"%S\" already exists on disk #%d, partition #%d, in SystemRoot '%wZ'\n",
|
|
|
|
NtOsInstall->InstallationName, NtOsInstall->VendorName,
|
|
|
|
NtOsInstall->DiskNumber, NtOsInstall->PartitionNumber, &NtOsInstall->SystemNtPath);
|
2017-05-22 01:19:08 +00:00
|
|
|
//
|
|
|
|
// NOTE: We may use its "IsDefault" attribute, and only keep the entries that have IsDefault == TRUE...
|
|
|
|
// Setting IsDefault to TRUE would imply searching for the "Default" entry in the loader configuration file.
|
|
|
|
//
|
2017-05-13 16:13:19 +00:00
|
|
|
return NtOsInstall;
|
|
|
|
}
|
|
|
|
|
2017-05-22 22:59:11 +00:00
|
|
|
ArcPathLength = (wcslen(SystemRootArcPath) + 1) * sizeof(WCHAR);
|
|
|
|
// NtPathLength = ROUND_UP(SystemRootNtPath->Length + sizeof(UNICODE_NULL), sizeof(WCHAR));
|
|
|
|
NtPathLength = SystemRootNtPath->Length + sizeof(UNICODE_NULL);
|
|
|
|
|
2017-05-13 16:13:19 +00:00
|
|
|
/* None was found, so add a new one */
|
2017-05-22 22:59:11 +00:00
|
|
|
NtOsInstall = RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY,
|
|
|
|
sizeof(*NtOsInstall) +
|
|
|
|
ArcPathLength + NtPathLength);
|
2017-05-13 16:13:19 +00:00
|
|
|
if (!NtOsInstall)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
NtOsInstall->DiskNumber = DiskNumber;
|
|
|
|
NtOsInstall->PartitionNumber = PartitionNumber;
|
2017-05-22 22:59:11 +00:00
|
|
|
NtOsInstall->PartEntry = PartEntry;
|
|
|
|
|
2018-01-28 22:32:52 +00:00
|
|
|
NtOsInstall->Machine = Machine;
|
|
|
|
|
2017-05-22 22:59:11 +00:00
|
|
|
RtlInitEmptyUnicodeString(&NtOsInstall->SystemArcPath,
|
|
|
|
(PWCHAR)(NtOsInstall + 1),
|
|
|
|
ArcPathLength);
|
|
|
|
RtlCopyMemory(NtOsInstall->SystemArcPath.Buffer, SystemRootArcPath, ArcPathLength);
|
|
|
|
NtOsInstall->SystemArcPath.Length = ArcPathLength - sizeof(UNICODE_NULL);
|
|
|
|
|
|
|
|
RtlInitEmptyUnicodeString(&NtOsInstall->SystemNtPath,
|
|
|
|
(PWCHAR)((ULONG_PTR)(NtOsInstall + 1) + ArcPathLength),
|
|
|
|
NtPathLength);
|
|
|
|
RtlCopyUnicodeString(&NtOsInstall->SystemNtPath, SystemRootNtPath);
|
|
|
|
NtOsInstall->PathComponent = NtOsInstall->SystemNtPath.Buffer +
|
|
|
|
(PathComponent - SystemRootNtPath->Buffer);
|
|
|
|
|
[SETUPLIB] Introduce a lot of (Work in progress) functions to manipulate boot entries from different boot "stores".
This concerns so far, only freeldr.ini and to an extent, boot.ini, but planning in the future to add support for registry-oriented BCD
as well as possibly direct (u)EFI entries, using the corresponding NT functions.
This code is so far only used in osdetect.c, but will be soon used by usetup's bootsup.c (note that some helper functions: CreateCommonFreeLdrSections()
and (Un)protectBootIni() are already taken from it and used in bldrsup.c).
- In EnumerateNTOSBootEntries(), continue enumerating the boot entries until the user callback returns an status code that is not successful.
- Remove some old code from osdetect.c; use directly BootEntry->FriendlyName when building the display names of the available installations, since now
BootEntry->FriendlyName is a PCWSTR (and not a UNICODE_STRING anymore).
svn path=/branches/setup_improvements/; revision=74943
[SETUPLIB] Make the NTOS_BOOT_ENTRY structure more generic, so that it can wrap around either actual NTOS boot entry options, or FreeLdr-like boot-sector options.
In a sense, the NTOS_BOOT_ENTRY structure now looks much more like the NT structure "BOOT_ENTRY".
- Adapt the code in bldrsup.c to these modifications, and re-enable FreeLdr-like boot-sector-file support code that was commented out.
More code cleanup will follow later.
svn path=/branches/setup_improvements/; revision=74952
2017-06-07 15:58:44 +00:00
|
|
|
RtlStringCchCopyW(NtOsInstall->InstallationName,
|
|
|
|
ARRAYSIZE(NtOsInstall->InstallationName),
|
|
|
|
InstallationName);
|
2017-05-13 16:13:19 +00:00
|
|
|
|
2017-12-29 18:37:28 +00:00
|
|
|
RtlStringCchCopyW(NtOsInstall->VendorName,
|
|
|
|
ARRAYSIZE(NtOsInstall->VendorName),
|
|
|
|
VendorName);
|
|
|
|
|
|
|
|
AppendGenericListEntry(List, NtOsInstall, FALSE);
|
2017-05-13 16:13:19 +00:00
|
|
|
|
|
|
|
return NtOsInstall;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VOID
|
|
|
|
FindNTOSInstallations(
|
2017-05-22 01:19:08 +00:00
|
|
|
IN OUT PGENERIC_LIST List,
|
|
|
|
IN PPARTLIST PartList,
|
|
|
|
IN PPARTENTRY PartEntry)
|
2017-05-13 16:13:19 +00:00
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
2017-05-22 22:59:11 +00:00
|
|
|
ULONG DiskNumber = PartEntry->DiskEntry->DiskNumber;
|
|
|
|
ULONG PartitionNumber = PartEntry->PartitionNumber;
|
[SETUPLIB] Introduce a lot of (Work in progress) functions to manipulate boot entries from different boot "stores".
This concerns so far, only freeldr.ini and to an extent, boot.ini, but planning in the future to add support for registry-oriented BCD
as well as possibly direct (u)EFI entries, using the corresponding NT functions.
This code is so far only used in osdetect.c, but will be soon used by usetup's bootsup.c (note that some helper functions: CreateCommonFreeLdrSections()
and (Un)protectBootIni() are already taken from it and used in bldrsup.c).
- In EnumerateNTOSBootEntries(), continue enumerating the boot entries until the user callback returns an status code that is not successful.
- Remove some old code from osdetect.c; use directly BootEntry->FriendlyName when building the display names of the available installations, since now
BootEntry->FriendlyName is a PCWSTR (and not a UNICODE_STRING anymore).
svn path=/branches/setup_improvements/; revision=74943
[SETUPLIB] Make the NTOS_BOOT_ENTRY structure more generic, so that it can wrap around either actual NTOS boot entry options, or FreeLdr-like boot-sector options.
In a sense, the NTOS_BOOT_ENTRY structure now looks much more like the NT structure "BOOT_ENTRY".
- Adapt the code in bldrsup.c to these modifications, and re-enable FreeLdr-like boot-sector-file support code that was commented out.
More code cleanup will follow later.
svn path=/branches/setup_improvements/; revision=74952
2017-06-07 15:58:44 +00:00
|
|
|
HANDLE PartitionDirectoryHandle;
|
2017-05-13 16:13:19 +00:00
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
UNICODE_STRING PartitionRootPath;
|
2017-06-08 17:30:23 +00:00
|
|
|
BOOT_STORE_TYPE Type;
|
[SETUPLIB] Introduce a lot of (Work in progress) functions to manipulate boot entries from different boot "stores".
This concerns so far, only freeldr.ini and to an extent, boot.ini, but planning in the future to add support for registry-oriented BCD
as well as possibly direct (u)EFI entries, using the corresponding NT functions.
This code is so far only used in osdetect.c, but will be soon used by usetup's bootsup.c (note that some helper functions: CreateCommonFreeLdrSections()
and (Un)protectBootIni() are already taken from it and used in bldrsup.c).
- In EnumerateNTOSBootEntries(), continue enumerating the boot entries until the user callback returns an status code that is not successful.
- Remove some old code from osdetect.c; use directly BootEntry->FriendlyName when building the display names of the available installations, since now
BootEntry->FriendlyName is a PCWSTR (and not a UNICODE_STRING anymore).
svn path=/branches/setup_improvements/; revision=74943
[SETUPLIB] Make the NTOS_BOOT_ENTRY structure more generic, so that it can wrap around either actual NTOS boot entry options, or FreeLdr-like boot-sector options.
In a sense, the NTOS_BOOT_ENTRY structure now looks much more like the NT structure "BOOT_ENTRY".
- Adapt the code in bldrsup.c to these modifications, and re-enable FreeLdr-like boot-sector-file support code that was commented out.
More code cleanup will follow later.
svn path=/branches/setup_improvements/; revision=74952
2017-06-07 15:58:44 +00:00
|
|
|
PVOID BootStoreHandle;
|
2017-05-25 23:52:50 +00:00
|
|
|
ENUM_INSTALLS_DATA Data;
|
|
|
|
ULONG Version;
|
2017-05-13 16:13:19 +00:00
|
|
|
WCHAR PathBuffer[MAX_PATH];
|
2017-05-22 01:19:08 +00:00
|
|
|
|
2019-02-24 18:04:57 +00:00
|
|
|
ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
|
|
|
|
|
2017-05-13 16:13:19 +00:00
|
|
|
/* Set PartitionRootPath */
|
[SETUPLIB] Introduce a lot of (Work in progress) functions to manipulate boot entries from different boot "stores".
This concerns so far, only freeldr.ini and to an extent, boot.ini, but planning in the future to add support for registry-oriented BCD
as well as possibly direct (u)EFI entries, using the corresponding NT functions.
This code is so far only used in osdetect.c, but will be soon used by usetup's bootsup.c (note that some helper functions: CreateCommonFreeLdrSections()
and (Un)protectBootIni() are already taken from it and used in bldrsup.c).
- In EnumerateNTOSBootEntries(), continue enumerating the boot entries until the user callback returns an status code that is not successful.
- Remove some old code from osdetect.c; use directly BootEntry->FriendlyName when building the display names of the available installations, since now
BootEntry->FriendlyName is a PCWSTR (and not a UNICODE_STRING anymore).
svn path=/branches/setup_improvements/; revision=74943
[SETUPLIB] Make the NTOS_BOOT_ENTRY structure more generic, so that it can wrap around either actual NTOS boot entry options, or FreeLdr-like boot-sector options.
In a sense, the NTOS_BOOT_ENTRY structure now looks much more like the NT structure "BOOT_ENTRY".
- Adapt the code in bldrsup.c to these modifications, and re-enable FreeLdr-like boot-sector-file support code that was commented out.
More code cleanup will follow later.
svn path=/branches/setup_improvements/; revision=74952
2017-06-07 15:58:44 +00:00
|
|
|
RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
|
|
|
|
L"\\Device\\Harddisk%lu\\Partition%lu\\",
|
|
|
|
DiskNumber, PartitionNumber);
|
2017-05-13 16:13:19 +00:00
|
|
|
RtlInitUnicodeString(&PartitionRootPath, PathBuffer);
|
2018-10-28 22:33:29 +00:00
|
|
|
DPRINT("FindNTOSInstallations: PartitionRootPath: '%wZ'\n", &PartitionRootPath);
|
2017-05-13 16:13:19 +00:00
|
|
|
|
|
|
|
/* Open the partition */
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&PartitionRootPath,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
[SETUPLIB] Introduce a lot of (Work in progress) functions to manipulate boot entries from different boot "stores".
This concerns so far, only freeldr.ini and to an extent, boot.ini, but planning in the future to add support for registry-oriented BCD
as well as possibly direct (u)EFI entries, using the corresponding NT functions.
This code is so far only used in osdetect.c, but will be soon used by usetup's bootsup.c (note that some helper functions: CreateCommonFreeLdrSections()
and (Un)protectBootIni() are already taken from it and used in bldrsup.c).
- In EnumerateNTOSBootEntries(), continue enumerating the boot entries until the user callback returns an status code that is not successful.
- Remove some old code from osdetect.c; use directly BootEntry->FriendlyName when building the display names of the available installations, since now
BootEntry->FriendlyName is a PCWSTR (and not a UNICODE_STRING anymore).
svn path=/branches/setup_improvements/; revision=74943
[SETUPLIB] Make the NTOS_BOOT_ENTRY structure more generic, so that it can wrap around either actual NTOS boot entry options, or FreeLdr-like boot-sector options.
In a sense, the NTOS_BOOT_ENTRY structure now looks much more like the NT structure "BOOT_ENTRY".
- Adapt the code in bldrsup.c to these modifications, and re-enable FreeLdr-like boot-sector-file support code that was commented out.
More code cleanup will follow later.
svn path=/branches/setup_improvements/; revision=74952
2017-06-07 15:58:44 +00:00
|
|
|
Status = NtOpenFile(&PartitionDirectoryHandle,
|
|
|
|
FILE_LIST_DIRECTORY | FILE_TRAVERSE | SYNCHRONIZE,
|
2017-05-13 16:13:19 +00:00
|
|
|
&ObjectAttributes,
|
|
|
|
&IoStatusBlock,
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
|
|
FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2017-05-22 22:59:11 +00:00
|
|
|
DPRINT1("Failed to open partition '%wZ', Status 0x%08lx\n", &PartitionRootPath, Status);
|
2017-05-13 16:13:19 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-05-25 23:52:50 +00:00
|
|
|
Data.List = List;
|
|
|
|
Data.PartList = PartList;
|
|
|
|
|
2017-05-13 16:13:19 +00:00
|
|
|
/* Try to see whether we recognize some NT boot loaders */
|
2017-05-25 23:52:50 +00:00
|
|
|
for (Type = FreeLdr; Type < BldrTypeMax; ++Type)
|
2017-05-13 16:13:19 +00:00
|
|
|
{
|
2017-06-08 17:30:23 +00:00
|
|
|
Status = FindBootStore(PartitionDirectoryHandle, Type, &Version);
|
2017-05-13 16:13:19 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* The loader does not exist, continue with another one */
|
2018-10-28 22:33:29 +00:00
|
|
|
DPRINT("Loader type '%d' does not exist, or an error happened (Status 0x%08lx), continue with another one...\n",
|
|
|
|
Type, Status);
|
2017-05-13 16:13:19 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-05-25 23:52:50 +00:00
|
|
|
/* The loader exists, try to enumerate its boot entries */
|
2018-10-28 22:33:29 +00:00
|
|
|
DPRINT("Analyze the OS installations for loader type '%d' in disk #%d, partition #%d\n",
|
|
|
|
Type, DiskNumber, PartitionNumber);
|
2017-05-13 16:13:19 +00:00
|
|
|
|
2017-06-08 17:30:23 +00:00
|
|
|
Status = OpenBootStoreByHandle(&BootStoreHandle, PartitionDirectoryHandle, Type, FALSE);
|
[SETUPLIB] Introduce a lot of (Work in progress) functions to manipulate boot entries from different boot "stores".
This concerns so far, only freeldr.ini and to an extent, boot.ini, but planning in the future to add support for registry-oriented BCD
as well as possibly direct (u)EFI entries, using the corresponding NT functions.
This code is so far only used in osdetect.c, but will be soon used by usetup's bootsup.c (note that some helper functions: CreateCommonFreeLdrSections()
and (Un)protectBootIni() are already taken from it and used in bldrsup.c).
- In EnumerateNTOSBootEntries(), continue enumerating the boot entries until the user callback returns an status code that is not successful.
- Remove some old code from osdetect.c; use directly BootEntry->FriendlyName when building the display names of the available installations, since now
BootEntry->FriendlyName is a PCWSTR (and not a UNICODE_STRING anymore).
svn path=/branches/setup_improvements/; revision=74943
[SETUPLIB] Make the NTOS_BOOT_ENTRY structure more generic, so that it can wrap around either actual NTOS boot entry options, or FreeLdr-like boot-sector options.
In a sense, the NTOS_BOOT_ENTRY structure now looks much more like the NT structure "BOOT_ENTRY".
- Adapt the code in bldrsup.c to these modifications, and re-enable FreeLdr-like boot-sector-file support code that was commented out.
More code cleanup will follow later.
svn path=/branches/setup_improvements/; revision=74952
2017-06-07 15:58:44 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Could not open the NTOS boot store of type '%d' (Status 0x%08lx), continue with another one...\n",
|
|
|
|
Type, Status);
|
|
|
|
continue;
|
|
|
|
}
|
2017-06-08 17:30:23 +00:00
|
|
|
EnumerateBootStoreEntries(BootStoreHandle, EnumerateInstallations, &Data);
|
|
|
|
CloseBootStore(BootStoreHandle);
|
2017-05-13 16:13:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Close the partition */
|
[SETUPLIB] Introduce a lot of (Work in progress) functions to manipulate boot entries from different boot "stores".
This concerns so far, only freeldr.ini and to an extent, boot.ini, but planning in the future to add support for registry-oriented BCD
as well as possibly direct (u)EFI entries, using the corresponding NT functions.
This code is so far only used in osdetect.c, but will be soon used by usetup's bootsup.c (note that some helper functions: CreateCommonFreeLdrSections()
and (Un)protectBootIni() are already taken from it and used in bldrsup.c).
- In EnumerateNTOSBootEntries(), continue enumerating the boot entries until the user callback returns an status code that is not successful.
- Remove some old code from osdetect.c; use directly BootEntry->FriendlyName when building the display names of the available installations, since now
BootEntry->FriendlyName is a PCWSTR (and not a UNICODE_STRING anymore).
svn path=/branches/setup_improvements/; revision=74943
[SETUPLIB] Make the NTOS_BOOT_ENTRY structure more generic, so that it can wrap around either actual NTOS boot entry options, or FreeLdr-like boot-sector options.
In a sense, the NTOS_BOOT_ENTRY structure now looks much more like the NT structure "BOOT_ENTRY".
- Adapt the code in bldrsup.c to these modifications, and re-enable FreeLdr-like boot-sector-file support code that was commented out.
More code cleanup will follow later.
svn path=/branches/setup_improvements/; revision=74952
2017-06-07 15:58:44 +00:00
|
|
|
NtClose(PartitionDirectoryHandle);
|
2017-05-13 16:13:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
FORCEINLINE BOOLEAN
|
|
|
|
ShouldICheckThisPartition(
|
|
|
|
IN PPARTENTRY PartEntry)
|
|
|
|
{
|
|
|
|
if (!PartEntry)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return PartEntry->IsPartitioned &&
|
|
|
|
!IsContainerPartition(PartEntry->PartitionType) /* alternatively: PartEntry->PartitionNumber != 0 */ &&
|
|
|
|
!PartEntry->New &&
|
|
|
|
(PartEntry->FormatState == Preformatted /* || PartEntry->FormatState == Formatted */);
|
|
|
|
}
|
|
|
|
|
|
|
|
// EnumerateNTOSInstallations
|
|
|
|
PGENERIC_LIST
|
|
|
|
CreateNTOSInstallationsList(
|
|
|
|
IN PPARTLIST PartList)
|
|
|
|
{
|
|
|
|
PGENERIC_LIST List;
|
|
|
|
PLIST_ENTRY Entry, Entry2;
|
|
|
|
PDISKENTRY DiskEntry;
|
|
|
|
PPARTENTRY PartEntry;
|
|
|
|
|
|
|
|
List = CreateGenericList();
|
|
|
|
if (List == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* Loop each available disk ... */
|
|
|
|
Entry = PartList->DiskListHead.Flink;
|
|
|
|
while (Entry != &PartList->DiskListHead)
|
|
|
|
{
|
|
|
|
DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
|
|
|
|
Entry = Entry->Flink;
|
|
|
|
|
2018-10-28 22:33:29 +00:00
|
|
|
DPRINT("Disk #%d\n", DiskEntry->DiskNumber);
|
2017-05-13 16:13:19 +00:00
|
|
|
|
|
|
|
/* ... and for each disk, loop each available partition */
|
|
|
|
|
|
|
|
/* First, the primary partitions */
|
|
|
|
Entry2 = DiskEntry->PrimaryPartListHead.Flink;
|
|
|
|
while (Entry2 != &DiskEntry->PrimaryPartListHead)
|
|
|
|
{
|
|
|
|
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
|
|
|
|
Entry2 = Entry2->Flink;
|
|
|
|
|
2017-05-22 01:19:08 +00:00
|
|
|
ASSERT(PartEntry->DiskEntry == DiskEntry);
|
|
|
|
|
2018-10-28 22:33:29 +00:00
|
|
|
DPRINT(" Primary Partition #%d, index %d - Type 0x%02x, IsLogical = %s, IsPartitioned = %s, IsNew = %s, AutoCreate = %s, FormatState = %lu -- Should I check it? %s\n",
|
|
|
|
PartEntry->PartitionNumber, PartEntry->PartitionIndex,
|
|
|
|
PartEntry->PartitionType, PartEntry->LogicalPartition ? "TRUE" : "FALSE",
|
|
|
|
PartEntry->IsPartitioned ? "TRUE" : "FALSE",
|
|
|
|
PartEntry->New ? "Yes" : "No",
|
|
|
|
PartEntry->AutoCreate ? "Yes" : "No",
|
|
|
|
PartEntry->FormatState,
|
|
|
|
ShouldICheckThisPartition(PartEntry) ? "YES!" : "NO!");
|
2017-05-13 16:13:19 +00:00
|
|
|
|
|
|
|
if (ShouldICheckThisPartition(PartEntry))
|
2017-05-22 01:19:08 +00:00
|
|
|
FindNTOSInstallations(List, PartList, PartEntry);
|
2017-05-13 16:13:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Then, the logical partitions (present in the extended partition) */
|
|
|
|
Entry2 = DiskEntry->LogicalPartListHead.Flink;
|
|
|
|
while (Entry2 != &DiskEntry->LogicalPartListHead)
|
|
|
|
{
|
|
|
|
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
|
|
|
|
Entry2 = Entry2->Flink;
|
|
|
|
|
2017-05-22 01:19:08 +00:00
|
|
|
ASSERT(PartEntry->DiskEntry == DiskEntry);
|
|
|
|
|
2018-10-28 22:33:29 +00:00
|
|
|
DPRINT(" Logical Partition #%d, index %d - Type 0x%02x, IsLogical = %s, IsPartitioned = %s, IsNew = %s, AutoCreate = %s, FormatState = %lu -- Should I check it? %s\n",
|
|
|
|
PartEntry->PartitionNumber, PartEntry->PartitionIndex,
|
|
|
|
PartEntry->PartitionType, PartEntry->LogicalPartition ? "TRUE" : "FALSE",
|
|
|
|
PartEntry->IsPartitioned ? "TRUE" : "FALSE",
|
|
|
|
PartEntry->New ? "Yes" : "No",
|
|
|
|
PartEntry->AutoCreate ? "Yes" : "No",
|
|
|
|
PartEntry->FormatState,
|
|
|
|
ShouldICheckThisPartition(PartEntry) ? "YES!" : "NO!");
|
2017-05-13 16:13:19 +00:00
|
|
|
|
|
|
|
if (ShouldICheckThisPartition(PartEntry))
|
2017-05-22 01:19:08 +00:00
|
|
|
FindNTOSInstallations(List, PartList, PartEntry);
|
2017-05-13 16:13:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-28 22:33:29 +00:00
|
|
|
#ifndef NDEBUG
|
2017-05-13 16:13:19 +00:00
|
|
|
/**** Debugging: List all the collected installations ****/
|
2017-05-22 01:19:08 +00:00
|
|
|
DumpNTOSInstalls(List);
|
2018-10-28 22:33:29 +00:00
|
|
|
#endif
|
2017-05-13 16:13:19 +00:00
|
|
|
|
|
|
|
return List;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|