Removed outdated email addresses.
[reactos.git] / reactos / ntoskrnl / io / iomgr / arcname.c
index 85f0a5d..798219b 100644 (file)
@@ -1,14 +1,13 @@
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
- * FILE:            ntoskrnl/io/arcname.c
- * PURPOSE:         Creates ARC names for boot devices
- *
- * PROGRAMMERS:     Eric Kohl (ekohl@rz-online.de)
- */
-
-/* INCLUDES *****************************************************************/
+/*
+* PROJECT:         ReactOS Kernel
+* LICENSE:         GPL - See COPYING in the top level directory
+* FILE:            ntoskrnl/io/iomgr/arcname.c
+* PURPOSE:         ARC Path Initialization Functions
+* PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+*                  Eric Kohl
+*/
+
+/* INCLUDES ******************************************************************/
 
 #include <ntoskrnl.h>
 #define NDEBUG
@@ -18,8 +17,9 @@
 
 UNICODE_STRING IoArcHalDeviceName, IoArcBootDeviceName;
 PCHAR IoLoaderArcBootDeviceName;
+extern PROS_LOADER_PARAMETER_BLOCK KeRosLoaderBlock;
 
-/* FUNCTIONS ****************************************************************/
+/* FUNCTIONS *****************************************************************/
 
 BOOLEAN
 INIT_FUNCTION
@@ -28,57 +28,97 @@ IopApplyRosCdromArcHack(IN ULONG i)
 {
     ULONG DeviceNumber = -1;
     OBJECT_ATTRIBUTES ObjectAttributes;
+    ANSI_STRING InstallName;
     UNICODE_STRING DeviceName;
-    WCHAR Buffer[MAX_PATH];
-    CHAR AnsiBuffer[MAX_PATH];
+    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\\%s\\ntoskrnl.exe", i, RosSysPath);
+        RtlInitAnsiString(&InstallName, Buffer);
+        Status = RtlAnsiStringToUnicodeString(&DeviceName, &InstallName, TRUE);
+        if (!NT_SUCCESS(Status)) return FALSE;
+
         /* 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;
+        /* Free the string */
+        RtlFreeUnicodeString(&DeviceName);
 
-        /* Build the name */
-        sprintf(p, "cdrom(%lu)", DeviceNumber);
+        /* 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);
+        }
 
-        /* Adjust original command line */
-        q = strchr(p, ')');
-        if (q)
+        if (!InitIsWinPEMode)
         {
-            q++;
-            strcpy(AnsiBuffer, q);
+            /* Build the name */
             sprintf(p, "cdrom(%lu)", DeviceNumber);
-            strcat(p, AnsiBuffer);
+
+            /* Adjust original command line */
+            q = strchr(p, ')');
+            if (q)
+            {
+                q++;
+                strcpy(Buffer, q);
+                sprintf(p, "cdrom(%lu)", DeviceNumber);
+                strcat(p, Buffer);
+            }
         }
     }
 
+    /* OK, how many disks are there? */
+    DeviceNumber += ConfigInfo->DiskCount;
+
     /* Return whether this is the CD or not */
-    if (DeviceNumber != 1) return TRUE;
+    if ((InitIsWinPEMode) || (ExpInTextModeSetup))
+    {
+        return TRUE;
+    }
+
+    /* Failed */
     return FALSE;
 }
 
