-/* $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)
- */
+/*
+* 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 *****************************************************************/
+/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
+
+/* GLOBALS *******************************************************************/
+
+UNICODE_STRING IoArcHalDeviceName, IoArcBootDeviceName;
+PCHAR IoLoaderArcBootDeviceName;
+extern PROS_LOADER_PARAMETER_BLOCK KeRosLoaderBlock;
-/* FUNCTIONS ****************************************************************/
+/* FUNCTIONS *****************************************************************/
BOOLEAN
INIT_FUNCTION
{
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;
}
-VOID
+BOOLEAN
INIT_FUNCTION
NTAPI
-IopEnumerateDisks(IN PLIST_ENTRY ListHead)
+IopGetDiskInformation(IN ULONG i,
+ OUT PULONG CheckSum,
+ OUT PULONG Signature,
+ OUT PULONG PartitionCount,
+ OUT PDEVICE_OBJECT *DiskDeviceObject)
{
- ULONG i, j;
+ ULONG j, Checksum;
ANSI_STRING TempString;
- CHAR Buffer[256];
+ CHAR Buffer[128];
UNICODE_STRING DeviceName;
NTSTATUS Status;
PDEVICE_OBJECT DeviceObject;
PIRP Irp;
IO_STATUS_BLOCK StatusBlock;
LARGE_INTEGER PartitionOffset;
- PPARTITION_SECTOR PartitionBuffer;
- PDISKENTRY DiskEntry;
+ PULONG PartitionBuffer;
- /* 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;
+ /* Build the name */
+ sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", i);
- /* 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;
- }
+ /* Convert it to Unicode */
+ RtlInitAnsiString(&TempString, Buffer);
+ Status = RtlAnsiStringToUnicodeString(&DeviceName, &TempString, TRUE);
+ if (!NT_SUCCESS(Status)) return FALSE;
- /* 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;
- }
+ /* Get the device pointer */
+ Status = IoGetDeviceObjectPointer(&DeviceName,
+ FILE_READ_ATTRIBUTES,
+ &FileObject,
+ &DeviceObject);
+ *DiskDeviceObject = DeviceObject;
- /* Check if we failed */
- if (!NT_SUCCESS(Status))
- {
- /* Try again */
- ObDereferenceObject(FileObject);
- continue;
- }
+ /* Free the string */
+ RtlFreeUnicodeString(&DeviceName);
- /* Read the partition table */
- Status = IoReadPartitionTable(DeviceObject,
- DiskGeometry.BytesPerSector,
- TRUE,
- &DriveLayout);
+ /* Move on if we failed */
+ if (!NT_SUCCESS(Status)) return FALSE;
- /* Dereference the file object */
+ /* 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);
- 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);
+ return FALSE;
}
-}
-NTSTATUS
-INIT_FUNCTION
-NTAPI
-IopAssignArcNamesToDisk(IN PDEVICE_OBJECT DeviceObject,
- IN PCHAR BootArcName,
- 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;
-
- /* 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);
+ /* 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;
+ }
- /* Convert it to unicode */
- RtlInitAnsiString(&TempString, Buffer);
- Status = RtlAnsiStringToUnicodeString(&DeviceName, &TempString, TRUE);
- if (!NT_SUCCESS(Status)) return Status;
+ /* Check if we failed */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Try again */
+ ObDereferenceObject(FileObject);
+ return FALSE;
+ }
- /* Build the ARC Device Name */
- sprintf(ArcBuffer, "\\ArcName\\%s", BootArcName);
+ /* Read the partition table */
+ Status = IoReadPartitionTable(DeviceObject,
+ DiskGeometry.BytesPerSector,
+ TRUE,
+ &DriveLayout);
- /* Convert it to Unicode */
- RtlInitAnsiString(&ArcNameString, ArcBuffer);
- Status = RtlAnsiStringToUnicodeString(&ArcName, &ArcNameString, TRUE);
- if (!NT_SUCCESS(Status)) return Status;
+ /* Dereference the file object */
+ ObDereferenceObject(FileObject);
+ if (!NT_SUCCESS(Status)) return FALSE;
- /* Create the symbolic link and free the strings */
- IoAssignArcName(&ArcName, &DeviceName);
- RtlFreeUnicodeString(&ArcName);
- RtlFreeUnicodeString(&DeviceName);
+ /* Set the offset to 0 */
+ PartitionOffset.QuadPart = 0;
- /* Loop all the partitions */
- for (i = 0; i < PartitionCount; i++)
+ /* Allocate a buffer for the partition */
+ PartitionBuffer = ExAllocatePoolWithTag(NonPagedPool,
+ DiskGeometry.BytesPerSector,
+ TAG_IO);
+ if (!PartitionBuffer)
{
- /* 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;
- }
+ /* Try again */
+ ExFreePoolWithTag(DriveLayout, TAG_FILE_SYSTEM);
+ return FALSE;
+ }
- /* 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 */
+ /* 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)
+ {
+ /* Try again */
+ ExFreePoolWithTag(PartitionBuffer, TAG_IO);
+ ExFreePoolWithTag(DriveLayout, TAG_FILE_SYSTEM);
+ return FALSE;
+ }
- /* Free the string now */
- RtlFreeUnicodeString(&BootPath);
- }
- }
+ /* 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;
+ }
- /* Build the full ARC name */
- sprintf(Buffer, "\\ArcName\\%spartition(%lu)", BootArcName, i + 1);
+ /* Check if we failed */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Try again */
+ ExFreePoolWithTag(PartitionBuffer, TAG_IO);
+ ExFreePoolWithTag(DriveLayout, TAG_FILE_SYSTEM);
+ return FALSE;
+ }
- /* Convert it to Unicode */
- RtlInitAnsiString(&ArcNameString, Buffer);
- Status = RtlAnsiStringToUnicodeString(&ArcName, &ArcNameString, TRUE);
- if (!NT_SUCCESS(Status)) continue;
+ /* Calculate the MBR checksum */
+ Checksum = 0;
+ for (j = 0; j < 128; j++) Checksum += PartitionBuffer[j];
- /* Create the symbolic link and free the strings */
- IoAssignArcName(&ArcName, &DeviceName);
- RtlFreeUnicodeString(&ArcName);
- RtlFreeUnicodeString(&DeviceName);
- }
+ /* Save the signature and checksum */
+ *CheckSum = ~Checksum + 1;
+ *Signature = DriveLayout->Signature;
+ *PartitionCount = DriveLayout->PartitionCount;
- /* Return success */
- return STATUS_SUCCESS;
+ /* Free the buffer */
+ 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;
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);
/* 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
* 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 */
return FALSE;
}
-NTSTATUS INIT_FUNCTION
-IoCreateArcNames(VOID)
+NTSTATUS
+INIT_FUNCTION
+NTAPI
+IopCreateArcNames(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
- PCONFIGURATION_INFORMATION ConfigInfo;
- ULONG i;
- NTSTATUS Status;
- PLIST_ENTRY BiosDiskListHead, Entry;
- LIST_ENTRY DiskListHead;
+ 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;
- PDISKENTRY DiskEntry;
+ NTSTATUS Status;
BOOLEAN FoundBoot = FALSE;
- PULONG Buffer;
+ PULONG PartitionBuffer;
- ConfigInfo = IoGetConfigurationInformation();
+ /* Check if we only have one disk on the machine */
+ SingleDisk = ArcDiskInfo->DiskSignatureListHead.Flink->Flink ==
+ (&ArcDiskInfo->DiskSignatureListHead);
- /* Get the boot ARC disk list */
- BiosDiskListHead = &KeLoaderBlock->ArcDiskInformation->
- DiskSignatureListHead;
+ /* Create the global HAL partition name */
+ sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcHalDeviceName);
+ RtlInitAnsiString(&ArcString, Buffer);
+ RtlAnsiStringToUnicodeString(&IoArcHalDeviceName, &ArcString, TRUE);
- /* Enumerate system disks */
- InitializeListHead(&DiskListHead);
- IopEnumerateDisks(&DiskListHead);
+ /* Create the global system partition name */
+ sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
+ RtlInitAnsiString(&ArcString, Buffer);
+ RtlAnsiStringToUnicodeString(&IoArcBootDeviceName, &ArcString, TRUE);
+
+ /* 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);
+ }
- while (!IsListEmpty(BiosDiskListHead))
+ /* Check if we only found a disk, but we're booting from CD-ROM */
+ if ((SingleDisk) && strstr(LoaderBlock->ArcBootDeviceName, "cdrom"))
{
- Entry = RemoveHeadList(BiosDiskListHead);
- ArcDiskEntry = CONTAINING_RECORD(Entry, ARC_DISK_SIGNATURE, ListEntry);
- Entry = DiskListHead.Flink;
- while (Entry != &DiskListHead)
+ /* Then disable single-disk mode, since there's a CD drive out there */
+ SingleDisk = FALSE;
+ }
+
+ /* Build the boot strings */
+ RtlInitAnsiString(&ArcBootString, LoaderBlock->ArcBootDeviceName);
+ RtlInitAnsiString(&ArcSystemString, LoaderBlock->ArcHalDeviceName);
+
+ /* Loop every detected disk */
+ for (i = 0; i < ConfigInfo->DiskCount; i++)
+ {
+ /* Get information about the disk */
+ if (!IopGetDiskInformation(i,
+ &Checksum,
+ &Signature,
+ &PartitionCount,
+ &DeviceObject))
+ {
+ /* Skip this disk */
+ continue;
+ }
+
+ /* Loop ARC disks */
+ for (NextEntry = ArcDiskInfo->DiskSignatureListHead.Flink;
+ NextEntry != &ArcDiskInfo->DiskSignatureListHead;
+ NextEntry = NextEntry->Flink)
{
- DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
- DPRINT1("Entry: %s\n", ArcDiskEntry->ArcName);
- if (DiskEntry->Checksum == ArcDiskEntry->CheckSum &&
- DiskEntry->Signature == ArcDiskEntry->Signature)
+ /* Get the current ARC disk signature entry */
+ ArcDiskEntry = CONTAINING_RECORD(NextEntry,
+ ARC_DISK_SIGNATURE,
+ ListEntry);
+
+ /*
+ * 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
+ */
+ if (((SingleDisk) && (ConfigInfo->DiskCount == 1)) ||
+ ((Checksum == ArcDiskEntry->CheckSum) &&
+ (Signature == ArcDiskEntry->Signature)))
{
- Status = IopAssignArcNamesToDisk(DiskEntry->DeviceObject,
- ArcDiskEntry->ArcName,
- DiskEntry->DiskNumber,
- DiskEntry->PartitionCount,
- &FoundBoot);
-
- RemoveEntryList(&DiskEntry->ListEntry);
- ExFreePool(DiskEntry);
- break;
+ /* 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++)
+ {
+ /* 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))
+ {
+ /* Remember that we found a Hard Disk Boot Device */
+ FoundBoot = TRUE;
+ }
+
+ /* Check if it's the system boot partition */
+ if (RtlEqualString(&ArcString, &ArcSystemString, 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 */
+
+ /* Free the string now */
+ RtlFreeUnicodeString(&BootPath);
+ }
+ }
+
+ /* 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);
+ }
}
- Entry = Entry->Flink;
}
}
- 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;
+ PartitionBuffer = ExAllocatePoolWithTag(NonPagedPool, 2048, TAG_IO);
+ if (!PartitionBuffer) 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;
+ if (IopAssignArcNamesToCdrom(LoaderBlock, PartitionBuffer, i)) break;
}
/* Free the buffer */
- ExFreePool(Buffer);
+ ExFreePoolWithTag(PartitionBuffer, TAG_IO);
}
/* Return success */