- Fixed the creation of arc names. Only valid partitions should be linked to an arc names.
- Create arc names only for partitions on disks, which are visible by the bios.
Modified: trunk/reactos/ntoskrnl/io/arcname.c

Modified: trunk/reactos/ntoskrnl/io/arcname.c
--- trunk/reactos/ntoskrnl/io/arcname.c	2005-09-15 17:19:31 UTC (rev 17864)
+++ trunk/reactos/ntoskrnl/io/arcname.c	2005-09-15 17:23:41 UTC (rev 17865)
@@ -19,56 +19,197 @@
 
 #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 @@
       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 @@
 			       &DeviceName);
       if (!NT_SUCCESS(Status))
 	return(Status);
+    }
 
-      Status = xHalQueryDriveLayout(&DeviceName,
-				    &LayoutInfo);
-      if (!NT_SUCCESS(Status))
-	return(Status);
+  /* create ARC names for hard disk drives */
+  InitializeListHead(&BiosDiskListHead);
+  InitializeListHead(&DiskListHead);
+  IopEnumerateBiosDisks(&BiosDiskListHead);
+  IopEnumerateDisks(&DiskListHead);
 
-      DPRINT("Number of partitions: %u\n", LayoutInfo->PartitionCount);
+  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)
+            {
 
-      for (j = 0;j < LayoutInfo->PartitionCount; j++)
-	{
-	  swprintf(DeviceNameBuffer,
-		   L"\\Device\\Harddisk%lu\\Partition%lu",
-		   i,
-		   j + 1);
-	  RtlInitUnicodeString(&DeviceName,
-			       DeviceNameBuffer);
+              Status = IopAssignArcNamesToDisk(DiskEntry->DeviceObject, RDiskNumber, DiskEntry->DiskNumber);
 
-	  swprintf(ArcNameBuffer,
-		   L"\\ArcName\\multi(0)disk(0)rdisk(%lu)partition(%lu)",
-		   k,
-		   j + 1);
-	  RtlInitUnicodeString(&ArcName,
-			       ArcNameBuffer);
-	  DPRINT("%wZ ==> %wZ\n",
-		 &ArcName,
-		 &DeviceName);
+              RemoveEntryList(&DiskEntry->ListEntry);
+              ExFreePool(DiskEntry);
+              break;
+            }
+          Entry = Entry->Flink;
+        }
+      RDiskNumber++;
+      ExFreePool(BiosDiskEntry);
+    }
 
-	  Status = IoAssignArcName(&ArcName,
-				   &DeviceName);
-	  if (!NT_SUCCESS(Status))
-	    return(Status);
-	}
-
-      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 @@
 }
 
 
-static NTSTATUS
+static NTSTATUS INIT_FUNCTION
 IopCheckCdromDevices(PULONG DeviceNumber)
 {
   PCONFIGURATION_INFORMATION ConfigInfo;