@@ -93,7 +133,7 @@ IopGetDiskInformation(IN ULONG i,
 {
     ULONG j, Checksum;
     ANSI_STRING TempString;
-    CHAR Buffer[256];
+    CHAR Buffer[128];
     UNICODE_STRING DeviceName;
     NTSTATUS Status;
     PDEVICE_OBJECT DeviceObject;
@@ -104,7 +144,7 @@ IopGetDiskInformation(IN ULONG i,
     PIRP Irp;
     IO_STATUS_BLOCK StatusBlock;
     LARGE_INTEGER PartitionOffset;
-    PPARTITION_SECTOR PartitionBuffer;
+    PULONG PartitionBuffer;
 
     /* Build the name */
     sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", i);
@@ -116,7 +156,7 @@ IopGetDiskInformation(IN ULONG i,
 
     /* Get the device pointer */
     Status = IoGetDeviceObjectPointer(&DeviceName,
-                                      FILE_READ_DATA,
+                                      FILE_READ_ATTRIBUTES,
                                       &FileObject,
                                       &DeviceObject);
     *DiskDeviceObject = DeviceObject;
@@ -179,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);
@@ -190,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);
@@ -204,17 +256,14 @@ IopGetDiskInformation(IN ULONG i,
     if (!NT_SUCCESS(Status))
     {
         /* Try again */
-        ExFreePool(PartitionBuffer);
-        ExFreePool(DriveLayout);
+        ExFreePoolWithTag(PartitionBuffer, TAG_IO);
+        ExFreePoolWithTag(DriveLayout, TAG_FILE_SYSTEM);
         return FALSE;
     }
 
     /* Calculate the MBR checksum */
     Checksum = 0;
-    for (j = 0; j < 128; j++)
-    {
-        Checksum += ((PULONG)PartitionBuffer)[j];
-    }
+    for (j = 0; j < 128; j++) Checksum += PartitionBuffer[j];
 
     /* Save the signature and checksum */
     *CheckSum = ~Checksum + 1;
@@ -222,19 +271,20 @@ IopGetDiskInformation(IN ULONG i,
     *PartitionCount = DriveLayout->PartitionCount;
 
     /* Free the buffer */
-    ExFreePool(PartitionBuffer);
-    ExFreePool(DriveLayout);
+    ExFreePoolWithTag(PartitionBuffer, TAG_IO);
+    ExFreePoolWithTag(DriveLayout, TAG_FILE_SYSTEM);
     return TRUE;
 }
 
 BOOLEAN
 INIT_FUNCTION
 NTAPI
-IopAssignArcNamesToCdrom(IN PULONG Buffer,
+IopAssignArcNamesToCdrom(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+                         IN PULONG Buffer,
                          IN ULONG DiskNumber)
 {
-    CHAR ArcBuffer[256];
-    ANSI_STRING TempString, ArcNameString;
+    CHAR ArcBuffer[128];
+    ANSI_STRING TempString;
     UNICODE_STRING DeviceName, ArcName;
     NTSTATUS Status;
     LARGE_INTEGER PartitionOffset;
@@ -244,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);
@@ -300,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
@@ -315,14 +391,17 @@ 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);
 
         /* Convert it to Unicode */
-        RtlInitAnsiString(&ArcNameString, ArcBuffer);
-        Status = RtlAnsiStringToUnicodeString(&ArcName, &ArcNameString, TRUE);
+        RtlInitAnsiString(&TempString, ArcBuffer);
+        Status = RtlAnsiStringToUnicodeString(&ArcName, &TempString, TRUE);
         if (!NT_SUCCESS(Status)) return FALSE;
 
         /* Create the symbolic link and free the strings */
@@ -340,13 +419,13 @@ IopAssignArcNamesToCdrom(IN PULONG Buffer,
 
 NTSTATUS
 INIT_FUNCTION
-IoCreateArcNames(VOID)
+NTAPI
+IopCreateArcNames(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 {
-    PLOADER_PARAMETER_BLOCK LoaderBlock = KeLoaderBlock;
     PCONFIGURATION_INFORMATION ConfigInfo = IoGetConfigurationInformation();
     PARC_DISK_INFORMATION ArcDiskInfo = LoaderBlock->ArcDiskInformation;
-    CHAR ArcBuffer[256], Buffer[256];
-    ANSI_STRING ArcBootString, ArcSystemString, ArcString, TempString, BootString;
+    CHAR Buffer[128];
+    ANSI_STRING ArcBootString, ArcSystemString, ArcString;
     UNICODE_STRING ArcName, BootPath, DeviceName;
     BOOLEAN SingleDisk;
     ULONG i, j, Length;
@@ -363,13 +442,13 @@ IoCreateArcNames(VOID)
                  (&ArcDiskInfo->DiskSignatureListHead);
 
     /* Create the global HAL partition name */
-    sprintf(ArcBuffer, "\\ArcName\\%s", LoaderBlock->ArcHalDeviceName);
-    RtlInitAnsiString(&ArcString, ArcBuffer);
+    sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcHalDeviceName);
+    RtlInitAnsiString(&ArcString, Buffer);
     RtlAnsiStringToUnicodeString(&IoArcHalDeviceName, &ArcString, TRUE);
 
     /* Create the global system partition name */
-    sprintf(ArcBuffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
-    RtlInitAnsiString(&ArcString, ArcBuffer);
+    sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
+    RtlInitAnsiString(&ArcString, Buffer);
     RtlAnsiStringToUnicodeString(&IoArcBootDeviceName, &ArcString, TRUE);
 
     /* Allocate memory for the string */
@@ -380,7 +459,7 @@ IoCreateArcNames(VOID)
     if (IoLoaderArcBootDeviceName)
     {
         /* Copy the name */
-        RtlMoveMemory(IoLoaderArcBootDeviceName,
+        RtlCopyMemory(IoLoaderArcBootDeviceName,
                       LoaderBlock->ArcBootDeviceName,
                       Length);
     }
@@ -433,16 +512,20 @@ IoCreateArcNames(VOID)
                 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", i);
 
                 /* Convert it to Unicode */
-                RtlInitAnsiString(&TempString, Buffer);
-                Status = RtlAnsiStringToUnicodeString(&DeviceName, &TempString, TRUE);
+                RtlInitAnsiString(&ArcString, Buffer);
+                Status = RtlAnsiStringToUnicodeString(&DeviceName,
+                                                      &ArcString,
+                                                      TRUE);
                 if (!NT_SUCCESS(Status)) continue;
 
                 /* Build the ARC Device Name */
-                sprintf(ArcBuffer, "\\ArcName\\%s", ArcDiskEntry->ArcName);
+                sprintf(Buffer, "\\ArcName\\%s", ArcDiskEntry->ArcName);
 
                 /* Convert it to Unicode */
-                RtlInitAnsiString(&ArcString, ArcBuffer);
-                Status = RtlAnsiStringToUnicodeString(&ArcName, &ArcString, TRUE);
+                RtlInitAnsiString(&ArcString, Buffer);
+                Status = RtlAnsiStringToUnicodeString(&ArcName,
+                                                      &ArcString,
+                                                      TRUE);
                 if (!NT_SUCCESS(Status)) continue;
 
                 /* Create the symbolic link and free the strings */
@@ -454,16 +537,24 @@ IoCreateArcNames(VOID)
                 for (j = 0; j < PartitionCount; j++)
                 {
                     /* Build the partition device name */
-                    sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition%lu", i, j + 1);
+                    sprintf(Buffer,
+                            "\\Device\\Harddisk%lu\\Partition%lu",
+                            i,
+                            j + 1);
 
                     /* Convert it to Unicode */
-                    RtlInitAnsiString(&TempString, Buffer);
-                    Status = RtlAnsiStringToUnicodeString(&DeviceName, &TempString, TRUE);
+                    RtlInitAnsiString(&ArcString, Buffer);
+                    Status = RtlAnsiStringToUnicodeString(&DeviceName,
+                                                          &ArcString,
+                                                          TRUE);
                     if (!NT_SUCCESS(Status)) continue;
 
                     /* Build the partial ARC name for this partition */
-                    sprintf(ArcBuffer, "%spartition(%lu)", ArcDiskEntry->ArcName, j + 1);
-                    RtlInitAnsiString(&ArcString, ArcBuffer);
+                    sprintf(Buffer,
+                            "%spartition(%lu)",
+                            ArcDiskEntry->ArcName,
+                            j + 1);
+                    RtlInitAnsiString(&ArcString, Buffer);
 
                     /* Check if this is the boot device */
                     if (RtlEqualString(&ArcString, &ArcBootString, TRUE))
@@ -476,8 +567,11 @@ IoCreateArcNames(VOID)
                     if (RtlEqualString(&ArcString, &ArcSystemString, TRUE))
                     {
                         /* It is, create a Unicode string for it */
-                        RtlInitAnsiString(&BootString, LoaderBlock->NtHalPathName);
-                        Status = RtlAnsiStringToUnicodeString(&BootPath, &BootString, TRUE);
+                        RtlInitAnsiString(&ArcString,
+                                          LoaderBlock->NtHalPathName);
+                        Status = RtlAnsiStringToUnicodeString(&BootPath,
+                                                              &ArcString,
+                                                              TRUE);
                         if (NT_SUCCESS(Status))
                         {
                             /* FIXME: Save in registry */
@@ -488,11 +582,16 @@ IoCreateArcNames(VOID)
                     }
 
                     /* Build the full ARC name */
-                    sprintf(Buffer, "\\ArcName\\%spartition(%lu)", ArcDiskEntry->ArcName, j + 1);
+                    sprintf(Buffer,
+                            "\\ArcName\\%spartition(%lu)",
+                            ArcDiskEntry->ArcName,
+                            j + 1);
 
                     /* Convert it to Unicode */
                     RtlInitAnsiString(&ArcString, Buffer);
-                    Status = RtlAnsiStringToUnicodeString(&ArcName, &ArcString, TRUE);
+                    Status = RtlAnsiStringToUnicodeString(&ArcName,
+                                                          &ArcString,
+                                                          TRUE);
                     if (!NT_SUCCESS(Status)) continue;
 
                     /* Create the symbolic link and free the strings */
@@ -515,11 +614,11 @@ IoCreateArcNames(VOID)
         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 */
-        ExFreePool(PartitionBuffer);
+        ExFreePoolWithTag(PartitionBuffer, TAG_IO);
     }
 
     /* Return success */