[ros-diffs] [ion] 24451: - Part 2 of ARC boot changes: Major modifications done to the existing code, as well as re-formatting and cleanup. Floppy ARC names are not created anymore (they don't exist), and CD-ROM ARC name is only created 1) when there is a boot CD and 2) only for the boot CD. This mimics NT functionality. - Optimize some code paths, mostly by not querying the whole GET_DRIVE_GEOMETRY IRP twice and reducing some buffer usage. Also re-factor some code better into smaller functions. - Document and work around currently FreeLDR incompatibility (lack of ARC_DISK_INFORMATION) data in LoaderBlock.

ion at svn.reactos.org ion at svn.reactos.org
Sun Oct 8 18:58:05 CEST 2006


Author: ion
Date: Sun Oct  8 20:58:03 2006
New Revision: 24451

URL: http://svn.reactos.org/svn/reactos?rev=24451&view=rev
Log:
- Part 2 of ARC boot changes: Major modifications done to the existing code, as well as re-formatting and cleanup. Floppy ARC names are not created anymore (they don't exist), and CD-ROM ARC name is only created 1) when there is a boot CD and 2) only for the boot CD. This mimics NT functionality.
- Optimize some code paths, mostly by not querying the whole GET_DRIVE_GEOMETRY IRP twice and reducing some buffer usage. Also re-factor some code better into smaller functions.
- Document and work around currently FreeLDR incompatibility (lack of ARC_DISK_INFORMATION) data in LoaderBlock.

Modified:
    trunk/reactos/include/reactos/arc/arc.h
    trunk/reactos/ntoskrnl/include/internal/io.h
    trunk/reactos/ntoskrnl/io/iomgr/arcname.c

Modified: trunk/reactos/include/reactos/arc/arc.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/arc/arc.h?rev=24451&r1=24450&r2=24451&view=diff
==============================================================================
--- trunk/reactos/include/reactos/arc/arc.h (original)
+++ trunk/reactos/include/reactos/arc/arc.h Sun Oct  8 20:58:03 2006
@@ -73,6 +73,19 @@
     struct _LDR_DATA_TABLE_ENTRY *DataTableEntry;
 } BOOT_DRIVER_LIST_ENTRY, *PBOOT_DRIVER_LIST_ENTRY;
 
+typedef struct _ARC_DISK_SIGNATURE
+{
+    LIST_ENTRY ListEntry;
+    ULONG Signature;
+    PCHAR ArcName;
+    ULONG CheckSum;
+    BOOLEAN ValidPartitionTable;
+    BOOLEAN xInt13;
+    BOOLEAN IsGpt;
+    BOOLEAN Reserved;
+    CHAR GptSignature[16];
+} ARC_DISK_SIGNATURE, *PARC_DISK_SIGNATURE;
+
 typedef struct _CONFIGURATION_COMPONENT
 {
     CONFIGURATION_CLASS Class;

Modified: trunk/reactos/ntoskrnl/include/internal/io.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/io.h?rev=24451&r1=24450&r2=24451&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/io.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/io.h Sun Oct  8 20:58:03 2006
@@ -423,6 +423,7 @@
     ULONG Signature;
     ULONG Checksum;
     PDEVICE_OBJECT DeviceObject;
+    ULONG PartitionCount;
 } DISKENTRY, *PDISKENTRY; 
 
 //

Modified: trunk/reactos/ntoskrnl/io/iomgr/arcname.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/arcname.c?rev=24451&r1=24450&r2=24451&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/arcname.c (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/arcname.c Sun Oct  8 20:58:03 2006
@@ -14,34 +14,6 @@
 #include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
-
-static NTSTATUS 
-STDCALL INIT_FUNCTION 
-DiskQueryRoutine(PWSTR ValueName, 
-                 ULONG ValueType, 
-                 PVOID ValueData, 
-                 ULONG ValueLength,
-                 PVOID Context,
-                 PVOID EntryContext);
-
-static VOID INIT_FUNCTION
-IopEnumerateBiosDisks(PLIST_ENTRY ListHead);
-
-static VOID INIT_FUNCTION
-IopEnumerateDisks(PLIST_ENTRY ListHead);
-
-static NTSTATUS INIT_FUNCTION
-IopAssignArcNamesToDisk(PDEVICE_OBJECT DeviceObject, ULONG RDisk, ULONG DiskNumber);
-
-#if defined (ALLOC_PRAGMA)
-#pragma alloc_text(INIT, DiskQueryRoutine)
-#pragma alloc_text(INIT, IopEnumerateBiosDisks)
-#pragma alloc_text(INIT, IopEnumerateDisks)
-#pragma alloc_text(INIT, IopAssignArcNamesToDisk)
-#pragma alloc_text(INIT, IoCreateArcNames)
-#pragma alloc_text(INIT, IoCreateSystemRootLink)
-#endif
-
 
 /* MACROS *******************************************************************/
 
@@ -174,420 +146,47 @@
     }
 }
 
