[CMAKE]
[reactos.git] / ntoskrnl / io / iomgr / arcname.c
index 798219b..a49fdfc 100644 (file)
@@ -5,6 +5,7 @@
 * PURPOSE:         ARC Path Initialization Functions
 * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
 *                  Eric Kohl
+*                  Pierre Schweitzer (pierre.schweitzer@reactos.org)
 */
 
 /* INCLUDES ******************************************************************/
 
 UNICODE_STRING IoArcHalDeviceName, IoArcBootDeviceName;
 PCHAR IoLoaderArcBootDeviceName;
-extern PROS_LOADER_PARAMETER_BLOCK KeRosLoaderBlock;
 
 /* FUNCTIONS *****************************************************************/
 
-BOOLEAN
+NTSTATUS
+INIT_FUNCTION
+NTAPI
+IopCreateArcNamesCd(IN PLOADER_PARAMETER_BLOCK LoaderBlock
+);
+
+NTSTATUS
 INIT_FUNCTION
 NTAPI
-IopApplyRosCdromArcHack(IN ULONG i)
+IopCreateArcNamesDisk(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+                      IN BOOLEAN SingleDisk,
+                      IN PBOOLEAN FoundBoot
+);
+
+NTSTATUS
+INIT_FUNCTION
+NTAPI
+IopCreateArcNames(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 {
-    ULONG DeviceNumber = -1;
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    ANSI_STRING InstallName;
-    UNICODE_STRING DeviceName;
-    CHAR Buffer[128], RosSysPath[16];
-    FILE_BASIC_INFORMATION FileInfo;
+    PARC_DISK_INFORMATION ArcDiskInfo = LoaderBlock->ArcDiskInformation;
+    CHAR Buffer[128];
+    ANSI_STRING ArcSystemString, ArcString;
+    BOOLEAN SingleDisk;
+    ULONG Length;
     NTSTATUS Status;
-    PCHAR p, q;
-    PCONFIGURATION_INFORMATION ConfigInfo = IoGetConfigurationInformation();
-    extern BOOLEAN InitIsWinPEMode, ExpInTextModeSetup;
+    BOOLEAN FoundBoot = FALSE;
 
-    /* Change this if you want ROS to boot properly from another directory */
-    sprintf(RosSysPath, "%s", "reactos");
+    /* Check if we only have one disk on the machine */
+    SingleDisk = ArcDiskInfo->DiskSignatureListHead.Flink->Flink ==
+                 (&ArcDiskInfo->DiskSignatureListHead);
 
-    /* Only ARC Name left - Build full ARC Name */
-    p = strstr(KeLoaderBlock->ArcBootDeviceName, "cdrom");
-    if (p)
-    {
-        /* Build installer name */
-        sprintf(Buffer, "\\Device\\CdRom%lu\\%s\\ntoskrnl.exe", i, RosSysPath);
-        RtlInitAnsiString(&InstallName, Buffer);
-        Status = RtlAnsiStringToUnicodeString(&DeviceName, &InstallName, TRUE);
-        if (!NT_SUCCESS(Status)) return FALSE;
-
-        /* Try to find the installer */
-        InitializeObjectAttributes(&ObjectAttributes,
-                                   &DeviceName,
-                                   0,
-                                   NULL,
-                                   NULL);
-        Status = ZwQueryAttributesFile(&ObjectAttributes, &FileInfo);
-
-        /* Free the string */
-        RtlFreeUnicodeString(&DeviceName);
-
-        /* Check if we found the file */
-        if (NT_SUCCESS(Status))
-        {
-            /* We did, save the device number */
-            DeviceNumber = i;
-        }
-        else
-        {
-            /* Build live CD kernel name */
-            sprintf(Buffer,
-                    "\\Device\\CdRom%lu\\%s\\system32\\ntoskrnl.exe",
-                    i, RosSysPath);
-            RtlInitAnsiString(&InstallName, Buffer);
-            Status = RtlAnsiStringToUnicodeString(&DeviceName,
-                                                  &InstallName,
-                                                  TRUE);
-            if (!NT_SUCCESS(Status)) return FALSE;
-
-            /* Try to find it */
-            InitializeObjectAttributes(&ObjectAttributes,
-                                       &DeviceName,
-                                       0,
-                                       NULL,
-                                       NULL);
-            Status = ZwQueryAttributesFile(&ObjectAttributes, &FileInfo);
-            if (NT_SUCCESS(Status)) DeviceNumber = i;
-
-            /* Free the string */
-            RtlFreeUnicodeString(&DeviceName);
-        }
+    /* Create the global HAL partition name */
+    sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcHalDeviceName);
+    RtlInitAnsiString(&ArcString, Buffer);
+    RtlAnsiStringToUnicodeString(&IoArcHalDeviceName, &ArcString, TRUE);
 
-        if (!InitIsWinPEMode)
-        {
-            /* Build the name */
-            sprintf(p, "cdrom(%lu)", DeviceNumber);
+    /* Create the global system partition name */
+    sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
+    RtlInitAnsiString(&ArcString, Buffer);
+    RtlAnsiStringToUnicodeString(&IoArcBootDeviceName, &ArcString, TRUE);
 
-            /* Adjust original command line */
-            q = strchr(p, ')');
-            if (q)
-            {
-                q++;
-                strcpy(Buffer, q);
-                sprintf(p, "cdrom(%lu)", DeviceNumber);
-                strcat(p, Buffer);
-            }
-        }
+    /* Allocate memory for the string */
+    Length = strlen(LoaderBlock->ArcBootDeviceName) + sizeof(ANSI_NULL);
+    IoLoaderArcBootDeviceName = ExAllocatePoolWithTag(PagedPool,
+                                                      Length,
+                                                      TAG_IO);
+    if (IoLoaderArcBootDeviceName)
+    {
+        /* Copy the name */
+        RtlCopyMemory(IoLoaderArcBootDeviceName,
+                      LoaderBlock->ArcBootDeviceName,
+                      Length);
     }
 
-    /* OK, how many disks are there? */
-    DeviceNumber += ConfigInfo->DiskCount;
+    /* Check if we only found a disk, but we're booting from CD-ROM */
+    if ((SingleDisk) && strstr(LoaderBlock->ArcBootDeviceName, "cdrom"))
+    {
+        /* Then disable single-disk mode, since there's a CD drive out there */
+        SingleDisk = FALSE;
+    }
 
-    /* Return whether this is the CD or not */
-    if ((InitIsWinPEMode) || (ExpInTextModeSetup))
+    /* Build the boot strings */
+    RtlInitAnsiString(&ArcSystemString, LoaderBlock->ArcHalDeviceName);
+
+    /* FIXME: Handle IoRemoteBootClient here and create appropriate symbolic link */
+
+    /* Loop every disk and try to find boot disk */
+    Status = IopCreateArcNamesDisk(LoaderBlock, SingleDisk, &FoundBoot);
+    /* If it succeed but we didn't find boot device, try to browse Cds */
+    if (NT_SUCCESS(Status) && !FoundBoot)
     {
-        return TRUE;
+        Status = IopCreateArcNamesCd(LoaderBlock);
     }
 
-    /* Failed */
-    return FALSE;
+    /* Return success */
+    return Status;
 }
 
-BOOLEAN
+NTSTATUS
 INIT_FUNCTION
 NTAPI
-IopGetDiskInformation(IN ULONG i,
-                      OUT PULONG CheckSum,
-                      OUT PULONG Signature,
-                      OUT PULONG PartitionCount,
-                      OUT PDEVICE_OBJECT *DiskDeviceObject)
+IopCreateArcNamesCd(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 {
-    ULONG j, Checksum;
-    ANSI_STRING TempString;
-    CHAR Buffer[128];
-    UNICODE_STRING DeviceName;
+    PIRP Irp;
+    KEVENT Event;
     NTSTATUS Status;
-    PDEVICE_OBJECT DeviceObject;
+    PLIST_ENTRY NextEntry;
     PFILE_OBJECT FileObject;
-    DISK_GEOMETRY DiskGeometry;
-    PDRIVE_LAYOUT_INFORMATION DriveLayout;
-    KEVENT Event;
-    PIRP Irp;
-    IO_STATUS_BLOCK StatusBlock;
-    LARGE_INTEGER PartitionOffset;
-    PULONG PartitionBuffer;
-
-    /* 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)) return FALSE;
-
-    /* Get the device pointer */
-    Status = IoGetDeviceObjectPointer(&DeviceName,
-                                      FILE_READ_ATTRIBUTES,
-                                      &FileObject,
-                                      &DeviceObject);
-    *DiskDeviceObject = DeviceObject;
+    PDEVICE_OBJECT DeviceObject;
+    LARGE_INTEGER StartingOffset;
+    IO_STATUS_BLOCK IoStatusBlock;
+    PULONG PartitionBuffer = NULL;
+    CHAR Buffer[128], ArcBuffer[128];
+    BOOLEAN NotEnabledPresent = FALSE;
+    STORAGE_DEVICE_NUMBER DeviceNumber;
+    ANSI_STRING DeviceStringA, ArcNameStringA;
+    PWSTR SymbolicLinkList, lSymbolicLinkList;
+    PARC_DISK_SIGNATURE ArcDiskSignature = NULL;
+    UNICODE_STRING DeviceStringW, ArcNameStringW;
+    ULONG DiskNumber, CdRomCount, CheckSum, i, EnabledDisks = 0;
+    PARC_DISK_INFORMATION ArcDiskInformation = LoaderBlock->ArcDiskInformation;
+
+    /* Get all the Cds present in the system */
+    CdRomCount = IoGetConfigurationInformation()->CdRomCount;
+
+    /* Get enabled Cds and check if result matches
+     * For the record, enabled Cds (or even disk) are Cds/disks
+     * that have been successfully handled by MountMgr driver
+     * and that already own their device name. This is the "new" way
+     * to handle them, that came with NT5.
+     * Currently, Windows 2003 provides an arc names creation based
+     * on both enabled drives and not enabled drives (lack from
+     * the driver).
+     * Given the current ReactOS state, that's good for us.
+     * To sum up, this is NOT a hack or whatsoever.
+     */
+    Status = IopFetchConfigurationInformation(&SymbolicLinkList,
+                                              GUID_DEVINTERFACE_CDROM,
+                                              CdRomCount,
+                                              &EnabledDisks);
+    if (!NT_SUCCESS(Status))
+    {
+        NotEnabledPresent = TRUE;
+    }
+    /* Save symbolic link list address in order to free it after */
+    lSymbolicLinkList = SymbolicLinkList;
+    /* For the moment, we won't fail */
+    Status = STATUS_SUCCESS;
+
+    /* Browse all the ARC devices trying to find the one matching boot device */
+    for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink;
+         NextEntry != &ArcDiskInformation->DiskSignatureListHead;
+         NextEntry = NextEntry->Flink)
+    {
+        ArcDiskSignature = CONTAINING_RECORD(NextEntry,
+                                             ARC_DISK_SIGNATURE,
+                                             ListEntry);
 
-    /* Free the string */
-    RtlFreeUnicodeString(&DeviceName);
+        if (strcmp(LoaderBlock->ArcBootDeviceName, ArcDiskSignature->ArcName) == 0)
+        {
+            break;
+        }
 
-    /* Move on if we failed */
-    if (!NT_SUCCESS(Status)) return FALSE;
+        ArcDiskSignature = NULL;
+    }
 
-    /* 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)
+    /* Not found... Not booting from a Cd */
+    if (!ArcDiskSignature)
     {
-        /* Try again */
-        ObDereferenceObject(FileObject);
-        return FALSE;
+        DPRINT("Failed finding a cd that could match current boot device\n");
+        goto Cleanup;
     }
 
-    /* Call the driver and check if we have to wait on it */
-    Status = IoCallDriver(DeviceObject, Irp);
-    if (Status == STATUS_PENDING)
+    /* Allocate needed space for reading Cd */
+    PartitionBuffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned, 2048, TAG_IO);
+    if (!PartitionBuffer)
     {
-        /* Wait on the driver */
-        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
-        Status = StatusBlock.Status;
+        DPRINT("Failed allocating resources!\n");
+        /* Here, we fail, BUT we return success, some Microsoft joke */
+        goto Cleanup;
     }
 
-    /* Check if we failed */
-    if (!NT_SUCCESS(Status))
+    /* If we have more enabled Cds, take that into account */
+    if (EnabledDisks > CdRomCount)
     {
-        /* Try again */
-        ObDereferenceObject(FileObject);
-        return FALSE;
+        CdRomCount = EnabledDisks;
     }
 
-    /* Read the partition table */
-    Status = IoReadPartitionTable(DeviceObject,
-                                  DiskGeometry.BytesPerSector,
-                                  TRUE,
-                                  &DriveLayout);
-
-    /* Dereference the file object */
-    ObDereferenceObject(FileObject);
-    if (!NT_SUCCESS(Status)) return FALSE;
-
-    /* Set the offset to 0 */
-    PartitionOffset.QuadPart = 0;
-
-    /* Allocate a buffer for the partition */
-    PartitionBuffer = ExAllocatePoolWithTag(NonPagedPool,
-                                            DiskGeometry.BytesPerSector,
-                                            TAG_IO);
-    if (!PartitionBuffer)
+    /* If we'll have to browse for none enabled Cds, fix higher count */
+    if (NotEnabledPresent && !EnabledDisks)
     {
-        /* Try again */
-        ExFreePoolWithTag(DriveLayout, TAG_FILE_SYSTEM);
-        return FALSE;
+        CdRomCount += 5;
     }
 
-    /* Build an IRP to read the partition sector */
-    KeInitializeEvent(&Event, NotificationEvent, FALSE);
-    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
-                                       DeviceObject,
-                                       PartitionBuffer,
-                                       DiskGeometry.BytesPerSector,
-                                       &PartitionOffset,
-                                       &Event,
-                                       &StatusBlock);
-    if (!Irp)
+    /* Finally, if in spite of all that work, we still don't have Cds, leave */
+    if (!CdRomCount)
     {
-        /* Try again  */
-        ExFreePoolWithTag(PartitionBuffer, TAG_IO);
-        ExFreePoolWithTag(DriveLayout, TAG_FILE_SYSTEM);
-        return FALSE;
+        goto Cleanup;
     }
 
