- Fixed the creation of arc names. Only valid partitions should be linked to an arc...
authorHartmut Birr <osexpert@googlemail.com>
Thu, 15 Sep 2005 17:23:41 +0000 (17:23 +0000)
committerHartmut Birr <osexpert@googlemail.com>
Thu, 15 Sep 2005 17:23:41 +0000 (17:23 +0000)
- Create arc names only for partitions on disks, which are visible by the bios.

svn path=/trunk/; revision=17865

reactos/ntoskrnl/io/arcname.c

index cff2b24..0e0b451 100644 (file)
 
 #define FS_VOLUME_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_VOLUME_INFORMATION))
 
-/* FUNCTIONS ****************************************************************/
+/* STRUCTURES ***************************************************************/
 
-NTSTATUS INIT_FUNCTION
-IoCreateArcNames(VOID)
+typedef struct _DISKENTRY
 {
-  PCONFIGURATION_INFORMATION ConfigInfo;
-  PDRIVE_LAYOUT_INFORMATION LayoutInfo = NULL;
-  WCHAR DeviceNameBuffer[80];
-  WCHAR ArcNameBuffer[80];
-  UNICODE_STRING DeviceName;
-  UNICODE_STRING ArcName;
-  ULONG i, j, k;
-  NTSTATUS Status;
-  PFILE_OBJECT FileObject;
+  LIST_ENTRY ListEntry;
+  ULONG DiskNumber;
+  ULONG Signature;
+  ULONG Checksum;
   PDEVICE_OBJECT DeviceObject;
-  BOOL IsRemovableMedia;
+} DISKENTRY, *PDISKENTRY; 
 
-  DPRINT("IoCreateArcNames() called\n");
+#define  PARTITION_TBL_SIZE 4
 
-  ConfigInfo = IoGetConfigurationInformation();
+#include <pshpack1.h>
 
-  /* create ARC names for floppy drives */
-  DPRINT("Floppy drives: %lu\n", ConfigInfo->FloppyCount);
-  for (i = 0; i < ConfigInfo->FloppyCount; i++)
+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>
+
+/* FUNCTIONS ****************************************************************/
+
+STATIC 
+NTSTATUS
+STDCALL
+INIT_FUNCTION
+DiskQueryRoutine(PWSTR ValueName,
+                 ULONG ValueType,
+                 PVOID ValueData,
+                 ULONG ValueLength,
+                 PVOID Context,
+                 PVOID EntryContext)
+{
+  PLIST_ENTRY ListHead = (PLIST_ENTRY)Context;
+  PULONG GlobalDiskCount = (PULONG)EntryContext;
+  PDISKENTRY DiskEntry;
+  UNICODE_STRING NameU;
+
+  if (ValueType == REG_SZ &&
+      ValueLength == 20 * sizeof(WCHAR))
     {
-      swprintf(DeviceNameBuffer,
-              L"\\Device\\Floppy%lu",
-              i);
-      RtlInitUnicodeString(&DeviceName,
-                          DeviceNameBuffer);
+      DiskEntry = ExAllocatePool(PagedPool, sizeof(DISKENTRY));
+      if (DiskEntry == NULL)
+        {
+          return STATUS_NO_MEMORY;
+        }
+      DiskEntry->DiskNumber = (*GlobalDiskCount)++;
 
-      swprintf(ArcNameBuffer,
-              L"\\ArcName\\multi(0)disk(0)fdisk(%lu)",
-              i);
-      RtlInitUnicodeString(&ArcName,
-                          ArcNameBuffer);
-      DPRINT("%wZ ==> %wZ\n",
-            &ArcName,
-            &DeviceName);
+      NameU.Buffer = (PWCHAR)ValueData;
+      NameU.Length = NameU.MaximumLength = 8 * sizeof(WCHAR);
+      RtlUnicodeStringToInteger(&NameU, 16, &DiskEntry->Checksum);
 
-      Status = IoAssignArcName(&ArcName,
-                              &DeviceName);
+      NameU.Buffer = (PWCHAR)ValueData + 9;
+      RtlUnicodeStringToInteger(&NameU, 16, &DiskEntry->Signature);
+
+      InsertTailList(ListHead, &DiskEntry->ListEntry);
+    }
+
+  return STATUS_SUCCESS;
+}
+
+#define ROOT_NAME   L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
+
+STATIC VOID INIT_FUNCTION
+IopEnumerateBiosDisks(PLIST_ENTRY ListHead)
+{
+  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))
-       return(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)ListHead,
+                                                      NULL);
+                      if (!NT_SUCCESS(Status))
+                        {
+                          break;
+                        }
+                      DiskCount++;
+                    }
+                }
+              ControllerCount++;
+            }
+        }
+      AdapterCount++;
     }