-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);
-      RtlInitUnicodeString(&DeviceName,
-			   DeviceNameBuffer);
-
-
-      Status = IoGetDeviceObjectPointer(&DeviceName,
-				        FILE_READ_DATA,
-				        &FileObject,
-				        &DeviceObject);
-      if (!NT_SUCCESS(Status))
-        {
-	  continue;
-	}
-      IsRemovableMedia = DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA ? TRUE : FALSE;
-      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)fdisk(%lu)",
-	       i);
-      RtlInitUnicodeString(&ArcName,
-			   ArcNameBuffer);
-      DPRINT("%wZ ==> %wZ\n",
-	     &ArcName,
-	     &DeviceName);
-
-      Status = IoAssignArcName(&ArcName,
-			       &DeviceName);
-      if (!NT_SUCCESS(Status))
-	return(Status);
-    }
-
-  /* create ARC names for hard disk drives */
-  InitializeListHead(&BiosDiskListHead);
-  InitializeListHead(&DiskListHead);
-  IopEnumerateBiosDisks(&BiosDiskListHead);
-  IopEnumerateDisks(&DiskListHead);
-
-  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);
-    }
-
-  while (!IsListEmpty(&DiskListHead))
-    {
-      Entry = RemoveHeadList(&DiskListHead);
-      DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
-      ExFreePool(DiskEntry);
-    }
-
-  /* create ARC names for cdrom drives */
-  DPRINT("CD-ROM drives: %lu\n", ConfigInfo->CdRomCount);
-  for (i = 0; i < ConfigInfo->CdRomCount; i++)
-    {
-      swprintf(DeviceNameBuffer,
-	       L"\\Device\\CdRom%lu",
-	       i);
-      RtlInitUnicodeString(&DeviceName,
-			   DeviceNameBuffer);
-
-      swprintf(ArcNameBuffer,
-	       L"\\ArcName\\multi(0)disk(0)cdrom(%lu)",
-	       i);
-      RtlInitUnicodeString(&ArcName,
-			   ArcNameBuffer);
-      DPRINT("%wZ ==> %wZ\n",
-	     &ArcName,
-	     &DeviceName);
-
-      Status = IoAssignArcName(&ArcName,
-			       &DeviceName);
-      if (!NT_SUCCESS(Status))
-	return(Status);
-    }
-
-  DPRINT("IoCreateArcNames() done\n");
-
-  return(STATUS_SUCCESS);
-}
-
-VOID
+BOOLEAN
 INIT_FUNCTION
 NTAPI