-    /* Call the driver and check if we have to wait */
-    Status = IoCallDriver(DeviceObject, Irp);
-    if (Status == STATUS_PENDING)
+    /* Start browsing Cds */
+    for (DiskNumber = 0, EnabledDisks = 0; DiskNumber < CdRomCount; DiskNumber++)
     {
-        /* Wait for completion */
-        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
-        Status = StatusBlock.Status;
+        /* Check if we have an enabled disk */
+        if (SymbolicLinkList && *SymbolicLinkList != UNICODE_NULL)
+        {
+            /* Create its device name using first symbolic link */
+            RtlInitUnicodeString(&DeviceStringW, lSymbolicLinkList);
+            /* Then, update symbolic links list */
+            lSymbolicLinkList += wcslen(lSymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR));
+
+            /* Get its associated device object and file object */
+            Status = IoGetDeviceObjectPointer(&DeviceStringW,
+                                              FILE_READ_ATTRIBUTES,
+                                              &FileObject,
+                                              &DeviceObject);
+            /* Failure? Good bye! */
+            if (!NT_SUCCESS(Status))
+            {
+                goto Cleanup;
+            }
+
+            /* Now, we'll ask the device its device number */
+            Irp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_DEVICE_NUMBER,
+                                                DeviceObject,
+                                                NULL,
+                                                0,
+                                                &DeviceNumber,
+                                                sizeof(STORAGE_DEVICE_NUMBER),
+                                                FALSE,
+                                                &Event,
+                                                &IoStatusBlock);
+            /* Failure? Good bye! */
+            if (!Irp)
+            {
+                /* Dereference file object before leaving */
+                ObDereferenceObject(FileObject);
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+                goto Cleanup;
+            }
+
+            /* Call the driver, and wait for it if needed */
+            KeInitializeEvent(&Event, NotificationEvent, FALSE);
+            Status = IoCallDriver(DeviceObject, Irp);
+            if (Status == STATUS_PENDING)
+            {
+                KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+                Status = IoStatusBlock.Status;
+            }
+            if (!NT_SUCCESS(Status))
+            {
+                ObDereferenceObject(FileObject);
+                goto Cleanup;
+            }
+
+            /* Finally, build proper device name */
+            sprintf(Buffer, "\\Device\\CdRom%lu", DeviceNumber.DeviceNumber);
+            RtlInitAnsiString(&DeviceStringA, Buffer);
+            Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
+            if (!NT_SUCCESS(Status))
+            {
+                ObDereferenceObject(FileObject);
+                goto Cleanup;
+            }
+        }
+        else
+        {
+            /* Create device name for the cd */
+            sprintf(Buffer, "\\Device\\CdRom%lu", EnabledDisks++);
+            RtlInitAnsiString(&DeviceStringA, Buffer);
+            Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
+            if (!NT_SUCCESS(Status))
+            {
+                goto Cleanup;
+            }
+
+            /* Get its device object */
+            Status = IoGetDeviceObjectPointer(&DeviceStringW,
+                                              FILE_READ_ATTRIBUTES,
+                                              &FileObject,
+                                              &DeviceObject);
+            if (!NT_SUCCESS(Status))
+            {
+                RtlFreeUnicodeString(&DeviceStringW);
+                goto Cleanup;
+            }
+        }
+
+        /* Initiate data for reading cd and compute checksum */
+        StartingOffset.QuadPart = 0x8000;
+        CheckSum = 0;
+        Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
+                                           DeviceObject,
+                                           PartitionBuffer,
+                                           2048,
+                                           &StartingOffset,
+                                           &Event,
+                                           &IoStatusBlock);
+        if (Irp)
+        {
+            /* Call the driver, and wait for it if needed */
+            KeInitializeEvent(&Event, NotificationEvent, FALSE);
+            Status = IoCallDriver(DeviceObject, Irp);
+            if (Status == STATUS_PENDING)
+            {
+                KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+                Status = IoStatusBlock.Status;
+            }
+
+            /* Reading succeed, compute checksum by adding data, 2048 bytes checksum */
+            if (NT_SUCCESS(Status))
+            {
+                for (i = 0; i < 2048 / sizeof(ULONG); i++)
+                {
+                    CheckSum += PartitionBuffer[i];
+                }
+            }
+        }
+
+        /* Dereference file object */
+        ObDereferenceObject(FileObject);
+
+        /* If checksums are matching, we have the proper cd */
+        if (CheckSum + ArcDiskSignature->CheckSum == 0)
+        {
+            /* Create ARC name */
+            sprintf(ArcBuffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
+            RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
+            Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE);
+            if (NT_SUCCESS(Status))
+            {
+                /* Create symbolic link */
+                IoCreateSymbolicLink(&ArcNameStringW, &DeviceStringW);
+                RtlFreeUnicodeString(&ArcNameStringW);
+                DPRINT1("Boot device found\n");
+            }
+
+            /* And quit, whatever happens */
+            RtlFreeUnicodeString(&DeviceStringW);
+            goto Cleanup;
+        }
+
+        /* Free string before trying another disk */
+        RtlFreeUnicodeString(&DeviceStringW);
     }
 
