[SETUPLIB] Retrieve and store the machine (architecture) ID of the discovered NTOS...
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 28 Jan 2018 22:32:52 +0000 (23:32 +0100)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Mon, 5 Nov 2018 23:09:13 +0000 (00:09 +0100)
base/setup/lib/utils/osdetect.c
base/setup/lib/utils/osdetect.h

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