-IopApplyRosCdromArcHack(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+IopApplyRosCdromArcHack(IN ULONG i)
 {
     ULONG DeviceNumber = -1;
-    PCONFIGURATION_INFORMATION ConfigInfo;
     OBJECT_ATTRIBUTES ObjectAttributes;
     UNICODE_STRING DeviceName;
     WCHAR Buffer[MAX_PATH];
     CHAR AnsiBuffer[MAX_PATH];
-    ULONG i;
     FILE_BASIC_INFORMATION FileInfo;
     NTSTATUS Status;
     PCHAR p, q;
 
     /* Only ARC Name left - Build full ARC Name */
-    p = strstr(LoaderBlock->ArcBootDeviceName, "cdrom");
+    p = strstr(KeLoaderBlock->ArcBootDeviceName, "cdrom");
     if (p)
     {
-        /* Get configuration information */
-        ConfigInfo = IoGetConfigurationInformation();
-        for (i = 0; i < ConfigInfo->CdRomCount; i++)
-        {
-            /* Try to find the installer */
-            swprintf(Buffer, L"\\Device\\CdRom%lu\\reactos\\ntoskrnl.exe", i);
-            RtlInitUnicodeString(&DeviceName, Buffer);
-            InitializeObjectAttributes(&ObjectAttributes,
-                                       &DeviceName,
-                                       0,
-                                       NULL,
-                                       NULL);
-            Status = ZwQueryAttributesFile(&ObjectAttributes, &FileInfo);
-            if (NT_SUCCESS(Status)) DeviceNumber = i;
-
-            /* Try to find live CD boot */
-            swprintf(Buffer,
-                     L"\\Device\\CdRom%lu\\reactos\\system32\\ntoskrnl.exe",
-                     i);
-            RtlInitUnicodeString(&DeviceName, Buffer);
-            InitializeObjectAttributes(&ObjectAttributes,
-                                       &DeviceName,
-                                       0,
-                                       NULL,
-                                       NULL);
-            Status = ZwQueryAttributesFile(&ObjectAttributes, &FileInfo);
-            if (NT_SUCCESS(Status)) DeviceNumber = i;
-        }
+        /* Try to find the installer */
+        swprintf(Buffer, L"\\Device\\CdRom%lu\\reactos\\ntoskrnl.exe", i);
+        RtlInitUnicodeString(&DeviceName, Buffer);
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &DeviceName,
+                                   0,
+                                   NULL,
+                                   NULL);
+        Status = ZwQueryAttributesFile(&ObjectAttributes, &FileInfo);
+        if (NT_SUCCESS(Status)) DeviceNumber = i;
+
+        /* Try to find live CD boot */
+        swprintf(Buffer,
+                 L"\\Device\\CdRom%lu\\reactos\\system32\\ntoskrnl.exe",
+                 i);
+        RtlInitUnicodeString(&DeviceName, Buffer);
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &DeviceName,
+                                   0,
+                                   NULL,
+                                   NULL);
+        Status = ZwQueryAttributesFile(&ObjectAttributes, &FileInfo);
+        if (NT_SUCCESS(Status)) DeviceNumber = i;
 
         /* Build the name */
         sprintf(p, "cdrom(%lu)", DeviceNumber);
@@ -602,6 +201,457 @@
             strcat(p, AnsiBuffer);
         }
     }
