Hi again,
some comments inline.
On 2017-05-15 03:59, hbelusca(a)svn.reactos.org wrote:
---
branches/setup_improvements/base/setup/usetup/osdetect.c [iso-8859-1] (original)
+++ branches/setup_improvements/base/setup/usetup/osdetect.c [iso-8859-1] Mon May 15
01:59:28 2017
@@ -19,6 +19,9 @@
/* GLOBALS ******************************************************************/
extern PPARTLIST PartitionList;
+
+/* Language-independent Vendor strings */
+static const PCWSTR KnownVendors[] = { L"ReactOS", L"Microsoft" };
/* VERSION RESOURCE API ******************************************************/
@@ -361,36 +364,331 @@
#endif
+
+/***
+*wchar_t *wcsstr(string1, string2) - search for string2 in string1
+* (wide strings)
Copypasta?
+*
+*Purpose:
+* finds the first occurrence of string2 in string1 (wide strings)
+*
+*Entry:
+* wchar_t *string1 - string to search in
+* wchar_t *string2 - string to search for
+*
+*Exit:
+* returns a pointer to the first occurrence of string2 in
+* string1, or NULL if string2 does not occur in string1
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+PWSTR FindSubStrI(PCWSTR str, PCWSTR strSearch)
+{
+ PWSTR cp = (PWSTR)str;
+ PWSTR s1, s2;
+
+ if (!*strSearch)
+ return (PWSTR)str;
+
+ while (*cp)
+ {
+ s1 = cp;
+ s2 = (PWSTR)strSearch;
+
+ while (*s1 && *s2 && (towupper(*s1) == towupper(*s2)))
+ ++s1, ++s2;
+
+ if (!*s2)
+ return cp;
+
+ ++cp;
+ }
+
+ return NULL;
+}
+
static BOOLEAN
-IsRecognizedOS(
+CheckForValidPEAndVendor(
+ IN HANDLE RootDirectory OPTIONAL,
+ IN PCWSTR PathName OPTIONAL,
+ IN PCWSTR FileName, // OPTIONAL
+ IN PCWSTR VendorName // Better would be OUT PCWSTR*, and the function returning
NTSTATUS ?
+ )
+{
+ BOOLEAN Success = FALSE;
+ NTSTATUS Status;
+ HANDLE FileHandle, SectionHandle;
+ // SIZE_T ViewSize;
+ PVOID ViewBase;
+ PVOID VersionBuffer = NULL; // Read-only
+ PVOID pvData = NULL;
+ UINT BufLen = 0;
+
+ Status = OpenAndMapFile(RootDirectory, PathName, FileName,
+ &FileHandle, &SectionHandle, &ViewBase);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to open and map file %wZ, Status 0x%08lx\n",
&FileName, Status);
+ return FALSE; // Status;
+ }
+
+ /* Make sure it's a valid PE file */
+ if (!RtlImageNtHeader(ViewBase))
+ {
+ DPRINT1("File %wZ does not seem to be a valid PE, bail out\n",
&FileName);
+ Status = STATUS_INVALID_IMAGE_FORMAT;
+ goto UnmapFile;
+ }
+
+ /*
+ * 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))
+ {
+ DPRINT1("Failed to get version resource for file %wZ, Status
0x%08lx\n", &FileName, Status);
+ goto UnmapFile;
+ }
+
+ Status = NtVerQueryValue(VersionBuffer, L"\\VarFileInfo\\Translation",
&pvData, &BufLen);
+ if (NT_SUCCESS(Status))
+ {
+ USHORT wCodePage = 0, wLangID = 0;
+ WCHAR FileInfo[MAX_PATH];
+ UNICODE_STRING Vendor;
+
+ wCodePage = LOWORD(*(ULONG*)pvData);
+ wLangID = HIWORD(*(ULONG*)pvData);
+
+ StringCchPrintfW(FileInfo, ARRAYSIZE(FileInfo),
+ L"StringFileInfo\\%04X%04X\\CompanyName",
+ wCodePage, wLangID);
+
+ Status = NtVerQueryValue(VersionBuffer, FileInfo, &pvData, &BufLen);
+ if (NT_SUCCESS(Status) && pvData)
+ {
+ /* BufLen includes the NULL terminator count */
+ RtlInitEmptyUnicodeString(&Vendor, pvData, BufLen * sizeof(WCHAR));
+ Vendor.Length = Vendor.MaximumLength - sizeof(UNICODE_NULL);
+
+ DPRINT1("Found version vendor: \"%wZ\" for file %wZ\n",
&Vendor, &FileName);
+
+ Success = !!FindSubStrI(pvData, VendorName);
+ }
+ else
+ {
+ DPRINT1("No version vendor found for file %wZ\n", &FileName);
+ }
+ }
+
+UnmapFile:
+ /* Finally, unmap and close the file */
+ UnMapFile(SectionHandle, ViewBase);
+ NtClose(FileHandle);
This seems clumsy. If there's a single function to open and map the
file, why isn't there one function to unmap and close?
+
+ return Success;
+}
+
+static BOOLEAN
+IsValidNTOSInstallation(
+ IN HANDLE PartitionHandle,
+ IN PCWSTR SystemRoot)
+{
+ BOOLEAN Success = FALSE;
+ USHORT i;
+ WCHAR PathBuffer[MAX_PATH];
+
+ // DoesPathExist(PartitionHandle, SystemRoot, L"System32\\"); etc...
+
+ /* Check for the existence of \SystemRoot\System32 */
+ StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer), L"%s%s", SystemRoot,
L"System32\\");
+ if (!DoesPathExist(PartitionHandle, PathBuffer))
+ {
+ // DPRINT1("Failed to open directory %wZ, Status 0x%08lx\n",
&FileName, Status);
You know there's DPRINT for exactly this purpose, right?
+ return FALSE;
+ }
+
+ /* Check for the existence of \SystemRoot\System32\drivers */
+ StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer), L"%s%s", SystemRoot,
L"System32\\drivers\\");
+ if (!DoesPathExist(PartitionHandle, PathBuffer))
+ {
+ // DPRINT1("Failed to open directory %wZ, Status 0x%08lx\n",
&FileName, Status);
+ return FALSE;
+ }
+
+ /* Check for the existence of \SystemRoot\System32\config */
+ StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer), L"%s%s", SystemRoot,
L"System32\\config\\");
+ if (!DoesPathExist(PartitionHandle, PathBuffer))
+ {
+ // DPRINT1("Failed to open directory %wZ, Status 0x%08lx\n",
&FileName, Status);
+ 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).
+ */
+ if (!DoesFileExist(PartitionHandle, SystemRoot,
L"System32\\config\\SYSTEM"))
+ {
+ // DPRINT1("Failed to open file %wZ, Status 0x%08lx\n", &FileName,
Status);
+ return FALSE;
+ }
+ if (!DoesFileExist(PartitionHandle, SystemRoot,
L"System32\\config\\SOFTWARE"))
+ {
+ // DPRINT1("Failed to open file %wZ, Status 0x%08lx\n", &FileName,
Status);
+ return FALSE;
+ }
+#endif
+
+ for (i = 0; i < ARRAYSIZE(KnownVendors); ++i)
+ {
+ /* Check for the existence of \SystemRoot\System32\ntoskrnl.exe and verify its
version */
+ Success = CheckForValidPEAndVendor(PartitionHandle, SystemRoot,
L"System32\\ntoskrnl.exe", KnownVendors[i]);
+
+ /* OPTIONAL: Check for the existence of \SystemRoot\System32\ntkrnlpa.exe */
+
+ /* Check for the existence of \SystemRoot\System32\ntdll.dll */
+ Success = CheckForValidPEAndVendor(PartitionHandle, SystemRoot,
L"System32\\ntdll.dll", KnownVendors[i]);
+
+ /* We have found a correct vendor combination */
+ if (Success)
+ break;
+ }
+
+ return Success;
+}
+
+typedef struct _NTOS_INSTALLATION
+{
+ LIST_ENTRY ListEntry;
+ ULONG DiskNumber;
+ ULONG PartitionNumber;
+// Vendor????
+ WCHAR SystemRoot[MAX_PATH];
+/**/WCHAR InstallationName[MAX_PATH];/**/
+} NTOS_INSTALLATION, *PNTOS_INSTALLATION;
+
+static VOID
+ListNTOSInstalls(
+ IN PGENERIC_LIST List)
+{
+ PGENERIC_LIST_ENTRY Entry;
+ PNTOS_INSTALLATION NtOsInstall;
+ ULONG NtOsInstallsCount = GetNumberOfListEntries(List);
+
+ DPRINT1("There %s %d installation%s detected:\n",
+ NtOsInstallsCount >= 2 ? "are" : "is",
+ NtOsInstallsCount,
+ NtOsInstallsCount >= 2 ? "s" : "");
+
+ Entry = GetFirstListEntry(List);
+ while (Entry)
+ {
+ NtOsInstall = (PNTOS_INSTALLATION)GetListEntryUserData(Entry);
Casts from PVOID to other pointer types are unnecessary.
Thanks,
Thomas