Removed outdated email addresses.
[reactos.git] / reactos / ntoskrnl / io / iomgr / arcname.c
index 6560a3d..798219b 100644 (file)
@@ -4,7 +4,7 @@
 * FILE:            ntoskrnl/io/iomgr/arcname.c
 * PURPOSE:         ARC Path Initialization Functions
 * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
-*                  Eric Kohl (ekohl@rz-online.de)
+*                  Eric Kohl
 */
 
 /* INCLUDES ******************************************************************/
@@ -17,6 +17,7 @@
 
 UNICODE_STRING IoArcHalDeviceName, IoArcBootDeviceName;
 PCHAR IoLoaderArcBootDeviceName;
+extern PROS_LOADER_PARAMETER_BLOCK KeRosLoaderBlock;
 
 /* FUNCTIONS *****************************************************************/
 
@@ -29,19 +30,22 @@ IopApplyRosCdromArcHack(IN ULONG i)
     OBJECT_ATTRIBUTES ObjectAttributes;
     ANSI_STRING InstallName;
     UNICODE_STRING DeviceName;
-    CHAR Buffer[128];
+    CHAR Buffer[128], RosSysPath[16];
     FILE_BASIC_INFORMATION FileInfo;
     NTSTATUS Status;
     PCHAR p, q;
     PCONFIGURATION_INFORMATION ConfigInfo = IoGetConfigurationInformation();
     extern BOOLEAN InitIsWinPEMode, ExpInTextModeSetup;
 
+    /* Change this if you want ROS to boot properly from another directory */
+    sprintf(RosSysPath, "%s", "reactos");
+
     /* Only ARC Name left - Build full ARC Name */
     p = strstr(KeLoaderBlock->ArcBootDeviceName, "cdrom");
     if (p)
     {
         /* Build installer name */
-        sprintf(Buffer, "\\Device\\CdRom%lu\\reactos\\ntoskrnl.exe", i);
+        sprintf(Buffer, "\\Device\\CdRom%lu\\%s\\ntoskrnl.exe", i, RosSysPath);
         RtlInitAnsiString(&InstallName, Buffer);
         Status = RtlAnsiStringToUnicodeString(&DeviceName, &InstallName, TRUE);
         if (!NT_SUCCESS(Status)) return FALSE;
@@ -67,8 +71,8 @@ IopApplyRosCdromArcHack(IN ULONG i)
         {
             /* Build live CD kernel name */
             sprintf(Buffer,
-                    "\\Device\\CdRom%lu\\reactos\\system32\\ntoskrnl.exe",
-                    i);
+                    "\\Device\\CdRom%lu\\%s\\system32\\ntoskrnl.exe",
+                    i, RosSysPath);
             RtlInitAnsiString(&InstallName, Buffer);
             Status = RtlAnsiStringToUnicodeString(&DeviceName,
                                                   &InstallName,
@@ -111,8 +115,6 @@ IopApplyRosCdromArcHack(IN ULONG i)
     /* Return whether this is the CD or not */
     if ((InitIsWinPEMode) || (ExpInTextModeSetup))
     {
-        /* Hack until IoAssignDriveLetters is fixed */
-        swprintf(SharedUserData->NtSystemRoot, L"%c:\\reactos", 'C' + DeviceNumber);
         return TRUE;
     }
 
@@ -217,7 +219,12 @@ IopGetDiskInformation(IN ULONG i,
     PartitionBuffer = ExAllocatePoolWithTag(NonPagedPool,
                                             DiskGeometry.BytesPerSector,
                                             TAG_IO);
-    if (!PartitionBuffer) return FALSE;
+    if (!PartitionBuffer)
+    {
+        /* Try again */
+        ExFreePoolWithTag(DriveLayout, TAG_FILE_SYSTEM);
+        return FALSE;
+    }
 
     /* Build an IRP to read the partition sector */
     KeInitializeEvent(&Event, NotificationEvent, FALSE);
@@ -228,6 +235,13 @@ IopGetDiskInformation(IN ULONG i,
                                        &PartitionOffset,
                                        &Event,
                                        &StatusBlock);
+    if (!Irp)
+    {
+        /* Try again  */
+        ExFreePoolWithTag(PartitionBuffer, TAG_IO);
+        ExFreePoolWithTag(DriveLayout, TAG_FILE_SYSTEM);
+        return FALSE;
+    }
 
     /* Call the driver and check if we have to wait */
     Status = IoCallDriver(DeviceObject, Irp);
@@ -265,7 +279,8 @@ IopGetDiskInformation(IN ULONG i,
 BOOLEAN
 INIT_FUNCTION
 NTAPI
-IopAssignArcNamesToCdrom(IN PULONG Buffer,
+IopAssignArcNamesToCdrom(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+                         IN PULONG Buffer,
                          IN ULONG DiskNumber)
 {
     CHAR ArcBuffer[128];
@@ -279,6 +294,10 @@ IopAssignArcNamesToCdrom(IN PULONG Buffer,
     ULONG i, CheckSum = 0;
     PDEVICE_OBJECT DeviceObject;
     PFILE_OBJECT FileObject;
+    PARC_DISK_INFORMATION ArcDiskInfo = LoaderBlock->ArcDiskInformation;
+    PLIST_ENTRY NextEntry;
+    PARC_DISK_SIGNATURE ArcDiskEntry;
+    BOOLEAN IsBootCdRom = FALSE;
 
     /* Build the device name */
     sprintf(ArcBuffer, "\\Device\\CdRom%lu", DiskNumber);
@@ -335,6 +354,28 @@ IopAssignArcNamesToCdrom(IN PULONG Buffer,
     /* Now calculate the checksum */
     for (i = 0; i < 2048 / sizeof(ULONG); i++) CheckSum += Buffer[i];
 
+    if (KeRosLoaderBlock) goto freeldrhack;
+
+    /* 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
@@ -350,7 +391,10 @@ IopAssignArcNamesToCdrom(IN PULONG Buffer,
      * 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))
+    IsBootCdRom = IopApplyRosCdromArcHack(DiskNumber);
+
+checkbootcd:
+    if (IsBootCdRom)
     {
         /* This is the boot CD-ROM, build the ARC name */
         sprintf(ArcBuffer, "\\ArcName\\%s", KeLoaderBlock->ArcBootDeviceName);
@@ -570,7 +614,7 @@ IopCreateArcNames(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
         for (i = 0; i < ConfigInfo->CdRomCount; i++)
         {
             /* Give it an ARC name */
-            if (IopAssignArcNamesToCdrom(PartitionBuffer, i)) break;
+            if (IopAssignArcNamesToCdrom(LoaderBlock, PartitionBuffer, i)) break;
         }
 
         /* Free the buffer */