+}
 
-  /* create ARC names for hard disk drives */
-  DPRINT("Disk drives: %lu\n", ConfigInfo->DiskCount);
-  for (i = 0, k = 0; i < ConfigInfo->DiskCount; i++)
+STATIC VOID INIT_FUNCTION
+IopEnumerateDisks(PLIST_ENTRY ListHead)
+{
+  ULONG i, k;
+  PDISKENTRY DiskEntry;
+  DISK_GEOMETRY DiskGeometry;
+  KEVENT Event;
+  PIRP Irp;
+  IO_STATUS_BLOCK StatusBlock;
+  LARGE_INTEGER PartitionOffset;
+  PULONG Buffer;
+  WCHAR DeviceNameBuffer[80];
+  UNICODE_STRING DeviceName;
+  NTSTATUS Status;
+  PDEVICE_OBJECT DeviceObject;
+  PFILE_OBJECT FileObject;
+  BOOLEAN IsRemovableMedia;
+  PPARTITION_SECTOR PartitionBuffer = NULL;
+  ULONG PartitionBufferSize = 0;
+
+
+  for (i = 0; i < IoGetConfigurationInformation()->DiskCount; i++)
     {
+
       swprintf(DeviceNameBuffer,
               L"\\Device\\Harddisk%lu\\Partition0",
               i);
@@ -88,12 +229,249 @@ IoCreateArcNames(VOID)
       ObDereferenceObject(FileObject);
       if (IsRemovableMedia)
         {
+          ObDereferenceObject(DeviceObject);
           continue;
        }
+      DiskEntry = ExAllocatePool(PagedPool, sizeof(DISKENTRY));
+      if (DiskEntry == NULL)
+        {
+          KEBUGCHECK(0);
+        }
+      DiskEntry->DiskNumber = i;
+      DiskEntry->DeviceObject = DeviceObject;
+
+      /* determine the sector size */
+      KeInitializeEvent(&Event, NotificationEvent, FALSE);
+      Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY,
+                                         DeviceObject,
+                                         NULL,
+                                         0,
+                                         &DiskGeometry,
+                                         sizeof(DISK_GEOMETRY),
+                                         FALSE,
+                                         &Event,
+                                         &StatusBlock);
+      if (Irp == NULL)
+        {
+          KEBUGCHECK(0);
+        }
+
+      Status = IoCallDriver(DeviceObject, Irp);
+      if (Status == STATUS_PENDING)
+        {
+          KeWaitForSingleObject(&Event,
+                               Executive,
+                               KernelMode,
+                               FALSE,
+                               NULL);
+          Status = StatusBlock.Status;
+        }
+      if (!NT_SUCCESS(Status))
+        {
+          KEBUGCHECK(0);
+        }
+      if (PartitionBuffer != NULL && PartitionBufferSize < DiskGeometry.BytesPerSector)
+        {
+          ExFreePool(PartitionBuffer);
+          PartitionBuffer = NULL;
+        }
+      if (PartitionBuffer == NULL)
+        {
+          PartitionBufferSize = max(DiskGeometry.BytesPerSector, PAGE_SIZE);
+          PartitionBuffer = ExAllocatePool(PagedPool, PartitionBufferSize);
+          if (PartitionBuffer == NULL)
+            {
+              KEBUGCHECK(0);
+            }
+        }
+
+      /* read the partition sector */
+      KeInitializeEvent(&Event, NotificationEvent, FALSE);
+      PartitionOffset.QuadPart = 0;
+      Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
+                                        DeviceObject,
+                                        PartitionBuffer,
+                                        DiskGeometry.BytesPerSector,
+                                        &PartitionOffset,
+                                        &Event,
+                                        &StatusBlock);
+      Status = IoCallDriver(DeviceObject, Irp);
+      if (Status == STATUS_PENDING)
+        {
+          KeWaitForSingleObject(&Event,
+                               Executive,
+                               KernelMode,
+                               FALSE,
+                               NULL);
+          Status = StatusBlock.Status;
+        }
+
+      if (!NT_SUCCESS(Status))
+        {
+          KEBUGCHECK(0);
+        }
+
+      /* Calculate the MBR checksum */
+      DiskEntry->Checksum = 0;
+      Buffer = (PULONG)PartitionBuffer;
+      for (k = 0; k < 128; k++)
+        {
+          DiskEntry->Checksum += Buffer[k];
+        }
+      DiskEntry->Checksum = ~DiskEntry->Checksum + 1;
+      DiskEntry->Signature = PartitionBuffer->Signature;
+
+      InsertTailList(ListHead, &DiskEntry->ListEntry);
+    }
+  if (PartitionBuffer)
+    {
+      ExFreePool(PartitionBuffer);
+    }
+}
+
+STATIC NTSTATUS INIT_FUNCTION
+IopAssignArcNamesToDisk(PDEVICE_OBJECT DeviceObject, ULONG RDisk, ULONG DiskNumber)
+{
+  WCHAR DeviceNameBuffer[80];
+  WCHAR ArcNameBuffer[80];
+  UNICODE_STRING DeviceName;
+  UNICODE_STRING ArcName;
+  PDRIVE_LAYOUT_INFORMATION LayoutInfo = NULL;
+  NTSTATUS Status;
+  ULONG i;
+  KEVENT Event;
+  PIRP Irp;
+  IO_STATUS_BLOCK StatusBlock;
+  ULONG PartitionNumber;
+
+  swprintf(DeviceNameBuffer,
+          L"\\Device\\Harddisk%lu\\Partition0",
+          DiskNumber);
+  RtlInitUnicodeString(&DeviceName,
+                      DeviceNameBuffer);
+
+  swprintf(ArcNameBuffer,
+          L"\\ArcName\\multi(0)disk(0)rdisk(%lu)",
+          RDisk);
+  RtlInitUnicodeString(&ArcName,
+                      ArcNameBuffer);
+
+  DPRINT("%wZ ==> %wZ\n", &ArcName, &DeviceName);
+
+  Status = IoAssignArcName(&ArcName, &DeviceName);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1("IoAssignArcName failed, status=%lx\n", Status);
+      return(Status);
+    }
+
+  LayoutInfo = ExAllocatePool(PagedPool, 2 * PAGE_SIZE);
+  if (LayoutInfo == NULL)
+    {
+      return STATUS_NO_MEMORY;
+    }
+  KeInitializeEvent(&Event, NotificationEvent, FALSE);
+  Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_LAYOUT,
+                                     DeviceObject,
+                                     NULL,
+                                     0,
+                                     LayoutInfo,
+                                     2 * PAGE_SIZE,
+                                     FALSE,
+                                     &Event,
+                                     &StatusBlock);
+  if (Irp == NULL)
+    {
+      ExFreePool(LayoutInfo);
+      return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+  Status = IoCallDriver(DeviceObject, Irp);
+  if (Status == STATUS_PENDING)
+    {
+      KeWaitForSingleObject(&Event,
+                           Executive,
+                           KernelMode,
+                           FALSE,
+                           NULL);
+      Status = StatusBlock.Status;
+    }
+  if (!NT_SUCCESS(Status))
+    {
+      ExFreePool(LayoutInfo);
+      return Status;
+    }
+
+  DPRINT("Number of partitions: %u\n", LayoutInfo->PartitionCount);
+  
+  PartitionNumber = 1;
+  for (i = 0; i < LayoutInfo->PartitionCount; i++)
+    {
+      if (!IsContainerPartition(LayoutInfo->PartitionEntry[i].PartitionType) &&
+          LayoutInfo->PartitionEntry[i].PartitionType != PARTITION_ENTRY_UNUSED)
+        {
+          
+          swprintf(DeviceNameBuffer,
+                  L"\\Device\\Harddisk%lu\\Partition%lu",
+                  DiskNumber,
+                  PartitionNumber);
+          RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
+
+          swprintf(ArcNameBuffer,
+                  L"\\ArcName\\multi(0)disk(0)rdisk(%lu)partition(%lu)",
+                  RDisk,
+                  PartitionNumber);
+          RtlInitUnicodeString(&ArcName, ArcNameBuffer);
+
+          DPRINT("%wZ ==> %wZ\n", &ArcName, &DeviceName);
+
+          Status = IoAssignArcName(&ArcName, &DeviceName);
+          if (!NT_SUCCESS(Status))
+            {
+              DPRINT1("IoAssignArcName failed, status=%lx\n", Status);
+              ExFreePool(LayoutInfo);
+             return(Status);
+            }
+          PartitionNumber++;
+        }
+    }
+  ExFreePool(LayoutInfo);
+  return STATUS_SUCCESS;
+}
+
+NTSTATUS INIT_FUNCTION
+IoCreateArcNames(VOID)
+{
+  PCONFIGURATION_INFORMATION ConfigInfo;
+  WCHAR DeviceNameBuffer[80];
+  WCHAR ArcNameBuffer[80];
+  UNICODE_STRING DeviceName;
+  UNICODE_STRING ArcName;
+  ULONG i, RDiskNumber;
+  NTSTATUS Status;
+  LIST_ENTRY BiosDiskListHead;
+  LIST_ENTRY DiskListHead;
+  PLIST_ENTRY Entry;
+  PDISKENTRY BiosDiskEntry;
+  PDISKENTRY DiskEntry;
+
+  DPRINT("IoCreateArcNames() called\n");
+
+  ConfigInfo = IoGetConfigurationInformation();
+
+  /* create ARC names for floppy drives */
+  DPRINT("Floppy drives: %lu\n", ConfigInfo->FloppyCount);
+  for (i = 0; i < ConfigInfo->FloppyCount; i++)
+    {
+      swprintf(DeviceNameBuffer,
+              L"\\Device\\Floppy%lu",
+              i);
+      RtlInitUnicodeString(&DeviceName,
+                          DeviceNameBuffer);
 
       swprintf(ArcNameBuffer,
-              L"\\ArcName\\multi(0)disk(0)rdisk(%lu)partition(0)",
-              k);
+              L"\\ArcName\\multi(0)disk(0)fdisk(%lu)",
+              i);
       RtlInitUnicodeString(&ArcName,
                           ArcNameBuffer);
       DPRINT("%wZ ==> %wZ\n",
@@ -104,42 +482,44 @@ IoCreateArcNames(VOID)
                               &DeviceName);
       if (!NT_SUCCESS(Status))
        return(Status);
+    }
 
