- Do only allow to install reactos on disks which are visible by the bios.

- Arrange the disks in the same sequence how they was detected by the bios.  
- Create a registry entry in MountedDevices for each recognized partition.

svn path=/trunk/; revision=17864
This commit is contained in:
Hartmut Birr 2005-09-15 17:19:31 +00:00
parent a9ef5d9d40
commit 9f214815b7
4 changed files with 401 additions and 4 deletions

View file

@ -1,6 +1,6 @@
/*
* ReactOS kernel
* Copyright (C) 2002, 2003 ReactOS Team
* Copyright (C) 2002, 2003, 2004, 2005 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -23,6 +23,7 @@
* PURPOSE: Partition list functions
* PROGRAMMER: Eric Kohl
* Casper S. Hornstrup (chorns@users.sourceforge.net)
* Hartmut Birr
*/
#include <usetup.h>
@ -421,6 +422,128 @@ ScanForUnpartitionedDiskSpace (PDISKENTRY DiskEntry)
}
}
NTSTATUS
STDCALL
DiskQueryRoutine(PWSTR ValueName,
ULONG ValueType,
PVOID ValueData,
ULONG ValueLength,
PVOID Context,
PVOID EntryContext)
{
PLIST_ENTRY ListHead = (PLIST_ENTRY)Context;
PULONG GlobalDiskCount = (PULONG)EntryContext;
PBIOSDISKENTRY BiosDiskEntry;
UNICODE_STRING NameU;
if (ValueType == REG_SZ &&
ValueLength == 20 * sizeof(WCHAR))
{
BiosDiskEntry = RtlAllocateHeap(ProcessHeap, 0, sizeof(BIOSDISKENTRY));
if (BiosDiskEntry == NULL)
{
return STATUS_NO_MEMORY;
}
BiosDiskEntry->DiskNumber = (*GlobalDiskCount)++;
NameU.Buffer = (PWCHAR)ValueData;
NameU.Length = NameU.MaximumLength = 8 * sizeof(WCHAR);
RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Checksum);
NameU.Buffer = (PWCHAR)ValueData + 9;
RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Signature);
InsertTailList(ListHead, &BiosDiskEntry->ListEntry);
}
return STATUS_SUCCESS;
}
#define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
STATIC VOID
EnumerateBiosDiskEntries(PPARTLIST PartList)
{
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
WCHAR Name[100];
ULONG AdapterCount;
ULONG ControllerCount;
ULONG DiskCount;
NTSTATUS Status;
ULONG GlobalDiskCount=0;
memset(QueryTable, 0, sizeof(QueryTable));
QueryTable[0].Name = L"Identifier";
QueryTable[0].QueryRoutine = DiskQueryRoutine;
QueryTable[0].EntryContext = (PVOID)&GlobalDiskCount;
AdapterCount = 0;
while (1)
{
swprintf(Name, L"%s\\%lu", ROOT_NAME, AdapterCount);
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
Name,
&QueryTable[1],
NULL,
NULL);
if (!NT_SUCCESS(Status))
{
break;
}
swprintf(Name, L"%s\\%lu\\DiskController", ROOT_NAME, AdapterCount);
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
Name,
&QueryTable[1],
NULL,
NULL);
if (NT_SUCCESS(Status))
{
ControllerCount = 0;
while (1)
{
swprintf(Name, L"%s\\%lu\\DiskController\\%lu", ROOT_NAME, AdapterCount, ControllerCount);
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
Name,
&QueryTable[1],
NULL,
NULL);
if (!NT_SUCCESS(Status))
{
break;
}
swprintf(Name, L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral", ROOT_NAME, AdapterCount, ControllerCount);
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
Name,
&QueryTable[1],
NULL,
NULL);
if (NT_SUCCESS(Status))
{
DiskCount = 0;
while (1)
{
swprintf(Name, L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral\\%lu", ROOT_NAME, AdapterCount, ControllerCount, DiskCount);
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
Name,
QueryTable,
(PVOID)&PartList->BiosDiskListHead,
NULL);
if (!NT_SUCCESS(Status))
{
break;
}
DiskCount++;
}
}
ControllerCount++;
}
}
AdapterCount++;
}
}
static VOID
AddDiskToList (HANDLE FileHandle,
@ -433,6 +556,15 @@ AddDiskToList (HANDLE FileHandle,
PDISKENTRY DiskEntry;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
PPARTITION_SECTOR Mbr;
PULONG Buffer;
LARGE_INTEGER FileOffset;
WCHAR Identifier[20];
ULONG Checksum;
ULONG Signature;
ULONG i;
PLIST_ENTRY ListEntry;
PBIOSDISKENTRY BiosDiskEntry;
Status = NtDeviceIoControlFile (FileHandle,
NULL,
@ -469,6 +601,51 @@ AddDiskToList (HANDLE FileHandle,
return;
}
Mbr = RtlAllocateHeap(ProcessHeap,
0,
DiskGeometry.BytesPerSector);
if (Mbr == NULL)
{
return;
}
FileOffset.QuadPart = 0;
Status = NtReadFile(FileHandle,
NULL,
NULL,
NULL,
&Iosb,
(PVOID)Mbr,
DiskGeometry.BytesPerSector,
&FileOffset,
NULL);
if (!NT_SUCCESS(Status))
{
RtlFreeHeap(ProcessHeap,
0,
Mbr);
DPRINT1("NtReadFile failed, status=%x\n", Status);
return;
}
Signature = Mbr->Signature;
/* Calculate the MBR checksum */
Checksum = 0;
Buffer = (PULONG)Mbr;
for (i = 0; i < 128; i++)
{
Checksum += Buffer[i];
}
Checksum = ~Checksum + 1;
RtlFreeHeap (ProcessHeap,
0,
Mbr);
swprintf(Identifier, L"%08x-%08x-A", Checksum, Signature);
DPRINT("Identifier: %S\n", Identifier);
DiskEntry = (PDISKENTRY)RtlAllocateHeap (ProcessHeap,
0,
sizeof(DISKENTRY));
@ -477,6 +654,35 @@ AddDiskToList (HANDLE FileHandle,
return;
}
DiskEntry->Checksum = Checksum;
DiskEntry->Signature = Signature;
DiskEntry->BiosFound = FALSE;
ListEntry = List->BiosDiskListHead.Flink;
while(ListEntry != &List->BiosDiskListHead)
{
BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
if (BiosDiskEntry->Signature == Signature &&
BiosDiskEntry->Checksum == Checksum)
{
if (!DiskEntry->BiosFound)
{
DiskEntry->BiosDiskNumber = BiosDiskEntry->DiskNumber;
DiskEntry->BiosFound = TRUE;
}
else
{
}
}
ListEntry = ListEntry->Flink;
}
if (!DiskEntry->BiosFound)
{
RtlFreeHeap(ProcessHeap, 0, DiskEntry);
return;
}
InitializeListHead (&DiskEntry->PartListHead);
DiskEntry->Cylinders = DiskGeometry.Cylinders.QuadPart;
@ -509,8 +715,7 @@ AddDiskToList (HANDLE FileHandle,
GetDriverName (DiskEntry);
InsertTailList (&List->DiskListHead,
&DiskEntry->ListEntry);
InsertAscendingList(&List->DiskListHead, DISKENTRY, ListEntry, DiskEntry, BiosDiskNumber);
LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)RtlAllocateHeap (ProcessHeap,
0,
@ -587,6 +792,9 @@ CreatePartitionList (SHORT Left,
List->CurrentPartition = NULL;
InitializeListHead (&List->DiskListHead);
InitializeListHead (&List->BiosDiskListHead);
EnumerateBiosDiskEntries(List);
Status = NtQuerySystemInformation (SystemDeviceInformation,
&Sdi,
@ -667,6 +875,7 @@ VOID
DestroyPartitionList (PPARTLIST List)
{
PDISKENTRY DiskEntry;
PBIOSDISKENTRY BiosDiskEntry;
PPARTENTRY PartEntry;
PLIST_ENTRY Entry;
@ -694,6 +903,15 @@ DestroyPartitionList (PPARTLIST List)
RtlFreeHeap (ProcessHeap, 0, DiskEntry);
}
/* release the bios disk info */
while(!IsListEmpty(&List->BiosDiskListHead))
{
Entry = RemoveHeadList(&List->BiosDiskListHead);
BiosDiskEntry = CONTAINING_RECORD(Entry, BIOSDISKENTRY, ListEntry);
RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
}
/* Release list head */
RtlFreeHeap (ProcessHeap, 0, List);
}
@ -2000,7 +2218,29 @@ WritePartitionsToDisk (PPARTLIST List)
DriveLayoutSize);
DriveLayout->PartitionCount = PartitionCount;
if (DiskEntry->Signature == 0)
{
LARGE_INTEGER SystemTime;
TIME_FIELDS TimeFields;
PUCHAR Buffer;
NtQuerySystemTime (&SystemTime);
RtlTimeToTimeFields (&SystemTime, &TimeFields);
Buffer = (PUCHAR)&DiskEntry->Signature;
Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF);
Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF);
Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF);
Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF);
/* FIXME:
* check for an existing signature
*/
}
DriveLayout->Signature = DiskEntry->Signature;
Index = 0;
Entry2 = DiskEntry->PartListHead.Flink;
while (Entry2 != &DiskEntry->PartListHead)
@ -2095,4 +2335,42 @@ WritePartitionsToDisk (PPARTLIST List)
return TRUE;
}
BOOL SetMountedDeviceValues(PPARTLIST List)
{
PLIST_ENTRY Entry1, Entry2;
PDISKENTRY DiskEntry;
PPARTENTRY PartEntry;
if (List == NULL)
{
return FALSE;
}
Entry1 = List->DiskListHead.Flink;
while (Entry1 != &List->DiskListHead)
{
DiskEntry = CONTAINING_RECORD (Entry1,
DISKENTRY,
ListEntry);
Entry2 = DiskEntry->PartListHead.Flink;
while (Entry2 != &DiskEntry->PartListHead)
{
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
if (!PartEntry->Unpartitioned && PartEntry->DriveLetter)
{
if (!SetMountedDeviceValue(PartEntry->DriveLetter, DiskEntry->Signature, PartEntry->PartInfo[0].StartingOffset))
{
return FALSE;
}
}
Entry2 = Entry2->Flink;
}
Entry1 = Entry1->Flink;
}
return TRUE;
}
/* EOF */

