- Do only allow to install reactos on disks which are visible by the bios.
authorHartmut Birr <osexpert@googlemail.com>
Thu, 15 Sep 2005 17:19:31 +0000 (17:19 +0000)
committerHartmut Birr <osexpert@googlemail.com>
Thu, 15 Sep 2005 17:19:31 +0000 (17:19 +0000)
- 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

reactos/subsys/system/usetup/partlist.c
reactos/subsys/system/usetup/partlist.h
reactos/subsys/system/usetup/registry.c
reactos/subsys/system/usetup/usetup.c

index 352f123..3de2448 100644 (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 */
index 65b6381..42f9ef5 100644 (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,
index 4295e69..e169f98 100644 (file)
 #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 */
index 9ee260c..e930201 100644 (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;