-    /* Check if we failed */
-    if (!NT_SUCCESS(Status))
+Cleanup:
+    if (PartitionBuffer)
     {
-        /* Try again */
         ExFreePoolWithTag(PartitionBuffer, TAG_IO);
-        ExFreePoolWithTag(DriveLayout, TAG_FILE_SYSTEM);
-        return FALSE;
     }
 
-    /* Calculate the MBR checksum */
-    Checksum = 0;
-    for (j = 0; j < 128; j++) Checksum += PartitionBuffer[j];
-
-    /* Save the signature and checksum */
-    *CheckSum = ~Checksum + 1;
-    *Signature = DriveLayout->Signature;
-    *PartitionCount = DriveLayout->PartitionCount;
+    if (SymbolicLinkList)
+    {
+        ExFreePool(SymbolicLinkList);
+    }
 
-    /* Free the buffer */
-    ExFreePoolWithTag(PartitionBuffer, TAG_IO);
-    ExFreePoolWithTag(DriveLayout, TAG_FILE_SYSTEM);
-    return TRUE;
+    return Status;
 }
 
-BOOLEAN
+NTSTATUS
 INIT_FUNCTION
 NTAPI
-IopAssignArcNamesToCdrom(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
-                         IN PULONG Buffer,
-                         IN ULONG DiskNumber)
+IopCreateArcNamesDisk(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+                      IN BOOLEAN SingleDisk,
+                      IN PBOOLEAN FoundBoot)
 {
-    CHAR ArcBuffer[128];
-    ANSI_STRING TempString;
-    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;
-    PARC_DISK_INFORMATION ArcDiskInfo = LoaderBlock->ArcDiskInformation;
+    PVOID Data;
+    KEVENT Event;
+    NTSTATUS Status;
     PLIST_ENTRY NextEntry;
-    PARC_DISK_SIGNATURE ArcDiskEntry;
-    BOOLEAN IsBootCdRom = FALSE;
+    PFILE_OBJECT FileObject;
+    DISK_GEOMETRY DiskGeometry;
+    PDEVICE_OBJECT DeviceObject;
+    LARGE_INTEGER StartingOffset;
+    PULONG PartitionBuffer = NULL;
+    IO_STATUS_BLOCK IoStatusBlock;
+    CHAR Buffer[128], ArcBuffer[128];
+    BOOLEAN NotEnabledPresent = FALSE;
+    STORAGE_DEVICE_NUMBER DeviceNumber;
+    PARC_DISK_SIGNATURE ArcDiskSignature;
+    PWSTR SymbolicLinkList, lSymbolicLinkList;
+    PDRIVE_LAYOUT_INFORMATION_EX DriveLayout = NULL;
+    UNICODE_STRING DeviceStringW, ArcNameStringW, HalPathStringW;
+    ULONG DiskNumber, DiskCount, CheckSum, i, Signature, EnabledDisks = 0;
+    PARC_DISK_INFORMATION ArcDiskInformation = LoaderBlock->ArcDiskInformation;
+    ANSI_STRING ArcBootString, ArcSystemString, DeviceStringA, ArcNameStringA, HalPathStringA;
+
+    /* Initialise device number */
+    DeviceNumber.DeviceNumber = 0xFFFFFFFF;
+    /* Get all the disks present in the system */
+    DiskCount = IoGetConfigurationInformation()->DiskCount;
+
+    /* Get enabled disks and check if result matches */
+    Status = IopFetchConfigurationInformation(&SymbolicLinkList,
+                                              GUID_DEVINTERFACE_DISK,
+                                              DiskCount,
+                                              &EnabledDisks);
+    if (!NT_SUCCESS(Status))
+    {
+        NotEnabledPresent = TRUE;
+    }
 
-    /* Build the device name */
-    sprintf(ArcBuffer, "\\Device\\CdRom%lu", DiskNumber);
+    /* Save symbolic link list address in order to free it after */
+    lSymbolicLinkList = SymbolicLinkList;
 
-    /* Convert it to Unicode */
-    RtlInitAnsiString(&TempString, ArcBuffer);
-    Status = RtlAnsiStringToUnicodeString(&DeviceName, &TempString, TRUE);
-    if (!NT_SUCCESS(Status)) return FALSE;
+    /* Build the boot strings */
+    RtlInitAnsiString(&ArcBootString, LoaderBlock->ArcBootDeviceName);
+    RtlInitAnsiString(&ArcSystemString, LoaderBlock->ArcHalDeviceName);
 
-    /* Get the device for it */
-    Status = IoGetDeviceObjectPointer(&DeviceName,
-                                      FILE_READ_ATTRIBUTES,
-                                      &FileObject,
-                                      &DeviceObject);
-    if (!NT_SUCCESS(Status))
+    /* If we have more enabled disks, take that into account */
+    if (EnabledDisks > DiskCount)
     {
-        /* Free the string and fail */
-        RtlFreeUnicodeString(&DeviceName);
-        return FALSE;
+        DiskCount = EnabledDisks;
     }
 
-    /* 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)
+    /* If we'll have to browse for none enabled disks, fix higher count */
+    if (NotEnabledPresent && !EnabledDisks)
     {
-        /* Free the string and fail */
-        RtlFreeUnicodeString(&DeviceName);
-        return FALSE;
+        DiskCount += 20;
     }
 
-    /* Call the driver and check if we have to wait on it */
-    Status = IoCallDriver(DeviceObject, Irp);
-    if (Status == STATUS_PENDING)
+    /* Finally, if in spite of all that work, we still don't have disks, leave */
+    if (!DiskCount)
     {
-        /* Wait for completion */
-        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
-        Status = IoStatusBlock.Status;
+        goto Cleanup;
     }
 
-    /* Dereference the file object */
-    ObDereferenceObject(FileObject);
-    if (!NT_SUCCESS(Status)) return FALSE;
+    /* Start browsing disks */
+    for (DiskNumber = 0; DiskNumber < DiskCount; DiskNumber++)
+    {
+        /* Check if we have an enabled disk */
+        if (lSymbolicLinkList && *lSymbolicLinkList != UNICODE_NULL)
+        {
+            /* Create its device name using first symbolic link */
+            RtlInitUnicodeString(&DeviceStringW, lSymbolicLinkList);
+            /* Then, update symbolic links list */
+            lSymbolicLinkList += wcslen(lSymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR));
+
+            /* Get its associated device object and file object */
+            Status = IoGetDeviceObjectPointer(&DeviceStringW,
+                                              FILE_READ_ATTRIBUTES,
+                                              &FileObject,
+                                              &DeviceObject);
+            if (NT_SUCCESS(Status))
+            {
+                /* Now, we'll ask the device its device number */
+                Irp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_DEVICE_NUMBER,
+                                                    DeviceObject,
+                                                    NULL,
+                                                    0,
+                                                    &DeviceNumber,
+                                                    sizeof(STORAGE_DEVICE_NUMBER),
+                                                    FALSE,
+                                                    &Event,
+                                                    &IoStatusBlock);
+                /* Missing resources is a shame... No need to go farther */
+                if (!Irp)
+                {
+                    ObDereferenceObject(FileObject);
+                    Status = STATUS_INSUFFICIENT_RESOURCES;
+                    goto Cleanup;
+                }
 
-    /* Now calculate the checksum */
-    for (i = 0; i < 2048 / sizeof(ULONG); i++) CheckSum += Buffer[i];
+                /* Call the driver, and wait for it if needed */
+                KeInitializeEvent(&Event, NotificationEvent, FALSE);
+                Status = IoCallDriver(DeviceObject, Irp);
+                if (Status == STATUS_PENDING)
+                {
+                    KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+                    Status = IoStatusBlock.Status;
+                }
 
-    if (KeRosLoaderBlock) goto freeldrhack;
+                /* If we didn't get the appriopriate data, just skip that disk */
+                if (!NT_SUCCESS(Status))
+                {
+                   ObDereferenceObject(FileObject);
+                   continue;
+                }
+            }
 
-    /* Search if this device is the actual boot CD */
-    for (NextEntry = ArcDiskInfo->DiskSignatureListHead.Flink;
-         NextEntry != &ArcDiskInfo->DiskSignatureListHead;
-         NextEntry = NextEntry->Flink)
-    {
-        /* Get the current ARC disk signature entry */
-        ArcDiskEntry = CONTAINING_RECORD(NextEntry,
-                                         ARC_DISK_SIGNATURE,
-                                         ListEntry);
-        /* And check if checksums and arc names match */
-        if (CheckSum == ArcDiskEntry->CheckSum &&
-            strcmp(KeLoaderBlock->ArcBootDeviceName, ArcDiskEntry->ArcName) == 0)
-        {
-            IsBootCdRom = TRUE;
-            break;
-        }
-    }
-    goto checkbootcd;
-
-freeldrhack:
-    /*
-     * 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.
-     */
-    IsBootCdRom = IopApplyRosCdromArcHack(DiskNumber);
+            /* End of enabled disks enumeration */
+            if (NotEnabledPresent && *lSymbolicLinkList == UNICODE_NULL)
+            {
+                /* No enabled disk worked, reset field */
+                if (DeviceNumber.DeviceNumber == 0xFFFFFFFF)
+                {
+                    DeviceNumber.DeviceNumber = 0;
+                }
 
-checkbootcd:
-    if (IsBootCdRom)
-    {
-        /* This is the boot CD-ROM, build the ARC name */
-        sprintf(ArcBuffer, "\\ArcName\\%s", KeLoaderBlock->ArcBootDeviceName);
+                /* Update disk number to enable the following not enabled disks */
+                if (DeviceNumber.DeviceNumber > DiskNumber)
+                {
+                    DiskNumber = DeviceNumber.DeviceNumber;
+                }
 
-        /* Convert it to Unicode */
-        RtlInitAnsiString(&TempString, ArcBuffer);
-        Status = RtlAnsiStringToUnicodeString(&ArcName, &TempString, TRUE);
-        if (!NT_SUCCESS(Status)) return FALSE;
+                /* Increase a bit more */
+                DiskCount = DiskNumber + 20;
+            }
+        }
+        else
+        {
+            /* Create device name for the disk */
+            sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", DiskNumber);
+            RtlInitAnsiString(&DeviceStringA, Buffer);
+            Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
+            if (!NT_SUCCESS(Status))
+            {
+                goto Cleanup;
+            }
 
-        /* Create the symbolic link and free the strings */
-        IoAssignArcName(&ArcName, &DeviceName);
-        RtlFreeUnicodeString(&ArcName);
-        RtlFreeUnicodeString(&DeviceName);
+            /* Get its device object */
+            Status = IoGetDeviceObjectPointer(&DeviceStringW,
+                                              FILE_READ_ATTRIBUTES,
+                                              &FileObject,
+                                              &DeviceObject);
 
-        /* Let caller know that we've found the boot CD */
-        return TRUE;
-    }
+            RtlFreeUnicodeString(&DeviceStringW);
+            /* This is a security measure, to ensure DiskNumber will be used */
+            DeviceNumber.DeviceNumber = 0xFFFFFFFF;
+        }
 
