[SETUPLIB] Store the vendor name for each discovered NTOS installation.

Take also the opportunity to simplify a little bit the code.
This commit is contained in:
Hermès Bélusca-Maïto 2017-12-29 19:37:28 +01:00
parent a5bcd956fa
commit f80ec8b822
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
2 changed files with 93 additions and 71 deletions

View file

@ -26,18 +26,15 @@
/* GLOBALS ******************************************************************/ /* GLOBALS ******************************************************************/
/* Language-independent Vendor strings */ /* Language-independent Vendor strings */
static const PCWSTR KnownVendors[] = { L"ReactOS", L"Microsoft" }; static const PCWSTR KnownVendors[] = { VENDOR_REACTOS, VENDOR_MICROSOFT };
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
static BOOLEAN static BOOLEAN
IsValidNTOSInstallation_UStr(
IN PUNICODE_STRING SystemRootPath);
/*static*/ BOOLEAN
IsValidNTOSInstallation( IsValidNTOSInstallation(
IN PCWSTR SystemRoot); IN PUNICODE_STRING SystemRootPath,
OUT PUNICODE_STRING VendorName OPTIONAL);
static PNTOS_INSTALLATION static PNTOS_INSTALLATION
FindExistingNTOSInstall( FindExistingNTOSInstall(
@ -49,13 +46,14 @@ FindExistingNTOSInstall(
static PNTOS_INSTALLATION static PNTOS_INSTALLATION
AddNTOSInstallation( AddNTOSInstallation(
IN PGENERIC_LIST List, IN PGENERIC_LIST List,
IN PCWSTR InstallationName,
IN PCWSTR VendorName,
IN PCWSTR SystemRootArcPath, IN PCWSTR SystemRootArcPath,
IN PUNICODE_STRING SystemRootNtPath, // or PCWSTR ? IN PUNICODE_STRING SystemRootNtPath, // or PCWSTR ?
IN PCWSTR PathComponent, // Pointer inside SystemRootNtPath buffer IN PCWSTR PathComponent, // Pointer inside SystemRootNtPath buffer
IN ULONG DiskNumber, IN ULONG DiskNumber,
IN ULONG PartitionNumber, IN ULONG PartitionNumber,
IN PPARTENTRY PartEntry OPTIONAL, IN PPARTENTRY PartEntry OPTIONAL);
IN PCWSTR InstallationName);
typedef struct _ENUM_INSTALLS_DATA typedef struct _ENUM_INSTALLS_DATA
{ {
@ -74,17 +72,20 @@ EnumerateInstallations(
{ {
PENUM_INSTALLS_DATA Data = (PENUM_INSTALLS_DATA)Parameter; PENUM_INSTALLS_DATA Data = (PENUM_INSTALLS_DATA)Parameter;
PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions; PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
PNTOS_INSTALLATION NtOsInstall; PNTOS_INSTALLATION NtOsInstall;
UNICODE_STRING SystemRootPath;
WCHAR SystemRoot[MAX_PATH];
WCHAR InstallNameW[MAX_PATH];
ULONG DiskNumber = 0, PartitionNumber = 0; ULONG DiskNumber = 0, PartitionNumber = 0;
PCWSTR PathComponent = NULL; PCWSTR PathComponent = NULL;
PDISKENTRY DiskEntry = NULL; PDISKENTRY DiskEntry = NULL;
PPARTENTRY PartEntry = NULL; PPARTENTRY PartEntry = NULL;
UNICODE_STRING SystemRootPath;
WCHAR SystemRoot[MAX_PATH];
UNICODE_STRING VendorName;
WCHAR VendorNameBuffer[MAX_PATH];
/* We have a boot entry */ /* We have a boot entry */
/* Check for supported boot type "Windows2003" */ /* Check for supported boot type "Windows2003" */
@ -126,8 +127,8 @@ EnumerateInstallations(
NtOsInstall = FindExistingNTOSInstall(Data->List, Options->OsLoadPath, NULL); NtOsInstall = FindExistingNTOSInstall(Data->List, Options->OsLoadPath, NULL);
if (NtOsInstall) if (NtOsInstall)
{ {
DPRINT1(" An NTOS installation with name \"%S\" already exists in SystemRoot '%wZ'\n", DPRINT1(" An NTOS installation with name \"%S\" from vendor \"%S\" already exists in SystemRoot '%wZ'\n",
NtOsInstall->InstallationName, &NtOsInstall->SystemArcPath); NtOsInstall->InstallationName, NtOsInstall->VendorName, &NtOsInstall->SystemArcPath);
/* Continue the enumeration */ /* Continue the enumeration */
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -155,8 +156,8 @@ EnumerateInstallations(
NtOsInstall = FindExistingNTOSInstall(Data->List, NULL /*Options->OsLoadPath*/, &SystemRootPath); NtOsInstall = FindExistingNTOSInstall(Data->List, NULL /*Options->OsLoadPath*/, &SystemRootPath);
if (NtOsInstall) if (NtOsInstall)
{ {
DPRINT1(" An NTOS installation with name \"%S\" already exists in SystemRoot '%wZ'\n", DPRINT1(" An NTOS installation with name \"%S\" from vendor \"%S\" already exists in SystemRoot '%wZ'\n",
NtOsInstall->InstallationName, &NtOsInstall->SystemNtPath); NtOsInstall->InstallationName, NtOsInstall->VendorName, &NtOsInstall->SystemNtPath);
/* Continue the enumeration */ /* Continue the enumeration */
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -164,7 +165,8 @@ EnumerateInstallations(
DPRINT1("EnumerateInstallations: SystemRootPath: '%wZ'\n", &SystemRootPath); DPRINT1("EnumerateInstallations: SystemRootPath: '%wZ'\n", &SystemRootPath);
/* 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 */
if (!IsValidNTOSInstallation_UStr(&SystemRootPath)) RtlInitEmptyUnicodeString(&VendorName, VendorNameBuffer, sizeof(VendorNameBuffer));
if (!IsValidNTOSInstallation(&SystemRootPath, &VendorName))
{ {
/* Continue the enumeration */ /* Continue the enumeration */
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -192,27 +194,12 @@ EnumerateInstallations(
} }
/* Add the discovered NTOS installation into the list */ /* Add the discovered NTOS installation into the list */
if (PartEntry && PartEntry->DriveLetter) AddNTOSInstallation(Data->List,
{ BootEntry->FriendlyName,
/* We have retrieved a partition that is mounted */ VendorName.Buffer, // FIXME: What if it's not NULL-terminated?
RtlStringCchPrintfW(InstallNameW, ARRAYSIZE(InstallNameW), Options->OsLoadPath,
L"%C:%s \"%s\"",
PartEntry->DriveLetter,
PathComponent,
BootEntry->FriendlyName);
}
else
{
/* We failed somewhere, just show the NT path */
RtlStringCchPrintfW(InstallNameW, ARRAYSIZE(InstallNameW),
L"%wZ \"%s\"",
&SystemRootPath,
BootEntry->FriendlyName);
}
AddNTOSInstallation(Data->List, Options->OsLoadPath,
&SystemRootPath, PathComponent, &SystemRootPath, PathComponent,
DiskNumber, PartitionNumber, PartEntry, DiskNumber, PartitionNumber, PartEntry);
InstallNameW);
/* Continue the enumeration */ /* Continue the enumeration */
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -348,14 +335,28 @@ UnmapCloseFile:
// //
static BOOLEAN static BOOLEAN
IsValidNTOSInstallationByHandle( IsValidNTOSInstallationByHandle(
IN HANDLE SystemRootDirectory) IN HANDLE SystemRootDirectory,
OUT PUNICODE_STRING VendorName OPTIONAL)
{ {
BOOLEAN Success = FALSE; BOOLEAN Success = FALSE;
PCWSTR PathName; PCWSTR PathName;
USHORT i; USHORT i;
UNICODE_STRING VendorName; UNICODE_STRING LocalVendorName;
WCHAR VendorNameBuffer[MAX_PATH]; WCHAR VendorNameBuffer[MAX_PATH];
/* 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;
}
/* Check for the existence of \SystemRoot\System32 */ /* Check for the existence of \SystemRoot\System32 */
PathName = L"System32\\"; PathName = L"System32\\";
if (!DoesDirExist(SystemRootDirectory, PathName)) if (!DoesDirExist(SystemRootDirectory, PathName))
@ -399,11 +400,11 @@ IsValidNTOSInstallationByHandle(
} }
#endif #endif
RtlInitEmptyUnicodeString(&VendorName, VendorNameBuffer, sizeof(VendorNameBuffer)); RtlInitEmptyUnicodeString(&LocalVendorName, VendorNameBuffer, sizeof(VendorNameBuffer));
/* 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, &VendorName); Success = CheckForValidPEAndVendor(SystemRootDirectory, PathName, &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);
@ -412,7 +413,7 @@ IsValidNTOSInstallationByHandle(
{ {
for (i = 0; i < ARRAYSIZE(KnownVendors); ++i) for (i = 0; i < ARRAYSIZE(KnownVendors); ++i)
{ {
Success = !!FindSubStrI(VendorName.Buffer, KnownVendors[i]); Success = !!FindSubStrI(LocalVendorName.Buffer, KnownVendors[i]);
if (Success) if (Success)
{ {
/* We have found a correct vendor combination */ /* We have found a correct vendor combination */
@ -422,18 +423,26 @@ IsValidNTOSInstallationByHandle(
} }
} }
/* 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, &VendorName); Success = CheckForValidPEAndVendor(SystemRootDirectory, PathName, &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)
{ {
if (!!FindSubStrI(VendorName.Buffer, KnownVendors[i])) if (!!FindSubStrI(LocalVendorName.Buffer, KnownVendors[i]))
{ {
/* We have found a correct vendor combination */ /* We have found a correct vendor combination */
DPRINT1("IsValidNTOSInstallation: The user-mode DLL '%S' is from %S\n", PathName, KnownVendors[i]); DPRINT1("IsValidNTOSInstallation: The user-mode DLL '%S' is from %S\n", PathName, KnownVendors[i]);
@ -442,12 +451,21 @@ IsValidNTOSInstallationByHandle(
} }
} }
/* 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;
} }
static BOOLEAN static BOOLEAN
IsValidNTOSInstallation_UStr( IsValidNTOSInstallation(
IN PUNICODE_STRING SystemRootPath) IN PUNICODE_STRING SystemRootPath,
OUT PUNICODE_STRING VendorName OPTIONAL)
{ {
NTSTATUS Status; NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
@ -473,22 +491,13 @@ IsValidNTOSInstallation_UStr(
return FALSE; return FALSE;
} }
Success = IsValidNTOSInstallationByHandle(SystemRootDirectory); Success = IsValidNTOSInstallationByHandle(SystemRootDirectory, VendorName);
/* Done! */ /* Done! */
NtClose(SystemRootDirectory); NtClose(SystemRootDirectory);
return Success; return Success;
} }
/*static*/ BOOLEAN
IsValidNTOSInstallation(
IN PCWSTR SystemRoot)
{
UNICODE_STRING SystemRootPath;
RtlInitUnicodeString(&SystemRootPath, SystemRoot);
return IsValidNTOSInstallationByHandle(&SystemRootPath);
}
static VOID static VOID
DumpNTOSInstalls( DumpNTOSInstalls(
IN PGENERIC_LIST List) IN PGENERIC_LIST List)
@ -502,11 +511,9 @@ DumpNTOSInstalls(
NtOsInstallsCount, NtOsInstallsCount,
NtOsInstallsCount >= 2 ? "s" : ""); NtOsInstallsCount >= 2 ? "s" : "");
Entry = GetFirstListEntry(List); for (Entry = GetFirstListEntry(List); Entry; Entry = GetNextListEntry(Entry))
while (Entry)
{ {
NtOsInstall = (PNTOS_INSTALLATION)GetListEntryUserData(Entry); NtOsInstall = (PNTOS_INSTALLATION)GetListEntryData(Entry);
Entry = GetNextListEntry(Entry);
DPRINT1(" On disk #%d, partition #%d: Installation \"%S\" in SystemRoot '%wZ'\n", DPRINT1(" On disk #%d, partition #%d: Installation \"%S\" in SystemRoot '%wZ'\n",
NtOsInstall->DiskNumber, NtOsInstall->PartitionNumber, NtOsInstall->DiskNumber, NtOsInstall->PartitionNumber,
@ -536,11 +543,9 @@ FindExistingNTOSInstall(
RtlInitUnicodeString(&SystemArcPath, SystemRootArcPath); RtlInitUnicodeString(&SystemArcPath, SystemRootArcPath);
Entry = GetFirstListEntry(List); for (Entry = GetFirstListEntry(List); Entry; Entry = GetNextListEntry(Entry))
while (Entry)
{ {
NtOsInstall = (PNTOS_INSTALLATION)GetListEntryUserData(Entry); NtOsInstall = (PNTOS_INSTALLATION)GetListEntryData(Entry);
Entry = GetNextListEntry(Entry);
/* /*
* Note that if both ARC paths are equal, then the corresponding * Note that if both ARC paths are equal, then the corresponding
@ -565,13 +570,14 @@ FindExistingNTOSInstall(
static PNTOS_INSTALLATION static PNTOS_INSTALLATION
AddNTOSInstallation( AddNTOSInstallation(
IN PGENERIC_LIST List, IN PGENERIC_LIST List,
IN PCWSTR InstallationName,
IN PCWSTR VendorName,
IN PCWSTR SystemRootArcPath, IN PCWSTR SystemRootArcPath,
IN PUNICODE_STRING SystemRootNtPath, // or PCWSTR ? IN PUNICODE_STRING SystemRootNtPath, // or PCWSTR ?
IN PCWSTR PathComponent, // Pointer inside SystemRootNtPath buffer IN PCWSTR PathComponent, // Pointer inside SystemRootNtPath buffer
IN ULONG DiskNumber, IN ULONG DiskNumber,
IN ULONG PartitionNumber, IN ULONG PartitionNumber,
IN PPARTENTRY PartEntry OPTIONAL, IN PPARTENTRY PartEntry OPTIONAL)
IN PCWSTR InstallationName)
{ {
PNTOS_INSTALLATION NtOsInstall; PNTOS_INSTALLATION NtOsInstall;
SIZE_T ArcPathLength, NtPathLength; SIZE_T ArcPathLength, NtPathLength;
@ -580,8 +586,9 @@ AddNTOSInstallation(
NtOsInstall = FindExistingNTOSInstall(List, SystemRootArcPath, SystemRootNtPath); NtOsInstall = FindExistingNTOSInstall(List, SystemRootArcPath, SystemRootNtPath);
if (NtOsInstall) if (NtOsInstall)
{ {
DPRINT1("An NTOS installation with name \"%S\" already exists on disk #%d, partition #%d, in SystemRoot '%wZ'\n", DPRINT1("An NTOS installation with name \"%S\" from vendor \"%S\" already exists on disk #%d, partition #%d, in SystemRoot '%wZ'\n",
NtOsInstall->InstallationName, NtOsInstall->DiskNumber, NtOsInstall->PartitionNumber, &NtOsInstall->SystemNtPath); NtOsInstall->InstallationName, NtOsInstall->VendorName,
NtOsInstall->DiskNumber, NtOsInstall->PartitionNumber, &NtOsInstall->SystemNtPath);
// //
// NOTE: We may use its "IsDefault" attribute, and only keep the entries that have IsDefault == TRUE... // 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. // Setting IsDefault to TRUE would imply searching for the "Default" entry in the loader configuration file.
@ -621,8 +628,11 @@ AddNTOSInstallation(
ARRAYSIZE(NtOsInstall->InstallationName), ARRAYSIZE(NtOsInstall->InstallationName),
InstallationName); InstallationName);
// Having the GENERIC_LIST storing the display item string plainly sucks... RtlStringCchCopyW(NtOsInstall->VendorName,
AppendGenericListEntry(List, InstallationName, NtOsInstall, FALSE); ARRAYSIZE(NtOsInstall->VendorName),
VendorName);
AppendGenericListEntry(List, NtOsInstall, FALSE);
return NtOsInstall; return NtOsInstall;
} }

View file

@ -8,11 +8,14 @@
#pragma once #pragma once
/* Language-independent Vendor strings */
#define VENDOR_REACTOS L"ReactOS"
#define VENDOR_MICROSOFT L"Microsoft"
typedef struct _NTOS_INSTALLATION 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.
// Vendor???? (Microsoft / ReactOS)
UNICODE_STRING SystemArcPath; // Normalized ARC path UNICODE_STRING SystemArcPath; // Normalized ARC path
UNICODE_STRING SystemNtPath; // Corresponding NT path UNICODE_STRING SystemNtPath; // Corresponding NT path
PCWSTR PathComponent; // Pointer inside SystemNtPath.Buffer PCWSTR PathComponent; // Pointer inside SystemNtPath.Buffer
@ -20,6 +23,8 @@ typedef struct _NTOS_INSTALLATION
ULONG PartitionNumber; ULONG PartitionNumber;
PPARTENTRY PartEntry; PPARTENTRY PartEntry;
WCHAR InstallationName[MAX_PATH]; WCHAR InstallationName[MAX_PATH];
WCHAR VendorName[MAX_PATH];
// CHAR Data[ANYSIZE_ARRAY];
} NTOS_INSTALLATION, *PNTOS_INSTALLATION; } NTOS_INSTALLATION, *PNTOS_INSTALLATION;
// EnumerateNTOSInstallations // EnumerateNTOSInstallations
@ -27,4 +32,11 @@ PGENERIC_LIST
CreateNTOSInstallationsList( CreateNTOSInstallationsList(
IN PPARTLIST List); IN PPARTLIST List);
/*
* 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.
*/
PCWSTR FindSubStrI(PCWSTR str, PCWSTR strSearch);
/* EOF */ /* EOF */