* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Eric Kohl
* Casper S. Hornstrup (chorns@users.sourceforge.net)
-* Pierre Schweitzer
*/
/* INCLUDES ******************************************************************/
#include <debug.h>
#include <internal/hal.h>
+/* DEPRECATED FUNCTIONS ******************************************************/
+
+#if 1
const WCHAR DiskMountString[] = L"\\DosDevices\\%C:";
#define AUTO_DRIVE MAXULONG
EZ_Drive
} DISK_MANAGER;
-typedef enum _PARTITION_TYPE
-{
- BootablePartition,
- PrimaryPartition,
- LogicalPartition,
- FtPartition,
- UnknownPartition,
- DataPartition
-} PARTITION_TYPE, *PPARTITION_TYPE;
-
-NTSTATUS
-FASTCALL
-HalpQueryDriveLayout(IN PUNICODE_STRING DeviceName,
- OUT PDRIVE_LAYOUT_INFORMATION *LayoutInfo)
+static BOOLEAN
+HalpAssignDrive(IN PUNICODE_STRING PartitionName,
+ IN ULONG DriveNumber,
+ IN UCHAR DriveType,
+ IN ULONG Signature,
+ IN LARGE_INTEGER StartingOffset,
+ IN HANDLE hKey,
+ IN PUNICODE_STRING BootDevice,
+ OUT PUCHAR NtSystemPath)
{
- IO_STATUS_BLOCK StatusBlock;
- PDEVICE_OBJECT DeviceObject = NULL;
- PFILE_OBJECT FileObject;
- KEVENT Event;
- PIRP Irp;
+ WCHAR DriveNameBuffer[16];
+ UNICODE_STRING DriveName;
+ ULONG i;
NTSTATUS Status;
- ULONG BufferSize;
- PDRIVE_LAYOUT_INFORMATION Buffer;
- PAGED_CODE();
-
- /* Get device pointers */
- Status = IoGetDeviceObjectPointer(DeviceName,
- FILE_READ_ATTRIBUTES,
- &FileObject,
- &DeviceObject);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
+ REG_DISK_MOUNT_INFO DiskMountInfo;
- /* Get attached device object */
- DeviceObject = IoGetAttachedDeviceReference(FileObject->DeviceObject);
- ObDereferenceObject(FileObject);
+ DPRINT("HalpAssignDrive()\n");
- /* Do not handle removable media */
- if (BooleanFlagOn(DeviceObject->Characteristics, FILE_REMOVABLE_MEDIA))
+ if ((DriveNumber != AUTO_DRIVE) && (DriveNumber < 26))
{
- ObDereferenceObject(DeviceObject);
- return STATUS_NO_MEDIA;
+ /* Force assignment */
+ KeAcquireGuardedMutex(&ObpDeviceMapLock);
+ if ((ObSystemDeviceMap->DriveMap & (1 << DriveNumber)) != 0)
+ {
+ DbgPrint("Drive letter already used!\n");
+ KeReleaseGuardedMutex(&ObpDeviceMapLock);
+ return FALSE;
+ }
+ KeReleaseGuardedMutex(&ObpDeviceMapLock);
}
-
- /* We'll loop until our buffer is big enough */
- Buffer = NULL;
- BufferSize = 0x1000;
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
- do
+ else
{
- /* If we already had a buffer, it means it's not big
- * enough, so free and multiply size by two
- */
- if (Buffer != NULL)
+ /* Automatic assignment */
+ DriveNumber = AUTO_DRIVE;
+ KeAcquireGuardedMutex(&ObpDeviceMapLock);
+ for (i = 2; i < 26; i++)
{
- ExFreePoolWithTag(Buffer, TAG_FSTUB);
- BufferSize *= 2;
+ if ((ObSystemDeviceMap->DriveMap & (1 << i)) == 0)
+ {
+ DriveNumber = i;
+ break;
+ }
}
+ KeReleaseGuardedMutex(&ObpDeviceMapLock);
- /* Allocate buffer for output buffer */
- Buffer = ExAllocatePoolWithTag(NonPagedPool, BufferSize, TAG_FSTUB);
- if (Buffer == NULL)
+ if (DriveNumber == AUTO_DRIVE)
{
- Status = STATUS_NO_MEMORY;
- break;
+ DbgPrint("No drive letter available!\n");
+ return FALSE;
}
+ }
- /* Build the IRP to query drive layout */
- Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_LAYOUT,
- DeviceObject,
- NULL,
- 0,
- Buffer,
- BufferSize,
- FALSE,
- &Event,
- &StatusBlock);
- if (Irp == NULL)
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- break;
- }
+ DPRINT("DriveNumber %lu\n", DriveNumber);
- /* Call the driver and wait if appropriate */
- Status = IoCallDriver(DeviceObject, Irp);
- if (Status == STATUS_PENDING)
+ /* Build drive name */
+ swprintf(DriveNameBuffer,
+ L"\\??\\%C:",
+ 'A' + DriveNumber);
+ RtlInitUnicodeString(&DriveName,
+ DriveNameBuffer);
+
+ DPRINT(" %wZ ==> %wZ\n",
+ &DriveName,
+ PartitionName);
+
+ /* Create symbolic link */
+ Status = IoCreateSymbolicLink(&DriveName,
+ PartitionName);
+
+ if (hKey &&
+ DriveType == DOSDEVICE_DRIVE_FIXED &&
+ Signature)
+ {
+ DiskMountInfo.Signature = Signature;
+ DiskMountInfo.StartingOffset = StartingOffset;
+ swprintf(DriveNameBuffer, DiskMountString, L'A' + DriveNumber);
+ RtlInitUnicodeString(&DriveName, DriveNameBuffer);
+
+ Status = ZwSetValueKey(hKey,
+ &DriveName,
+ 0,
+ REG_BINARY,
+ &DiskMountInfo,
+ sizeof(DiskMountInfo));
+ if (!NT_SUCCESS(Status))
{
- KeWaitForSingleObject(&Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- Status = StatusBlock.Status;
+ DPRINT1("ZwCreateValueKey failed for %wZ, status=%x\n", &DriveName, Status);
}
- /* If buffer is too small, keep looping */
- } while (Status == STATUS_BUFFER_TOO_SMALL);
+ }
- /* We're done with the device */
- ObDereferenceObject(DeviceObject);
+ /* Check if this is a boot partition */
+ if (RtlCompareUnicodeString(PartitionName, BootDevice, FALSE) == 0)
+ {
+ /* Set NtSystemPath to that partition's disk letter */
+ *NtSystemPath = (UCHAR)('A' + DriveNumber);
+ }
- /* If querying worked, then return the buffer to the caller */
- if (NT_SUCCESS(Status))
+ return TRUE;
+}
+
+ULONG
+xHalpGetRDiskCount(VOID)
+{
+ NTSTATUS Status;
+ UNICODE_STRING ArcName;
+ PWCHAR ArcNameBuffer;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE DirectoryHandle;
+ POBJECT_DIRECTORY_INFORMATION DirectoryInfo;
+ ULONG Skip;
+ ULONG ResultLength;
+ ULONG CurrentRDisk;
+ ULONG RDiskCount;
+ BOOLEAN First = TRUE;
+ ULONG Count;
+
+ DirectoryInfo = ExAllocatePoolWithTag(PagedPool, 2 * PAGE_SIZE, TAG_FILE_SYSTEM);
+ if (DirectoryInfo == NULL)
{
- ASSERT(Buffer != NULL);
- *LayoutInfo = Buffer;
+ return 0;
}
- /* Else, release the buffer if still allocated and fail */
- else
+
+ RtlInitUnicodeString(&ArcName, L"\\ArcName");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &ArcName,
+ 0,
+ NULL,
+ NULL);
+
+ Status = ZwOpenDirectoryObject (&DirectoryHandle,
+ DIRECTORY_ALL_ACCESS,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
{
- if (Buffer != NULL)
+ DPRINT1("ZwOpenDirectoryObject for %wZ failed, status=%lx\n", &ArcName, Status);
+ ExFreePoolWithTag(DirectoryInfo, TAG_FILE_SYSTEM);
+ return 0;
+ }
+
+ RDiskCount = 0;
+ Skip = 0;
+ while (NT_SUCCESS(Status))
+ {
+ Status = ZwQueryDirectoryObject (DirectoryHandle,
+ DirectoryInfo,
+ 2 * PAGE_SIZE,
+ FALSE,
+ First,
+ &Skip,
+ &ResultLength);
+ First = FALSE;
+ if (NT_SUCCESS(Status))
{
- ExFreePoolWithTag(Buffer, TAG_FSTUB);
+ Count = 0;
+ while (DirectoryInfo[Count].Name.Buffer)
+ {
+ DPRINT("Count %x\n", Count);
+ DirectoryInfo[Count].Name.Buffer[DirectoryInfo[Count].Name.Length / sizeof(WCHAR)] = 0;
+ ArcNameBuffer = DirectoryInfo[Count].Name.Buffer;
+ if (DirectoryInfo[Count].Name.Length >= sizeof(L"multi(0)disk(0)rdisk(0)") - sizeof(WCHAR) &&
+ !_wcsnicmp(ArcNameBuffer, L"multi(0)disk(0)rdisk(", (sizeof(L"multi(0)disk(0)rdisk(") - sizeof(WCHAR)) / sizeof(WCHAR)))
+ {
+ DPRINT("%S\n", ArcNameBuffer);
+ ArcNameBuffer += (sizeof(L"multi(0)disk(0)rdisk(") - sizeof(WCHAR)) / sizeof(WCHAR);
+ CurrentRDisk = 0;
+ while (iswdigit(*ArcNameBuffer))
+ {
+ CurrentRDisk = CurrentRDisk * 10 + *ArcNameBuffer - L'0';
+ ArcNameBuffer++;
+ }
+ if (!_wcsicmp(ArcNameBuffer, L")") &&
+ CurrentRDisk >= RDiskCount)
+ {
+ RDiskCount = CurrentRDisk + 1;
+ }
+ }
+ Count++;
+ }
}
}
- return Status;
+ ZwClose(DirectoryHandle);
+
+ ExFreePoolWithTag(DirectoryInfo, TAG_FILE_SYSTEM);
+ return RDiskCount;
}
NTSTATUS
-HalpQueryPartitionType(IN PUNICODE_STRING DeviceName,
- IN PDRIVE_LAYOUT_INFORMATION LayoutInfo,
- OUT PPARTITION_TYPE PartitionType)
+xHalpGetDiskNumberFromRDisk(ULONG RDisk, PULONG DiskNumber)
{
- USHORT i;
- PIRP Irp;
- KEVENT Event;
+ WCHAR NameBuffer[80];
+ UNICODE_STRING ArcName;
+ UNICODE_STRING LinkName;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE LinkHandle;
NTSTATUS Status;
- PFILE_OBJECT FileObject;
- PDEVICE_OBJECT DeviceObject;
- IO_STATUS_BLOCK IoStatusBlock;
- PARTITION_INFORMATION_EX PartitionInfo;
- PAGED_CODE();
+ swprintf(NameBuffer,
+ L"\\ArcName\\multi(0)disk(0)rdisk(%lu)",
+ RDisk);
+
+ RtlInitUnicodeString(&ArcName, NameBuffer);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &ArcName,
+ 0,
+ NULL,
+ NULL);
+ Status = ZwOpenSymbolicLinkObject(&LinkHandle,
+ SYMBOLIC_LINK_ALL_ACCESS,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ZwOpenSymbolicLinkObject failed for %wZ, status=%lx\n", &ArcName, Status);
+ return Status;
+ }
- /* Get device pointers */
- Status = IoGetDeviceObjectPointer(DeviceName,
- FILE_READ_ATTRIBUTES,
- &FileObject,
- &DeviceObject);
+ LinkName.Buffer = NameBuffer;
+ LinkName.Length = 0;
+ LinkName.MaximumLength = sizeof(NameBuffer);
+ Status = ZwQuerySymbolicLinkObject(LinkHandle,
+ &LinkName,
+ NULL);
+ ZwClose(LinkHandle);
if (!NT_SUCCESS(Status))
{
+ DPRINT1("ZwQuerySymbolicLinkObject failed, status=%lx\n", Status);
return Status;
}
+ if (LinkName.Length < sizeof(L"\\Device\\Harddisk0\\Partition0") - sizeof(WCHAR) ||
+ LinkName.Length >= sizeof(NameBuffer))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
- /* Get attached device object */
- DeviceObject = IoGetAttachedDeviceReference(FileObject->DeviceObject);
- ObDereferenceObject(FileObject);
+ NameBuffer[LinkName.Length / sizeof(WCHAR)] = 0;
+ if (_wcsnicmp(NameBuffer, L"\\Device\\Harddisk", (sizeof(L"\\Device\\Harddisk") - sizeof(WCHAR)) / sizeof(WCHAR)))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+ LinkName.Buffer += (sizeof(L"\\Device\\Harddisk") - sizeof(WCHAR)) / sizeof(WCHAR);
+
+ if (!iswdigit(*LinkName.Buffer))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+ *DiskNumber = 0;
+ while (iswdigit(*LinkName.Buffer))
+ {
+ *DiskNumber = *DiskNumber * 10 + *LinkName.Buffer - L'0';
+ LinkName.Buffer++;
+ }
+ if (_wcsicmp(LinkName.Buffer, L"\\Partition0"))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+FASTCALL
+xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName,
+ OUT PDRIVE_LAYOUT_INFORMATION *LayoutInfo)
+{
+ IO_STATUS_BLOCK StatusBlock;
+ DISK_GEOMETRY DiskGeometry;
+ PDEVICE_OBJECT DeviceObject = NULL;
+ PFILE_OBJECT FileObject;
+ KEVENT Event;
+ PIRP Irp;
+ NTSTATUS Status;
+
+ DPRINT("xHalpQueryDriveLayout %wZ %p\n",
+ DeviceName,
+ LayoutInfo);
- /* Assume logical partition for removable devices */
- if (BooleanFlagOn(DeviceObject->Characteristics, FILE_REMOVABLE_MEDIA))
+ /* Get the drives sector size */
+ Status = IoGetDeviceObjectPointer(DeviceName,
+ FILE_READ_ATTRIBUTES,
+ &FileObject,
+ &DeviceObject);
+ if (!NT_SUCCESS(Status))
{
- ObDereferenceObject(DeviceObject);
- *PartitionType = LogicalPartition;
- return STATUS_SUCCESS;
+ DPRINT("Status %x\n", Status);
+ return(Status);
}
- /* For the others, query partition info */
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
- Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO_EX,
- DeviceObject,
- NULL,
- 0,
- &PartitionInfo,
- sizeof(PartitionInfo),
- FALSE,
- &Event,
- &IoStatusBlock);
+ KeInitializeEvent(&Event,
+ NotificationEvent,
+ FALSE);
+
+ Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY,
+ DeviceObject,
+ NULL,
+ 0,
+ &DiskGeometry,
+ sizeof(DISK_GEOMETRY),
+ FALSE,
+ &Event,
+ &StatusBlock);
if (Irp == NULL)
{
- ObDereferenceObject(DeviceObject);
- return STATUS_INSUFFICIENT_RESOURCES;
+ ObDereferenceObject(FileObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
}
- Status = IoCallDriver(DeviceObject, Irp);
+ Status = IoCallDriver(DeviceObject,
+ Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- Status = IoStatusBlock.Status;
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ Status = StatusBlock.Status;
}
-
- /* We're done with the device */
- ObDereferenceObject(DeviceObject);
-
- /* If we failed querying partition info, try to return something
- * if caller didn't provide a precise layout, assume logical
- * partition and fake success. Otherwise, just fail.
- */
if (!NT_SUCCESS(Status))
{
- if (LayoutInfo == NULL)
+ if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
{
- *PartitionType = LogicalPartition;
- return STATUS_SUCCESS;
+ DiskGeometry.BytesPerSector = 512;
+ }
+ else
+ {
+ ObDereferenceObject(FileObject);
+ return(Status);
}
-
- return Status;
}
- /* First, handle non MBR style (easy cases) */
- if (PartitionInfo.PartitionStyle != PARTITION_STYLE_MBR)
+ DPRINT("DiskGeometry.BytesPerSector: %lu\n",
+ DiskGeometry.BytesPerSector);
+
+ if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
{
- /* If not GPT, we don't know what it is */
- if (PartitionInfo.PartitionStyle != PARTITION_STYLE_GPT)
+ PDRIVE_LAYOUT_INFORMATION Buffer;
+
+ /* Allocate a partition list for a single entry. */
+ Buffer = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(DRIVE_LAYOUT_INFORMATION), TAG_FILE_SYSTEM);
+ if (Buffer != NULL)
{
- *PartitionType = UnknownPartition;
- return STATUS_SUCCESS;
- }
+ RtlZeroMemory(Buffer,
+ sizeof(DRIVE_LAYOUT_INFORMATION));
+ Buffer->PartitionCount = 1;
+ *LayoutInfo = Buffer;
- /* Check whether that's data partition */
- if (RtlCompareMemory(&PartitionInfo.Gpt.PartitionType,
- &PARTITION_BASIC_DATA_GUID,
- sizeof(GUID)) == sizeof(GUID))
+ Status = STATUS_SUCCESS;
+ }
+ else
{
- *PartitionType = DataPartition;
- return STATUS_SUCCESS;
+ Status = STATUS_UNSUCCESSFUL;
}
-
- /* Otherwise, we don't know */
- *PartitionType = UnknownPartition;
- return STATUS_SUCCESS;
}
+ else
+ {
+ /* Read the partition table */
+ Status = IoReadPartitionTable(DeviceObject,
+ DiskGeometry.BytesPerSector,
+ TRUE,
+ LayoutInfo);
+ }
+
+ ObDereferenceObject(FileObject);
+
+ return(Status);
+}
+
+VOID
+FASTCALL
+xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PSTRING NtDeviceName,
+ OUT PUCHAR NtSystemPath,
+ OUT PSTRING NtSystemPathString)
+{
+ PDRIVE_LAYOUT_INFORMATION *LayoutArray;
+ PCONFIGURATION_INFORMATION ConfigInfo;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK StatusBlock;
+ UNICODE_STRING UnicodeString1;
+ UNICODE_STRING UnicodeString2;
+ HANDLE FileHandle;
+ PWSTR Buffer1;
+ PWSTR Buffer2;
+ ULONG i, j, k;
+ ULONG DiskNumber;
+ ULONG RDisk;
+ NTSTATUS Status;
+ HANDLE hKey;
+ ULONG Length;
+ PKEY_VALUE_PARTIAL_INFORMATION PartialInformation;
+ PREG_DISK_MOUNT_INFO DiskMountInfo;
+ ULONG RDiskCount;
+ UNICODE_STRING BootDevice;
+
+ Status = RtlAnsiStringToUnicodeString(&BootDevice,
+ NtDeviceName,
+ TRUE);
+
+ DPRINT("xHalIoAssignDriveLetters()\n");
+
+ ConfigInfo = IoGetConfigurationInformation();
+
+ RDiskCount = xHalpGetRDiskCount();
- /* If we don't recognize partition type, return unknown */
- if (!IsRecognizedPartition(PartitionInfo.Mbr.PartitionType))
+ DPRINT("RDiskCount %lu\n", RDiskCount);
+
+ Buffer1 = ExAllocatePoolWithTag(PagedPool,
+ 64 * sizeof(WCHAR),
+ TAG_FILE_SYSTEM);
+ if (!Buffer1) return;
+
+ Buffer2 = ExAllocatePoolWithTag(PagedPool,
+ 32 * sizeof(WCHAR),
+ TAG_FILE_SYSTEM);
+ if (!Buffer2)
{
- *PartitionType = UnknownPartition;
- return STATUS_SUCCESS;
+ ExFreePoolWithTag(Buffer1, TAG_FILE_SYSTEM);
+ return;
}
- /* Check if that's a FT volume */
- if (IsFTPartition(PartitionInfo.Mbr.PartitionType))
+ PartialInformation = ExAllocatePoolWithTag(PagedPool,
+ sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(REG_DISK_MOUNT_INFO),
+ TAG_FILE_SYSTEM);
+ if (!PartialInformation)
{
- *PartitionType = FtPartition;
- return STATUS_SUCCESS;
+ ExFreePoolWithTag(Buffer2, TAG_FILE_SYSTEM);
+ ExFreePoolWithTag(Buffer1, TAG_FILE_SYSTEM);
+ return;
}
- /* If the caller didn't provide the complete layout, just return */
- if (LayoutInfo == NULL)
+ DiskMountInfo = (PREG_DISK_MOUNT_INFO) PartialInformation->Data;
+
+ /* Create or open the 'MountedDevices' key */
+ RtlInitUnicodeString(&UnicodeString1, L"\\Registry\\Machine\\SYSTEM\\MountedDevices");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &UnicodeString1,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ NULL,
+ NULL);
+ Status = ZwCreateKey(&hKey,
+ KEY_ALL_ACCESS,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ NULL);
+ if (!NT_SUCCESS(Status))
{
- *PartitionType = LogicalPartition;
- return STATUS_SUCCESS;
+ hKey = NULL;
+ DPRINT("ZwCreateKey failed for %wZ, status=%x\n", &UnicodeString1, Status);
}
- /* Now, evaluate the partition to the 4 in the input layout */
- for (i = 0; i < 4; ++i)
+ /* Create PhysicalDrive links */
+ DPRINT("Physical disk drives: %lu\n", ConfigInfo->DiskCount);
+ for (i = 0; i < ConfigInfo->DiskCount; i++)
{
- /* If we find a partition matching */
- if (LayoutInfo->PartitionEntry[i].StartingOffset.QuadPart == PartitionInfo.StartingOffset.QuadPart)
+ swprintf(Buffer1, L"\\Device\\Harddisk%lu\\Partition0", i);
+ RtlInitUnicodeString(&UnicodeString1, Buffer1);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &UnicodeString1,
+ 0,
+ NULL,
+ NULL);
+
+ Status = ZwOpenFile(&FileHandle,
+ FILE_READ_DATA | SYNCHRONIZE,
+ &ObjectAttributes,
+ &StatusBlock,
+ FILE_SHARE_READ,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (NT_SUCCESS(Status))
{
- /* Return boot if boot flag is set */
- if (PartitionInfo.Mbr.BootIndicator)
- {
- *PartitionType = BootablePartition;
- }
- /* Primary otherwise */
- else
- {
- *PartitionType = PrimaryPartition;
- }
+ ZwClose(FileHandle);
- return STATUS_SUCCESS;
- }
- }
+ swprintf(Buffer2, L"\\??\\PhysicalDrive%lu", i);
+ RtlInitUnicodeString(&UnicodeString2, Buffer2);
- /* Otherwise, assume logical */
- *PartitionType = LogicalPartition;
- return STATUS_SUCCESS;
-}
+ DPRINT("Creating link: %S ==> %S\n",
+ Buffer2,
+ Buffer1);
-PULONG
-IopComputeHarddiskDerangements(IN ULONG DiskCount)
-{
- PIRP Irp;
- KEVENT Event;
- ULONG i, j, k;
- PULONG Devices;
- NTSTATUS Status;
- WCHAR Buffer[100];
- UNICODE_STRING ArcName;
- PFILE_OBJECT FileObject;
- PDEVICE_OBJECT DeviceObject;
- IO_STATUS_BLOCK IoStatusBlock;
- STORAGE_DEVICE_NUMBER DeviceNumber;
+ IoCreateSymbolicLink(&UnicodeString2,
+ &UnicodeString1);
+ }
+ }
- /* No disks, nothing to do */
- if (DiskCount == 0)
+ /* Initialize layout array */
+ if (ConfigInfo->DiskCount == 0)
+ goto end_assign_disks;
+ LayoutArray = ExAllocatePoolWithTag(NonPagedPool,
+ ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION), TAG_FILE_SYSTEM);
+ if (!LayoutArray)
{
- return NULL;
+ ExFreePoolWithTag(PartialInformation, TAG_FILE_SYSTEM);
+ ExFreePoolWithTag(Buffer2, TAG_FILE_SYSTEM);
+ ExFreePoolWithTag(Buffer1, TAG_FILE_SYSTEM);
+ if (hKey) ObCloseHandle(hKey, KernelMode);
+ return;
}
- /* Allocate a buffer big enough to hold all the disks */
- Devices = ExAllocatePoolWithTag(PagedPool | POOL_COLD_ALLOCATION,
- sizeof(ULONG) * DiskCount,
- TAG_FSTUB);
- if (Devices == NULL)
+ RtlZeroMemory(LayoutArray,
+ ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION));
+ for (i = 0; i < ConfigInfo->DiskCount; i++)
{
- return NULL;
+ swprintf(Buffer1, L"\\Device\\Harddisk%lu\\Partition0", i);
+ RtlInitUnicodeString(&UnicodeString1, Buffer1);
+
+ Status = xHalQueryDriveLayout(&UnicodeString1, &LayoutArray[i]);
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint("xHalQueryDriveLayout() failed (Status = 0x%lx)\n",
+ Status);
+ LayoutArray[i] = NULL;
+ continue;
+ }
+ /* We don't use the RewritePartition value while mounting the disks.
+ * We use this value for marking pre-assigned (registry) partitions.
+ */
+ for (j = 0; j < LayoutArray[i]->PartitionCount; j++)
+ {
+ LayoutArray[i]->PartitionEntry[j].RewritePartition = FALSE;
+ }
}
- /* Now, we'll query all the disks */
- for (i = 0; i < DiskCount; ++i)
+#ifndef NDEBUG
+ /* Dump layout array */
+ for (i = 0; i < ConfigInfo->DiskCount; i++)
{
- /* Using their ARC name */
- swprintf(Buffer, L"\\ArcName\\multi(0)disk(0)rdisk(%d)", i);
- RtlInitUnicodeString(&ArcName, Buffer);
- /* Get the attached DeviceObject */
- if (NT_SUCCESS(IoGetDeviceObjectPointer(&ArcName, FILE_READ_ATTRIBUTES, &FileObject, &DeviceObject)))
+ DPRINT("Harddisk %d:\n",
+ i);
+
+ if (LayoutArray[i] == NULL)
+ continue;
+
+ DPRINT("Logical partitions: %d\n",
+ LayoutArray[i]->PartitionCount);
+
+ for (j = 0; j < LayoutArray[i]->PartitionCount; j++)
{
- DeviceObject = IoGetAttachedDeviceReference(FileObject->DeviceObject);
- ObDereferenceObject(FileObject);
+ DPRINT(" %d: nr:%x boot:%x type:%x startblock:%I64u count:%I64u\n",
+ j,
+ LayoutArray[i]->PartitionEntry[j].PartitionNumber,
+ LayoutArray[i]->PartitionEntry[j].BootIndicator,
+ LayoutArray[i]->PartitionEntry[j].PartitionType,
+ LayoutArray[i]->PartitionEntry[j].StartingOffset.QuadPart,
+ LayoutArray[i]->PartitionEntry[j].PartitionLength.QuadPart);
+ }
+ }
+#endif
- /* And query it for device number */
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
- Irp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_DEVICE_NUMBER,
- DeviceObject,
- NULL,
- 0,
- &DeviceNumber,
- sizeof(DeviceNumber),
- FALSE,
- &Event,
- &IoStatusBlock);
- if (Irp != NULL)
+ /* Assign pre-assigned (registry) partitions */
+ if (hKey)
+ {
+ for (k = 2; k < 26; k++)
+ {
+ swprintf(Buffer1, DiskMountString, L'A' + k);
+ RtlInitUnicodeString(&UnicodeString1, Buffer1);
+ Status = ZwQueryValueKey(hKey,
+ &UnicodeString1,
+ KeyValuePartialInformation,
+ PartialInformation,
+ sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(REG_DISK_MOUNT_INFO),
+ &Length);
+ if (NT_SUCCESS(Status) &&
+ PartialInformation->Type == REG_BINARY &&
+ PartialInformation->DataLength == sizeof(REG_DISK_MOUNT_INFO))
{
- Status = IoCallDriver(DeviceObject, Irp);
- if (Status == STATUS_PENDING)
+ DPRINT("%wZ => %08x:%08x%08x\n", &UnicodeString1, DiskMountInfo->Signature,
+ DiskMountInfo->StartingOffset.u.HighPart, DiskMountInfo->StartingOffset.u.LowPart);
{
- KeWaitForSingleObject(&Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- Status = IoStatusBlock.Status;
+ BOOLEAN Found = FALSE;
+ for (i = 0; i < ConfigInfo->DiskCount; i++)
+ {
+ DPRINT("%x\n", LayoutArray[i]->Signature);
+ if (LayoutArray[i] &&
+ LayoutArray[i]->Signature &&
+ LayoutArray[i]->Signature == DiskMountInfo->Signature)
+ {
+ for (j = 0; j < LayoutArray[i]->PartitionCount; j++)
+ {
+ if (LayoutArray[i]->PartitionEntry[j].StartingOffset.QuadPart == DiskMountInfo->StartingOffset.QuadPart)
+ {
+ if (IsRecognizedPartition(LayoutArray[i]->PartitionEntry[j].PartitionType) &&
+ LayoutArray[i]->PartitionEntry[j].RewritePartition == FALSE)
+ {
+ swprintf(Buffer2,
+ L"\\Device\\Harddisk%lu\\Partition%lu",
+ i,
+ LayoutArray[i]->PartitionEntry[j].PartitionNumber);
+ RtlInitUnicodeString(&UnicodeString2, Buffer2);
+
+ /* Assign drive */
+ DPRINT(" %wZ\n", &UnicodeString2);
+ Found = HalpAssignDrive(&UnicodeString2,
+ k,
+ DOSDEVICE_DRIVE_FIXED,
+ DiskMountInfo->Signature,
+ DiskMountInfo->StartingOffset,
+ NULL,
+ &BootDevice,
+ NtSystemPath);
+ /* Mark the partition as assigned */
+ LayoutArray[i]->PartitionEntry[j].RewritePartition = TRUE;
+ }
+ break;
+ }
+ }
+ }
+ }
+ if (Found == FALSE)
+ {
+ /* We didn't find a partition for this entry, remove them. */
+ Status = ZwDeleteValueKey(hKey, &UnicodeString1);
+ }
}
+ }
+ }
+ }
- ObDereferenceObject(DeviceObject);
-
- /* In case of a success remember device number */
- if (NT_SUCCESS(Status))
+ /* Assign bootable partition on first harddisk */
+ DPRINT("Assigning bootable primary partition on first harddisk:\n");
+ if (RDiskCount > 0)
+ {
+ Status = xHalpGetDiskNumberFromRDisk(0, &DiskNumber);
+ if (NT_SUCCESS(Status) &&
+ DiskNumber < ConfigInfo->DiskCount &&
+ LayoutArray[DiskNumber])
+ {
+ /* Search for bootable partition */
+ for (j = 0; j < NUM_PARTITION_TABLE_ENTRIES && j < LayoutArray[DiskNumber]->PartitionCount; j++)
+ {
+ if ((LayoutArray[DiskNumber]->PartitionEntry[j].BootIndicator != FALSE) &&
+ IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType))
{
- Devices[i] = DeviceNumber.DeviceNumber;
- /* Move on, not to fall into our default case */
- continue;
+ if (LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE)
+ {
+ swprintf(Buffer2,
+ L"\\Device\\Harddisk%lu\\Partition%lu",
+ DiskNumber,
+ LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
+ RtlInitUnicodeString(&UnicodeString2, Buffer2);
+
+ /* Assign drive */
+ DPRINT(" %wZ\n", &UnicodeString2);
+ HalpAssignDrive(&UnicodeString2,
+ AUTO_DRIVE,
+ DOSDEVICE_DRIVE_FIXED,
+ LayoutArray[DiskNumber]->Signature,
+ LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
+ hKey,
+ &BootDevice,
+ NtSystemPath);
+ /* Mark the partition as assigned */
+ LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
+ }
+ break;
}
}
- else
- {
- ObDereferenceObject(DeviceObject);
- }
-
- /* Default case, for failures, set -1 */
- Devices[i] = -1;
}
}
- /* Now, we'll check all device numbers */
- for (i = 0; i < DiskCount; ++i)
+ /* Assign remaining primary partitions */
+ DPRINT("Assigning remaining primary partitions:\n");
+ for (RDisk = 0; RDisk < RDiskCount; RDisk++)
{
- /* First of all, check if we're at the right place */
- for (j = 0; j < DiskCount; ++j)
+ Status = xHalpGetDiskNumberFromRDisk(RDisk, &DiskNumber);
+ if (NT_SUCCESS(Status) &&
+ DiskNumber < ConfigInfo->DiskCount &&
+ LayoutArray[DiskNumber])
{
- if (Devices[j] == i)
+ /* Search for primary partitions */
+ for (j = 0; (j < NUM_PARTITION_TABLE_ENTRIES) && (j < LayoutArray[DiskNumber]->PartitionCount); j++)
{
- break;
+ if (LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE &&
+ IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType))
+ {
+ swprintf(Buffer2,
+ L"\\Device\\Harddisk%lu\\Partition%lu",
+ DiskNumber,
+ LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
+ RtlInitUnicodeString(&UnicodeString2, Buffer2);
+
+ /* Assign drive */
+ DPRINT(" %wZ\n",
+ &UnicodeString2);
+ HalpAssignDrive(&UnicodeString2,
+ AUTO_DRIVE,
+ DOSDEVICE_DRIVE_FIXED,
+ LayoutArray[DiskNumber]->Signature,
+ LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
+ hKey,
+ &BootDevice,
+ NtSystemPath);
+ /* Mark the partition as assigned */
+ LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
+ }
}
}
+ }
- /* If not, perform the change */
- if (j >= DiskCount)
+ /* Assign extended (logical) partitions */
+ DPRINT("Assigning extended (logical) partitions:\n");
+ for (RDisk = 0; RDisk < RDiskCount; RDisk++)
+ {
+ Status = xHalpGetDiskNumberFromRDisk(RDisk, &DiskNumber);
+ if (NT_SUCCESS(Status) &&
+ DiskNumber < ConfigInfo->DiskCount &&
+ LayoutArray[DiskNumber])
{
- k = 0;
- while (Devices[k] != -1)
+ /* Search for extended partitions */
+ for (j = NUM_PARTITION_TABLE_ENTRIES; j < LayoutArray[DiskNumber]->PartitionCount; j++)
{
- if (++k >= DiskCount)
+ if (IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType) &&
+ LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE &&
+ LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber != 0)
{
- break;
+ swprintf(Buffer2,
+ L"\\Device\\Harddisk%lu\\Partition%lu",
+ DiskNumber,
+ LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
+ RtlInitUnicodeString(&UnicodeString2, Buffer2);
+
+ /* Assign drive */
+ DPRINT(" %wZ\n",
+ &UnicodeString2);
+ HalpAssignDrive(&UnicodeString2,
+ AUTO_DRIVE,
+ DOSDEVICE_DRIVE_FIXED,
+ LayoutArray[DiskNumber]->Signature,
+ LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
+ hKey,
+ &BootDevice,
+ NtSystemPath);
+ /* Mark the partition as assigned */
+ LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
}
}
+ }
+ }
- if (k < DiskCount)
+ /* Assign remaining primary partitions without an arc-name */
+ DPRINT("Assigning remaining primary partitions:\n");
+ for (DiskNumber = 0; DiskNumber < ConfigInfo->DiskCount; DiskNumber++)
+ {
+ if (LayoutArray[DiskNumber])
+ {
+ /* Search for primary partitions */
+ for (j = 0; (j < NUM_PARTITION_TABLE_ENTRIES) && (j < LayoutArray[DiskNumber]->PartitionCount); j++)
{
- Devices[k] = i;
+ if (LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE &&
+ IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType))
+ {
+ swprintf(Buffer2,
+ L"\\Device\\Harddisk%lu\\Partition%lu",
+ DiskNumber,
+ LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
+ RtlInitUnicodeString(&UnicodeString2, Buffer2);
+
+ /* Assign drive */
+ DPRINT(" %wZ\n",
+ &UnicodeString2);
+ HalpAssignDrive(&UnicodeString2,
+ AUTO_DRIVE,
+ DOSDEVICE_DRIVE_FIXED,
+ LayoutArray[DiskNumber]->Signature,
+ LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
+ hKey,
+ &BootDevice,
+ NtSystemPath);
+ /* Mark the partition as assigned */
+ LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
+ }
}
}
}
- /* Return our device derangement map */
- return Devices;
-}
-
-NTSTATUS
-HalpNextMountLetter(IN PUNICODE_STRING DeviceName,
- OUT PUCHAR DriveLetter)
-{
- PIRP Irp;
- KEVENT Event;
- NTSTATUS Status;
- UNICODE_STRING MountMgr;
- PFILE_OBJECT FileObject;
- PDEVICE_OBJECT DeviceObject;
- IO_STATUS_BLOCK IoStatusBlock;
- PMOUNTMGR_DRIVE_LETTER_TARGET Target;
- MOUNTMGR_DRIVE_LETTER_INFORMATION LetterInfo;
-
- /* To get next mount letter, we need the MountMgr */
- RtlInitUnicodeString(&MountMgr, L"\\Device\\MountPointManager");
- Status = IoGetDeviceObjectPointer(&MountMgr,
- FILE_READ_ATTRIBUTES,
- &FileObject,
- &DeviceObject);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- /* Allocate our input buffer */
- Target = ExAllocatePoolWithTag(PagedPool,
- DeviceName->Length + FIELD_OFFSET(MOUNTMGR_DRIVE_LETTER_TARGET, DeviceName),
- TAG_FSTUB);
- if (Target == NULL)
- {
- ObDereferenceObject(FileObject);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- /* And fill it with the device hat needs a drive letter */
- Target->DeviceNameLength = DeviceName->Length;
- RtlCopyMemory(&Target->DeviceName[0], DeviceName->Buffer, DeviceName->Length);
-
- /* Call the mount manager */
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
- Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER,
- DeviceObject,
- Target,
- DeviceName->Length + FIELD_OFFSET(MOUNTMGR_DRIVE_LETTER_TARGET, DeviceName),
- &LetterInfo,
- sizeof(LetterInfo),
- FALSE,
- &Event,
- &IoStatusBlock);
- if (Irp == NULL)
- {
- ExFreePoolWithTag(Target, TAG_FSTUB);
- ObDereferenceObject(FileObject);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- Status = IoCallDriver(DeviceObject, Irp);
- if (Status == STATUS_PENDING)
- {
- KeWaitForSingleObject(&Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- Status = IoStatusBlock.Status;
- }
-
- ExFreePoolWithTag(Target, TAG_FSTUB);
- ObDereferenceObject(FileObject);
-
- DPRINT("Done: %d %c\n", LetterInfo.DriveLetterWasAssigned,
- LetterInfo.CurrentDriveLetter);
-
- /* Return the drive letter the MountMgr potentially assigned */
- *DriveLetter = LetterInfo.CurrentDriveLetter;
-
- /* Also return the success */
- return Status;
-}
-
-NTSTATUS
-HalpSetMountLetter(IN PUNICODE_STRING DeviceName,
- UCHAR DriveLetter)
-{
- PIRP Irp;
- KEVENT Event;
- NTSTATUS Status;
- WCHAR Buffer[30];
- ULONG InputBufferLength;
- PFILE_OBJECT FileObject;
- PDEVICE_OBJECT DeviceObject;
- IO_STATUS_BLOCK IoStatusBlock;
- UNICODE_STRING DosDevice, MountMgr;
- PMOUNTMGR_CREATE_POINT_INPUT InputBuffer;
-
- /* Setup the DosDevice name */
- swprintf(Buffer, L"\\DosDevices\\%c:", DriveLetter);
- RtlInitUnicodeString(&DosDevice, Buffer);
-
- /* Allocate the input buffer for the MountMgr */
- InputBufferLength = DosDevice.Length + DeviceName->Length + sizeof(MOUNTMGR_CREATE_POINT_INPUT);
- InputBuffer = ExAllocatePoolWithTag(PagedPool, InputBufferLength, TAG_FSTUB);
- if (InputBuffer == NULL)
- {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- /* Fill the input buffer */
- InputBuffer->SymbolicLinkNameOffset = sizeof(MOUNTMGR_CREATE_POINT_INPUT);
- InputBuffer->SymbolicLinkNameLength = DosDevice.Length;
- InputBuffer->DeviceNameOffset = DosDevice.Length + sizeof(MOUNTMGR_CREATE_POINT_INPUT);
- InputBuffer->DeviceNameLength = DeviceName->Length;
- RtlCopyMemory(&InputBuffer[1], DosDevice.Buffer, DosDevice.Length);
- RtlCopyMemory((PVOID)((ULONG_PTR)InputBuffer + InputBuffer->DeviceNameOffset),
- DeviceName->Buffer,
- DeviceName->Length);
-
- /* Get the MountMgr device pointer, to send the IOCTL */
- RtlInitUnicodeString(&MountMgr, L"\\Device\\MountPointManager");
- Status = IoGetDeviceObjectPointer(&MountMgr,
- FILE_READ_ATTRIBUTES,
- &FileObject,
- &DeviceObject);
- if (!NT_SUCCESS(Status))
+ /* Assign extended (logical) partitions without an arc-name */
+ DPRINT("Assigning extended (logical) partitions:\n");
+ for (DiskNumber = 0; DiskNumber < ConfigInfo->DiskCount; DiskNumber++)
{
- ExFreePoolWithTag(InputBuffer, TAG_FSTUB);
- return Status;
- }
-
- /* Call the MountMgr */
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
- Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_CREATE_POINT,
- DeviceObject,
- InputBuffer,
- InputBufferLength,
- NULL,
- 0,
- FALSE,
- &Event,
- &IoStatusBlock);
- if (Irp == NULL)
- {
- ObDereferenceObject(FileObject);
- ExFreePoolWithTag(InputBuffer, TAG_FSTUB);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- Status = IoCallDriver(DeviceObject, Irp);
- if (Status == STATUS_PENDING)
- {
- KeWaitForSingleObject(&Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- Status = IoStatusBlock.Status;
- }
-
- ObDereferenceObject(FileObject);
- ExFreePoolWithTag(InputBuffer, TAG_FSTUB);
-
- /* Return the MountMgr status */
- return Status;
-}
-
-UCHAR
-HalpNextDriveLetter(IN PUNICODE_STRING DeviceName,
- IN PSTRING NtDeviceName,
- OUT PUCHAR NtSystemPath,
- BOOLEAN IsRemovable)
-{
- UCHAR i;
- WCHAR Buffer[40];
- UCHAR DriveLetter;
- UNICODE_STRING FloppyString, CdString, NtDeviceNameU, DosDevice;
-
- /* Quick path, ask directly the mount manager to assign the next
- * free drive letter
- */
- if (NT_SUCCESS(HalpNextMountLetter(DeviceName, &DriveLetter)))
- {
- return DriveLetter;
- }
-
- /* We'll allow MountMgr to fail only for non vital path */
- if (NtDeviceName == NULL || NtSystemPath == NULL)
- {
- return -1;
- }
-
- /* And for removable devices */
- if (!IsRemovable)
- {
- return 0;
- }
-
- /* Removable might be floppy or cdrom */
- RtlInitUnicodeString(&FloppyString, L"\\Device\\Floppy");
- RtlInitUnicodeString(&CdString, L"\\Device\\CdRom");
-
- /* If floppy, start at A */
- if (RtlPrefixUnicodeString(&FloppyString, DeviceName, TRUE))
- {
- DriveLetter = 'A';
- }
- /* If CD start C */
- else if (RtlPrefixUnicodeString(&CdString, DeviceName, TRUE))
- {
- DriveLetter = 'D';
- }
- /* For the rest start at C */
- else
- {
- DriveLetter = 'C';
- }
-
- /* Now, try to assign a drive letter manually with the MountMgr */
- for (i = DriveLetter; i <= 'Z'; ++i)
- {
- if (NT_SUCCESS(HalpSetMountLetter(DeviceName, i)))
+ if (LayoutArray[DiskNumber])
{
- /* If it worked, if we were managing system path, update manually */
- if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&NtDeviceNameU, NtDeviceName, TRUE)))
+ /* Search for extended partitions */
+ for (j = NUM_PARTITION_TABLE_ENTRIES; j < LayoutArray[DiskNumber]->PartitionCount; j++)
{
- if (RtlEqualUnicodeString(&NtDeviceNameU, DeviceName, TRUE))
+ if (IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType) &&
+ LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE &&
+ LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber != 0)
{
- *NtSystemPath = i;
+ swprintf(Buffer2,
+ L"\\Device\\Harddisk%lu\\Partition%lu",
+ DiskNumber,
+ LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
+ RtlInitUnicodeString(&UnicodeString2, Buffer2);
+
+ /* Assign drive */
+ DPRINT(" %wZ\n",
+ &UnicodeString2);
+ HalpAssignDrive(&UnicodeString2,
+ AUTO_DRIVE,
+ DOSDEVICE_DRIVE_FIXED,
+ LayoutArray[DiskNumber]->Signature,
+ LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
+ hKey,
+ &BootDevice,
+ NtSystemPath);
+ /* Mark the partition as assigned */
+ LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
}
-
- RtlFreeUnicodeString(&NtDeviceNameU);
}
-
- return i;
}
}
- /* Last fall back, we're not on a PnP device... */
- for (i = DriveLetter; i <= 'Z'; ++i)
+ /* Assign removable disk drives */
+ DPRINT("Assigning removable disk drives:\n");
+ for (i = 0; i < ConfigInfo->DiskCount; i++)
{
- /* We'll link manually, without MountMgr knowing anything about the device */
- swprintf(Buffer, L"\\DosDevices\\%c:", i);
- RtlInitUnicodeString(&DosDevice, Buffer);
-
- /* If linking worked, then the letter was free ;-) */
- if (NT_SUCCESS(IoCreateSymbolicLink(&DosDevice, DeviceName)))
+ if (LayoutArray[i])
{
- /* If it worked, if we were managing system path, update manually */
- if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&NtDeviceNameU, NtDeviceName, TRUE)))
+ /* Search for virtual partitions */
+ if (LayoutArray[i]->PartitionCount == 1 &&
+ LayoutArray[i]->PartitionEntry[0].PartitionType == 0)
{
- if (RtlEqualUnicodeString(&NtDeviceNameU, DeviceName, TRUE))
- {
- *NtSystemPath = i;
- }
-
- RtlFreeUnicodeString(&NtDeviceNameU);
+ swprintf(Buffer2, L"\\Device\\Harddisk%lu\\Partition1", i);
+ RtlInitUnicodeString(&UnicodeString2, Buffer2);
+
+ /* Assign drive */
+ DPRINT(" %wZ\n",
+ &UnicodeString2);
+ HalpAssignDrive(&UnicodeString2,
+ AUTO_DRIVE,
+ DOSDEVICE_DRIVE_REMOVABLE,
+ 0,
+ RtlConvertLongToLargeInteger(0),
+ hKey,
+ &BootDevice,
+ NtSystemPath);
}
-
- return i;
}
}
- /* We're done, nothing happened */
- return 0;
-}
-
-BOOLEAN
-HalpIsOldStyleFloppy(PUNICODE_STRING DeviceName)
-{
- PIRP Irp;
- KEVENT Event;
- NTSTATUS Status;
- MOUNTDEV_NAME DevName;
- PFILE_OBJECT FileObject;
- PDEVICE_OBJECT DeviceObject;
- IO_STATUS_BLOCK IoStatusBlock;
- PAGED_CODE();
-
- /* Get the attached device object to our device */
- if (!NT_SUCCESS(IoGetDeviceObjectPointer(DeviceName,
- FILE_READ_ATTRIBUTES,
- &FileObject,
- &DeviceObject)))
- {
- return FALSE;
- }
-
- DeviceObject = IoGetAttachedDeviceReference(FileObject->DeviceObject);
- ObDereferenceObject(FileObject);
-
- /* Query its device name (ie, check floppy.sys implements MountMgr interface) */
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
- Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
- DeviceObject,
- NULL,
- 0,
- &DevName,
- sizeof(DevName),
- FALSE,
- &Event,
- &IoStatusBlock);
- if (Irp == NULL)
- {
- ObDereferenceObject(DeviceObject);
- return FALSE;
- }
-
- Status = IoCallDriver(DeviceObject, Irp);
- if (Status == STATUS_PENDING)
- {
- KeWaitForSingleObject(&Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- Status = IoStatusBlock.Status;
- }
-
- /* If status is not STATUS_BUFFER_OVERFLOW, it means
- * it's pre-mountmgr driver, aka "Old style".
- */
- ObDereferenceObject(DeviceObject);
- return (Status != STATUS_BUFFER_OVERFLOW);
-}
-
-NTSTATUS
-HalpDeleteMountLetter(UCHAR DriveLetter)
-{
- PIRP Irp;
- KEVENT Event;
- NTSTATUS Status;
- WCHAR Buffer[30];
- ULONG InputBufferLength;
- PFILE_OBJECT FileObject;
- PDEVICE_OBJECT DeviceObject;
- IO_STATUS_BLOCK IoStatusBlock;
- PMOUNTMGR_MOUNT_POINT InputBuffer;
- UNICODE_STRING DosDevice, MountMgr;
- PMOUNTMGR_MOUNT_POINTS OutputBuffer;
-
- /* Setup the device name of the letter to delete */
- swprintf(Buffer, L"\\DosDevices\\%c:", DriveLetter);
- RtlInitUnicodeString(&DosDevice, Buffer);
-
- /* Allocate the input buffer for MountMgr */
- InputBufferLength = DosDevice.Length + sizeof(MOUNTMGR_MOUNT_POINT);
- InputBuffer = ExAllocatePoolWithTag(PagedPool, InputBufferLength, TAG_FSTUB);
- if (InputBuffer == NULL)
- {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- /* Fill it in */
- RtlZeroMemory(InputBuffer, InputBufferLength);
- InputBuffer->SymbolicLinkNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
- InputBuffer->SymbolicLinkNameLength = DosDevice.Length;
- RtlCopyMemory(&InputBuffer[1], DosDevice.Buffer, DosDevice.Length);
-
- /* Allocate big enough output buffer (we don't care about the output) */
- OutputBuffer = ExAllocatePoolWithTag(PagedPool, 0x1000, TAG_FSTUB);
- if (OutputBuffer == NULL)
- {
- ExFreePoolWithTag(InputBuffer, TAG_FSTUB);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- /* Get the device pointer to the MountMgr */
- RtlInitUnicodeString(&MountMgr, L"\\Device\\MountPointManager");
- Status = IoGetDeviceObjectPointer(&MountMgr,
- FILE_READ_ATTRIBUTES,
- &FileObject,
- &DeviceObject);
- if (!NT_SUCCESS(Status))
- {
- ExFreePoolWithTag(OutputBuffer, TAG_FSTUB);
- ExFreePoolWithTag(InputBuffer, TAG_FSTUB);
- return Status;
- }
-
- /* Call the mount manager to delete the drive letter */
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
- Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_DELETE_POINTS,
- DeviceObject,
- InputBuffer,
- InputBufferLength,
- OutputBuffer,
- 0x1000,
- FALSE,
- &Event,
- &IoStatusBlock);
- if (Irp == NULL)
+ /* Free layout array */
+ for (i = 0; i < ConfigInfo->DiskCount; i++)
{
- ObDereferenceObject(FileObject);
- ExFreePoolWithTag(OutputBuffer, TAG_FSTUB);
- ExFreePoolWithTag(InputBuffer, TAG_FSTUB);
- return STATUS_INSUFFICIENT_RESOURCES;
+ if (LayoutArray[i] != NULL)
+ ExFreePoolWithTag(LayoutArray[i], TAG_FILE_SYSTEM);
}
+ ExFreePoolWithTag(LayoutArray, TAG_FILE_SYSTEM);
+end_assign_disks:
- Status = IoCallDriver(DeviceObject, Irp);
- if (Status == STATUS_PENDING)
+ /* Assign floppy drives */
+ DPRINT("Floppy drives: %lu\n", ConfigInfo->FloppyCount);
+ for (i = 0; i < ConfigInfo->FloppyCount; i++)
{
- KeWaitForSingleObject(&Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- Status = IoStatusBlock.Status;
- }
-
- ObDereferenceObject(FileObject);
- ExFreePoolWithTag(OutputBuffer, TAG_FSTUB);
- ExFreePoolWithTag(InputBuffer, TAG_FSTUB);
-
- return Status;
-}
-
-VOID
-HalpEnableAutomaticDriveLetterAssignment(VOID)
-{
- PIRP Irp;
- KEVENT Event;
- NTSTATUS Status;
- UNICODE_STRING MountMgr;
- PFILE_OBJECT FileObject;
- PDEVICE_OBJECT DeviceObject;
- IO_STATUS_BLOCK IoStatusBlock;
+ swprintf(Buffer1, L"\\Device\\Floppy%lu", i);
+ RtlInitUnicodeString(&UnicodeString1, Buffer1);
- /* Get the device pointer to the MountMgr */
- RtlInitUnicodeString(&MountMgr, L"\\Device\\MountPointManager");
- Status = IoGetDeviceObjectPointer(&MountMgr,
- FILE_READ_ATTRIBUTES,
- &FileObject,
- &DeviceObject);
- if (!NT_SUCCESS(Status))
- {
- return;
+ /* Assign drive letters A: or B: or first free drive letter */
+ DPRINT(" %wZ\n",
+ &UnicodeString1);
+ HalpAssignDrive(&UnicodeString1,
+ (i < 2) ? i : AUTO_DRIVE,
+ DOSDEVICE_DRIVE_REMOVABLE,
+ 0,
+ RtlConvertLongToLargeInteger(0),
+ hKey,
+ &BootDevice,
+ NtSystemPath);
}
- /* Just send an IOCTL to enable the feature */
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
- Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_AUTO_DL_ASSIGNMENTS,
- DeviceObject,
- NULL,
- 0,
- NULL,
- 0,
- FALSE,
- &Event,
- &IoStatusBlock);
- if (Irp == NULL)
+ /* Assign cdrom drives */
+ DPRINT("CD-Rom drives: %lu\n", ConfigInfo->CdRomCount);
+ for (i = 0; i < ConfigInfo->CdRomCount; i++)
{
- return;
- }
+ swprintf(Buffer1, L"\\Device\\CdRom%lu", i);
+ RtlInitUnicodeString(&UnicodeString1, Buffer1);
- Status = IoCallDriver(DeviceObject, Irp);
- if (Status == STATUS_PENDING)
- {
- KeWaitForSingleObject(&Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- Status = IoStatusBlock.Status;
+ /* Assign first free drive letter */
+ DPRINT(" %wZ\n", &UnicodeString1);
+ HalpAssignDrive(&UnicodeString1,
+ AUTO_DRIVE,
+ DOSDEVICE_DRIVE_CDROM,
+ 0,
+ RtlConvertLongToLargeInteger(0),
+ hKey,
+ &BootDevice,
+ NtSystemPath);
}
- ObDereferenceObject(FileObject);
+ /* Anything else to do? */
- return;
+ ExFreePoolWithTag(PartialInformation, TAG_FILE_SYSTEM);
+ ExFreePoolWithTag(Buffer2, TAG_FILE_SYSTEM);
+ ExFreePoolWithTag(Buffer1, TAG_FILE_SYSTEM);
+ if (hKey) ObCloseHandle(hKey, KernelMode);
}
-VOID
-FASTCALL
-xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
- IN PSTRING NtDeviceName,
- OUT PUCHAR NtSystemPath,
- OUT PSTRING NtSystemPathString)
-{
- USHORT i;
- PULONG Devices;
- NTSTATUS Status;
- WCHAR Buffer[50];
- HANDLE FileHandle;
- UCHAR DriveLetter;
- BOOLEAN SystemFound;
- IO_STATUS_BLOCK StatusBlock;
- PARTITION_TYPE PartitionType;
- ANSI_STRING StringA1, StringA2;
- PSTR Buffer1, Buffer2, LoadOptions;
- OBJECT_ATTRIBUTES ObjectAttributes;
- PDRIVE_LAYOUT_INFORMATION LayoutInfo;
- PCONFIGURATION_INFORMATION ConfigInfo;
- UNICODE_STRING StringU1, StringU2, StringU3;
- ULONG Increment, DiskCount, RealDiskCount, HarddiskCount, PartitionCount, SystemPartition;
-
- PAGED_CODE();
-
- /* Get our disk count */
- ConfigInfo = IoGetConfigurationInformation();
- DiskCount = ConfigInfo->DiskCount;
- RealDiskCount = 0;
-
- /* Allocate two generic string buffers we'll use and reuser later on */
- Buffer1 = ExAllocatePoolWithTag(NonPagedPool, 128, TAG_FSTUB);
- Buffer2 = ExAllocatePoolWithTag(NonPagedPool, 64, TAG_FSTUB);
- if (Buffer1 == NULL || Buffer2 == NULL)
- {
- KeBugCheck(ASSIGN_DRIVE_LETTERS_FAILED);
- }
-
- /* In case of a remote boot, setup system path */
- if (IoRemoteBootClient)
- {
- PSTR Last, Saved;
-
- /* Find last \ */
- Last = strrchr(LoaderBlock->NtBootPathName, '\\');
- Saved = NULL;
- /* Misformed name, fail */
- if (Last == NULL)
- {
- KeBugCheck(ASSIGN_DRIVE_LETTERS_FAILED);
- }
-
- /* In case the name was terminated by a \... */
- if (Last[1] == ANSI_NULL)
- {
- /* Erase it, save position and find the previous \ */
- *Last = ANSI_NULL;
- Saved = Last;
- Last = strrchr(LoaderBlock->NtBootPathName, '\\');
- *Saved = '\\';
- }
-
- /* Misformed name, fail */
- if (Last == NULL)
- {
- KeBugCheck(ASSIGN_DRIVE_LETTERS_FAILED);
- }
-
- /* For a remote boot, assign X drive letter */
- NtSystemPath[0] = 'X';
- NtSystemPath[1] = ':';
- /* And copy the end of the boot path */
- strcpy((PSTR)&NtSystemPath[2], Last);
-
- /* If we had to remove the trailing \, remove it here too */
- if (Saved != NULL)
- {
- NtSystemPath[strlen((PSTR)NtSystemPath) - 1] = ANSI_NULL;
- }
-
- /* Setup output string */
- RtlInitString(NtSystemPathString, (PSTR)NtSystemPath);
- }
-
- /* For each of our disks, create the physical device DOS device */
- Increment = 0;
- if (DiskCount != 0)
- {
- for (i = 0; i < DiskCount; ++i)
- {
- /* Setup the origin name */
- sprintf(Buffer1, "\\Device\\Harddisk%d\\Partition%d", i, 0);
- RtlInitAnsiString(&StringA1, Buffer1);
- if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&StringU1, &StringA1, TRUE)))
- {
- /* We cannot fail */
- KeBugCheck(ASSIGN_DRIVE_LETTERS_FAILED);
- }
-
- /* Open the device */
- InitializeObjectAttributes(&ObjectAttributes,
- &StringU1,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
- Status = ZwOpenFile(&FileHandle,
- SYNCHRONIZE | FILE_READ_DATA,
- &ObjectAttributes,
- &StatusBlock,
- FILE_SHARE_READ,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (NT_SUCCESS(Status))
- {
- /* If we managed, create the link */
- sprintf(Buffer2, "\\DosDevices\\PhysicalDrive%d", i);
- RtlInitAnsiString(&StringA2, Buffer2);
- Status = RtlAnsiStringToUnicodeString(&StringU2, &StringA2, TRUE);
- if (NT_SUCCESS(Status))
- {
- IoCreateSymbolicLink(&StringU2, &StringU1);
- RtlFreeUnicodeString(&StringU2);
- }
-
- ZwClose(FileHandle);
-
- RealDiskCount = i + 1;
- }
-
- RtlFreeUnicodeString(&StringU1);
-
- if (!NT_SUCCESS(Status))
- {
- if (Increment < 50)
- {
- ++Increment;
- ++DiskCount;
- }
- }
- }
- }
-
- /* We done for our buffers */
- ExFreePoolWithTag(Buffer1, TAG_FSTUB);
- ExFreePoolWithTag(Buffer2, TAG_FSTUB);
-
- /* Upcase our load options, if any */
- if (LoaderBlock->LoadOptions != NULL)
- {
- LoadOptions = _strupr(LoaderBlock->LoadOptions);
- }
- else
- {
- LoadOptions = NULL;
- }
-
- /* If we boot with /MININT (system hive as volatile) option, assign X letter to boot device */
- if (LoadOptions != NULL &&
- strstr(LoadOptions, "MININT") != 0 &&
- NT_SUCCESS(RtlAnsiStringToUnicodeString(&StringU1, NtDeviceName, TRUE)))
- {
- if (NT_SUCCESS(HalpSetMountLetter(&StringU1, 'X')))
- {
- *NtSystemPath = 'X';
- }
-
- RtlFreeUnicodeString(&StringU1);
- }
-
- /* Compute our disks derangements */
- DiskCount -= Increment;
- if (RealDiskCount > DiskCount)
- {
- DiskCount = RealDiskCount;
- }
- Devices = IopComputeHarddiskDerangements(DiskCount);
-
- /* Now, start browsing all our disks for assigning drive letters
- * Here, we'll only handle boot partition and primary partitions
- */
- HarddiskCount = 0;
- for (i = 0; i < DiskCount; ++i)
- {
- /* Get device ID according to derangements map */
- if (Devices != NULL)
- {
- HarddiskCount = Devices[i];
- }
-
- /* Query disk layout */
- swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition0", HarddiskCount);
- RtlInitUnicodeString(&StringU1, Buffer);
- if (!NT_SUCCESS(HalpQueryDriveLayout(&StringU1, &LayoutInfo)))
- {
- LayoutInfo = NULL;
- }
-
- /* Assume we didn't find system */
- SystemFound = FALSE;
- swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, 1);
- RtlInitUnicodeString(&StringU1, Buffer);
- /* Query partition info for our disk */
- if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
- {
- /* It failed, retry for all the partitions */
- for (PartitionCount = 1; ; ++PartitionCount)
- {
- swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
- RtlInitUnicodeString(&StringU1, Buffer);
- if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
- {
- break;
- }
-
- /* We found a primary partition, assign a drive letter */
- if (PartitionType == PrimaryPartition)
- {
- HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, 0);
- break;
- }
- }
- }
- else
- {
- /* All right */
- for (PartitionCount = 2; ; ++PartitionCount)
- {
- /* If our partition is bootable (MBR) or data (GPT), that's system partition */
- if (PartitionType == BootablePartition || PartitionType == DataPartition)
- {
- SystemFound = TRUE;
-
- /* Assign a drive letter and stop here if MBR */
- HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, 0);
- if (PartitionType == BootablePartition)
- {
- break;
- }
- }
-
- /* Keep looping on all the partitions */
- swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
- RtlInitUnicodeString(&StringU1, Buffer);
- if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
- {
- /* Mount every primary partition if we didn't find system */
- if (!SystemFound)
- {
- for (PartitionCount = 1; ; ++PartitionCount)
- {
- swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
- RtlInitUnicodeString(&StringU1, Buffer);
- if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
- {
- break;
- }
-
- if (PartitionType == PrimaryPartition)
- {
- HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, 0);
- break;
- }
- }
- }
-
- break;
- }
- }
- }
-
- /* Free layout, we'll reallocate it for next device */
- if (LayoutInfo != NULL)
- {
- ExFreePoolWithTag(LayoutInfo, TAG_FSTUB);
- }
-
- HarddiskCount = i + 1;
- }
-
- /* Now, assign logical partitions */
- for (i = 0; i < DiskCount; ++i)
- {
- /* Get device ID according to derangements map */
- if (Devices != NULL)
- {
- HarddiskCount = Devices[i];
- }
- else
- {
- HarddiskCount = i;
- }
-
- /* Query device layout */
- swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition0", HarddiskCount);
- RtlInitUnicodeString(&StringU1, Buffer);
- if (!NT_SUCCESS(HalpQueryDriveLayout(&StringU1, &LayoutInfo)))
- {
- LayoutInfo = NULL;
- }
-
- /* And assign drive letter to logical partitions */
- for (PartitionCount = 1; ; ++PartitionCount)
- {
- swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
- RtlInitUnicodeString(&StringU1, Buffer);
- if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
- {
- break;
- }
-
- if (PartitionType == LogicalPartition)
- {
- HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, 0);
- }
- }
-
- /* Free layout, we'll reallocate it for next device */
- if (LayoutInfo != NULL)
- {
- ExFreePoolWithTag(LayoutInfo, 0);
- }
- }
-
- /* Now, assign drive letters to everything else */
- for (i = 0; i < DiskCount; ++i)
- {
- /* Get device ID according to derangements map */
- if (Devices != NULL)
- {
- HarddiskCount = Devices[i];
- }
- else
- {
- HarddiskCount = i;
- }
-
- /* Query device layout */
- swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition0", HarddiskCount);
- RtlInitUnicodeString(&StringU1, Buffer);
- if (!NT_SUCCESS(HalpQueryDriveLayout(&StringU1, &LayoutInfo)))
- {
- LayoutInfo = NULL;
- }
-
- /* Save system partition if any */
- SystemPartition = 0;
- for (PartitionCount = 1; ; ++PartitionCount)
- {
- swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
- RtlInitUnicodeString(&StringU1, Buffer);
- if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
- {
- break;
- }
-
- if ((PartitionType == BootablePartition || PartitionType == PrimaryPartition) && (SystemPartition == 0))
- {
- SystemPartition = PartitionCount;
- }
- }
-
- /* And assign drive letter to anything but system partition */
- for (PartitionCount = 1; ; ++PartitionCount)
- {
- if (PartitionCount != SystemPartition)
- {
- swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
- RtlInitUnicodeString(&StringU1, Buffer);
- if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
- {
- if (LayoutInfo != NULL)
- {
- ExFreePoolWithTag(LayoutInfo, 0);
- }
-
- break;
- }
-
- if (PartitionType == PrimaryPartition || PartitionType == FtPartition)
- {
- HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, 0);
- }
- }
- }
- }
-
- /* We're done with disks, if we have a device map, free it */
- if (Devices != NULL)
- {
- ExFreePoolWithTag(Devices, TAG_FSTUB);
- }
-
- /* Now, assign drive letter to floppy drives */
- for (i = 0; i < ConfigInfo->FloppyCount; ++i)
- {
- swprintf(Buffer, L"\\Device\\Floppy%d", i);
- RtlInitUnicodeString(&StringU1, Buffer);
- if (HalpIsOldStyleFloppy(&StringU1))
- {
- HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, TRUE);
- }
- }
-
- /* And CD drives */
- for (i = 0; i < ConfigInfo->CdRomCount; ++i)
- {
- swprintf(Buffer, L"\\Device\\CdRom%d", i);
- RtlInitUnicodeString(&StringU1, Buffer);
- HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, TRUE);
- }
-
- /* If not remote boot, handle NtDeviceName */
- if (!IoRemoteBootClient && NT_SUCCESS(RtlAnsiStringToUnicodeString(&StringU1, NtDeviceName, TRUE)))
- {
- /* Assign it a drive letter */
- DriveLetter = HalpNextDriveLetter(&StringU1, NULL, NULL, TRUE);
- if (DriveLetter != 0)
- {
- if (DriveLetter != 0xFF)
- {
- *NtSystemPath = DriveLetter;
- }
- }
- /* If it fails through mount manager, retry manually */
- else
- {
- RtlInitUnicodeString(&StringU2, L"\\Device\\Floppy");
- RtlInitUnicodeString(&StringU3, L"\\Device\\CdRom");
-
- if (RtlPrefixUnicodeString(&StringU2, &StringU1, TRUE))
- {
- DriveLetter = 'A';
- }
- else if (RtlPrefixUnicodeString(&StringU3, &StringU1, TRUE))
- {
- DriveLetter = 'D';
- }
- else
- {
- DriveLetter = 'C';
- }
-
- /* Try any drive letter */
- while (HalpSetMountLetter(&StringU1, DriveLetter) != STATUS_SUCCESS)
- {
- ++DriveLetter;
-
- if (DriveLetter > 'Z')
- {
- break;
- }
- }
-
- /* If we're beyond Z (ie, no slot left) */
- if (DriveLetter > 'Z')
- {
- /* Delete Z, and reuse it for system */
- HalpDeleteMountLetter('Z');
- HalpSetMountLetter(&StringU1, 'Z');
- *NtSystemPath = 'Z';
- }
- else
- {
- /* Return matching drive letter */
- *NtSystemPath = DriveLetter;
- }
- }
-
- RtlFreeUnicodeString(&StringU1);
- }
-
- /* Enable auto assignement for mountmgr */
- HalpEnableAutomaticDriveLetterAssignment();
-}
+#endif
/* PRIVATE FUNCTIONS *********************************************************/