-    /* No boot CD found */
-    return FALSE;
-}
+        /* Something failed somewhere earlier, just skip the disk */
+        if (!NT_SUCCESS(Status))
+        {
+            continue;
+        }
 
-NTSTATUS
-INIT_FUNCTION
-NTAPI
-IopCreateArcNames(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
-{
-    PCONFIGURATION_INFORMATION ConfigInfo = IoGetConfigurationInformation();
-    PARC_DISK_INFORMATION ArcDiskInfo = LoaderBlock->ArcDiskInformation;
-    CHAR Buffer[128];
-    ANSI_STRING ArcBootString, ArcSystemString, ArcString;
-    UNICODE_STRING ArcName, BootPath, DeviceName;
-    BOOLEAN SingleDisk;
-    ULONG i, j, Length;
-    PDEVICE_OBJECT DeviceObject;
-    ULONG Signature, Checksum, PartitionCount;
-    PLIST_ENTRY NextEntry;
-    PARC_DISK_SIGNATURE ArcDiskEntry;
-    NTSTATUS Status;
-    BOOLEAN FoundBoot = FALSE;
-    PULONG PartitionBuffer;
+        /* Let's ask the disk for its geometry */
+        Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY,
+                                            DeviceObject,
+                                            NULL,
+                                            0,
+                                            &DiskGeometry,
+                                            sizeof(DISK_GEOMETRY),
+                                            FALSE,
+                                            &Event,
+                                            &IoStatusBlock);
+        /* Missing resources is a shame... No need to go farther */
+        if (!Irp)
+        {
+            ObDereferenceObject(FileObject);
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            goto Cleanup;
+        }
 
-    /* Check if we only have one disk on the machine */
-    SingleDisk = ArcDiskInfo->DiskSignatureListHead.Flink->Flink ==
-                 (&ArcDiskInfo->DiskSignatureListHead);
+        /* Call the driver, and wait for it if needed */
+        KeInitializeEvent(&Event, NotificationEvent, FALSE);
+        Status = IoCallDriver(DeviceObject, Irp);
+        if (Status == STATUS_PENDING)
+        {
+            KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+            Status = IoStatusBlock.Status;
+        }
+        /* Failure, skip disk */
+        if (!NT_SUCCESS(Status))
+        {
+            ObDereferenceObject(FileObject);
+            continue;
+        }
 
-    /* Create the global HAL partition name */
-    sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcHalDeviceName);
-    RtlInitAnsiString(&ArcString, Buffer);
-    RtlAnsiStringToUnicodeString(&IoArcHalDeviceName, &ArcString, TRUE);
+        /* Read the partition table */
+        Status = IoReadPartitionTableEx(DeviceObject,
+                                        &DriveLayout);
+        if (!NT_SUCCESS(Status))
+        {
+            ObDereferenceObject(FileObject);
+            continue;
+        }
 