View file

@ -68,6 +68,15 @@ typedef struct _PARTENTRY
} PARTENTRY, *PPARTENTRY;
typedef struct _BIOSDISKENTRY
{
LIST_ENTRY ListEntry;
ULONG DiskNumber;
ULONG Signature;
ULONG Checksum;
} BIOSDISKENTRY, *PBIOSDISKENTRY;
typedef struct _DISKENTRY
{
LIST_ENTRY ListEntry;
@ -81,6 +90,11 @@ typedef struct _DISKENTRY
ULONGLONG CylinderSize;
ULONGLONG TrackSize;
BOOLEAN BiosFound;
ULONG BiosDiskNumber;
ULONG Signature;
ULONG Checksum;
ULONG DiskNumber;
USHORT Port;
USHORT Bus;
@ -118,10 +132,46 @@ typedef struct _PARTLIST
PPARTENTRY ActiveBootPartition;
LIST_ENTRY DiskListHead;
LIST_ENTRY BiosDiskListHead;
} PARTLIST, *PPARTLIST;
#define PARTITION_TBL_SIZE 4
#include <pshpack1.h>
typedef struct _PARTITION
{
unsigned char BootFlags; /* bootable? 0=no, 128=yes */
unsigned char StartingHead; /* beginning head number */
unsigned char StartingSector; /* beginning sector number */
unsigned char StartingCylinder; /* 10 bit nmbr, with high 2 bits put in begsect */
unsigned char PartitionType; /* Operating System type indicator code */
unsigned char EndingHead; /* ending head number */
unsigned char EndingSector; /* ending sector number */
unsigned char EndingCylinder; /* also a 10 bit nmbr, with same high 2 bit trick */
unsigned int StartingBlock; /* first sector relative to start of disk */
unsigned int SectorCount; /* number of sectors in partition */
} PARTITION, *PPARTITION;
typedef struct _PARTITION_SECTOR
{
UCHAR BootCode[440]; /* 0x000 */
ULONG Signature; /* 0x1B8 */
UCHAR Reserved[2]; /* 0x1BC */
PARTITION Partition[PARTITION_TBL_SIZE]; /* 0x1BE */
USHORT Magic; /* 0x1FE */
} PARTITION_SECTOR, *PPARTITION_SECTOR;
#include <poppack.h>
typedef struct
{
LIST_ENTRY ListEntry;
ULONG DiskNumber;
ULONG Idendifier;
ULONG Signature;
} BIOS_DISK, *PBIOS_DISK;
PPARTLIST
CreatePartitionList (SHORT Left,

View file

@ -45,6 +45,15 @@
#define FLG_ADDREG_TYPE_NONE (0x00020000 | FLG_ADDREG_BINVALUETYPE)
#define FLG_ADDREG_TYPE_MASK (0xFFFF0000 | FLG_ADDREG_BINVALUETYPE)
#include <pshpack1.h>
typedef struct _REG_DISK_MOUNT_INFO
{
ULONG Signature;
LARGE_INTEGER StartingOffset;
} REG_DISK_MOUNT_INFO, *PREG_DISK_MOUNT_INFO;
#include <poppack.h>
/* FUNCTIONS ****************************************************************/
@ -640,4 +649,61 @@ SetInstallPathValue(PUNICODE_STRING InstallPath)
return TRUE;
}
BOOLEAN
SetMountedDeviceValue(CHAR Letter, ULONG Signature, LARGE_INTEGER StartingOffset)
{
OBJECT_ATTRIBUTES ObjectAttributes;
WCHAR ValueNameBuffer[16];
UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\MountedDevices");
UNICODE_STRING ValueName;
REG_DISK_MOUNT_INFO MountInfo;
NTSTATUS Status;
HANDLE KeyHandle;
swprintf(ValueNameBuffer, L"\\DosDevices\\%C:", Letter);
RtlInitUnicodeString(&ValueName, ValueNameBuffer);
InitializeObjectAttributes (&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenKey (&KeyHandle,
KEY_ALL_ACCESS,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
Status = NtCreateKey(&KeyHandle,
KEY_ALL_ACCESS,
&ObjectAttributes,
0,
NULL,
REG_OPTION_NON_VOLATILE,
NULL);
}
if (!NT_SUCCESS(Status))
{
DPRINT1("NtCreateKey() failed (Status %lx)\n", Status);
return FALSE;
}
MountInfo.Signature = Signature;
MountInfo.StartingOffset = StartingOffset;
Status = NtSetValueKey (KeyHandle,
&ValueName,
0,
REG_BINARY,
(PVOID)&MountInfo,
sizeof(MountInfo));
NtClose(KeyHandle);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
return FALSE;
}
return TRUE;
}
/* EOF */

View file

@ -2545,7 +2545,7 @@ InstallDirectoryPage1(PWCHAR InstallDir, PDISKENTRY DiskEntry, PPARTENTRY PartEn
RtlFreeUnicodeString(&DestinationArcPath);
swprintf(PathBuffer,
L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
DiskEntry->DiskNumber,
DiskEntry->BiosDiskNumber,
PartEntry->PartInfo[0].PartitionNumber);
if (InstallDir[0] != L'\\')
wcscat(PathBuffer,
@ -3241,6 +3241,9 @@ RegistryPage(PINPUT_RECORD Ir)
}
}
/* Update the mounted devices list */
SetMountedDeviceValues(PartitionList);
SetStatusText(" Done...");
return BOOT_LOADER_PAGE;