Author: tfaber
Date: Mon May 22 12:20:31 2017
New Revision: 74623
URL: http://svn.reactos.org/svn/reactos?rev=74623&view=rev
Log:
[HAL]
- Correctly prepare the I/O port map for V86 mode by making HalpSavedIoMap actually point to it instead of to the parent structure. Fixes boot with video BIOS code that relies on I/O ports FF00 through FFFF.
CORE-13306 #resolve
Modified:
trunk/reactos/hal/halx86/generic/bios.c
Modified: trunk/reactos/hal/halx86/generic/bios.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/generic/bios.c?…
==============================================================================
--- trunk/reactos/hal/halx86/generic/bios.c [iso-8859-1] (original)
+++ trunk/reactos/hal/halx86/generic/bios.c [iso-8859-1] Mon May 22 12:20:31 2017
@@ -390,7 +390,7 @@
//
// Loop the I/O Map
//
- for (i = j = 0; i < (IOPM_SIZE) / 2; i++)
+ for (i = j = 0; i < IOPM_SIZE / sizeof(USHORT); i++)
{
//
// Check for non-FFFF entry
@@ -415,7 +415,10 @@
//
// Terminate it
//
- while (i++ < (IOPM_FULL_SIZE / 2)) *Entry++ = 0xFFFF;
+ while (i++ < IOPM_FULL_SIZE / sizeof(USHORT))
+ {
+ *Entry++ = 0xFFFF;
+ }
//
// Return the entries we saved
@@ -542,7 +545,7 @@
//
// Save a copy of the I/O Map and delete it
//
- HalpSavedIoMap = (PUSHORT)&(KeGetPcr()->TSS->IoMaps[0]);
+ HalpSavedIoMap = (PUSHORT)KeGetPcr()->TSS->IoMaps[0].IoMap;
HalpStoreAndClearIopm();
//
Author: hbelusca
Date: Mon May 22 01:19:08 2017
New Revision: 74622
URL: http://svn.reactos.org/svn/reactos?rev=74622&view=rev
Log:
[USETUP]: Improve the NTOS installations detector. In all the disks/partitions available, it searches for the presence of freeldr.ini / boot.ini, open & parse them, and enumerates the available boot entries (as candidates for installations). For each of them, it maps their ARC paths into the NT namespace (hence the ARC 2 NT path resolver committed in r74621), then attempts to detect in these paths the existence of NTOS installations.
The code needs some cleaning (and factoring out redundancies, etc...) but works: http://i.imgur.com/cSDN3La.png
In this example, there is a ReactOS installation on the second primary partition "D:" formatted in FAT32, and a Windows installation on the logical partition "F:" and they are correctly recognized as such (the ARC paths in the freeldr.ini/boot.ini are mapped to NT paths from which we can recognize the presence of an installation, then the hard-disk & partition numbers are mapped back to the correct partition, and from there the partition letters are retrieved correctly and displayed in the installations list on the left in the screenshot).
NOTE: If you try to compile the usetup branch, it won't (yet), because I don't commit yet some local changes I have regarding how the functions DoesPathExist() and DoesFileExist() are used (I'm trying to stabilize their interface).
Modified:
branches/setup_improvements/base/setup/usetup/osdetect.c
branches/setup_improvements/base/setup/usetup/osdetect.h
Modified: branches/setup_improvements/base/setup/usetup/osdetect.c
URL: http://svn.reactos.org/svn/reactos/branches/setup_improvements/base/setup/u…
==============================================================================
--- 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 22 01:19:08 2017
@@ -92,28 +92,41 @@
// {BootMgr, L"bootmgr" , ???}
};
-#if 0
-
-static VOID
-EnumerateInstallationsFreeLdr()
+
+static BOOLEAN
+IsValidNTOSInstallation(
+ IN HANDLE SystemRootDirectory OPTIONAL,
+ IN PCWSTR SystemRoot OPTIONAL);
+
+static PNTOS_INSTALLATION
+AddNTOSInstallation(
+ IN PGENERIC_LIST List,
+ IN ULONG DiskNumber,
+ IN ULONG PartitionNumber,
+ IN PCWSTR SystemRoot,
+ IN PCWSTR InstallationName);
+
+static NTSTATUS
+FreeLdrEnumerateInstallations(
+ IN OUT PGENERIC_LIST List,
+ IN PPARTLIST PartList,
+ // IN PPARTENTRY PartEntry,
+ IN PCHAR FileBuffer,
+ IN ULONG FileLength)
{
NTSTATUS Status;
PINICACHE IniCache;
- PINICACHESECTION IniSection;
- PINICACHESECTION OsIniSection;
- WCHAR SectionName[80];
- WCHAR OsName[80];
- WCHAR SystemPath[200];
- WCHAR SectionName2[200];
- PWCHAR KeyData;
- ULONG i,j;
+ PINICACHEITERATOR Iterator;
+ PINICACHESECTION IniSection, OsIniSection;
+ PWCHAR SectionName, KeyData;
+ WCHAR InstallName[MAX_PATH];
/* Open an *existing* FreeLdr.ini configuration file */
- Status = IniCacheLoad(&IniCache, IniPath, FALSE);
+ Status = IniCacheLoadFromMemory(&IniCache, FileBuffer, FileLength, FALSE);
if (!NT_SUCCESS(Status))
return Status;
- /* Get "Operating Systems" section */
+ /* Get the "Operating Systems" section */
IniSection = IniCacheGetSection(IniCache, L"Operating Systems");
if (IniSection == NULL)
{
@@ -121,69 +134,335 @@
return STATUS_UNSUCCESSFUL;
}
- /* NOTE that we enumerate all the valid installations, not just the default one */
- while (TRUE)
- {
- Status = IniCacheGetKey(IniSection, SectionName, &KeyData);
+ /* Enumerate all the valid installations */
+ Iterator = IniCacheFindFirstValue(IniSection, &SectionName, &KeyData);
+ if (!Iterator) goto Quit;
+ do
+ {
+ // FIXME: Poor-man quotes removal (improvement over bootsup.c:UpdateFreeLoaderIni).
+ if (KeyData[0] == L'"')
+ {
+ /* Quoted name, copy up to the closing quote */
+ PWCHAR Begin = &KeyData[1];
+ PWCHAR End = wcschr(Begin, L'"');
+ if (!End)
+ End = Begin + wcslen(Begin);
+ StringCchCopyNW(InstallName, ARRAYSIZE(InstallName),
+ Begin, End - Begin);
+ }
+ else
+ {
+ /* Non-quoted name, copy everything */
+ StringCchCopyW(InstallName, ARRAYSIZE(InstallName), KeyData);
+ }
+
+ DPRINT1("Possible installation '%S' in OS section '%S'\n", InstallName, SectionName);
+
+ /* Search for an existing ReactOS entry */
+ OsIniSection = IniCacheGetSection(IniCache, SectionName);
+ if (!OsIniSection)
+ continue;
+
+ /* Check for supported boot type "Windows2003" */
+ Status = IniCacheGetKey(OsIniSection, L"BootType", &KeyData);
+ if (NT_SUCCESS(Status))
+ {
+ // TODO: What to do with "Windows" ; "WindowsNT40" ; "ReactOSSetup" ?
+ if ((KeyData == NULL) ||
+ ( (_wcsicmp(KeyData, L"Windows2003") != 0) &&
+ (_wcsicmp(KeyData, L"\"Windows2003\"") != 0) ))
+ {
+ /* This is not a ReactOS entry */
+ continue;
+ }
+ }
+ else
+ {
+ /* Certainly not a ReactOS installation */
+ continue;
+ }
+
+ /* BootType is Windows2003. Now check SystemPath. */
+ Status = IniCacheGetKey(OsIniSection, L"SystemPath", &KeyData);
if (!NT_SUCCESS(Status))
- break;
-
- // TODO some foobaring...
-
- // TODO 2 : Remind the entry name so that we may display it as available installation...
-
- /* Search for an existing ReactOS entry */
- OsIniSection = IniCacheGetSection(IniCache, SectionName2);
- if (OsIniSection != NULL)
- {
- BOOLEAN UseExistingEntry = TRUE;
-
- /* Check for supported boot type "Windows2003" */
- Status = IniCacheGetKey(OsIniSection, L"BootType", &KeyData);
- if (NT_SUCCESS(Status))
+ {
+ DPRINT1(" A Win2k3 install '%S' without an ARC path?!\n", InstallName);
+ continue;
+ }
+
+ {
+ HANDLE SystemRootDirectory;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING SystemRootPath;
+ WCHAR SystemRoot[MAX_PATH];
+ WCHAR InstallNameW[MAX_PATH];
+
+ DPRINT1(" Found a candidate Win2k3 install '%S' with ARC path '%S'\n", InstallName, KeyData);
+
+ // Note that in ARC path, the disk number is the BIOS disk number, so a conversion
+ // should be done.
+
+ // TODO 1: Normalize the ARC path.
+
+ // TODO 2: Check whether we already have an installation with this ARC path.
+ // If that's the case, stop there. If not, continue...
+
+ /*
+ * 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));
+ if (!ArcPathToNtPath(&SystemRootPath, KeyData, PartList))
+ {
+ DPRINT1("ArcPathToNtPath(%S) failed, installation skipped.\n", KeyData);
+ // FIXME: Do not continue!
+ continue;
+ }
+
+ DPRINT1("ArcPathToNtPath() succeeded: %S --> %wZ\n", KeyData, &SystemRootPath);
+
+ // TODO 3: Check whether we already have an installation with this NT path.
+ // If that's the case, stop there. If not, continue...
+
+ /* Set SystemRootPath */
+ DPRINT1("FreeLdrEnumerateInstallations: SystemRootPath: %wZ\n", &SystemRootPath);
+
+ /* Open SystemRootPath */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &SystemRootPath,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ Status = NtOpenFile(&SystemRootDirectory,
+ FILE_LIST_DIRECTORY | SYNCHRONIZE,
+ &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);
+ continue;
+ }
+
+ if (IsValidNTOSInstallation(SystemRootDirectory, NULL))
+ {
+ ULONG DiskNumber, PartitionNumber;
+ PCWSTR PathComponent;
+ PDISKENTRY DiskEntry = NULL;
+ PPARTENTRY PartEntry = NULL;
+
+ DPRINT1("Found a valid NTOS installation in SystemRoot ARC path %S, NT path %wZ\n", KeyData, &SystemRootPath);
+
+ /* From the NT path, compute the disk, partition and path components */
+ if (NtPathToDiskPartComponents(SystemRootPath.Buffer, &DiskNumber, &PartitionNumber, &PathComponent))
{
- if ((KeyData == NULL) ||
- ( (_wcsicmp(KeyData, L"Windows2003") != 0) &&
- (_wcsicmp(KeyData, L"\"Windows2003\"") != 0) ))
- {
- /* This is not a ReactOS entry */
- UseExistingEntry = FALSE;
- }
+ DPRINT1("SystemRootPath = '%wZ' points to disk #%d, partition #%d, path '%S'\n",
+ &SystemRootPath, DiskNumber, PartitionNumber, PathComponent);
+
+ /* Retrieve the corresponding disk and partition */
+ if (!GetDiskOrPartition(PartList, DiskNumber, PartitionNumber, &DiskEntry, &PartEntry))
+ DPRINT1("GetDiskOrPartition(disk #%d, partition #%d) failed\n", DiskNumber, PartitionNumber);
}
else
{
- UseExistingEntry = FALSE;
+ DPRINT1("NtPathToDiskPartComponents(%wZ) failed\n", &SystemRootPath);
}
- if (UseExistingEntry)
+ if (PartEntry && PartEntry->DriveLetter)
{
- /* BootType is Windows2003. Now check SystemPath. */
- Status = IniCacheGetKey(OsIniSection, L"SystemPath", &KeyData);
- if (NT_SUCCESS(Status))
- {
- swprintf(SystemPath, L"\"%s\"", ArcPath);
- if ((KeyData == NULL) ||
- ( (_wcsicmp(KeyData, ArcPath) != 0) &&
- (_wcsicmp(KeyData, SystemPath) != 0) ))
- {
- /* This entry is a ReactOS entry, but the SystemRoot
- does not match the one we are looking for. */
- UseExistingEntry = FALSE;
- }
- }
- else
- {
- UseExistingEntry = FALSE;
- }
+ /* We have retrieved a partition that is mounted */
+ StringCchPrintfW(InstallNameW, ARRAYSIZE(InstallNameW), L"%C:%s \"%s\"",
+ PartEntry->DriveLetter, PathComponent, InstallName);
}
- }
- }
-
+ else
+ {
+ /* We failed somewhere, just show the NT path */
+ StringCchPrintfW(InstallNameW, ARRAYSIZE(InstallNameW), L"%wZ \"%s\"",
+ &SystemRootPath, InstallName);
+ }
+ AddNTOSInstallation(List, 0, 0 /*DiskNumber, PartitionNumber*/, KeyData, InstallNameW);
+ }
+
+ NtClose(SystemRootDirectory);
+ }
+ }
+ while (IniCacheFindNextValue(Iterator, &SectionName, &KeyData));
+
+ IniCacheFindClose(Iterator);
+
+Quit:
IniCacheDestroy(IniCache);
-}
-
-#endif
-
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+NtLdrEnumerateInstallations(
+ IN OUT PGENERIC_LIST List,
+ IN PPARTLIST PartList,
+ // IN PPARTENTRY PartEntry,
+ IN PCHAR FileBuffer,
+ IN ULONG FileLength)
+{
+ NTSTATUS Status;
+ PINICACHE IniCache;
+ PINICACHEITERATOR Iterator;
+ PINICACHESECTION IniSection;
+ PWCHAR SectionName, KeyData;
+ WCHAR InstallName[MAX_PATH];
+
+ /* Open an *existing* FreeLdr.ini configuration file */
+ Status = IniCacheLoadFromMemory(&IniCache, FileBuffer, FileLength, FALSE);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ /* Get the "Operating Systems" section */
+ IniSection = IniCacheGetSection(IniCache, L"operating systems");
+ if (IniSection == NULL)
+ {
+ IniCacheDestroy(IniCache);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /* Enumerate all the valid installations */
+ Iterator = IniCacheFindFirstValue(IniSection, &SectionName, &KeyData);
+ if (!Iterator) goto Quit;
+ do
+ {
+ // FIXME: Poor-man quotes removal (improvement over bootsup.c:UpdateFreeLoaderIni).
+ if (KeyData[0] == L'"')
+ {
+ /* Quoted name, copy up to the closing quote */
+ PWCHAR Begin = &KeyData[1];
+ PWCHAR End = wcschr(Begin, L'"');
+ if (!End)
+ End = Begin + wcslen(Begin);
+ StringCchCopyNW(InstallName, ARRAYSIZE(InstallName),
+ Begin, End - Begin);
+ }
+ else
+ {
+ /* Non-quoted name, copy everything */
+ StringCchCopyW(InstallName, ARRAYSIZE(InstallName), KeyData);
+ }
+
+ DPRINT1("Possible installation '%S' with ARC path '%S'\n", InstallName, SectionName);
+
+ // FIXME TODO: Determine whether we indeed have an ARC path, in which case
+ // this is an NT installation, or, whether we have something else like a DOS
+ // path, which means that we are booting a boot sector...
+
+ DPRINT1(" Found a Win2k3 install '%S' with ARC path '%S'\n", InstallName, SectionName);
+ // TODO: Dissect it in order to retrieve the real disk drive & partition numbers.
+ // Note that in ARC path, the disk number is the BIOS disk number, so a conversion
+ // should be done.
+ {
+ HANDLE SystemRootDirectory;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING SystemRootPath;
+ WCHAR SystemRoot[MAX_PATH];
+ WCHAR InstallNameW[MAX_PATH];
+
+ // Note that in ARC path, the disk number is the BIOS disk number, so a conversion
+ // should be done.
+
+ // TODO 1: Normalize the ARC path.
+
+ // TODO 2: Check whether we already have an installation with this ARC path.
+ // If that's the case, stop there. If not, continue...
+
+ /*
+ * 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));
+ if (!ArcPathToNtPath(&SystemRootPath, SectionName, PartList))
+ {
+ DPRINT1("ArcPathToNtPath(%S) failed, installation skipped.\n", SectionName);
+ // FIXME: Do not continue!
+ continue;
+ }
+
+ DPRINT1("ArcPathToNtPath() succeeded: %S --> %wZ\n", SectionName, &SystemRootPath);
+
+ // TODO 3: Check whether we already have an installation with this NT path.
+ // If that's the case, stop there. If not, continue...
+
+ /* Set SystemRootPath */
+ DPRINT1("NtLdrEnumerateInstallations: SystemRootPath: %wZ\n", &SystemRootPath);
+
+ /* Open SystemRootPath */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &SystemRootPath,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ Status = NtOpenFile(&SystemRootDirectory,
+ FILE_LIST_DIRECTORY | SYNCHRONIZE,
+ &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);
+ continue;
+ }
+
+ if (IsValidNTOSInstallation(SystemRootDirectory, NULL))
+ {
+ ULONG DiskNumber, PartitionNumber;
+ PCWSTR PathComponent;
+ PDISKENTRY DiskEntry = NULL;
+ PPARTENTRY PartEntry = NULL;
+
+ DPRINT1("Found a valid NTOS installation in SystemRoot ARC path %S, NT path %wZ\n", SectionName, &SystemRootPath);
+
+ /* From the NT path, compute the disk, partition and path components */
+ if (NtPathToDiskPartComponents(SystemRootPath.Buffer, &DiskNumber, &PartitionNumber, &PathComponent))
+ {
+ DPRINT1("SystemRootPath = '%wZ' points to disk #%d, partition #%d, path '%S'\n",
+ &SystemRootPath, DiskNumber, PartitionNumber, PathComponent);
+
+ /* Retrieve the corresponding disk and partition */
+ if (!GetDiskOrPartition(PartList, DiskNumber, PartitionNumber, &DiskEntry, &PartEntry))
+ DPRINT1("GetDiskOrPartition(disk #%d, partition #%d) failed\n", DiskNumber, PartitionNumber);
+ }
+ else
+ {
+ DPRINT1("NtPathToDiskPartComponents(%wZ) failed\n", &SystemRootPath);
+ }
+
+ if (PartEntry && PartEntry->DriveLetter)
+ {
+ /* We have retrieved a partition that is mounted */
+ StringCchPrintfW(InstallNameW, ARRAYSIZE(InstallNameW), L"%C:%s \"%s\"",
+ PartEntry->DriveLetter, PathComponent, InstallName);
+ }
+ else
+ {
+ /* We failed somewhere, just show the NT path */
+ StringCchPrintfW(InstallNameW, ARRAYSIZE(InstallNameW), L"%wZ \"%s\"",
+ &SystemRootPath, InstallName);
+ }
+ AddNTOSInstallation(List, 0, 0 /*DiskNumber, PartitionNumber*/, SectionName, InstallNameW);
+ }
+
+ NtClose(SystemRootDirectory);
+ }
+ }
+ while (IniCacheFindNextValue(Iterator, &SectionName, &KeyData));
+
+ IniCacheFindClose(Iterator);
+
+Quit:
+ IniCacheDestroy(IniCache);
+ return STATUS_SUCCESS;
+}
/***
*wchar_t *wcsstr(string1, string2) - search for string2 in string1
@@ -234,8 +513,8 @@
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 ?
+ IN PCWSTR FileName, // OPTIONAL
+ OUT PUNICODE_STRING VendorName
)
{
BOOLEAN Success = FALSE;
@@ -247,18 +526,24 @@
PVOID pvData = NULL;
UINT BufLen = 0;
+ if (VendorName->MaximumLength < sizeof(UNICODE_NULL))
+ return FALSE;
+
+ *VendorName->Buffer = UNICODE_NULL;
+ VendorName->Length = 0;
+
Status = OpenAndMapFile(RootDirectory, PathName, FileName,
- &FileHandle, &SectionHandle, &ViewBase);
+ &FileHandle, &SectionHandle, &ViewBase, NULL);
if (!NT_SUCCESS(Status))
{
- DPRINT1("Failed to open and map file %wZ, Status 0x%08lx\n", &FileName, Status);
+ DPRINT1("Failed to open and map file %S, 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);
+ DPRINT1("File %S does not seem to be a valid PE, bail out\n", FileName);
Status = STATUS_INVALID_IMAGE_FORMAT;
goto UnmapFile;
}
@@ -270,7 +555,7 @@
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);
+ DPRINT1("Failed to get version resource for file %S, Status 0x%08lx\n", FileName, Status);
goto UnmapFile;
}
@@ -279,7 +564,6 @@
{
USHORT wCodePage = 0, wLangID = 0;
WCHAR FileInfo[MAX_PATH];
- UNICODE_STRING Vendor;
wCodePage = LOWORD(*(ULONG*)pvData);
wLangID = HIWORD(*(ULONG*)pvData);
@@ -289,21 +573,26 @@
wCodePage, wLangID);
Status = NtVerQueryValue(VersionBuffer, FileInfo, &pvData, &BufLen);
- if (NT_SUCCESS(Status) && pvData)
+
+ /* Fixup the Status in case pvData is NULL */
+ if (NT_SUCCESS(Status) && !pvData)
+ Status = STATUS_NOT_FOUND;
+
+ 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);
- }
- }
+ DPRINT1("Found version vendor: \"%S\" for file %S\n", pvData, FileName);
+
+ StringCbCopyNW(VendorName->Buffer, VendorName->MaximumLength,
+ pvData, BufLen * sizeof(WCHAR));
+ VendorName->Length = wcslen(VendorName->Buffer) * sizeof(WCHAR);
+
+ Success = TRUE;
+ }
+ }
+
+ if (!NT_SUCCESS(Status))
+ DPRINT1("No version vendor found for file %S\n", FileName);
UnmapFile:
/* Finally, unmap and close the file */
@@ -313,36 +602,55 @@
return Success;
}
+//
+// 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).
+//
static BOOLEAN
IsValidNTOSInstallation(
- IN HANDLE PartitionHandle,
- IN PCWSTR SystemRoot)
+ IN HANDLE SystemRootDirectory OPTIONAL,
+ IN PCWSTR SystemRoot OPTIONAL)
{
BOOLEAN Success = FALSE;
USHORT i;
WCHAR PathBuffer[MAX_PATH];
-
- // DoesPathExist(PartitionHandle, SystemRoot, L"System32\\"); etc...
+ UNICODE_STRING VendorName;
+
+ /*
+ * Use either the 'SystemRootDirectory' handle or the 'SystemRoot' string,
+ * depending on what the user gave to us in entry.
+ */
+ if (SystemRootDirectory)
+ SystemRoot = NULL;
+ // else SystemRootDirectory == NULL and SystemRoot is what it is.
+
+ /* If both the parameters are NULL we cannot do anything else more */
+ if (!SystemRootDirectory && !SystemRoot)
+ return FALSE;
+
+ // DoesPathExist(SystemRootDirectory, 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))
+ StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer), L"%s%s", SystemRoot ? SystemRoot : L"", L"System32\\");
+ if (!DoesPathExist(SystemRootDirectory, PathBuffer))
{
// DPRINT1("Failed to open directory %wZ, Status 0x%08lx\n", &FileName, Status);
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))
+ StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer), L"%s%s", SystemRoot ? SystemRoot : L"", L"System32\\drivers\\");
+ if (!DoesPathExist(SystemRootDirectory, 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))
+ StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer), L"%s%s", SystemRoot ? SystemRoot : L"", L"System32\\config\\");
+ if (!DoesPathExist(SystemRootDirectory, PathBuffer))
{
// DPRINT1("Failed to open directory %wZ, Status 0x%08lx\n", &FileName, Status);
return FALSE;
@@ -353,38 +661,64 @@
* 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"))
+ if (!DoesFileExist(SystemRootDirectory, 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"))
+ if (!DoesFileExist(SystemRootDirectory, 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;
+ RtlInitEmptyUnicodeString(&VendorName, PathBuffer, sizeof(PathBuffer));
+
+ /* Check for the existence of \SystemRoot\System32\ntoskrnl.exe and retrieves its vendor name */
+ Success = CheckForValidPEAndVendor(SystemRootDirectory, SystemRoot, L"System32\\ntoskrnl.exe", &VendorName);
+ if (!Success)
+ DPRINT1("Kernel file ntoskrnl.exe is either not a PE file, or does not have any vendor?\n");
+
+ /* The kernel gives the OS its flavour */
+ if (Success)
+ {
+ for (i = 0; i < ARRAYSIZE(KnownVendors); ++i)
+ {
+ Success = !!FindSubStrI(VendorName.Buffer, KnownVendors[i]);
+ if (Success)
+ {
+ /* We have found a correct vendor combination */
+ DPRINT1("IsValidNTOSInstallation: We've got an NTOS installation from %S !\n", KnownVendors[i]);
+ break;
+ }
+ }
+ }
+
+ /* OPTIONAL: Check for the existence of \SystemRoot\System32\ntkrnlpa.exe */
+
+ /* Check for the existence of \SystemRoot\System32\ntdll.dll and retrieves its vendor name */
+ Success = CheckForValidPEAndVendor(SystemRootDirectory, SystemRoot, L"System32\\ntdll.dll", &VendorName);
+ if (!Success)
+ DPRINT1("User-mode file ntdll.dll is either not a PE file, or does not have any vendor?\n");
+ if (Success)
+ {
+ for (i = 0; i < ARRAYSIZE(KnownVendors); ++i)
+ {
+ if (!!FindSubStrI(VendorName.Buffer, KnownVendors[i]))
+ {
+ /* We have found a correct vendor combination */
+ DPRINT1("IsValidNTOSInstallation: The user-mode file ntdll.dll is from %S\n", KnownVendors[i]);
+ break;
+ }
+ }
}
return Success;
}
static VOID
-ListNTOSInstalls(
+DumpNTOSInstalls(
IN PGENERIC_LIST List)
{
PGENERIC_LIST_ENTRY Entry;
@@ -455,6 +789,10 @@
{
DPRINT1("An NTOS installation with name \"%S\" already exists on disk #%d, partition #%d, in SystemRoot %S\n",
NtOsInstall->InstallationName, NtOsInstall->DiskNumber, NtOsInstall->PartitionNumber, NtOsInstall->SystemRoot);
+ //
+ // 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.
+ //
return NtOsInstall;
}
@@ -477,9 +815,9 @@
static VOID
FindNTOSInstallations(
- IN PGENERIC_LIST List,
- IN ULONG DiskNumber,
- IN ULONG PartitionNumber)
+ IN OUT PGENERIC_LIST List,
+ IN PPARTLIST PartList,
+ IN PPARTENTRY PartEntry)
{
NTSTATUS Status;
UINT i;
@@ -489,15 +827,18 @@
UNICODE_STRING PartitionRootPath;
HANDLE SectionHandle;
// SIZE_T ViewSize;
+ ULONG FileSize;
PVOID ViewBase;
WCHAR PathBuffer[MAX_PATH];
- WCHAR SystemRoot[MAX_PATH];
- WCHAR InstallNameW[MAX_PATH];
+
+PDISKENTRY DiskEntry = PartEntry->DiskEntry;
+ULONG DiskNumber = DiskEntry->DiskNumber;
+ULONG PartitionNumber = PartEntry->PartitionNumber;
/* Set PartitionRootPath */
- swprintf(PathBuffer,
- L"\\Device\\Harddisk%lu\\Partition%lu\\",
- DiskNumber, PartitionNumber);
+ StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+ L"\\Device\\Harddisk%lu\\Partition%lu\\",
+ DiskNumber, PartitionNumber);
RtlInitUnicodeString(&PartitionRootPath, PathBuffer);
DPRINT1("FindNTOSInstallations: PartitionRootPath: %wZ\n", &PartitionRootPath);
@@ -532,7 +873,7 @@
/* Check whether the loader configuration file exists */
Status = OpenAndMapFile(PartitionHandle, NULL, NtosBootLoaders[i].LoaderConfigurationFile,
- &FileHandle, &SectionHandle, &ViewBase);
+ &FileHandle, &SectionHandle, &ViewBase, &FileSize);
if (!NT_SUCCESS(Status))
{
/* The loader does not exist, continue with another one */
@@ -542,31 +883,21 @@
}
/* The loader configuration file exists, interpret it to find valid installations */
- // TODO!!
- DPRINT1("TODO: Analyse the OS installations inside %S !\n", NtosBootLoaders[i].LoaderConfigurationFile);
-
- // Here we get a SystemRootPath for each installation // FIXME!
- // FIXME: Do NOT hardcode the path!! But retrieve it from boot.ini etc...
- StringCchCopyW(SystemRoot, ARRAYSIZE(SystemRoot), L"WINDOWS\\");
- if (IsValidNTOSInstallation(PartitionHandle, SystemRoot))
- {
- DPRINT1("Found a valid NTOS installation in disk #%d, partition #%d, SystemRoot %S\n",
- DiskNumber, PartitionNumber, SystemRoot);
- StringCchPrintfW(InstallNameW, ARRAYSIZE(InstallNameW), L"%C: \\Device\\Harddisk%lu\\Partition%lu\\%s \"%s\"",
- 'X' /* FIXME: Partition letter */, DiskNumber, PartitionNumber, SystemRoot, L"Windows (placeholder)");
- AddNTOSInstallation(List, DiskNumber, PartitionNumber, SystemRoot, InstallNameW);
- }
-
- // Here we get a SystemRootPath for each installation // FIXME!
- // FIXME: Do NOT hardcode the path!! But retrieve it from boot.ini etc...
- StringCchCopyW(SystemRoot, ARRAYSIZE(SystemRoot), L"ReactOS\\");
- if (IsValidNTOSInstallation(PartitionHandle, SystemRoot))
- {
- DPRINT1("Found a valid NTOS installation in disk #%d, partition #%d, SystemRoot %S\n",
- DiskNumber, PartitionNumber, SystemRoot);
- StringCchPrintfW(InstallNameW, ARRAYSIZE(InstallNameW), L"%C: \\Device\\Harddisk%lu\\Partition%lu\\%s \"%s\"",
- 'X' /* FIXME: Partition letter */, DiskNumber, PartitionNumber, SystemRoot, L"ReactOS (placeholder)");
- AddNTOSInstallation(List, DiskNumber, PartitionNumber, SystemRoot, InstallNameW);
+ DPRINT1("Analyse the OS installations inside '%S' in disk #%d, partition #%d\n",
+ NtosBootLoaders[i].LoaderConfigurationFile, DiskNumber, PartitionNumber);
+ switch (NtosBootLoaders[i].Type)
+ {
+ case FreeLdr:
+ Status = FreeLdrEnumerateInstallations(List, PartList, ViewBase, FileSize);
+ break;
+
+ case NtLdr:
+ Status = NtLdrEnumerateInstallations(List, PartList, ViewBase, FileSize);
+ break;
+
+ default:
+ DPRINT1("Loader type %d is currently unsupported!\n", NtosBootLoaders[i].Type);
+ Status = STATUS_SUCCESS;
}
/* Finally, unmap and close the file */
@@ -623,6 +954,8 @@
{
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
Entry2 = Entry2->Flink;
+
+ ASSERT(PartEntry->DiskEntry == DiskEntry);
DPRINT1(" 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,
@@ -634,7 +967,7 @@
ShouldICheckThisPartition(PartEntry) ? "YES!" : "NO!");
if (ShouldICheckThisPartition(PartEntry))
- FindNTOSInstallations(List, DiskEntry->DiskNumber, PartEntry->PartitionNumber);
+ FindNTOSInstallations(List, PartList, PartEntry);
}
/* Then, the logical partitions (present in the extended partition) */
@@ -643,6 +976,8 @@
{
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
Entry2 = Entry2->Flink;
+
+ ASSERT(PartEntry->DiskEntry == DiskEntry);
DPRINT1(" 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,
@@ -654,12 +989,12 @@
ShouldICheckThisPartition(PartEntry) ? "YES!" : "NO!");
if (ShouldICheckThisPartition(PartEntry))
- FindNTOSInstallations(List, DiskEntry->DiskNumber, PartEntry->PartitionNumber);
+ FindNTOSInstallations(List, PartList, PartEntry);
}
}
/**** Debugging: List all the collected installations ****/
- ListNTOSInstalls(List);
+ DumpNTOSInstalls(List);
return List;
}
Modified: branches/setup_improvements/base/setup/usetup/osdetect.h
URL: http://svn.reactos.org/svn/reactos/branches/setup_improvements/base/setup/u…
==============================================================================
--- branches/setup_improvements/base/setup/usetup/osdetect.h [iso-8859-1] (original)
+++ branches/setup_improvements/base/setup/usetup/osdetect.h [iso-8859-1] Mon May 22 01:19:08 2017
@@ -4,8 +4,12 @@
LIST_ENTRY ListEntry;
ULONG DiskNumber;
ULONG PartitionNumber;
-// Vendor????
- WCHAR SystemRoot[MAX_PATH];
+ PPARTENTRY PartEntry;
+// BOOLEAN IsDefault; // TRUE / FALSE whether this installation is marked as "default" in its corresponding loader configuration file.
+// Vendor???? (Microsoft / ReactOS)
+/**/WCHAR SystemRoot[MAX_PATH];/**/
+ UNICODE_STRING SystemArcPath; // Normalized ARC path
+ UNICODE_STRING SystemNtPath; // Corresponding NT path
/**/WCHAR InstallationName[MAX_PATH];/**/
} NTOS_INSTALLATION, *PNTOS_INSTALLATION;
Author: hbelusca
Date: Sun May 21 23:45:43 2017
New Revision: 74619
URL: http://svn.reactos.org/svn/reactos?rev=74619&view=rev
Log:
[USETUP]: filesup module:
- Add a NtPathToDiskPartComponents helper, that takes in input a fully qualified NT path to a file on hard disk, e.g.: \Device\Harddisk1\Partition2\foo\bar, and returns in output the disk number ('1'), the partition number ('2'), and the the path component "\foo\bar" that is after the device-harddisk-partition stuff.
- Make the OpenAndMapFile return the file size of the opened file.
Both of these additions will be used soon.
- Turn a 'isspace' into a 'iswspace'.
Modified:
branches/setup_improvements/base/setup/usetup/filesup.c
branches/setup_improvements/base/setup/usetup/filesup.h
Modified: branches/setup_improvements/base/setup/usetup/filesup.c
URL: http://svn.reactos.org/svn/reactos/branches/setup_improvements/base/setup/u…
==============================================================================
--- branches/setup_improvements/base/setup/usetup/filesup.c [iso-8859-1] (original)
+++ branches/setup_improvements/base/setup/usetup/filesup.c [iso-8859-1] Sun May 21 23:45:43 2017
@@ -428,7 +428,7 @@
/* Check for whitespaces */
for (i = 0; i < Length; i++)
{
- if (isspace(InstallDir[i]))
+ if (iswspace(InstallDir[i]))
return FALSE;
}
@@ -547,6 +547,117 @@
return NT_SUCCESS(Status);
}
+/*
+ * The format of NtPath should be:
+ * \Device\HarddiskXXX\PartitionYYY[\path] ,
+ * where XXX and YYY respectively represent the hard disk and partition numbers,
+ * and [\path] represent an optional path (separated by '\\').
+ *
+ * If a NT path of such a form is correctly parsed, the function returns respectively:
+ * - in pDiskNumber: the hard disk number XXX,
+ * - in pPartNumber: the partition number YYY,
+ * - in PathComponent: pointer value (inside NtPath) to the beginning of \path.
+ *
+ * NOTE: The function does not accept leading whitespace.
+ */
+BOOLEAN
+NtPathToDiskPartComponents(
+ IN PCWSTR NtPath,
+ OUT PULONG pDiskNumber,
+ OUT PULONG pPartNumber,
+ OUT PCWSTR* PathComponent OPTIONAL)
+{
+ ULONG DiskNumber, PartNumber;
+ PCWSTR Path;
+
+ *pDiskNumber = 0;
+ *pPartNumber = 0;
+ if (PathComponent) *PathComponent = NULL;
+
+ Path = NtPath;
+
+ if (_wcsnicmp(Path, L"\\Device\\Harddisk", 16) != 0)
+ {
+ /* The NT path doesn't start with the prefix string, thus it cannot be a hard disk device path */
+ DPRINT1("'%S' : Not a possible hard disk device.\n", NtPath);
+ return FALSE;
+ }
+
+ Path += 16;
+
+ /* A number must be present now */
+ if (!iswdigit(*Path))
+ {
+ DPRINT1("'%S' : expected a number! Not a regular hard disk device.\n", Path);
+ return FALSE;
+ }
+ DiskNumber = wcstoul(Path, (PWSTR*)&Path, 10);
+
+ /* Either NULL termination, or a path separator must be present now */
+ if (!Path)
+ {
+ DPRINT1("An error happened!\n");
+ return FALSE;
+ }
+ else if (*Path && *Path != OBJ_NAME_PATH_SEPARATOR)
+ {
+ DPRINT1("'%S' : expected a path separator!\n", Path);
+ return FALSE;
+ }
+
+ if (!*Path)
+ {
+ DPRINT1("The path only specified a hard disk (and nothing else, like a partition...), so we stop there.\n");
+ goto Quit;
+ }
+
+ /* Here, *Path == L'\\' */
+
+ if (_wcsnicmp(Path, L"\\Partition", 10) != 0)
+ {
+ /* Actually, \Partition is optional so, if we don't have it, we still return success. Or should we? */
+ DPRINT1("'%S' : unexpected format!\n", NtPath);
+ goto Quit;
+ }
+
+ Path += 10;
+
+ /* A number must be present now */
+ if (!iswdigit(*Path))
+ {
+ /* If we don't have a number it means this part of path is actually not a partition specifier, so we shouldn't fail either. Or should we? */
+ DPRINT1("'%S' : expected a number!\n", Path);
+ goto Quit;
+ }
+ PartNumber = wcstoul(Path, (PWSTR*)&Path, 10);
+
+ /* Either NULL termination, or a path separator must be present now */
+ if (!Path)
+ {
+ /* We fail here because wcstoul failed for whatever reason */
+ DPRINT1("An error happened!\n");
+ return FALSE;
+ }
+ else if (*Path && *Path != OBJ_NAME_PATH_SEPARATOR)
+ {
+ /* We shouldn't fail here because it just means this part of path is actually not a partition specifier. Or should we? */
+ DPRINT1("'%S' : expected a path separator!\n", Path);
+ goto Quit;
+ }
+
+ /* OK, here we really have a partition specifier: return its number */
+ *pPartNumber = PartNumber;
+
+Quit:
+ /* Return the disk number */
+ *pDiskNumber = DiskNumber;
+
+ /* Return the path component also, if the user wants it */
+ if (PathComponent) *PathComponent = Path;
+
+ return TRUE;
+}
+
NTSTATUS
OpenAndMapFile(
IN HANDLE RootDirectory OPTIONAL,
@@ -554,7 +665,8 @@
IN PCWSTR FileName, // OPTIONAL
OUT PHANDLE FileHandle, // IN OUT PHANDLE OPTIONAL
OUT PHANDLE SectionHandle,
- OUT PVOID* BaseAddress)
+ OUT PVOID* BaseAddress,
+ OUT PULONG FileSize OPTIONAL)
{
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
@@ -593,6 +705,31 @@
{
DPRINT1("Failed to open file %wZ, Status 0x%08lx\n", &Name, Status);
return Status;
+ }
+
+ if (FileSize)
+ {
+ /* Query the file size */
+ FILE_STANDARD_INFORMATION FileInfo;
+ Status = NtQueryInformationFile(*FileHandle,
+ &IoStatusBlock,
+ &FileInfo,
+ sizeof(FileInfo),
+ FileStandardInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
+ NtClose(*FileHandle);
+ *FileHandle = NULL;
+ return Status;
+ }
+
+ if (FileInfo.EndOfFile.HighPart != 0)
+ DPRINT1("WARNING!! The file %wZ is too large!\n", Name);
+
+ *FileSize = FileInfo.EndOfFile.LowPart;
+
+ DPRINT("File size: %lu\n", *FileSize);
}
/* Map the file in memory */
Modified: branches/setup_improvements/base/setup/usetup/filesup.h
URL: http://svn.reactos.org/svn/reactos/branches/setup_improvements/base/setup/u…
==============================================================================
--- branches/setup_improvements/base/setup/usetup/filesup.h [iso-8859-1] (original)
+++ branches/setup_improvements/base/setup/usetup/filesup.h [iso-8859-1] Sun May 21 23:45:43 2017
@@ -64,6 +64,13 @@
IN PCWSTR PathName OPTIONAL,
IN PCWSTR FileName);
+BOOLEAN
+NtPathToDiskPartComponents(
+ IN PCWSTR NtPath,
+ OUT PULONG pDiskNumber,
+ OUT PULONG pPartNumber,
+ OUT PCWSTR* PathComponent OPTIONAL);
+
NTSTATUS
OpenAndMapFile(
IN HANDLE RootDirectory OPTIONAL,
@@ -71,7 +78,8 @@
IN PCWSTR FileName, // OPTIONAL
OUT PHANDLE FileHandle, // IN OUT PHANDLE OPTIONAL
OUT PHANDLE SectionHandle,
- OUT PVOID* BaseAddress);
+ OUT PVOID* BaseAddress,
+ OUT PULONG FileSize OPTIONAL);
BOOLEAN
UnMapFile(