-    /* Create the global system partition name */
-    sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
-    RtlInitAnsiString(&ArcString, Buffer);
-    RtlAnsiStringToUnicodeString(&IoArcBootDeviceName, &ArcString, TRUE);
+        /* Ensure we have at least 512 bytes per sector */
+        if (DiskGeometry.BytesPerSector < 512)
+        {
+            DiskGeometry.BytesPerSector = 512;
+        }
 
-    /* Allocate memory for the string */
-    Length = strlen(LoaderBlock->ArcBootDeviceName) + sizeof(ANSI_NULL);
-    IoLoaderArcBootDeviceName = ExAllocatePoolWithTag(PagedPool,
-                                                      Length,
-                                                      TAG_IO);
-    if (IoLoaderArcBootDeviceName)
-    {
-        /* Copy the name */
-        RtlCopyMemory(IoLoaderArcBootDeviceName,
-                      LoaderBlock->ArcBootDeviceName,
-                      Length);
-    }
+        /* Check MBR type against EZ Drive type */
+        StartingOffset.QuadPart = 0;
+        HalExamineMBR(DeviceObject, DiskGeometry.BytesPerSector, 0x55, &Data);
+        if (Data)
+        {
+            /* If MBR is of the EZ Drive type, we'll read after it */
+            StartingOffset.QuadPart = DiskGeometry.BytesPerSector;
+            ExFreePool(Data);
+        }
 