+
+    /* Return whether this is the CD or not */
+    if (DeviceNumber != 1) return TRUE;
+    return FALSE;
+}
+
+VOID
+INIT_FUNCTION
+NTAPI
+IopEnumerateDisks(IN PLIST_ENTRY ListHead)
+{
+    ULONG i, j;
+    ANSI_STRING TempString;
+    CHAR Buffer[256];
+    UNICODE_STRING DeviceName;
+    NTSTATUS Status;
+    PDEVICE_OBJECT DeviceObject;
+    PFILE_OBJECT FileObject;
+    DISK_GEOMETRY DiskGeometry;
+    PDRIVE_LAYOUT_INFORMATION DriveLayout;
+    KEVENT Event;
+    PIRP Irp;
+    IO_STATUS_BLOCK StatusBlock;
+    LARGE_INTEGER PartitionOffset;
+    PPARTITION_SECTOR PartitionBuffer;
+    PDISKENTRY DiskEntry;
+
+    /* Loop every detected disk */
+    for (i = 0; i < IoGetConfigurationInformation()->DiskCount; i++)
+    {
+        /* Build the name */
+        sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", i);
+
+        /* Convert it to Unicode */
+        RtlInitAnsiString(&TempString, Buffer);
+        Status = RtlAnsiStringToUnicodeString(&DeviceName, &TempString, TRUE);
+        if (!NT_SUCCESS(Status)) continue;
+
+        /* Get the device pointer */
+        Status = IoGetDeviceObjectPointer(&DeviceName,
+                                          FILE_READ_DATA,
+                                          &FileObject,
+                                          &DeviceObject);
+
+        /* Free the string */
+        RtlFreeUnicodeString(&DeviceName);
+
+        /* Move on if we failed */
+        if (!NT_SUCCESS(Status)) continue;
+
+        /* Allocate the ROS disk Entry */
+        DiskEntry = ExAllocatePoolWithTag(PagedPool, sizeof(DISKENTRY), TAG_IO);
+        DiskEntry->DiskNumber = i;
+        DiskEntry->DeviceObject = DeviceObject;
+
+        /* Build an IRP to 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)
+        {
+            /* Try again */
+            ObDereferenceObject(FileObject);
+            continue;
+        }
+
+        /* Call the driver and check if we have to wait on it */
+        Status = IoCallDriver(DeviceObject, Irp);
+        if (Status == STATUS_PENDING)
+        {
+            /* Wait on the driver */
+            KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+            Status = StatusBlock.Status;
+        }
+
+        /* Check if we failed */
+        if (!NT_SUCCESS(Status))
+        {
+            /* Try again */
+            ObDereferenceObject(FileObject);
+            continue;
+        }
+
+        /* Read the partition table */
+        Status = IoReadPartitionTable(DeviceObject,
+                                      DiskGeometry.BytesPerSector,
+                                      TRUE,
+                                      &DriveLayout);
+
+        /* Dereference the file object */
+        ObDereferenceObject(FileObject);
+        if (!NT_SUCCESS(Status)) continue;
+
+        /* Set the offset to 0 */
+        PartitionOffset.QuadPart = 0;
+
+        /* Allocate a buffer for the partition */
+        PartitionBuffer = ExAllocatePoolWithTag(NonPagedPool,
+                                                DiskGeometry.BytesPerSector,
+                                                TAG_IO);
+        if (!PartitionBuffer) continue;
+
+        /* Build an IRP to read the partition sector */
+        KeInitializeEvent(&Event, NotificationEvent, FALSE);
+        Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
+                                           DeviceObject,
+                                           PartitionBuffer,
+                                           DiskGeometry.BytesPerSector,
+                                           &PartitionOffset,
+                                           &Event,
+                                           &StatusBlock);
+
+        /* Call the driver and check if we have to wait */
+        Status = IoCallDriver(DeviceObject, Irp);
+        if (Status == STATUS_PENDING)
+        {
+            /* Wait for completion */
+            KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+            Status = StatusBlock.Status;
+        }
+
+        /* Check if we failed */
+        if (!NT_SUCCESS(Status))
+        {
+            /* Try again */
+            ExFreePool(PartitionBuffer);
+            ExFreePool(DriveLayout);
+            continue;
+        }
+
+        /* Calculate the MBR checksum */
+        DiskEntry->Checksum = 0;
+        for (j = 0; j < 128; j++)
+        {
+            DiskEntry->Checksum += ((PULONG)PartitionBuffer)[j];
+        }
+
+        /* Save the signature and checksum */
+        DiskEntry->Checksum = ~DiskEntry->Checksum + 1;
+        DiskEntry->Signature = DriveLayout->Signature;
+        DiskEntry->PartitionCount = DriveLayout->PartitionCount;
+
+        /* Insert it into the list */
+        InsertTailList(ListHead, &DiskEntry->ListEntry);
+
+        /* Free the buffer */
+        ExFreePool(PartitionBuffer);
+        ExFreePool(DriveLayout);
+    }
+}
+
+NTSTATUS
+INIT_FUNCTION
+NTAPI
+IopAssignArcNamesToDisk(IN PDEVICE_OBJECT DeviceObject,
+                        IN ULONG RDisk,
+                        IN ULONG DiskNumber,
+                        IN ULONG PartitionCount,
+                        IN PBOOLEAN FoundHdBoot)
+{
+    CHAR Buffer[256];
+    CHAR ArcBuffer[256];
+    ANSI_STRING TempString, ArcNameString, BootString;
+    ANSI_STRING ArcBootString, ArcSystemString;
+    UNICODE_STRING DeviceName, ArcName, BootPath;
+    ULONG i;
+    NTSTATUS Status;
+
+    /* HACK: Build the ARC name that FreeLDR should've given us */
+    CHAR BootArcName[256]; // should come from FREELDR
+    sprintf(BootArcName, "multi(0)disk(0)rdisk(%lu)", RDisk);
+
+    /* Set default */
+    *FoundHdBoot = FALSE;
+
+    /* Build the boot strings */
+    RtlInitAnsiString(&ArcBootString, KeLoaderBlock->ArcBootDeviceName);
+    RtlInitAnsiString(&ArcSystemString, KeLoaderBlock->ArcHalDeviceName);
+
+    /* Build the NT Device Name */
+    sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", DiskNumber);
+
+    /* Convert it to unicode */
+    RtlInitAnsiString(&TempString, Buffer);
+    Status = RtlAnsiStringToUnicodeString(&DeviceName, &TempString, TRUE);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Build the ARC Device Name */
+    sprintf(ArcBuffer, "\\ArcName\\%s", BootArcName);
+
+    /* Convert it to Unicode */
+    RtlInitAnsiString(&ArcNameString, ArcBuffer);
+    Status = RtlAnsiStringToUnicodeString(&ArcName, &ArcNameString, TRUE);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Create the symbolic link and free the strings */
+    IoAssignArcName(&ArcName, &DeviceName);
+    RtlFreeUnicodeString(&ArcName);
+    RtlFreeUnicodeString(&DeviceName);
+
+    /* Loop all the partitions */
+    for (i = 0; i < PartitionCount; i++)
+    {
+        /* Build the partition device name */
+        sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition%lu", DiskNumber, i+1);
+
+        /* Convert it to Unicode */
+        RtlInitAnsiString(&TempString, Buffer);
+        Status = RtlAnsiStringToUnicodeString(&DeviceName, &TempString, TRUE);
+        if (!NT_SUCCESS(Status)) continue;
+
+        /* Build the partial ARC name for this partition */
+        sprintf(ArcBuffer, "%spartition(%lu)", BootArcName, i + 1);
+        RtlInitAnsiString(&ArcNameString, ArcBuffer);
+
+        /* Check if this is the boot device */
+        if (RtlEqualString(&ArcNameString, &ArcBootString, TRUE))
+        {
+            /* Remember that we found a Hard Disk Boot Device */
+            *FoundHdBoot = TRUE;
+        }
+
+        /* Check if it's the system boot partition */
+        if (RtlEqualString(&ArcNameString, &ArcSystemString, TRUE))
+        {
+            /* It is, create a Unicode string for it */
+            RtlInitAnsiString(&BootString, KeLoaderBlock->NtHalPathName);
+            Status = RtlAnsiStringToUnicodeString(&BootPath, &BootString, TRUE);
+            if (NT_SUCCESS(Status))
+            {
+                /* FIXME: Save in registry */
+
+                /* Free the string now */
+                RtlFreeUnicodeString(&BootPath);
+            }
+        }
+
+        /* Build the full ARC name */
+        sprintf(Buffer, "\\ArcName\\%spartition(%lu)", BootArcName, i + 1);
+
+        /* Convert it to Unicode */
+        RtlInitAnsiString(&ArcNameString, Buffer);
+        Status = RtlAnsiStringToUnicodeString(&ArcName, &ArcNameString, TRUE);
+        if (!NT_SUCCESS(Status)) continue;
+
+        /* Create the symbolic link and free the strings */
+        IoAssignArcName(&ArcName, &DeviceName);
+        RtlFreeUnicodeString(&ArcName);
+        RtlFreeUnicodeString(&DeviceName);
+    }
+
+    /* Return success */
+    return STATUS_SUCCESS;
+}
+
+BOOLEAN
+INIT_FUNCTION
+NTAPI
+IopAssignArcNamesToCdrom(IN PULONG Buffer,
+                         IN ULONG DiskNumber)
+{
+    CHAR ArcBuffer[256];
+    ANSI_STRING TempString, ArcNameString;
+    UNICODE_STRING DeviceName, ArcName;
+    NTSTATUS Status;
+    LARGE_INTEGER PartitionOffset;
+    KEVENT Event;
+    IO_STATUS_BLOCK IoStatusBlock;
+    PIRP Irp;
+    ULONG i, CheckSum = 0;
+    PDEVICE_OBJECT DeviceObject;
+    PFILE_OBJECT FileObject;
+
+    /* Build the device name */
+    sprintf(ArcBuffer, "\\Device\\CdRom%lu", DiskNumber);
+
+    /* Convert it to Unicode */
+    RtlInitAnsiString(&TempString, ArcBuffer);
+    Status = RtlAnsiStringToUnicodeString(&DeviceName, &TempString, TRUE);
+    if (!NT_SUCCESS(Status)) return FALSE;
+
+    /* Get the device for it */
+    Status = IoGetDeviceObjectPointer(&DeviceName,
+                                      FILE_READ_ATTRIBUTES,
+                                      &FileObject,
+                                      &DeviceObject);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Free the string and fail */
+        RtlFreeUnicodeString(&DeviceName);
+        return FALSE;
+    }
+
+    /* Setup the event */
+    KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+    /* Set the offset and build the read IRP */
+    PartitionOffset.QuadPart = 0x8000;
+    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
+                                       DeviceObject,
+                                       Buffer,
+                                       2048,
+                                       &PartitionOffset,
+                                       &Event,
+                                       &IoStatusBlock);
+    if (!Irp)
+    {
+        /* Free the string and fail */
+        RtlFreeUnicodeString(&DeviceName);
+        return FALSE;
+    }
+
+    /* Call the driver and check if we have to wait on it */
+    Status = IoCallDriver(DeviceObject, Irp);
+    if (Status == STATUS_PENDING)
+    {
+        /* Wait for completion */
+        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+        Status = IoStatusBlock.Status;
+    }
+
+    /* Dereference the file object */
+    ObDereferenceObject(FileObject);
+    if (!NT_SUCCESS(Status)) return FALSE;
+
+    /* Now calculate the checksum */
+    for (i = 0; i < 2048 / sizeof(ULONG); i++) CheckSum += Buffer[i];
+
+    /*
+     * FIXME: In normal conditions, NTLDR/FreeLdr sends the *proper* CDROM
+     * ARC Path name, and what happens here is a comparision of both checksums
+     * in order to see if this is the actual boot CD.
+     *
+     * In ReactOS this doesn't currently happen, instead we have a hack on top
+     * of this file which scans the CD for the ntoskrnl.exe file, then modifies
+     * the LoaderBlock's ARC Path with the right CDROM path. Consequently, we
+     * get the same state as if NTLDR had properly booted us, except that we do
+     * not actually need to check the signature, since the hack already did the
+     * check for ntoskrnl.exe, which is just as good.
+     *
+     * The signature code stays however, because eventually FreeLDR will work
+     * like NTLDR, and, conversly, we do want to be able to be booted by NTLDR.
+     */
+    if (IopApplyRosCdromArcHack(DiskNumber))
+    {
+        /* This is the boot CD-ROM, build the ARC name */
+        sprintf(ArcBuffer, "\\ArcName\\%s", KeLoaderBlock->ArcBootDeviceName);
+
+        /* Convert it to Unicode */
+        RtlInitAnsiString(&ArcNameString, ArcBuffer);
+        Status = RtlAnsiStringToUnicodeString(&ArcName, &ArcNameString, TRUE);
+        if (!NT_SUCCESS(Status)) return FALSE;
+
+        /* Create the symbolic link and free the strings */
+        IoAssignArcName(&ArcName, &DeviceName);
+        RtlFreeUnicodeString(&ArcName);
+        RtlFreeUnicodeString(&DeviceName);
+
+        /* Let caller know that we've found the boot CD */
+        return TRUE;
+    }
+
+    /* No boot CD found */
+    return FALSE;
+}
+
+NTSTATUS INIT_FUNCTION
+IoCreateArcNames(VOID)
+{
+    PCONFIGURATION_INFORMATION ConfigInfo;
+    ULONG i, RDiskNumber;
+    NTSTATUS Status;
+    LIST_ENTRY BiosDiskListHead;
+    LIST_ENTRY DiskListHead;
+    PLIST_ENTRY Entry;
+    PDISKENTRY BiosDiskEntry;
+    PDISKENTRY DiskEntry;
+    BOOLEAN FoundBoot;
+    PULONG Buffer;
+
+    ConfigInfo = IoGetConfigurationInformation();
+
+    /* create ARC names for hard disk drives */
+    InitializeListHead(&BiosDiskListHead);
+    InitializeListHead(&DiskListHead);
+    IopEnumerateBiosDisks(&BiosDiskListHead);
+    IopEnumerateDisks(&DiskListHead);
+
+    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,
+                                                 DiskEntry->PartitionCount,
+                                                 &FoundBoot);
+
+                RemoveEntryList(&DiskEntry->ListEntry);
+                ExFreePool(DiskEntry);
+                break;
+            }
+            Entry = Entry->Flink;
+        }
+        RDiskNumber++;
+        ExFreePool(BiosDiskEntry);
+    }
+
+    while (!IsListEmpty(&DiskListHead))
+    {
+        Entry = RemoveHeadList(&DiskListHead);
+        DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
+        ExFreePool(DiskEntry);
+    }
+
+    /* Check if we didn't find the boot disk */
+    if (!FoundBoot)
+    {
+        /* Allocate a buffer for the CD-ROM MBR */
+        Buffer = ExAllocatePoolWithTag(NonPagedPool, 2048, TAG_IO);
+        if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES;
+
+        /* Loop every CD-ROM */
+        for (i = 0; i < ConfigInfo->CdRomCount; i++)
+        {
+            /* Give it an ARC name */
+            if (IopAssignArcNamesToCdrom(Buffer, i)) break;
+        }
+
+        /* Free the buffer */
+        ExFreePool(Buffer);
+    }
+
+    /* Return success */
+    return STATUS_SUCCESS;
 }
 
 NTSTATUS
@@ -617,9 +667,6 @@
     UNICODE_STRING LinkName, TargetName, ArcName;
     HANDLE LinkHandle;
 
-    /* Check if this is a CD-ROM boot */
-    IopApplyRosCdromArcHack(LoaderBlock);
-
     /* Create the Unicode name for the current ARC boot device */
     sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
     RtlInitAnsiString(&TargetString, Buffer);




More information about the Ros-diffs mailing list