-      Status = xHalQueryDriveLayout(&DeviceName,
-                                   &LayoutInfo);
-      if (!NT_SUCCESS(Status))
-       return(Status);
-
-      DPRINT("Number of partitions: %u\n", LayoutInfo->PartitionCount);
+  /* create ARC names for hard disk drives */
+  InitializeListHead(&BiosDiskListHead);
+  InitializeListHead(&DiskListHead);
+  IopEnumerateBiosDisks(&BiosDiskListHead);
+  IopEnumerateDisks(&DiskListHead);
 
-      for (j = 0;j < LayoutInfo->PartitionCount; j++)
-       {
-         swprintf(DeviceNameBuffer,
-                  L"\\Device\\Harddisk%lu\\Partition%lu",
-                  i,
-                  j + 1);
-         RtlInitUnicodeString(&DeviceName,
-                              DeviceNameBuffer);
-
-         swprintf(ArcNameBuffer,
-                  L"\\ArcName\\multi(0)disk(0)rdisk(%lu)partition(%lu)",
-                  k,
-                  j + 1);
-         RtlInitUnicodeString(&ArcName,
-                              ArcNameBuffer);
-         DPRINT("%wZ ==> %wZ\n",
-                &ArcName,
-                &DeviceName);
-
-         Status = IoAssignArcName(&ArcName,
-                                  &DeviceName);
-         if (!NT_SUCCESS(Status))
-           return(Status);
-       }
+  RDiskNumber = 0;
+  while (!IsListEmpty(&BiosDiskListHead))
+    {
+      Entry = RemoveHeadList(&BiosDiskListHead);
+      BiosDiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
+      Entry = DiskListHead.Flink;
+      while (Entry != &DiskListHead)
+        {
+          DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
+          if (DiskEntry->Checksum == BiosDiskEntry->Checksum &&
+              DiskEntry->Signature == BiosDiskEntry->Signature)
+            {
+
+              Status = IopAssignArcNamesToDisk(DiskEntry->DeviceObject, RDiskNumber, DiskEntry->DiskNumber);
+
+              RemoveEntryList(&DiskEntry->ListEntry);
+              ExFreePool(DiskEntry);
+              break;
+            }
+          Entry = Entry->Flink;
+        }
+      RDiskNumber++;
+      ExFreePool(BiosDiskEntry);
+    }
 
-      ExFreePool(LayoutInfo);
-      LayoutInfo = NULL;
-      k++;
+  while (!IsListEmpty(&DiskListHead))
+    {
+      Entry = RemoveHeadList(&DiskListHead);
+      DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
+      ExFreePool(DiskEntry);
     }
 
   /* create ARC names for cdrom drives */
@@ -173,7 +553,7 @@ IoCreateArcNames(VOID)
 }
 
 
-static NTSTATUS
+static NTSTATUS INIT_FUNCTION
 IopCheckCdromDevices(PULONG DeviceNumber)
 {
   PCONFIGURATION_INFORMATION ConfigInfo;