-    /* Check if we only found a disk, but we're booting from CD-ROM */
-    if ((SingleDisk) && strstr(LoaderBlock->ArcBootDeviceName, "cdrom"))
-    {
-        /* Then disable single-disk mode, since there's a CD drive out there */
-        SingleDisk = FALSE;
-    }
+        /* Allocate for reading enough data for checksum */
+        PartitionBuffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned, DiskGeometry.BytesPerSector, TAG_IO);
+        if (!PartitionBuffer)
+        {
+            ObDereferenceObject(FileObject);
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            goto Cleanup;
+        }
 
-    /* Build the boot strings */
-    RtlInitAnsiString(&ArcBootString, LoaderBlock->ArcBootDeviceName);
-    RtlInitAnsiString(&ArcSystemString, LoaderBlock->ArcHalDeviceName);
+        /* Read a sector for computing checksum */
+        Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
+                                           DeviceObject,
+                                           PartitionBuffer,
+                                           DiskGeometry.BytesPerSector,
+                                           &StartingOffset,
+                                           &Event,
+                                           &IoStatusBlock);
+        if (!Irp)
+        {
+            ObDereferenceObject(FileObject);
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            goto Cleanup;
+        }
 
-    /* Loop every detected disk */
-    for (i = 0; i < ConfigInfo->DiskCount; i++)
-    {
-        /* Get information about the disk */
-        if (!IopGetDiskInformation(i,
-                                   &Checksum,
-                                   &Signature,
-                                   &PartitionCount,
-                                   &DeviceObject))
+        /* Call the driver to perform reading */
+        KeInitializeEvent(&Event, NotificationEvent, FALSE);
+        Status = IoCallDriver(DeviceObject, Irp);
+        if (Status == STATUS_PENDING)
+        {
+            KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+            Status = IoStatusBlock.Status;
+        }
+        if (!NT_SUCCESS(Status))
         {
-            /* Skip this disk */
+            ExFreePool(DriveLayout);
+            ExFreePoolWithTag(PartitionBuffer, TAG_IO);
+            ObDereferenceObject(FileObject);
             continue;
         }
 
-        /* Loop ARC disks */
-        for (NextEntry = ArcDiskInfo->DiskSignatureListHead.Flink;
-             NextEntry != &ArcDiskInfo->DiskSignatureListHead;
-             NextEntry = NextEntry->Flink)
+        ObDereferenceObject(FileObject);
+
+        /* Calculate checksum, that's an easy computation, just adds read data */
+        for (i = 0, CheckSum = 0; i < 512 / sizeof(ULONG) ; i++)
         {
-            /* Get the current ARC disk signature entry */
-            ArcDiskEntry = CONTAINING_RECORD(NextEntry,
-                                             ARC_DISK_SIGNATURE,
-                                             ListEntry);
+            CheckSum += PartitionBuffer[i];
+        }
 
-            /*
-             * Now check if the signature and checksum match, unless this is
-             * the only disk that was in the ARC list, and also in the device
-             * tree, in which case the check is bypassed and we accept the disk
+        /* Browse each ARC disk */
+        for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink;
+             NextEntry != &ArcDiskInformation->DiskSignatureListHead;
+             NextEntry = NextEntry->Flink)
+        {
+            ArcDiskSignature = CONTAINING_RECORD(NextEntry,
+                                                 ARC_DISK_SIGNATURE,
+                                                 ListEntry);
+
+            /* If they matches, ie
+             * - There's only one disk for both BIOS and detected/enabled
+             * - Signatures are matching
+             * - Checksums are matching
+             * - This is MBR
              */
-            if (((SingleDisk) && (ConfigInfo->DiskCount == 1)) ||
-                ((Checksum == ArcDiskEntry->CheckSum) &&
-                 (Signature == ArcDiskEntry->Signature)))
+            if (((SingleDisk && DiskCount == 1) ||
+                (IopVerifyDiskSignature(DriveLayout, ArcDiskSignature, &Signature) &&
+                 (ArcDiskSignature->CheckSum + CheckSum == 0))) &&
+                (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR))
             {
-                /* Build the NT Device Name */
-                sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", i);
-
-                /* Convert it to Unicode */
-                RtlInitAnsiString(&ArcString, Buffer);
-                Status = RtlAnsiStringToUnicodeString(&DeviceName,
-                                                      &ArcString,
-                                                      TRUE);
-                if (!NT_SUCCESS(Status)) continue;
-
-                /* Build the ARC Device Name */
-                sprintf(Buffer, "\\ArcName\\%s", ArcDiskEntry->ArcName);
-
-                /* Convert it to Unicode */
-                RtlInitAnsiString(&ArcString, Buffer);
-                Status = RtlAnsiStringToUnicodeString(&ArcName,
-                                                      &ArcString,
-                                                      TRUE);
-                if (!NT_SUCCESS(Status)) continue;
-
-                /* Create the symbolic link and free the strings */
-                IoAssignArcName(&ArcName, &DeviceName);
-                RtlFreeUnicodeString(&ArcName);
-                RtlFreeUnicodeString(&DeviceName);
-
-                /* Loop all the partitions */
-                for (j = 0; j < PartitionCount; j++)
+                /* Create device name */
+                sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", (DeviceNumber.DeviceNumber != 0xFFFFFFFF) ? DeviceNumber.DeviceNumber : DiskNumber);
+                RtlInitAnsiString(&DeviceStringA, Buffer);
+                Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
+                if (!NT_SUCCESS(Status))
+                {
+                    goto Cleanup;
+                }
+
+                /* Create ARC name */
+                sprintf(ArcBuffer, "\\ArcName\\%s", ArcDiskSignature->ArcName);
+                RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
+                Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE);
+                if (!NT_SUCCESS(Status))
                 {
-                    /* Build the partition device name */
-                    sprintf(Buffer,
-                            "\\Device\\Harddisk%lu\\Partition%lu",
-                            i,
-                            j + 1);
-
-                    /* Convert it to Unicode */
-                    RtlInitAnsiString(&ArcString, Buffer);
-                    Status = RtlAnsiStringToUnicodeString(&DeviceName,
-                                                          &ArcString,
-                                                          TRUE);
-                    if (!NT_SUCCESS(Status)) continue;
-
-                    /* Build the partial ARC name for this partition */
-                    sprintf(Buffer,
-                            "%spartition(%lu)",
-                            ArcDiskEntry->ArcName,
-                            j + 1);
-                    RtlInitAnsiString(&ArcString, Buffer);
-
-                    /* Check if this is the boot device */
-                    if (RtlEqualString(&ArcString, &ArcBootString, TRUE))
+                    RtlFreeUnicodeString(&DeviceStringW);
+                    goto Cleanup;
+                }
+
+                /* Link both */
+                IoCreateSymbolicLink(&ArcNameStringW, &DeviceStringW);
+
+                /* And release resources */
+                RtlFreeUnicodeString(&ArcNameStringW);
+                RtlFreeUnicodeString(&DeviceStringW);
+
+                /* Now, browse for every partition */
+                for (i = 1; i <= DriveLayout->PartitionCount; i++)
+                {
+                    /* Create device name */
+                    sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition%lu", (DeviceNumber.DeviceNumber != 0xFFFFFFFF) ? DeviceNumber.DeviceNumber : DiskNumber, i);
+                    RtlInitAnsiString(&DeviceStringA, Buffer);
+                    Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
+                    if (!NT_SUCCESS(Status))
                     {
-                        /* Remember that we found a Hard Disk Boot Device */
-                        FoundBoot = TRUE;
+                        goto Cleanup;
                     }
 
-                    /* Check if it's the system boot partition */
-                    if (RtlEqualString(&ArcString, &ArcSystemString, TRUE))
+                    /* Create partial ARC name */
+                    sprintf(ArcBuffer, "%spartition(%lu)", ArcDiskSignature->ArcName, i);
+                    RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
+
+                    /* Is that boot device? */
+                    if (RtlEqualString(&ArcNameStringA, &ArcBootString, TRUE))
                     {
-                        /* It is, create a Unicode string for it */
-                        RtlInitAnsiString(&ArcString,
-                                          LoaderBlock->NtHalPathName);
-                        Status = RtlAnsiStringToUnicodeString(&BootPath,
-                                                              &ArcString,
-                                                              TRUE);
-                        if (NT_SUCCESS(Status))
-                        {
-                            /* FIXME: Save in registry */
+                        DPRINT("Found boot device\n");
+                        *FoundBoot = TRUE;
+                    }
 
-                            /* Free the string now */
-                            RtlFreeUnicodeString(&BootPath);
+                    /* Is that system partition? */
+                    if (RtlEqualString(&ArcNameStringA, &ArcSystemString, TRUE))
+                    {
+                        /* Create HAL path name */
+                        RtlInitAnsiString(&HalPathStringA, LoaderBlock->NtHalPathName);
+                        Status = RtlAnsiStringToUnicodeString(&HalPathStringW, &HalPathStringA, TRUE);
+                        if (!NT_SUCCESS(Status))
+                        {
+                            RtlFreeUnicodeString(&DeviceStringW);
+                            goto Cleanup;
                         }
+
+                        /* Then store those information to registry */
+                        IopStoreSystemPartitionInformation(&DeviceStringW, &HalPathStringW);
+                        RtlFreeUnicodeString(&HalPathStringW);
+                    }
+
+                    /* Create complete ARC name */
+                    sprintf(ArcBuffer, "\\ArcName\\%spartition(%lu)", ArcDiskSignature->ArcName, i);
+                    RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
+                    Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE);
+                    if (!NT_SUCCESS(Status))
+                    {
+                        RtlFreeUnicodeString(&DeviceStringW);
+                        goto Cleanup;
                     }
 
-                    /* Build the full ARC name */
-                    sprintf(Buffer,
-                            "\\ArcName\\%spartition(%lu)",
-                            ArcDiskEntry->ArcName,
-                            j + 1);
-
-                    /* Convert it to Unicode */
-                    RtlInitAnsiString(&ArcString, Buffer);
-                    Status = RtlAnsiStringToUnicodeString(&ArcName,
-                                                          &ArcString,
-                                                          TRUE);
-                    if (!NT_SUCCESS(Status)) continue;
-
-                    /* Create the symbolic link and free the strings */
-                    IoAssignArcName(&ArcName, &DeviceName);
-                    RtlFreeUnicodeString(&ArcName);
-                    RtlFreeUnicodeString(&DeviceName);
+                    /* Link device name & ARC name */
+                    IoCreateSymbolicLink(&ArcNameStringW, &DeviceStringW);
+
+                    /* Release strings */
+                    RtlFreeUnicodeString(&ArcNameStringW);
+                    RtlFreeUnicodeString(&DeviceStringW);
                 }
             }
