[SETUPLIB] Retrieve and store the machine (architecture) ID of the discovered NTOS installations. Will be used later.

This commit is contained in:
Hermès Bélusca-Maïto 2018-01-28 23:32:52 +01:00
parent f41750ab7f
commit e282ec39a2
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
2 changed files with 66 additions and 26 deletions

View file

@ -34,6 +34,7 @@ static const PCWSTR KnownVendors[] = { VENDOR_REACTOS, VENDOR_MICROSOFT };
static BOOLEAN static BOOLEAN
IsValidNTOSInstallation( IsValidNTOSInstallation(
IN PUNICODE_STRING SystemRootPath, IN PUNICODE_STRING SystemRootPath,
OUT PUSHORT Machine OPTIONAL,
OUT PUNICODE_STRING VendorName OPTIONAL); OUT PUNICODE_STRING VendorName OPTIONAL);
static PNTOS_INSTALLATION static PNTOS_INSTALLATION
@ -47,6 +48,7 @@ static PNTOS_INSTALLATION
AddNTOSInstallation( AddNTOSInstallation(
IN PGENERIC_LIST List, IN PGENERIC_LIST List,
IN PCWSTR InstallationName, IN PCWSTR InstallationName,
IN USHORT Machine,
IN PCWSTR VendorName, IN PCWSTR VendorName,
IN PCWSTR SystemRootArcPath, IN PCWSTR SystemRootArcPath,
IN PUNICODE_STRING SystemRootNtPath, // or PCWSTR ? IN PUNICODE_STRING SystemRootNtPath, // or PCWSTR ?
@ -82,6 +84,7 @@ EnumerateInstallations(
UNICODE_STRING SystemRootPath; UNICODE_STRING SystemRootPath;
WCHAR SystemRoot[MAX_PATH]; WCHAR SystemRoot[MAX_PATH];
USHORT Machine;
UNICODE_STRING VendorName; UNICODE_STRING VendorName;
WCHAR VendorNameBuffer[MAX_PATH]; WCHAR VendorNameBuffer[MAX_PATH];
@ -166,7 +169,7 @@ EnumerateInstallations(
/* Check if this is a valid NTOS installation; stop there if it isn't one */ /* Check if this is a valid NTOS installation; stop there if it isn't one */
RtlInitEmptyUnicodeString(&VendorName, VendorNameBuffer, sizeof(VendorNameBuffer)); RtlInitEmptyUnicodeString(&VendorName, VendorNameBuffer, sizeof(VendorNameBuffer));
if (!IsValidNTOSInstallation(&SystemRootPath, &VendorName)) if (!IsValidNTOSInstallation(&SystemRootPath, &Machine, &VendorName))
{ {
/* Continue the enumeration */ /* Continue the enumeration */
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -196,6 +199,7 @@ EnumerateInstallations(
/* Add the discovered NTOS installation into the list */ /* Add the discovered NTOS installation into the list */
AddNTOSInstallation(Data->List, AddNTOSInstallation(Data->List,
BootEntry->FriendlyName, BootEntry->FriendlyName,
Machine,
VendorName.Buffer, // FIXME: What if it's not NULL-terminated? VendorName.Buffer, // FIXME: What if it's not NULL-terminated?
Options->OsLoadPath, Options->OsLoadPath,
&SystemRootPath, PathComponent, &SystemRootPath, PathComponent,
@ -239,14 +243,15 @@ static BOOLEAN
CheckForValidPEAndVendor( CheckForValidPEAndVendor(
IN HANDLE RootDirectory OPTIONAL, IN HANDLE RootDirectory OPTIONAL,
IN PCWSTR PathNameToFile, IN PCWSTR PathNameToFile,
OUT PUNICODE_STRING VendorName OUT PUSHORT Machine,
) OUT PUNICODE_STRING VendorName)
{ {
BOOLEAN Success = FALSE; BOOLEAN Success = FALSE;
NTSTATUS Status; NTSTATUS Status;
HANDLE FileHandle, SectionHandle; HANDLE FileHandle, SectionHandle;
// SIZE_T ViewSize; // SIZE_T ViewSize;
PVOID ViewBase; PVOID ViewBase;
PIMAGE_NT_HEADERS NtHeader;
PVOID VersionBuffer = NULL; // Read-only PVOID VersionBuffer = NULL; // Read-only
PVOID pvData = NULL; PVOID pvData = NULL;
UINT BufLen = 0; UINT BufLen = 0;
@ -266,14 +271,18 @@ CheckForValidPEAndVendor(
return FALSE; // Status; return FALSE; // Status;
} }
/* Make sure it's a valid PE file */ /* Make sure it's a valid NT PE file */
if (!RtlImageNtHeader(ViewBase)) NtHeader = RtlImageNtHeader(ViewBase);
if (!NtHeader)
{ {
DPRINT1("File '%S' does not seem to be a valid PE, bail out\n", PathNameToFile); DPRINT1("File '%S' does not seem to be a valid NT PE file, bail out\n", PathNameToFile);
Status = STATUS_INVALID_IMAGE_FORMAT; Status = STATUS_INVALID_IMAGE_FORMAT;
goto UnmapCloseFile; goto UnmapCloseFile;
} }
/* Retrieve the target architecture of this PE module */
*Machine = NtHeader->FileHeader.Machine;
/* /*
* Search for a valid executable version and vendor. * Search for a valid executable version and vendor.
* NOTE: The module is loaded as a data file, it should be marked as such. * NOTE: The module is loaded as a data file, it should be marked as such.
@ -336,11 +345,13 @@ UnmapCloseFile:
static BOOLEAN static BOOLEAN
IsValidNTOSInstallationByHandle( IsValidNTOSInstallationByHandle(
IN HANDLE SystemRootDirectory, IN HANDLE SystemRootDirectory,
OUT PUSHORT Machine OPTIONAL,
OUT PUNICODE_STRING VendorName OPTIONAL) OUT PUNICODE_STRING VendorName OPTIONAL)
{ {
BOOLEAN Success = FALSE; BOOLEAN Success = FALSE;
PCWSTR PathName; PCWSTR PathName;
USHORT i; USHORT i;
USHORT LocalMachine;
UNICODE_STRING LocalVendorName; UNICODE_STRING LocalVendorName;
WCHAR VendorNameBuffer[MAX_PATH]; WCHAR VendorNameBuffer[MAX_PATH];
@ -404,11 +415,17 @@ IsValidNTOSInstallationByHandle(
/* Check for the existence of \SystemRoot\System32\ntoskrnl.exe and retrieves its vendor name */ /* Check for the existence of \SystemRoot\System32\ntoskrnl.exe and retrieves its vendor name */
PathName = L"System32\\ntoskrnl.exe"; PathName = L"System32\\ntoskrnl.exe";
Success = CheckForValidPEAndVendor(SystemRootDirectory, PathName, &LocalVendorName); Success = CheckForValidPEAndVendor(SystemRootDirectory, PathName, &LocalMachine, &LocalVendorName);
if (!Success) if (!Success)
DPRINT1("Kernel executable '%S' is either not a PE file, or does not have any vendor?\n", PathName); 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 */ /*
* 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.
*/
if (Success) if (Success)
{ {
for (i = 0; i < ARRAYSIZE(KnownVendors); ++i) for (i = 0; i < ARRAYSIZE(KnownVendors); ++i)
@ -421,23 +438,32 @@ IsValidNTOSInstallationByHandle(
break; break;
} }
} }
}
/* Return the vendor name */ /* Return the target architecture */
if (VendorName) if (Machine)
{ {
/* Copy the string and invalidate the pointer */ /* Copy the value and invalidate the pointer */
RtlCopyUnicodeString(VendorName, &LocalVendorName); *Machine = LocalMachine;
VendorName = NULL; Machine = NULL;
}
/* Return the vendor name */
if (VendorName)
{
/* Copy the string and invalidate the pointer */
RtlCopyUnicodeString(VendorName, &LocalVendorName);
VendorName = NULL;
}
} }
/* OPTIONAL: Check for the existence of \SystemRoot\System32\ntkrnlpa.exe */ /* OPTIONAL: Check for the existence of \SystemRoot\System32\ntkrnlpa.exe */
/* Check for the existence of \SystemRoot\System32\ntdll.dll and retrieves its vendor name */ /* Check for the existence of \SystemRoot\System32\ntdll.dll and retrieves its vendor name */
PathName = L"System32\\ntdll.dll"; PathName = L"System32\\ntdll.dll";
Success = CheckForValidPEAndVendor(SystemRootDirectory, PathName, &LocalVendorName); Success = CheckForValidPEAndVendor(SystemRootDirectory, PathName, &LocalMachine, &LocalVendorName);
if (!Success) if (!Success)
DPRINT1("User-mode DLL '%S' is either not a PE file, or does not have any vendor?\n", PathName); DPRINT1("User-mode DLL '%S' is either not a PE file, or does not have any vendor?\n", PathName);
if (Success) if (Success)
{ {
for (i = 0; i < ARRAYSIZE(KnownVendors); ++i) for (i = 0; i < ARRAYSIZE(KnownVendors); ++i)
@ -449,14 +475,22 @@ IsValidNTOSInstallationByHandle(
break; break;
} }
} }
}
/* Return the vendor name if not already obtained */ /* Return the target architecture if not already obtained */
if (VendorName) if (Machine)
{ {
/* Copy the string and invalidate the pointer */ /* Copy the value and invalidate the pointer */
RtlCopyUnicodeString(VendorName, &LocalVendorName); *Machine = LocalMachine;
VendorName = NULL; Machine = NULL;
}
/* Return the vendor name if not already obtained */
if (VendorName)
{
/* Copy the string and invalidate the pointer */
RtlCopyUnicodeString(VendorName, &LocalVendorName);
VendorName = NULL;
}
} }
return Success; return Success;
@ -465,6 +499,7 @@ IsValidNTOSInstallationByHandle(
static BOOLEAN static BOOLEAN
IsValidNTOSInstallation( IsValidNTOSInstallation(
IN PUNICODE_STRING SystemRootPath, IN PUNICODE_STRING SystemRootPath,
OUT PUSHORT Machine,
OUT PUNICODE_STRING VendorName OPTIONAL) OUT PUNICODE_STRING VendorName OPTIONAL)
{ {
NTSTATUS Status; NTSTATUS Status;
@ -491,7 +526,8 @@ IsValidNTOSInstallation(
return FALSE; return FALSE;
} }
Success = IsValidNTOSInstallationByHandle(SystemRootDirectory, VendorName); Success = IsValidNTOSInstallationByHandle(SystemRootDirectory,
Machine, VendorName);
/* Done! */ /* Done! */
NtClose(SystemRootDirectory); NtClose(SystemRootDirectory);
@ -573,6 +609,7 @@ static PNTOS_INSTALLATION
AddNTOSInstallation( AddNTOSInstallation(
IN PGENERIC_LIST List, IN PGENERIC_LIST List,
IN PCWSTR InstallationName, IN PCWSTR InstallationName,
IN USHORT Machine,
IN PCWSTR VendorName, IN PCWSTR VendorName,
IN PCWSTR SystemRootArcPath, IN PCWSTR SystemRootArcPath,
IN PUNICODE_STRING SystemRootNtPath, // or PCWSTR ? IN PUNICODE_STRING SystemRootNtPath, // or PCWSTR ?
@ -613,6 +650,8 @@ AddNTOSInstallation(
NtOsInstall->PartitionNumber = PartitionNumber; NtOsInstall->PartitionNumber = PartitionNumber;
NtOsInstall->PartEntry = PartEntry; NtOsInstall->PartEntry = PartEntry;
NtOsInstall->Machine = Machine;
RtlInitEmptyUnicodeString(&NtOsInstall->SystemArcPath, RtlInitEmptyUnicodeString(&NtOsInstall->SystemArcPath,
(PWCHAR)(NtOsInstall + 1), (PWCHAR)(NtOsInstall + 1),
ArcPathLength); ArcPathLength);

View file

@ -16,8 +16,9 @@ typedef struct _NTOS_INSTALLATION
{ {
LIST_ENTRY ListEntry; LIST_ENTRY ListEntry;
// BOOLEAN IsDefault; // TRUE / FALSE whether this installation is marked as "default" in its corresponding loader configuration file. // BOOLEAN IsDefault; // TRUE / FALSE whether this installation is marked as "default" in its corresponding loader configuration file.
UNICODE_STRING SystemArcPath; // Normalized ARC path USHORT Machine; // Target architecture of the NTOS installation
UNICODE_STRING SystemNtPath; // Corresponding NT path UNICODE_STRING SystemArcPath; // Normalized ARC path ("ArcSystemRoot")
UNICODE_STRING SystemNtPath; // Corresponding NT path ("NtSystemRoot")
PCWSTR PathComponent; // Pointer inside SystemNtPath.Buffer PCWSTR PathComponent; // Pointer inside SystemNtPath.Buffer
ULONG DiskNumber; ULONG DiskNumber;
ULONG PartitionNumber; ULONG PartitionNumber;