diff --git a/reactos/subsys/system/usetup/partlist.c b/reactos/subsys/system/usetup/partlist.c index 352f1237fe4..3de244885b0 100644 --- a/reactos/subsys/system/usetup/partlist.c +++ b/reactos/subsys/system/usetup/partlist.c @@ -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 @@ -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 */ diff --git a/reactos/subsys/system/usetup/partlist.h b/reactos/subsys/system/usetup/partlist.h index 65b6381c94e..42f9ef586a7 100644 --- a/reactos/subsys/system/usetup/partlist.h +++ b/reactos/subsys/system/usetup/partlist.h @@ -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 + +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 + +typedef struct +{ + LIST_ENTRY ListEntry; + ULONG DiskNumber; + ULONG Idendifier; + ULONG Signature; +} BIOS_DISK, *PBIOS_DISK; PPARTLIST CreatePartitionList (SHORT Left, diff --git a/reactos/subsys/system/usetup/registry.c b/reactos/subsys/system/usetup/registry.c index 4295e699149..e169f98cd93 100644 --- a/reactos/subsys/system/usetup/registry.c +++ b/reactos/subsys/system/usetup/registry.c @@ -45,6 +45,15 @@ #define FLG_ADDREG_TYPE_NONE (0x00020000 | FLG_ADDREG_BINVALUETYPE) #define FLG_ADDREG_TYPE_MASK (0xFFFF0000 | FLG_ADDREG_BINVALUETYPE) +#include + +typedef struct _REG_DISK_MOUNT_INFO +{ + ULONG Signature; + LARGE_INTEGER StartingOffset; +} REG_DISK_MOUNT_INFO, *PREG_DISK_MOUNT_INFO; + +#include /* 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 */ diff --git a/reactos/subsys/system/usetup/usetup.c b/reactos/subsys/system/usetup/usetup.c index 9ee260cea6d..e930201678c 100644 --- a/reactos/subsys/system/usetup/usetup.c +++ b/reactos/subsys/system/usetup/usetup.c @@ -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;