+            else
+            {
+                /* In case there's a valid partition, a matching signature,
+                   BUT a none matching checksum, or there's a duplicate
+                   signature, or even worse a virus played with partition
+                   table */
+                if (ArcDiskSignature->Signature == Signature &&
+                    (ArcDiskSignature->CheckSum + CheckSum != 0) &&
+                    ArcDiskSignature->ValidPartitionTable)
+                 {
+                     DPRINT("Be careful, or you have a duplicate disk signature, or a virus altered your MBR!\n");
+                 }
+            }
         }
+
+        /* Release memory before jumping to next item */
+        ExFreePool(DriveLayout);
+        DriveLayout = NULL;
+        ExFreePoolWithTag(PartitionBuffer, TAG_IO);
+        PartitionBuffer = NULL;
     }
 
-    /* Check if we didn't find the boot disk */
-    if (!FoundBoot)
+    Status = STATUS_SUCCESS;
+
+Cleanup:
+    if (SymbolicLinkList)
     {
-        /* Allocate a buffer for the CD-ROM MBR */
-        PartitionBuffer = ExAllocatePoolWithTag(NonPagedPool, 2048, TAG_IO);
-        if (!PartitionBuffer) return STATUS_INSUFFICIENT_RESOURCES;
+        ExFreePool(SymbolicLinkList);
+    }
 
-        /* Loop every CD-ROM */
-        for (i = 0; i < ConfigInfo->CdRomCount; i++)
-        {
-            /* Give it an ARC name */
-            if (IopAssignArcNamesToCdrom(LoaderBlock, PartitionBuffer, i)) break;
-        }
+    if (DriveLayout)
+    {
+        ExFreePool(DriveLayout);
+    }
 
-        /* Free the buffer */
+    if (PartitionBuffer)
+    {
         ExFreePoolWithTag(PartitionBuffer, TAG_IO);
     }
 
-    /* Return success */
-    return STATUS_SUCCESS;
+    return Status;
 }
 
 NTSTATUS
 NTAPI
+INIT_FUNCTION
 IopReassignSystemRoot(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
                       OUT PANSI_STRING NtBootPath)
 {
@@ -733,4 +892,54 @@ IopReassignSystemRoot(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
     return TRUE;
 }
 
+BOOLEAN
+NTAPI
+IopVerifyDiskSignature(IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout,
+                       IN PARC_DISK_SIGNATURE ArcDiskSignature,
+                       OUT PULONG Signature)
+{
+    /* First condition: having a valid partition table */
+    if (!ArcDiskSignature->ValidPartitionTable)
+    {
+        return FALSE;
+    }
+
+    /* If that partition table is the MBR */
+    if (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR)
+    {
+        /* Then check MBR signature */
+        if (DriveLayout->Mbr.Signature == ArcDiskSignature->Signature)
+        {
+            /* And return it */
+            if (Signature)
+            {
+                *Signature = DriveLayout->Mbr.Signature;
+            }
+
+            return TRUE;
+        }
+    }
+    /* If that partition table is the GPT */
+    else if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT)
+    {
+        /* Check we are using GPT and compare GUID */
+        if (ArcDiskSignature->IsGpt &&
+            (((PULONG)ArcDiskSignature->GptSignature)[0] == DriveLayout->Gpt.DiskId.Data1 &&
+             ((PUSHORT)ArcDiskSignature->GptSignature)[2] == DriveLayout->Gpt.DiskId.Data2 &&
+             ((PUSHORT)ArcDiskSignature->GptSignature)[3] == DriveLayout->Gpt.DiskId.Data3 &&
+             ((PULONGLONG)ArcDiskSignature->GptSignature)[1] == ((PULONGLONG)DriveLayout->Gpt.DiskId.Data4)[0]))
+        {
+            /* There's no signature to give, so we just zero output */
+            if (Signature)
+            {
+                *Signature = 0;
+            }
+            return TRUE;
+        }
+    }
+
+    /* If we fall here, it means that something went wrong, so return that */
+    return FALSE;
+}
+
 /* EOF */