1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: ReactOS Kernel
3c2c66affSColin Finck * LICENSE: GPL - See COPYING in the top level directory
4c2c66affSColin Finck * FILE: ntoskrnl/fstub/disksup.c
5c2c66affSColin Finck * PURPOSE: I/O HAL Routines for Disk Access
6c2c66affSColin Finck * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7c2c66affSColin Finck * Eric Kohl
8c2c66affSColin Finck * Casper S. Hornstrup (chorns@users.sourceforge.net)
95ab1cfc5SPierre Schweitzer * Pierre Schweitzer
10c2c66affSColin Finck */
11c2c66affSColin Finck
12c2c66affSColin Finck /* INCLUDES ******************************************************************/
13c2c66affSColin Finck
14c2c66affSColin Finck #include <ntoskrnl.h>
15c2c66affSColin Finck #define NDEBUG
16c2c66affSColin Finck #include <debug.h>
17c2c66affSColin Finck #include <internal/hal.h>
18c2c66affSColin Finck
19c2c66affSColin Finck const WCHAR DiskMountString[] = L"\\DosDevices\\%C:";
20c2c66affSColin Finck
21c2c66affSColin Finck #define AUTO_DRIVE MAXULONG
22c2c66affSColin Finck
23c2c66affSColin Finck #define PARTITION_MAGIC 0xaa55
24c2c66affSColin Finck
25c2c66affSColin Finck #define EFI_PMBR_OSTYPE_EFI 0xEE
26c2c66affSColin Finck
27c2c66affSColin Finck #include <pshpack1.h>
28c2c66affSColin Finck
29c2c66affSColin Finck typedef struct _REG_DISK_MOUNT_INFO
30c2c66affSColin Finck {
31c2c66affSColin Finck ULONG Signature;
32c2c66affSColin Finck LARGE_INTEGER StartingOffset;
33c2c66affSColin Finck } REG_DISK_MOUNT_INFO, *PREG_DISK_MOUNT_INFO;
34c2c66affSColin Finck
35c2c66affSColin Finck #include <poppack.h>
36c2c66affSColin Finck
37c2c66affSColin Finck typedef enum _DISK_MANAGER
38c2c66affSColin Finck {
39c2c66affSColin Finck NoDiskManager,
40c2c66affSColin Finck OntrackDiskManager,
41c2c66affSColin Finck EZ_Drive
42c2c66affSColin Finck } DISK_MANAGER;
43c2c66affSColin Finck
445ab1cfc5SPierre Schweitzer typedef enum _PARTITION_TYPE
45c2c66affSColin Finck {
465ab1cfc5SPierre Schweitzer BootablePartition,
475ab1cfc5SPierre Schweitzer PrimaryPartition,
485ab1cfc5SPierre Schweitzer LogicalPartition,
495ab1cfc5SPierre Schweitzer FtPartition,
505ab1cfc5SPierre Schweitzer UnknownPartition,
515ab1cfc5SPierre Schweitzer DataPartition
525ab1cfc5SPierre Schweitzer } PARTITION_TYPE, *PPARTITION_TYPE;
53c2c66affSColin Finck
54c2c66affSColin Finck NTSTATUS
55c2c66affSColin Finck FASTCALL
HalpQueryDriveLayout(IN PUNICODE_STRING DeviceName,OUT PDRIVE_LAYOUT_INFORMATION * LayoutInfo)565ab1cfc5SPierre Schweitzer HalpQueryDriveLayout(IN PUNICODE_STRING DeviceName,
57c2c66affSColin Finck OUT PDRIVE_LAYOUT_INFORMATION *LayoutInfo)
58c2c66affSColin Finck {
59c2c66affSColin Finck IO_STATUS_BLOCK StatusBlock;
60c2c66affSColin Finck PDEVICE_OBJECT DeviceObject = NULL;
61c2c66affSColin Finck PFILE_OBJECT FileObject;
62c2c66affSColin Finck KEVENT Event;
63c2c66affSColin Finck PIRP Irp;
64c2c66affSColin Finck NTSTATUS Status;
655ab1cfc5SPierre Schweitzer ULONG BufferSize;
665ab1cfc5SPierre Schweitzer PDRIVE_LAYOUT_INFORMATION Buffer;
675ab1cfc5SPierre Schweitzer PAGED_CODE();
68c2c66affSColin Finck
695ab1cfc5SPierre Schweitzer /* Get device pointers */
70c2c66affSColin Finck Status = IoGetDeviceObjectPointer(DeviceName,
71c2c66affSColin Finck FILE_READ_ATTRIBUTES,
72c2c66affSColin Finck &FileObject,
73c2c66affSColin Finck &DeviceObject);
74c2c66affSColin Finck if (!NT_SUCCESS(Status))
75c2c66affSColin Finck {
765ab1cfc5SPierre Schweitzer return Status;
77c2c66affSColin Finck }
78c2c66affSColin Finck
795ab1cfc5SPierre Schweitzer /* Get attached device object */
805ab1cfc5SPierre Schweitzer DeviceObject = IoGetAttachedDeviceReference(FileObject->DeviceObject);
815ab1cfc5SPierre Schweitzer ObDereferenceObject(FileObject);
82c2c66affSColin Finck
835ab1cfc5SPierre Schweitzer /* Do not handle removable media */
845ab1cfc5SPierre Schweitzer if (BooleanFlagOn(DeviceObject->Characteristics, FILE_REMOVABLE_MEDIA))
855ab1cfc5SPierre Schweitzer {
865ab1cfc5SPierre Schweitzer ObDereferenceObject(DeviceObject);
875ab1cfc5SPierre Schweitzer return STATUS_NO_MEDIA;
885ab1cfc5SPierre Schweitzer }
895ab1cfc5SPierre Schweitzer
905ab1cfc5SPierre Schweitzer /* We'll loop until our buffer is big enough */
915ab1cfc5SPierre Schweitzer Buffer = NULL;
925ab1cfc5SPierre Schweitzer BufferSize = 0x1000;
935ab1cfc5SPierre Schweitzer KeInitializeEvent(&Event, NotificationEvent, FALSE);
945ab1cfc5SPierre Schweitzer do
955ab1cfc5SPierre Schweitzer {
965ab1cfc5SPierre Schweitzer /* If we already had a buffer, it means it's not big
975ab1cfc5SPierre Schweitzer * enough, so free and multiply size by two
985ab1cfc5SPierre Schweitzer */
995ab1cfc5SPierre Schweitzer if (Buffer != NULL)
1005ab1cfc5SPierre Schweitzer {
1015ab1cfc5SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_FSTUB);
1025ab1cfc5SPierre Schweitzer BufferSize *= 2;
1035ab1cfc5SPierre Schweitzer }
1045ab1cfc5SPierre Schweitzer
1055ab1cfc5SPierre Schweitzer /* Allocate buffer for output buffer */
1065ab1cfc5SPierre Schweitzer Buffer = ExAllocatePoolWithTag(NonPagedPool, BufferSize, TAG_FSTUB);
1075ab1cfc5SPierre Schweitzer if (Buffer == NULL)
1085ab1cfc5SPierre Schweitzer {
1095ab1cfc5SPierre Schweitzer Status = STATUS_NO_MEMORY;
1105ab1cfc5SPierre Schweitzer break;
1115ab1cfc5SPierre Schweitzer }
1125ab1cfc5SPierre Schweitzer
1135ab1cfc5SPierre Schweitzer /* Build the IRP to query drive layout */
1145ab1cfc5SPierre Schweitzer Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_LAYOUT,
115c2c66affSColin Finck DeviceObject,
116c2c66affSColin Finck NULL,
117c2c66affSColin Finck 0,
1185ab1cfc5SPierre Schweitzer Buffer,
1195ab1cfc5SPierre Schweitzer BufferSize,
120c2c66affSColin Finck FALSE,
121c2c66affSColin Finck &Event,
122c2c66affSColin Finck &StatusBlock);
123c2c66affSColin Finck if (Irp == NULL)
124c2c66affSColin Finck {
1255ab1cfc5SPierre Schweitzer Status = STATUS_INSUFFICIENT_RESOURCES;
1265ab1cfc5SPierre Schweitzer break;
127c2c66affSColin Finck }
128c2c66affSColin Finck
1295ab1cfc5SPierre Schweitzer /* Call the driver and wait if appropriate */
1305ab1cfc5SPierre Schweitzer Status = IoCallDriver(DeviceObject, Irp);
131c2c66affSColin Finck if (Status == STATUS_PENDING)
132c2c66affSColin Finck {
133c2c66affSColin Finck KeWaitForSingleObject(&Event,
134c2c66affSColin Finck Executive,
135c2c66affSColin Finck KernelMode,
136c2c66affSColin Finck FALSE,
137c2c66affSColin Finck NULL);
138c2c66affSColin Finck Status = StatusBlock.Status;
139c2c66affSColin Finck }
1405ab1cfc5SPierre Schweitzer /* If buffer is too small, keep looping */
1415ab1cfc5SPierre Schweitzer } while (Status == STATUS_BUFFER_TOO_SMALL);
1425ab1cfc5SPierre Schweitzer
1435ab1cfc5SPierre Schweitzer /* We're done with the device */
1445ab1cfc5SPierre Schweitzer ObDereferenceObject(DeviceObject);
1455ab1cfc5SPierre Schweitzer
1465ab1cfc5SPierre Schweitzer /* If querying worked, then return the buffer to the caller */
1475ab1cfc5SPierre Schweitzer if (NT_SUCCESS(Status))
148c2c66affSColin Finck {
1495ab1cfc5SPierre Schweitzer ASSERT(Buffer != NULL);
1505ab1cfc5SPierre Schweitzer *LayoutInfo = Buffer;
151c2c66affSColin Finck }
1525ab1cfc5SPierre Schweitzer /* Else, release the buffer if still allocated and fail */
153c2c66affSColin Finck else
154c2c66affSColin Finck {
155c2c66affSColin Finck if (Buffer != NULL)
156c2c66affSColin Finck {
1575ab1cfc5SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_FSTUB);
1585ab1cfc5SPierre Schweitzer }
1595ab1cfc5SPierre Schweitzer }
160c2c66affSColin Finck
1615ab1cfc5SPierre Schweitzer return Status;
162c2c66affSColin Finck }
1635ab1cfc5SPierre Schweitzer
1645ab1cfc5SPierre Schweitzer NTSTATUS
HalpQueryPartitionType(IN PUNICODE_STRING DeviceName,IN PDRIVE_LAYOUT_INFORMATION LayoutInfo,OUT PPARTITION_TYPE PartitionType)1655ab1cfc5SPierre Schweitzer HalpQueryPartitionType(IN PUNICODE_STRING DeviceName,
1665ab1cfc5SPierre Schweitzer IN PDRIVE_LAYOUT_INFORMATION LayoutInfo,
1675ab1cfc5SPierre Schweitzer OUT PPARTITION_TYPE PartitionType)
1685ab1cfc5SPierre Schweitzer {
1695ab1cfc5SPierre Schweitzer USHORT i;
1705ab1cfc5SPierre Schweitzer PIRP Irp;
1715ab1cfc5SPierre Schweitzer KEVENT Event;
1725ab1cfc5SPierre Schweitzer NTSTATUS Status;
1735ab1cfc5SPierre Schweitzer PFILE_OBJECT FileObject;
1745ab1cfc5SPierre Schweitzer PDEVICE_OBJECT DeviceObject;
1755ab1cfc5SPierre Schweitzer IO_STATUS_BLOCK IoStatusBlock;
1765ab1cfc5SPierre Schweitzer PARTITION_INFORMATION_EX PartitionInfo;
1775ab1cfc5SPierre Schweitzer
1785ab1cfc5SPierre Schweitzer PAGED_CODE();
1795ab1cfc5SPierre Schweitzer
1805ab1cfc5SPierre Schweitzer /* Get device pointers */
1815ab1cfc5SPierre Schweitzer Status = IoGetDeviceObjectPointer(DeviceName,
1825ab1cfc5SPierre Schweitzer FILE_READ_ATTRIBUTES,
1835ab1cfc5SPierre Schweitzer &FileObject,
1845ab1cfc5SPierre Schweitzer &DeviceObject);
1855ab1cfc5SPierre Schweitzer if (!NT_SUCCESS(Status))
1865ab1cfc5SPierre Schweitzer {
1875ab1cfc5SPierre Schweitzer return Status;
1885ab1cfc5SPierre Schweitzer }
1895ab1cfc5SPierre Schweitzer
1905ab1cfc5SPierre Schweitzer /* Get attached device object */
1915ab1cfc5SPierre Schweitzer DeviceObject = IoGetAttachedDeviceReference(FileObject->DeviceObject);
1925ab1cfc5SPierre Schweitzer ObDereferenceObject(FileObject);
1935ab1cfc5SPierre Schweitzer
1945ab1cfc5SPierre Schweitzer /* Assume logical partition for removable devices */
1955ab1cfc5SPierre Schweitzer if (BooleanFlagOn(DeviceObject->Characteristics, FILE_REMOVABLE_MEDIA))
1965ab1cfc5SPierre Schweitzer {
1975ab1cfc5SPierre Schweitzer ObDereferenceObject(DeviceObject);
1985ab1cfc5SPierre Schweitzer *PartitionType = LogicalPartition;
1995ab1cfc5SPierre Schweitzer return STATUS_SUCCESS;
2005ab1cfc5SPierre Schweitzer }
2015ab1cfc5SPierre Schweitzer
2025ab1cfc5SPierre Schweitzer /* For the others, query partition info */
2035ab1cfc5SPierre Schweitzer KeInitializeEvent(&Event, NotificationEvent, FALSE);
2045ab1cfc5SPierre Schweitzer Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO_EX,
2055ab1cfc5SPierre Schweitzer DeviceObject,
2065ab1cfc5SPierre Schweitzer NULL,
2075ab1cfc5SPierre Schweitzer 0,
2085ab1cfc5SPierre Schweitzer &PartitionInfo,
2095ab1cfc5SPierre Schweitzer sizeof(PartitionInfo),
2105ab1cfc5SPierre Schweitzer FALSE,
2115ab1cfc5SPierre Schweitzer &Event,
2125ab1cfc5SPierre Schweitzer &IoStatusBlock);
2135ab1cfc5SPierre Schweitzer if (Irp == NULL)
2145ab1cfc5SPierre Schweitzer {
2155ab1cfc5SPierre Schweitzer ObDereferenceObject(DeviceObject);
2165ab1cfc5SPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES;
2175ab1cfc5SPierre Schweitzer }
2185ab1cfc5SPierre Schweitzer
2195ab1cfc5SPierre Schweitzer Status = IoCallDriver(DeviceObject, Irp);
2205ab1cfc5SPierre Schweitzer if (Status == STATUS_PENDING)
2215ab1cfc5SPierre Schweitzer {
2225ab1cfc5SPierre Schweitzer KeWaitForSingleObject(&Event,
2235ab1cfc5SPierre Schweitzer Executive,
2245ab1cfc5SPierre Schweitzer KernelMode,
2255ab1cfc5SPierre Schweitzer FALSE,
2265ab1cfc5SPierre Schweitzer NULL);
2275ab1cfc5SPierre Schweitzer Status = IoStatusBlock.Status;
2285ab1cfc5SPierre Schweitzer }
2295ab1cfc5SPierre Schweitzer
2305ab1cfc5SPierre Schweitzer /* We're done with the device */
2315ab1cfc5SPierre Schweitzer ObDereferenceObject(DeviceObject);
2325ab1cfc5SPierre Schweitzer
2335ab1cfc5SPierre Schweitzer /* If we failed querying partition info, try to return something
2345ab1cfc5SPierre Schweitzer * if caller didn't provide a precise layout, assume logical
2355ab1cfc5SPierre Schweitzer * partition and fake success. Otherwise, just fail.
2365ab1cfc5SPierre Schweitzer */
2375ab1cfc5SPierre Schweitzer if (!NT_SUCCESS(Status))
2385ab1cfc5SPierre Schweitzer {
2395ab1cfc5SPierre Schweitzer if (LayoutInfo == NULL)
2405ab1cfc5SPierre Schweitzer {
2415ab1cfc5SPierre Schweitzer *PartitionType = LogicalPartition;
2425ab1cfc5SPierre Schweitzer return STATUS_SUCCESS;
2435ab1cfc5SPierre Schweitzer }
2445ab1cfc5SPierre Schweitzer
2455ab1cfc5SPierre Schweitzer return Status;
2465ab1cfc5SPierre Schweitzer }
2475ab1cfc5SPierre Schweitzer
2485ab1cfc5SPierre Schweitzer /* First, handle non MBR style (easy cases) */
2495ab1cfc5SPierre Schweitzer if (PartitionInfo.PartitionStyle != PARTITION_STYLE_MBR)
2505ab1cfc5SPierre Schweitzer {
2515ab1cfc5SPierre Schweitzer /* If not GPT, we don't know what it is */
2525ab1cfc5SPierre Schweitzer if (PartitionInfo.PartitionStyle != PARTITION_STYLE_GPT)
2535ab1cfc5SPierre Schweitzer {
2545ab1cfc5SPierre Schweitzer *PartitionType = UnknownPartition;
2555ab1cfc5SPierre Schweitzer return STATUS_SUCCESS;
2565ab1cfc5SPierre Schweitzer }
2575ab1cfc5SPierre Schweitzer
2585ab1cfc5SPierre Schweitzer /* Check whether that's data partition */
2595ab1cfc5SPierre Schweitzer if (RtlCompareMemory(&PartitionInfo.Gpt.PartitionType,
2605ab1cfc5SPierre Schweitzer &PARTITION_BASIC_DATA_GUID,
2615ab1cfc5SPierre Schweitzer sizeof(GUID)) == sizeof(GUID))
2625ab1cfc5SPierre Schweitzer {
2635ab1cfc5SPierre Schweitzer *PartitionType = DataPartition;
2645ab1cfc5SPierre Schweitzer return STATUS_SUCCESS;
2655ab1cfc5SPierre Schweitzer }
2665ab1cfc5SPierre Schweitzer
2675ab1cfc5SPierre Schweitzer /* Otherwise, we don't know */
2685ab1cfc5SPierre Schweitzer *PartitionType = UnknownPartition;
2695ab1cfc5SPierre Schweitzer return STATUS_SUCCESS;
2705ab1cfc5SPierre Schweitzer }
2715ab1cfc5SPierre Schweitzer
2725ab1cfc5SPierre Schweitzer /* If we don't recognize partition type, return unknown */
2735ab1cfc5SPierre Schweitzer if (!IsRecognizedPartition(PartitionInfo.Mbr.PartitionType))
2745ab1cfc5SPierre Schweitzer {
2755ab1cfc5SPierre Schweitzer *PartitionType = UnknownPartition;
2765ab1cfc5SPierre Schweitzer return STATUS_SUCCESS;
2775ab1cfc5SPierre Schweitzer }
2785ab1cfc5SPierre Schweitzer
2795ab1cfc5SPierre Schweitzer /* Check if that's a FT volume */
280324285f0SPierre Schweitzer if (IsFTPartition(PartitionInfo.Mbr.PartitionType))
2815ab1cfc5SPierre Schweitzer {
2825ab1cfc5SPierre Schweitzer *PartitionType = FtPartition;
2835ab1cfc5SPierre Schweitzer return STATUS_SUCCESS;
2845ab1cfc5SPierre Schweitzer }
2855ab1cfc5SPierre Schweitzer
2865ab1cfc5SPierre Schweitzer /* If the caller didn't provide the complete layout, just return */
2875ab1cfc5SPierre Schweitzer if (LayoutInfo == NULL)
2885ab1cfc5SPierre Schweitzer {
2895ab1cfc5SPierre Schweitzer *PartitionType = LogicalPartition;
2905ab1cfc5SPierre Schweitzer return STATUS_SUCCESS;
2915ab1cfc5SPierre Schweitzer }
2925ab1cfc5SPierre Schweitzer
2935ab1cfc5SPierre Schweitzer /* Now, evaluate the partition to the 4 in the input layout */
2945ab1cfc5SPierre Schweitzer for (i = 0; i < 4; ++i)
2955ab1cfc5SPierre Schweitzer {
2965ab1cfc5SPierre Schweitzer /* If we find a partition matching */
2975ab1cfc5SPierre Schweitzer if (LayoutInfo->PartitionEntry[i].StartingOffset.QuadPart == PartitionInfo.StartingOffset.QuadPart)
2985ab1cfc5SPierre Schweitzer {
2995ab1cfc5SPierre Schweitzer /* Return boot if boot flag is set */
3005ab1cfc5SPierre Schweitzer if (PartitionInfo.Mbr.BootIndicator)
3015ab1cfc5SPierre Schweitzer {
3025ab1cfc5SPierre Schweitzer *PartitionType = BootablePartition;
3035ab1cfc5SPierre Schweitzer }
3045ab1cfc5SPierre Schweitzer /* Primary otherwise */
305c2c66affSColin Finck else
306c2c66affSColin Finck {
3075ab1cfc5SPierre Schweitzer *PartitionType = PrimaryPartition;
3085ab1cfc5SPierre Schweitzer }
3095ab1cfc5SPierre Schweitzer
3105ab1cfc5SPierre Schweitzer return STATUS_SUCCESS;
3115ab1cfc5SPierre Schweitzer }
3125ab1cfc5SPierre Schweitzer }
3135ab1cfc5SPierre Schweitzer
3145ab1cfc5SPierre Schweitzer /* Otherwise, assume logical */
3155ab1cfc5SPierre Schweitzer *PartitionType = LogicalPartition;
3165ab1cfc5SPierre Schweitzer return STATUS_SUCCESS;
3175ab1cfc5SPierre Schweitzer }
3185ab1cfc5SPierre Schweitzer
3195ab1cfc5SPierre Schweitzer PULONG
IopComputeHarddiskDerangements(IN ULONG DiskCount)3205ab1cfc5SPierre Schweitzer IopComputeHarddiskDerangements(IN ULONG DiskCount)
3215ab1cfc5SPierre Schweitzer {
3225ab1cfc5SPierre Schweitzer PIRP Irp;
3235ab1cfc5SPierre Schweitzer KEVENT Event;
3245ab1cfc5SPierre Schweitzer ULONG i, j, k;
3255ab1cfc5SPierre Schweitzer PULONG Devices;
3265ab1cfc5SPierre Schweitzer NTSTATUS Status;
3275ab1cfc5SPierre Schweitzer WCHAR Buffer[100];
3285ab1cfc5SPierre Schweitzer UNICODE_STRING ArcName;
3295ab1cfc5SPierre Schweitzer PFILE_OBJECT FileObject;
3305ab1cfc5SPierre Schweitzer PDEVICE_OBJECT DeviceObject;
3315ab1cfc5SPierre Schweitzer IO_STATUS_BLOCK IoStatusBlock;
3325ab1cfc5SPierre Schweitzer STORAGE_DEVICE_NUMBER DeviceNumber;
3335ab1cfc5SPierre Schweitzer
3345ab1cfc5SPierre Schweitzer /* No disks, nothing to do */
3355ab1cfc5SPierre Schweitzer if (DiskCount == 0)
3365ab1cfc5SPierre Schweitzer {
3375ab1cfc5SPierre Schweitzer return NULL;
3385ab1cfc5SPierre Schweitzer }
3395ab1cfc5SPierre Schweitzer
3405ab1cfc5SPierre Schweitzer /* Allocate a buffer big enough to hold all the disks */
3415ab1cfc5SPierre Schweitzer Devices = ExAllocatePoolWithTag(PagedPool | POOL_COLD_ALLOCATION,
3425ab1cfc5SPierre Schweitzer sizeof(ULONG) * DiskCount,
3435ab1cfc5SPierre Schweitzer TAG_FSTUB);
3445ab1cfc5SPierre Schweitzer if (Devices == NULL)
3455ab1cfc5SPierre Schweitzer {
3465ab1cfc5SPierre Schweitzer return NULL;
3475ab1cfc5SPierre Schweitzer }
3485ab1cfc5SPierre Schweitzer
3495ab1cfc5SPierre Schweitzer /* Now, we'll query all the disks */
3505ab1cfc5SPierre Schweitzer for (i = 0; i < DiskCount; ++i)
3515ab1cfc5SPierre Schweitzer {
3525ab1cfc5SPierre Schweitzer /* Using their ARC name */
3535ab1cfc5SPierre Schweitzer swprintf(Buffer, L"\\ArcName\\multi(0)disk(0)rdisk(%d)", i);
3545ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&ArcName, Buffer);
3555ab1cfc5SPierre Schweitzer /* Get the attached DeviceObject */
3565ab1cfc5SPierre Schweitzer if (NT_SUCCESS(IoGetDeviceObjectPointer(&ArcName, FILE_READ_ATTRIBUTES, &FileObject, &DeviceObject)))
3575ab1cfc5SPierre Schweitzer {
3585ab1cfc5SPierre Schweitzer DeviceObject = IoGetAttachedDeviceReference(FileObject->DeviceObject);
3595ab1cfc5SPierre Schweitzer ObDereferenceObject(FileObject);
3605ab1cfc5SPierre Schweitzer
3615ab1cfc5SPierre Schweitzer /* And query it for device number */
3625ab1cfc5SPierre Schweitzer KeInitializeEvent(&Event, NotificationEvent, FALSE);
3635ab1cfc5SPierre Schweitzer Irp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_DEVICE_NUMBER,
3645ab1cfc5SPierre Schweitzer DeviceObject,
3655ab1cfc5SPierre Schweitzer NULL,
3665ab1cfc5SPierre Schweitzer 0,
3675ab1cfc5SPierre Schweitzer &DeviceNumber,
3685ab1cfc5SPierre Schweitzer sizeof(DeviceNumber),
3695ab1cfc5SPierre Schweitzer FALSE,
3705ab1cfc5SPierre Schweitzer &Event,
3715ab1cfc5SPierre Schweitzer &IoStatusBlock);
3725ab1cfc5SPierre Schweitzer if (Irp != NULL)
3735ab1cfc5SPierre Schweitzer {
3745ab1cfc5SPierre Schweitzer Status = IoCallDriver(DeviceObject, Irp);
3755ab1cfc5SPierre Schweitzer if (Status == STATUS_PENDING)
3765ab1cfc5SPierre Schweitzer {
3775ab1cfc5SPierre Schweitzer KeWaitForSingleObject(&Event,
3785ab1cfc5SPierre Schweitzer Executive,
3795ab1cfc5SPierre Schweitzer KernelMode,
3805ab1cfc5SPierre Schweitzer FALSE,
3815ab1cfc5SPierre Schweitzer NULL);
3825ab1cfc5SPierre Schweitzer Status = IoStatusBlock.Status;
3835ab1cfc5SPierre Schweitzer }
3845ab1cfc5SPierre Schweitzer
3855ab1cfc5SPierre Schweitzer ObDereferenceObject(DeviceObject);
3865ab1cfc5SPierre Schweitzer
3875ab1cfc5SPierre Schweitzer /* In case of a success remember device number */
3885ab1cfc5SPierre Schweitzer if (NT_SUCCESS(Status))
3895ab1cfc5SPierre Schweitzer {
3905ab1cfc5SPierre Schweitzer Devices[i] = DeviceNumber.DeviceNumber;
3915ab1cfc5SPierre Schweitzer /* Move on, not to fall into our default case */
3925ab1cfc5SPierre Schweitzer continue;
393c2c66affSColin Finck }
394c2c66affSColin Finck }
395c2c66affSColin Finck else
396c2c66affSColin Finck {
3975ab1cfc5SPierre Schweitzer ObDereferenceObject(DeviceObject);
3985ab1cfc5SPierre Schweitzer }
3995ab1cfc5SPierre Schweitzer
4005ab1cfc5SPierre Schweitzer /* Default case, for failures, set -1 */
4015ab1cfc5SPierre Schweitzer Devices[i] = -1;
4025ab1cfc5SPierre Schweitzer }
4035ab1cfc5SPierre Schweitzer }
4045ab1cfc5SPierre Schweitzer
4055ab1cfc5SPierre Schweitzer /* Now, we'll check all device numbers */
4065ab1cfc5SPierre Schweitzer for (i = 0; i < DiskCount; ++i)
4075ab1cfc5SPierre Schweitzer {
4085ab1cfc5SPierre Schweitzer /* First of all, check if we're at the right place */
4095ab1cfc5SPierre Schweitzer for (j = 0; j < DiskCount; ++j)
4105ab1cfc5SPierre Schweitzer {
4115ab1cfc5SPierre Schweitzer if (Devices[j] == i)
4125ab1cfc5SPierre Schweitzer {
4135ab1cfc5SPierre Schweitzer break;
4145ab1cfc5SPierre Schweitzer }
4155ab1cfc5SPierre Schweitzer }
4165ab1cfc5SPierre Schweitzer
4175ab1cfc5SPierre Schweitzer /* If not, perform the change */
4185ab1cfc5SPierre Schweitzer if (j >= DiskCount)
4195ab1cfc5SPierre Schweitzer {
4205ab1cfc5SPierre Schweitzer k = 0;
4215ab1cfc5SPierre Schweitzer while (Devices[k] != -1)
4225ab1cfc5SPierre Schweitzer {
4235ab1cfc5SPierre Schweitzer if (++k >= DiskCount)
4245ab1cfc5SPierre Schweitzer {
4255ab1cfc5SPierre Schweitzer break;
4265ab1cfc5SPierre Schweitzer }
4275ab1cfc5SPierre Schweitzer }
4285ab1cfc5SPierre Schweitzer
4295ab1cfc5SPierre Schweitzer if (k < DiskCount)
4305ab1cfc5SPierre Schweitzer {
4315ab1cfc5SPierre Schweitzer Devices[k] = i;
4325ab1cfc5SPierre Schweitzer }
4335ab1cfc5SPierre Schweitzer }
4345ab1cfc5SPierre Schweitzer }
4355ab1cfc5SPierre Schweitzer
4365ab1cfc5SPierre Schweitzer /* Return our device derangement map */
4375ab1cfc5SPierre Schweitzer return Devices;
4385ab1cfc5SPierre Schweitzer }
4395ab1cfc5SPierre Schweitzer
4405ab1cfc5SPierre Schweitzer NTSTATUS
HalpNextMountLetter(IN PUNICODE_STRING DeviceName,OUT PUCHAR DriveLetter)4415ab1cfc5SPierre Schweitzer HalpNextMountLetter(IN PUNICODE_STRING DeviceName,
4425ab1cfc5SPierre Schweitzer OUT PUCHAR DriveLetter)
4435ab1cfc5SPierre Schweitzer {
4445ab1cfc5SPierre Schweitzer PIRP Irp;
4455ab1cfc5SPierre Schweitzer KEVENT Event;
4465ab1cfc5SPierre Schweitzer NTSTATUS Status;
4475ab1cfc5SPierre Schweitzer UNICODE_STRING MountMgr;
4485ab1cfc5SPierre Schweitzer PFILE_OBJECT FileObject;
4495ab1cfc5SPierre Schweitzer PDEVICE_OBJECT DeviceObject;
4505ab1cfc5SPierre Schweitzer IO_STATUS_BLOCK IoStatusBlock;
4515ab1cfc5SPierre Schweitzer PMOUNTMGR_DRIVE_LETTER_TARGET Target;
4525ab1cfc5SPierre Schweitzer MOUNTMGR_DRIVE_LETTER_INFORMATION LetterInfo;
4535ab1cfc5SPierre Schweitzer
4545ab1cfc5SPierre Schweitzer /* To get next mount letter, we need the MountMgr */
4555ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&MountMgr, L"\\Device\\MountPointManager");
4565ab1cfc5SPierre Schweitzer Status = IoGetDeviceObjectPointer(&MountMgr,
4575ab1cfc5SPierre Schweitzer FILE_READ_ATTRIBUTES,
4585ab1cfc5SPierre Schweitzer &FileObject,
4595ab1cfc5SPierre Schweitzer &DeviceObject);
4605ab1cfc5SPierre Schweitzer if (!NT_SUCCESS(Status))
4615ab1cfc5SPierre Schweitzer {
4625ab1cfc5SPierre Schweitzer return Status;
4635ab1cfc5SPierre Schweitzer }
4645ab1cfc5SPierre Schweitzer
4655ab1cfc5SPierre Schweitzer /* Allocate our input buffer */
4665ab1cfc5SPierre Schweitzer Target = ExAllocatePoolWithTag(PagedPool,
4675ab1cfc5SPierre Schweitzer DeviceName->Length + FIELD_OFFSET(MOUNTMGR_DRIVE_LETTER_TARGET, DeviceName),
4685ab1cfc5SPierre Schweitzer TAG_FSTUB);
4695ab1cfc5SPierre Schweitzer if (Target == NULL)
4705ab1cfc5SPierre Schweitzer {
4715ab1cfc5SPierre Schweitzer ObDereferenceObject(FileObject);
4725ab1cfc5SPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES;
4735ab1cfc5SPierre Schweitzer }
4745ab1cfc5SPierre Schweitzer
4755ab1cfc5SPierre Schweitzer /* And fill it with the device hat needs a drive letter */
4765ab1cfc5SPierre Schweitzer Target->DeviceNameLength = DeviceName->Length;
4775ab1cfc5SPierre Schweitzer RtlCopyMemory(&Target->DeviceName[0], DeviceName->Buffer, DeviceName->Length);
4785ab1cfc5SPierre Schweitzer
4795ab1cfc5SPierre Schweitzer /* Call the mount manager */
4805ab1cfc5SPierre Schweitzer KeInitializeEvent(&Event, NotificationEvent, FALSE);
4815ab1cfc5SPierre Schweitzer Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER,
4825ab1cfc5SPierre Schweitzer DeviceObject,
4835ab1cfc5SPierre Schweitzer Target,
4845ab1cfc5SPierre Schweitzer DeviceName->Length + FIELD_OFFSET(MOUNTMGR_DRIVE_LETTER_TARGET, DeviceName),
4855ab1cfc5SPierre Schweitzer &LetterInfo,
4865ab1cfc5SPierre Schweitzer sizeof(LetterInfo),
4875ab1cfc5SPierre Schweitzer FALSE,
4885ab1cfc5SPierre Schweitzer &Event,
4895ab1cfc5SPierre Schweitzer &IoStatusBlock);
4905ab1cfc5SPierre Schweitzer if (Irp == NULL)
4915ab1cfc5SPierre Schweitzer {
4925ab1cfc5SPierre Schweitzer ExFreePoolWithTag(Target, TAG_FSTUB);
4935ab1cfc5SPierre Schweitzer ObDereferenceObject(FileObject);
4945ab1cfc5SPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES;
4955ab1cfc5SPierre Schweitzer }
4965ab1cfc5SPierre Schweitzer
4975ab1cfc5SPierre Schweitzer Status = IoCallDriver(DeviceObject, Irp);
4985ab1cfc5SPierre Schweitzer if (Status == STATUS_PENDING)
4995ab1cfc5SPierre Schweitzer {
5005ab1cfc5SPierre Schweitzer KeWaitForSingleObject(&Event,
5015ab1cfc5SPierre Schweitzer Executive,
5025ab1cfc5SPierre Schweitzer KernelMode,
5035ab1cfc5SPierre Schweitzer FALSE,
5045ab1cfc5SPierre Schweitzer NULL);
5055ab1cfc5SPierre Schweitzer Status = IoStatusBlock.Status;
5065ab1cfc5SPierre Schweitzer }
5075ab1cfc5SPierre Schweitzer
5085ab1cfc5SPierre Schweitzer ExFreePoolWithTag(Target, TAG_FSTUB);
5095ab1cfc5SPierre Schweitzer ObDereferenceObject(FileObject);
5105ab1cfc5SPierre Schweitzer
5115ab1cfc5SPierre Schweitzer DPRINT("Done: %d %c\n", LetterInfo.DriveLetterWasAssigned,
5125ab1cfc5SPierre Schweitzer LetterInfo.CurrentDriveLetter);
5135ab1cfc5SPierre Schweitzer
5145ab1cfc5SPierre Schweitzer /* Return the drive letter the MountMgr potentially assigned */
5155ab1cfc5SPierre Schweitzer *DriveLetter = LetterInfo.CurrentDriveLetter;
5165ab1cfc5SPierre Schweitzer
5175ab1cfc5SPierre Schweitzer /* Also return the success */
5185ab1cfc5SPierre Schweitzer return Status;
5195ab1cfc5SPierre Schweitzer }
5205ab1cfc5SPierre Schweitzer
5215ab1cfc5SPierre Schweitzer NTSTATUS
HalpSetMountLetter(IN PUNICODE_STRING DeviceName,UCHAR DriveLetter)5225ab1cfc5SPierre Schweitzer HalpSetMountLetter(IN PUNICODE_STRING DeviceName,
5235ab1cfc5SPierre Schweitzer UCHAR DriveLetter)
5245ab1cfc5SPierre Schweitzer {
5255ab1cfc5SPierre Schweitzer PIRP Irp;
5265ab1cfc5SPierre Schweitzer KEVENT Event;
5275ab1cfc5SPierre Schweitzer NTSTATUS Status;
5285ab1cfc5SPierre Schweitzer WCHAR Buffer[30];
5295ab1cfc5SPierre Schweitzer ULONG InputBufferLength;
5305ab1cfc5SPierre Schweitzer PFILE_OBJECT FileObject;
5315ab1cfc5SPierre Schweitzer PDEVICE_OBJECT DeviceObject;
5325ab1cfc5SPierre Schweitzer IO_STATUS_BLOCK IoStatusBlock;
5335ab1cfc5SPierre Schweitzer UNICODE_STRING DosDevice, MountMgr;
5345ab1cfc5SPierre Schweitzer PMOUNTMGR_CREATE_POINT_INPUT InputBuffer;
5355ab1cfc5SPierre Schweitzer
5365ab1cfc5SPierre Schweitzer /* Setup the DosDevice name */
5375ab1cfc5SPierre Schweitzer swprintf(Buffer, L"\\DosDevices\\%c:", DriveLetter);
5385ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&DosDevice, Buffer);
5395ab1cfc5SPierre Schweitzer
5405ab1cfc5SPierre Schweitzer /* Allocate the input buffer for the MountMgr */
5415ab1cfc5SPierre Schweitzer InputBufferLength = DosDevice.Length + DeviceName->Length + sizeof(MOUNTMGR_CREATE_POINT_INPUT);
5425ab1cfc5SPierre Schweitzer InputBuffer = ExAllocatePoolWithTag(PagedPool, InputBufferLength, TAG_FSTUB);
5435ab1cfc5SPierre Schweitzer if (InputBuffer == NULL)
5445ab1cfc5SPierre Schweitzer {
5455ab1cfc5SPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES;
5465ab1cfc5SPierre Schweitzer }
5475ab1cfc5SPierre Schweitzer
5485ab1cfc5SPierre Schweitzer /* Fill the input buffer */
5495ab1cfc5SPierre Schweitzer InputBuffer->SymbolicLinkNameOffset = sizeof(MOUNTMGR_CREATE_POINT_INPUT);
5505ab1cfc5SPierre Schweitzer InputBuffer->SymbolicLinkNameLength = DosDevice.Length;
5515ab1cfc5SPierre Schweitzer InputBuffer->DeviceNameOffset = DosDevice.Length + sizeof(MOUNTMGR_CREATE_POINT_INPUT);
5525ab1cfc5SPierre Schweitzer InputBuffer->DeviceNameLength = DeviceName->Length;
5535ab1cfc5SPierre Schweitzer RtlCopyMemory(&InputBuffer[1], DosDevice.Buffer, DosDevice.Length);
5545ab1cfc5SPierre Schweitzer RtlCopyMemory((PVOID)((ULONG_PTR)InputBuffer + InputBuffer->DeviceNameOffset),
5555ab1cfc5SPierre Schweitzer DeviceName->Buffer,
5565ab1cfc5SPierre Schweitzer DeviceName->Length);
5575ab1cfc5SPierre Schweitzer
5585ab1cfc5SPierre Schweitzer /* Get the MountMgr device pointer, to send the IOCTL */
5595ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&MountMgr, L"\\Device\\MountPointManager");
5605ab1cfc5SPierre Schweitzer Status = IoGetDeviceObjectPointer(&MountMgr,
5615ab1cfc5SPierre Schweitzer FILE_READ_ATTRIBUTES,
5625ab1cfc5SPierre Schweitzer &FileObject,
5635ab1cfc5SPierre Schweitzer &DeviceObject);
5645ab1cfc5SPierre Schweitzer if (!NT_SUCCESS(Status))
5655ab1cfc5SPierre Schweitzer {
5665ab1cfc5SPierre Schweitzer ExFreePoolWithTag(InputBuffer, TAG_FSTUB);
5675ab1cfc5SPierre Schweitzer return Status;
5685ab1cfc5SPierre Schweitzer }
5695ab1cfc5SPierre Schweitzer
5705ab1cfc5SPierre Schweitzer /* Call the MountMgr */
5715ab1cfc5SPierre Schweitzer KeInitializeEvent(&Event, NotificationEvent, FALSE);
5725ab1cfc5SPierre Schweitzer Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_CREATE_POINT,
5735ab1cfc5SPierre Schweitzer DeviceObject,
5745ab1cfc5SPierre Schweitzer InputBuffer,
5755ab1cfc5SPierre Schweitzer InputBufferLength,
5765ab1cfc5SPierre Schweitzer NULL,
5775ab1cfc5SPierre Schweitzer 0,
5785ab1cfc5SPierre Schweitzer FALSE,
5795ab1cfc5SPierre Schweitzer &Event,
5805ab1cfc5SPierre Schweitzer &IoStatusBlock);
5815ab1cfc5SPierre Schweitzer if (Irp == NULL)
5825ab1cfc5SPierre Schweitzer {
5835ab1cfc5SPierre Schweitzer ObDereferenceObject(FileObject);
5845ab1cfc5SPierre Schweitzer ExFreePoolWithTag(InputBuffer, TAG_FSTUB);
5855ab1cfc5SPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES;
5865ab1cfc5SPierre Schweitzer }
5875ab1cfc5SPierre Schweitzer
5885ab1cfc5SPierre Schweitzer Status = IoCallDriver(DeviceObject, Irp);
5895ab1cfc5SPierre Schweitzer if (Status == STATUS_PENDING)
5905ab1cfc5SPierre Schweitzer {
5915ab1cfc5SPierre Schweitzer KeWaitForSingleObject(&Event,
5925ab1cfc5SPierre Schweitzer Executive,
5935ab1cfc5SPierre Schweitzer KernelMode,
5945ab1cfc5SPierre Schweitzer FALSE,
5955ab1cfc5SPierre Schweitzer NULL);
5965ab1cfc5SPierre Schweitzer Status = IoStatusBlock.Status;
5975ab1cfc5SPierre Schweitzer }
5985ab1cfc5SPierre Schweitzer
5995ab1cfc5SPierre Schweitzer ObDereferenceObject(FileObject);
6005ab1cfc5SPierre Schweitzer ExFreePoolWithTag(InputBuffer, TAG_FSTUB);
6015ab1cfc5SPierre Schweitzer
6025ab1cfc5SPierre Schweitzer /* Return the MountMgr status */
6035ab1cfc5SPierre Schweitzer return Status;
6045ab1cfc5SPierre Schweitzer }
6055ab1cfc5SPierre Schweitzer
6065ab1cfc5SPierre Schweitzer UCHAR
HalpNextDriveLetter(IN PUNICODE_STRING DeviceName,IN PSTRING NtDeviceName,OUT PUCHAR NtSystemPath,BOOLEAN IsRemovable)6075ab1cfc5SPierre Schweitzer HalpNextDriveLetter(IN PUNICODE_STRING DeviceName,
6085ab1cfc5SPierre Schweitzer IN PSTRING NtDeviceName,
6095ab1cfc5SPierre Schweitzer OUT PUCHAR NtSystemPath,
6105ab1cfc5SPierre Schweitzer BOOLEAN IsRemovable)
6115ab1cfc5SPierre Schweitzer {
6125ab1cfc5SPierre Schweitzer UCHAR i;
6135ab1cfc5SPierre Schweitzer WCHAR Buffer[40];
6145ab1cfc5SPierre Schweitzer UCHAR DriveLetter;
6155ab1cfc5SPierre Schweitzer UNICODE_STRING FloppyString, CdString, NtDeviceNameU, DosDevice;
6165ab1cfc5SPierre Schweitzer
6175ab1cfc5SPierre Schweitzer /* Quick path, ask directly the mount manager to assign the next
6185ab1cfc5SPierre Schweitzer * free drive letter
6195ab1cfc5SPierre Schweitzer */
6205ab1cfc5SPierre Schweitzer if (NT_SUCCESS(HalpNextMountLetter(DeviceName, &DriveLetter)))
6215ab1cfc5SPierre Schweitzer {
6225ab1cfc5SPierre Schweitzer return DriveLetter;
6235ab1cfc5SPierre Schweitzer }
6245ab1cfc5SPierre Schweitzer
6255ab1cfc5SPierre Schweitzer /* We'll allow MountMgr to fail only for non vital path */
6265ab1cfc5SPierre Schweitzer if (NtDeviceName == NULL || NtSystemPath == NULL)
6275ab1cfc5SPierre Schweitzer {
6285ab1cfc5SPierre Schweitzer return -1;
6295ab1cfc5SPierre Schweitzer }
6305ab1cfc5SPierre Schweitzer
6315ab1cfc5SPierre Schweitzer /* And for removable devices */
6325ab1cfc5SPierre Schweitzer if (!IsRemovable)
6335ab1cfc5SPierre Schweitzer {
6345ab1cfc5SPierre Schweitzer return 0;
6355ab1cfc5SPierre Schweitzer }
6365ab1cfc5SPierre Schweitzer
6375ab1cfc5SPierre Schweitzer /* Removable might be floppy or cdrom */
6385ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&FloppyString, L"\\Device\\Floppy");
6395ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&CdString, L"\\Device\\CdRom");
6405ab1cfc5SPierre Schweitzer
6415ab1cfc5SPierre Schweitzer /* If floppy, start at A */
6425ab1cfc5SPierre Schweitzer if (RtlPrefixUnicodeString(&FloppyString, DeviceName, TRUE))
6435ab1cfc5SPierre Schweitzer {
6445ab1cfc5SPierre Schweitzer DriveLetter = 'A';
6455ab1cfc5SPierre Schweitzer }
6465ab1cfc5SPierre Schweitzer /* If CD start C */
6475ab1cfc5SPierre Schweitzer else if (RtlPrefixUnicodeString(&CdString, DeviceName, TRUE))
6485ab1cfc5SPierre Schweitzer {
6495ab1cfc5SPierre Schweitzer DriveLetter = 'D';
6505ab1cfc5SPierre Schweitzer }
6515ab1cfc5SPierre Schweitzer /* For the rest start at C */
6525ab1cfc5SPierre Schweitzer else
6535ab1cfc5SPierre Schweitzer {
6545ab1cfc5SPierre Schweitzer DriveLetter = 'C';
6555ab1cfc5SPierre Schweitzer }
6565ab1cfc5SPierre Schweitzer
6575ab1cfc5SPierre Schweitzer /* Now, try to assign a drive letter manually with the MountMgr */
6585ab1cfc5SPierre Schweitzer for (i = DriveLetter; i <= 'Z'; ++i)
6595ab1cfc5SPierre Schweitzer {
6605ab1cfc5SPierre Schweitzer if (NT_SUCCESS(HalpSetMountLetter(DeviceName, i)))
6615ab1cfc5SPierre Schweitzer {
6625ab1cfc5SPierre Schweitzer /* If it worked, if we were managing system path, update manually */
6635ab1cfc5SPierre Schweitzer if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&NtDeviceNameU, NtDeviceName, TRUE)))
6645ab1cfc5SPierre Schweitzer {
6655ab1cfc5SPierre Schweitzer if (RtlEqualUnicodeString(&NtDeviceNameU, DeviceName, TRUE))
6665ab1cfc5SPierre Schweitzer {
6675ab1cfc5SPierre Schweitzer *NtSystemPath = i;
6685ab1cfc5SPierre Schweitzer }
6695ab1cfc5SPierre Schweitzer
6705ab1cfc5SPierre Schweitzer RtlFreeUnicodeString(&NtDeviceNameU);
6715ab1cfc5SPierre Schweitzer }
6725ab1cfc5SPierre Schweitzer
6735ab1cfc5SPierre Schweitzer return i;
6745ab1cfc5SPierre Schweitzer }
6755ab1cfc5SPierre Schweitzer }
6765ab1cfc5SPierre Schweitzer
6775ab1cfc5SPierre Schweitzer /* Last fall back, we're not on a PnP device... */
6785ab1cfc5SPierre Schweitzer for (i = DriveLetter; i <= 'Z'; ++i)
6795ab1cfc5SPierre Schweitzer {
6805ab1cfc5SPierre Schweitzer /* We'll link manually, without MountMgr knowing anything about the device */
6815ab1cfc5SPierre Schweitzer swprintf(Buffer, L"\\DosDevices\\%c:", i);
6825ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&DosDevice, Buffer);
6835ab1cfc5SPierre Schweitzer
6845ab1cfc5SPierre Schweitzer /* If linking worked, then the letter was free ;-) */
6855ab1cfc5SPierre Schweitzer if (NT_SUCCESS(IoCreateSymbolicLink(&DosDevice, DeviceName)))
6865ab1cfc5SPierre Schweitzer {
6875ab1cfc5SPierre Schweitzer /* If it worked, if we were managing system path, update manually */
6885ab1cfc5SPierre Schweitzer if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&NtDeviceNameU, NtDeviceName, TRUE)))
6895ab1cfc5SPierre Schweitzer {
6905ab1cfc5SPierre Schweitzer if (RtlEqualUnicodeString(&NtDeviceNameU, DeviceName, TRUE))
6915ab1cfc5SPierre Schweitzer {
6925ab1cfc5SPierre Schweitzer *NtSystemPath = i;
6935ab1cfc5SPierre Schweitzer }
6945ab1cfc5SPierre Schweitzer
6955ab1cfc5SPierre Schweitzer RtlFreeUnicodeString(&NtDeviceNameU);
6965ab1cfc5SPierre Schweitzer }
6975ab1cfc5SPierre Schweitzer
6985ab1cfc5SPierre Schweitzer return i;
6995ab1cfc5SPierre Schweitzer }
7005ab1cfc5SPierre Schweitzer }
7015ab1cfc5SPierre Schweitzer
7025ab1cfc5SPierre Schweitzer /* We're done, nothing happened */
7035ab1cfc5SPierre Schweitzer return 0;
7045ab1cfc5SPierre Schweitzer }
7055ab1cfc5SPierre Schweitzer
7065ab1cfc5SPierre Schweitzer BOOLEAN
HalpIsOldStyleFloppy(PUNICODE_STRING DeviceName)7075ab1cfc5SPierre Schweitzer HalpIsOldStyleFloppy(PUNICODE_STRING DeviceName)
7085ab1cfc5SPierre Schweitzer {
7095ab1cfc5SPierre Schweitzer PIRP Irp;
7105ab1cfc5SPierre Schweitzer KEVENT Event;
7115ab1cfc5SPierre Schweitzer NTSTATUS Status;
7125ab1cfc5SPierre Schweitzer MOUNTDEV_NAME DevName;
7135ab1cfc5SPierre Schweitzer PFILE_OBJECT FileObject;
7145ab1cfc5SPierre Schweitzer PDEVICE_OBJECT DeviceObject;
7155ab1cfc5SPierre Schweitzer IO_STATUS_BLOCK IoStatusBlock;
7165ab1cfc5SPierre Schweitzer PAGED_CODE();
7175ab1cfc5SPierre Schweitzer
7185ab1cfc5SPierre Schweitzer /* Get the attached device object to our device */
7195ab1cfc5SPierre Schweitzer if (!NT_SUCCESS(IoGetDeviceObjectPointer(DeviceName,
7205ab1cfc5SPierre Schweitzer FILE_READ_ATTRIBUTES,
7215ab1cfc5SPierre Schweitzer &FileObject,
7225ab1cfc5SPierre Schweitzer &DeviceObject)))
7235ab1cfc5SPierre Schweitzer {
7245ab1cfc5SPierre Schweitzer return FALSE;
7255ab1cfc5SPierre Schweitzer }
7265ab1cfc5SPierre Schweitzer
7275ab1cfc5SPierre Schweitzer DeviceObject = IoGetAttachedDeviceReference(FileObject->DeviceObject);
7285ab1cfc5SPierre Schweitzer ObDereferenceObject(FileObject);
7295ab1cfc5SPierre Schweitzer
7305ab1cfc5SPierre Schweitzer /* Query its device name (ie, check floppy.sys implements MountMgr interface) */
7315ab1cfc5SPierre Schweitzer KeInitializeEvent(&Event, NotificationEvent, FALSE);
7325ab1cfc5SPierre Schweitzer Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
7335ab1cfc5SPierre Schweitzer DeviceObject,
7345ab1cfc5SPierre Schweitzer NULL,
7355ab1cfc5SPierre Schweitzer 0,
7365ab1cfc5SPierre Schweitzer &DevName,
7375ab1cfc5SPierre Schweitzer sizeof(DevName),
7385ab1cfc5SPierre Schweitzer FALSE,
7395ab1cfc5SPierre Schweitzer &Event,
7405ab1cfc5SPierre Schweitzer &IoStatusBlock);
7415ab1cfc5SPierre Schweitzer if (Irp == NULL)
7425ab1cfc5SPierre Schweitzer {
7435ab1cfc5SPierre Schweitzer ObDereferenceObject(DeviceObject);
7445ab1cfc5SPierre Schweitzer return FALSE;
7455ab1cfc5SPierre Schweitzer }
7465ab1cfc5SPierre Schweitzer
7475ab1cfc5SPierre Schweitzer Status = IoCallDriver(DeviceObject, Irp);
7485ab1cfc5SPierre Schweitzer if (Status == STATUS_PENDING)
7495ab1cfc5SPierre Schweitzer {
7505ab1cfc5SPierre Schweitzer KeWaitForSingleObject(&Event,
7515ab1cfc5SPierre Schweitzer Executive,
7525ab1cfc5SPierre Schweitzer KernelMode,
7535ab1cfc5SPierre Schweitzer FALSE,
7545ab1cfc5SPierre Schweitzer NULL);
7555ab1cfc5SPierre Schweitzer Status = IoStatusBlock.Status;
7565ab1cfc5SPierre Schweitzer }
7575ab1cfc5SPierre Schweitzer
7585ab1cfc5SPierre Schweitzer /* If status is not STATUS_BUFFER_OVERFLOW, it means
7595ab1cfc5SPierre Schweitzer * it's pre-mountmgr driver, aka "Old style".
7605ab1cfc5SPierre Schweitzer */
7615ab1cfc5SPierre Schweitzer ObDereferenceObject(DeviceObject);
7625ab1cfc5SPierre Schweitzer return (Status != STATUS_BUFFER_OVERFLOW);
7635ab1cfc5SPierre Schweitzer }
7645ab1cfc5SPierre Schweitzer
7655ab1cfc5SPierre Schweitzer NTSTATUS
HalpDeleteMountLetter(UCHAR DriveLetter)7665ab1cfc5SPierre Schweitzer HalpDeleteMountLetter(UCHAR DriveLetter)
7675ab1cfc5SPierre Schweitzer {
7685ab1cfc5SPierre Schweitzer PIRP Irp;
7695ab1cfc5SPierre Schweitzer KEVENT Event;
7705ab1cfc5SPierre Schweitzer NTSTATUS Status;
7715ab1cfc5SPierre Schweitzer WCHAR Buffer[30];
7725ab1cfc5SPierre Schweitzer ULONG InputBufferLength;
7735ab1cfc5SPierre Schweitzer PFILE_OBJECT FileObject;
7745ab1cfc5SPierre Schweitzer PDEVICE_OBJECT DeviceObject;
7755ab1cfc5SPierre Schweitzer IO_STATUS_BLOCK IoStatusBlock;
7765ab1cfc5SPierre Schweitzer PMOUNTMGR_MOUNT_POINT InputBuffer;
7775ab1cfc5SPierre Schweitzer UNICODE_STRING DosDevice, MountMgr;
7785ab1cfc5SPierre Schweitzer PMOUNTMGR_MOUNT_POINTS OutputBuffer;
7795ab1cfc5SPierre Schweitzer
7805ab1cfc5SPierre Schweitzer /* Setup the device name of the letter to delete */
7815ab1cfc5SPierre Schweitzer swprintf(Buffer, L"\\DosDevices\\%c:", DriveLetter);
7825ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&DosDevice, Buffer);
7835ab1cfc5SPierre Schweitzer
7845ab1cfc5SPierre Schweitzer /* Allocate the input buffer for MountMgr */
7855ab1cfc5SPierre Schweitzer InputBufferLength = DosDevice.Length + sizeof(MOUNTMGR_MOUNT_POINT);
7865ab1cfc5SPierre Schweitzer InputBuffer = ExAllocatePoolWithTag(PagedPool, InputBufferLength, TAG_FSTUB);
7875ab1cfc5SPierre Schweitzer if (InputBuffer == NULL)
7885ab1cfc5SPierre Schweitzer {
7895ab1cfc5SPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES;
7905ab1cfc5SPierre Schweitzer }
7915ab1cfc5SPierre Schweitzer
7925ab1cfc5SPierre Schweitzer /* Fill it in */
7935ab1cfc5SPierre Schweitzer RtlZeroMemory(InputBuffer, InputBufferLength);
7945ab1cfc5SPierre Schweitzer InputBuffer->SymbolicLinkNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
7955ab1cfc5SPierre Schweitzer InputBuffer->SymbolicLinkNameLength = DosDevice.Length;
7965ab1cfc5SPierre Schweitzer RtlCopyMemory(&InputBuffer[1], DosDevice.Buffer, DosDevice.Length);
7975ab1cfc5SPierre Schweitzer
7985ab1cfc5SPierre Schweitzer /* Allocate big enough output buffer (we don't care about the output) */
7995ab1cfc5SPierre Schweitzer OutputBuffer = ExAllocatePoolWithTag(PagedPool, 0x1000, TAG_FSTUB);
8005ab1cfc5SPierre Schweitzer if (OutputBuffer == NULL)
8015ab1cfc5SPierre Schweitzer {
8025ab1cfc5SPierre Schweitzer ExFreePoolWithTag(InputBuffer, TAG_FSTUB);
8035ab1cfc5SPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES;
8045ab1cfc5SPierre Schweitzer }
8055ab1cfc5SPierre Schweitzer
8065ab1cfc5SPierre Schweitzer /* Get the device pointer to the MountMgr */
8075ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&MountMgr, L"\\Device\\MountPointManager");
8085ab1cfc5SPierre Schweitzer Status = IoGetDeviceObjectPointer(&MountMgr,
8095ab1cfc5SPierre Schweitzer FILE_READ_ATTRIBUTES,
8105ab1cfc5SPierre Schweitzer &FileObject,
8115ab1cfc5SPierre Schweitzer &DeviceObject);
8125ab1cfc5SPierre Schweitzer if (!NT_SUCCESS(Status))
8135ab1cfc5SPierre Schweitzer {
8145ab1cfc5SPierre Schweitzer ExFreePoolWithTag(OutputBuffer, TAG_FSTUB);
8155ab1cfc5SPierre Schweitzer ExFreePoolWithTag(InputBuffer, TAG_FSTUB);
8165ab1cfc5SPierre Schweitzer return Status;
8175ab1cfc5SPierre Schweitzer }
8185ab1cfc5SPierre Schweitzer
8195ab1cfc5SPierre Schweitzer /* Call the mount manager to delete the drive letter */
8205ab1cfc5SPierre Schweitzer KeInitializeEvent(&Event, NotificationEvent, FALSE);
8215ab1cfc5SPierre Schweitzer Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_DELETE_POINTS,
8225ab1cfc5SPierre Schweitzer DeviceObject,
8235ab1cfc5SPierre Schweitzer InputBuffer,
8245ab1cfc5SPierre Schweitzer InputBufferLength,
8255ab1cfc5SPierre Schweitzer OutputBuffer,
8265ab1cfc5SPierre Schweitzer 0x1000,
8275ab1cfc5SPierre Schweitzer FALSE,
8285ab1cfc5SPierre Schweitzer &Event,
8295ab1cfc5SPierre Schweitzer &IoStatusBlock);
8305ab1cfc5SPierre Schweitzer if (Irp == NULL)
8315ab1cfc5SPierre Schweitzer {
8325ab1cfc5SPierre Schweitzer ObDereferenceObject(FileObject);
8335ab1cfc5SPierre Schweitzer ExFreePoolWithTag(OutputBuffer, TAG_FSTUB);
8345ab1cfc5SPierre Schweitzer ExFreePoolWithTag(InputBuffer, TAG_FSTUB);
8355ab1cfc5SPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES;
8365ab1cfc5SPierre Schweitzer }
8375ab1cfc5SPierre Schweitzer
8385ab1cfc5SPierre Schweitzer Status = IoCallDriver(DeviceObject, Irp);
8395ab1cfc5SPierre Schweitzer if (Status == STATUS_PENDING)
8405ab1cfc5SPierre Schweitzer {
8415ab1cfc5SPierre Schweitzer KeWaitForSingleObject(&Event,
8425ab1cfc5SPierre Schweitzer Executive,
8435ab1cfc5SPierre Schweitzer KernelMode,
8445ab1cfc5SPierre Schweitzer FALSE,
8455ab1cfc5SPierre Schweitzer NULL);
8465ab1cfc5SPierre Schweitzer Status = IoStatusBlock.Status;
8475ab1cfc5SPierre Schweitzer }
8485ab1cfc5SPierre Schweitzer
8495ab1cfc5SPierre Schweitzer ObDereferenceObject(FileObject);
8505ab1cfc5SPierre Schweitzer ExFreePoolWithTag(OutputBuffer, TAG_FSTUB);
8515ab1cfc5SPierre Schweitzer ExFreePoolWithTag(InputBuffer, TAG_FSTUB);
8525ab1cfc5SPierre Schweitzer
8535ab1cfc5SPierre Schweitzer return Status;
8545ab1cfc5SPierre Schweitzer }
8555ab1cfc5SPierre Schweitzer
8565ab1cfc5SPierre Schweitzer VOID
HalpEnableAutomaticDriveLetterAssignment(VOID)8575ab1cfc5SPierre Schweitzer HalpEnableAutomaticDriveLetterAssignment(VOID)
8585ab1cfc5SPierre Schweitzer {
8595ab1cfc5SPierre Schweitzer PIRP Irp;
8605ab1cfc5SPierre Schweitzer KEVENT Event;
8615ab1cfc5SPierre Schweitzer NTSTATUS Status;
8625ab1cfc5SPierre Schweitzer UNICODE_STRING MountMgr;
8635ab1cfc5SPierre Schweitzer PFILE_OBJECT FileObject;
8645ab1cfc5SPierre Schweitzer PDEVICE_OBJECT DeviceObject;
8655ab1cfc5SPierre Schweitzer IO_STATUS_BLOCK IoStatusBlock;
8665ab1cfc5SPierre Schweitzer
8675ab1cfc5SPierre Schweitzer /* Get the device pointer to the MountMgr */
8685ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&MountMgr, L"\\Device\\MountPointManager");
8695ab1cfc5SPierre Schweitzer Status = IoGetDeviceObjectPointer(&MountMgr,
8705ab1cfc5SPierre Schweitzer FILE_READ_ATTRIBUTES,
8715ab1cfc5SPierre Schweitzer &FileObject,
8725ab1cfc5SPierre Schweitzer &DeviceObject);
8735ab1cfc5SPierre Schweitzer if (!NT_SUCCESS(Status))
8745ab1cfc5SPierre Schweitzer {
8755ab1cfc5SPierre Schweitzer return;
8765ab1cfc5SPierre Schweitzer }
8775ab1cfc5SPierre Schweitzer
8785ab1cfc5SPierre Schweitzer /* Just send an IOCTL to enable the feature */
8795ab1cfc5SPierre Schweitzer KeInitializeEvent(&Event, NotificationEvent, FALSE);
8805ab1cfc5SPierre Schweitzer Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_AUTO_DL_ASSIGNMENTS,
8815ab1cfc5SPierre Schweitzer DeviceObject,
8825ab1cfc5SPierre Schweitzer NULL,
8835ab1cfc5SPierre Schweitzer 0,
8845ab1cfc5SPierre Schweitzer NULL,
8855ab1cfc5SPierre Schweitzer 0,
8865ab1cfc5SPierre Schweitzer FALSE,
8875ab1cfc5SPierre Schweitzer &Event,
8885ab1cfc5SPierre Schweitzer &IoStatusBlock);
8895ab1cfc5SPierre Schweitzer if (Irp == NULL)
8905ab1cfc5SPierre Schweitzer {
8915ab1cfc5SPierre Schweitzer return;
8925ab1cfc5SPierre Schweitzer }
8935ab1cfc5SPierre Schweitzer
8945ab1cfc5SPierre Schweitzer Status = IoCallDriver(DeviceObject, Irp);
8955ab1cfc5SPierre Schweitzer if (Status == STATUS_PENDING)
8965ab1cfc5SPierre Schweitzer {
8975ab1cfc5SPierre Schweitzer KeWaitForSingleObject(&Event,
8985ab1cfc5SPierre Schweitzer Executive,
8995ab1cfc5SPierre Schweitzer KernelMode,
9005ab1cfc5SPierre Schweitzer FALSE,
9015ab1cfc5SPierre Schweitzer NULL);
9025ab1cfc5SPierre Schweitzer Status = IoStatusBlock.Status;
903c2c66affSColin Finck }
904c2c66affSColin Finck
905c2c66affSColin Finck ObDereferenceObject(FileObject);
906c2c66affSColin Finck
9075ab1cfc5SPierre Schweitzer return;
908c2c66affSColin Finck }
909c2c66affSColin Finck
910c2c66affSColin Finck VOID
911c2c66affSColin Finck FASTCALL
xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,IN PSTRING NtDeviceName,OUT PUCHAR NtSystemPath,OUT PSTRING NtSystemPathString)912c2c66affSColin Finck xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
913c2c66affSColin Finck IN PSTRING NtDeviceName,
914c2c66affSColin Finck OUT PUCHAR NtSystemPath,
915c2c66affSColin Finck OUT PSTRING NtSystemPathString)
916c2c66affSColin Finck {
9175ab1cfc5SPierre Schweitzer USHORT i;
9185ab1cfc5SPierre Schweitzer PULONG Devices;
919c2c66affSColin Finck NTSTATUS Status;
9205ab1cfc5SPierre Schweitzer WCHAR Buffer[50];
9215ab1cfc5SPierre Schweitzer HANDLE FileHandle;
9225ab1cfc5SPierre Schweitzer UCHAR DriveLetter;
9235ab1cfc5SPierre Schweitzer BOOLEAN SystemFound;
9245ab1cfc5SPierre Schweitzer IO_STATUS_BLOCK StatusBlock;
9255ab1cfc5SPierre Schweitzer PARTITION_TYPE PartitionType;
9265ab1cfc5SPierre Schweitzer ANSI_STRING StringA1, StringA2;
9275ab1cfc5SPierre Schweitzer PSTR Buffer1, Buffer2, LoadOptions;
9285ab1cfc5SPierre Schweitzer OBJECT_ATTRIBUTES ObjectAttributes;
9295ab1cfc5SPierre Schweitzer PDRIVE_LAYOUT_INFORMATION LayoutInfo;
9305ab1cfc5SPierre Schweitzer PCONFIGURATION_INFORMATION ConfigInfo;
9315ab1cfc5SPierre Schweitzer UNICODE_STRING StringU1, StringU2, StringU3;
9325ab1cfc5SPierre Schweitzer ULONG Increment, DiskCount, RealDiskCount, HarddiskCount, PartitionCount, SystemPartition;
933c2c66affSColin Finck
9345ab1cfc5SPierre Schweitzer PAGED_CODE();
935c2c66affSColin Finck
9365ab1cfc5SPierre Schweitzer /* Get our disk count */
937c2c66affSColin Finck ConfigInfo = IoGetConfigurationInformation();
9385ab1cfc5SPierre Schweitzer DiskCount = ConfigInfo->DiskCount;
9395ab1cfc5SPierre Schweitzer RealDiskCount = 0;
940c2c66affSColin Finck
9415ab1cfc5SPierre Schweitzer /* Allocate two generic string buffers we'll use and reuser later on */
9425ab1cfc5SPierre Schweitzer Buffer1 = ExAllocatePoolWithTag(NonPagedPool, 128, TAG_FSTUB);
9435ab1cfc5SPierre Schweitzer Buffer2 = ExAllocatePoolWithTag(NonPagedPool, 64, TAG_FSTUB);
9445ab1cfc5SPierre Schweitzer if (Buffer1 == NULL || Buffer2 == NULL)
945c2c66affSColin Finck {
9465ab1cfc5SPierre Schweitzer KeBugCheck(ASSIGN_DRIVE_LETTERS_FAILED);
947c2c66affSColin Finck }
948c2c66affSColin Finck
9495ab1cfc5SPierre Schweitzer /* In case of a remote boot, setup system path */
9505ab1cfc5SPierre Schweitzer if (IoRemoteBootClient)
951c2c66affSColin Finck {
9525ab1cfc5SPierre Schweitzer PSTR Last, Saved;
9535ab1cfc5SPierre Schweitzer
9545ab1cfc5SPierre Schweitzer /* Find last \ */
9555ab1cfc5SPierre Schweitzer Last = strrchr(LoaderBlock->NtBootPathName, '\\');
9565ab1cfc5SPierre Schweitzer Saved = NULL;
9575ab1cfc5SPierre Schweitzer /* Misformed name, fail */
9585ab1cfc5SPierre Schweitzer if (Last == NULL)
9595ab1cfc5SPierre Schweitzer {
9605ab1cfc5SPierre Schweitzer KeBugCheck(ASSIGN_DRIVE_LETTERS_FAILED);
961c2c66affSColin Finck }
962c2c66affSColin Finck
9635ab1cfc5SPierre Schweitzer /* In case the name was terminated by a \... */
9645ab1cfc5SPierre Schweitzer if (Last[1] == ANSI_NULL)
9655ab1cfc5SPierre Schweitzer {
9665ab1cfc5SPierre Schweitzer /* Erase it, save position and find the previous \ */
9675ab1cfc5SPierre Schweitzer *Last = ANSI_NULL;
9685ab1cfc5SPierre Schweitzer Saved = Last;
9695ab1cfc5SPierre Schweitzer Last = strrchr(LoaderBlock->NtBootPathName, '\\');
9705ab1cfc5SPierre Schweitzer *Saved = '\\';
9715ab1cfc5SPierre Schweitzer }
972c2c66affSColin Finck
9735ab1cfc5SPierre Schweitzer /* Misformed name, fail */
9745ab1cfc5SPierre Schweitzer if (Last == NULL)
9755ab1cfc5SPierre Schweitzer {
9765ab1cfc5SPierre Schweitzer KeBugCheck(ASSIGN_DRIVE_LETTERS_FAILED);
9775ab1cfc5SPierre Schweitzer }
9785ab1cfc5SPierre Schweitzer
9795ab1cfc5SPierre Schweitzer /* For a remote boot, assign X drive letter */
9805ab1cfc5SPierre Schweitzer NtSystemPath[0] = 'X';
9815ab1cfc5SPierre Schweitzer NtSystemPath[1] = ':';
9825ab1cfc5SPierre Schweitzer /* And copy the end of the boot path */
9835ab1cfc5SPierre Schweitzer strcpy((PSTR)&NtSystemPath[2], Last);
9845ab1cfc5SPierre Schweitzer
9855ab1cfc5SPierre Schweitzer /* If we had to remove the trailing \, remove it here too */
9865ab1cfc5SPierre Schweitzer if (Saved != NULL)
9875ab1cfc5SPierre Schweitzer {
9885ab1cfc5SPierre Schweitzer NtSystemPath[strlen((PSTR)NtSystemPath) - 1] = ANSI_NULL;
9895ab1cfc5SPierre Schweitzer }
9905ab1cfc5SPierre Schweitzer
9915ab1cfc5SPierre Schweitzer /* Setup output string */
9925ab1cfc5SPierre Schweitzer RtlInitString(NtSystemPathString, (PSTR)NtSystemPath);
9935ab1cfc5SPierre Schweitzer }
9945ab1cfc5SPierre Schweitzer
9955ab1cfc5SPierre Schweitzer /* For each of our disks, create the physical device DOS device */
9965ab1cfc5SPierre Schweitzer Increment = 0;
9975ab1cfc5SPierre Schweitzer if (DiskCount != 0)
9985ab1cfc5SPierre Schweitzer {
9995ab1cfc5SPierre Schweitzer for (i = 0; i < DiskCount; ++i)
10005ab1cfc5SPierre Schweitzer {
10015ab1cfc5SPierre Schweitzer /* Setup the origin name */
10025ab1cfc5SPierre Schweitzer sprintf(Buffer1, "\\Device\\Harddisk%d\\Partition%d", i, 0);
10035ab1cfc5SPierre Schweitzer RtlInitAnsiString(&StringA1, Buffer1);
10045ab1cfc5SPierre Schweitzer if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&StringU1, &StringA1, TRUE)))
10055ab1cfc5SPierre Schweitzer {
10065ab1cfc5SPierre Schweitzer /* We cannot fail */
10075ab1cfc5SPierre Schweitzer KeBugCheck(ASSIGN_DRIVE_LETTERS_FAILED);
10085ab1cfc5SPierre Schweitzer }
10095ab1cfc5SPierre Schweitzer
10105ab1cfc5SPierre Schweitzer /* Open the device */
1011c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes,
10125ab1cfc5SPierre Schweitzer &StringU1,
10135ab1cfc5SPierre Schweitzer OBJ_CASE_INSENSITIVE,
1014c2c66affSColin Finck NULL,
1015c2c66affSColin Finck NULL);
1016c2c66affSColin Finck Status = ZwOpenFile(&FileHandle,
10175ab1cfc5SPierre Schweitzer SYNCHRONIZE | FILE_READ_DATA,
1018c2c66affSColin Finck &ObjectAttributes,
1019c2c66affSColin Finck &StatusBlock,
1020c2c66affSColin Finck FILE_SHARE_READ,
1021c2c66affSColin Finck FILE_SYNCHRONOUS_IO_NONALERT);
1022c2c66affSColin Finck if (NT_SUCCESS(Status))
1023c2c66affSColin Finck {
10245ab1cfc5SPierre Schweitzer /* If we managed, create the link */
10255ab1cfc5SPierre Schweitzer sprintf(Buffer2, "\\DosDevices\\PhysicalDrive%d", i);
10265ab1cfc5SPierre Schweitzer RtlInitAnsiString(&StringA2, Buffer2);
10275ab1cfc5SPierre Schweitzer Status = RtlAnsiStringToUnicodeString(&StringU2, &StringA2, TRUE);
10285ab1cfc5SPierre Schweitzer if (NT_SUCCESS(Status))
10295ab1cfc5SPierre Schweitzer {
10305ab1cfc5SPierre Schweitzer IoCreateSymbolicLink(&StringU2, &StringU1);
10315ab1cfc5SPierre Schweitzer RtlFreeUnicodeString(&StringU2);
10325ab1cfc5SPierre Schweitzer }
10335ab1cfc5SPierre Schweitzer
1034c2c66affSColin Finck ZwClose(FileHandle);
1035c2c66affSColin Finck
10365ab1cfc5SPierre Schweitzer RealDiskCount = i + 1;
1037c2c66affSColin Finck }
1038c2c66affSColin Finck
10395ab1cfc5SPierre Schweitzer RtlFreeUnicodeString(&StringU1);
1040c2c66affSColin Finck
1041c2c66affSColin Finck if (!NT_SUCCESS(Status))
1042c2c66affSColin Finck {
10435ab1cfc5SPierre Schweitzer if (Increment < 50)
10445ab1cfc5SPierre Schweitzer {
10455ab1cfc5SPierre Schweitzer ++Increment;
10465ab1cfc5SPierre Schweitzer ++DiskCount;
1047c2c66affSColin Finck }
10485ab1cfc5SPierre Schweitzer }
10495ab1cfc5SPierre Schweitzer }
10505ab1cfc5SPierre Schweitzer }
10515ab1cfc5SPierre Schweitzer
10525ab1cfc5SPierre Schweitzer /* We done for our buffers */
10535ab1cfc5SPierre Schweitzer ExFreePoolWithTag(Buffer1, TAG_FSTUB);
10545ab1cfc5SPierre Schweitzer ExFreePoolWithTag(Buffer2, TAG_FSTUB);
10555ab1cfc5SPierre Schweitzer
10565ab1cfc5SPierre Schweitzer /* Upcase our load options, if any */
10575ab1cfc5SPierre Schweitzer if (LoaderBlock->LoadOptions != NULL)
10585ab1cfc5SPierre Schweitzer {
10595ab1cfc5SPierre Schweitzer LoadOptions = _strupr(LoaderBlock->LoadOptions);
10605ab1cfc5SPierre Schweitzer }
10615ab1cfc5SPierre Schweitzer else
10625ab1cfc5SPierre Schweitzer {
10635ab1cfc5SPierre Schweitzer LoadOptions = NULL;
10645ab1cfc5SPierre Schweitzer }
10655ab1cfc5SPierre Schweitzer
10665ab1cfc5SPierre Schweitzer /* If we boot with /MININT (system hive as volatile) option, assign X letter to boot device */
10675ab1cfc5SPierre Schweitzer if (LoadOptions != NULL &&
10685ab1cfc5SPierre Schweitzer strstr(LoadOptions, "MININT") != 0 &&
10695ab1cfc5SPierre Schweitzer NT_SUCCESS(RtlAnsiStringToUnicodeString(&StringU1, NtDeviceName, TRUE)))
10705ab1cfc5SPierre Schweitzer {
10715ab1cfc5SPierre Schweitzer if (NT_SUCCESS(HalpSetMountLetter(&StringU1, 'X')))
10725ab1cfc5SPierre Schweitzer {
10735ab1cfc5SPierre Schweitzer *NtSystemPath = 'X';
10745ab1cfc5SPierre Schweitzer }
10755ab1cfc5SPierre Schweitzer
10765ab1cfc5SPierre Schweitzer RtlFreeUnicodeString(&StringU1);
10775ab1cfc5SPierre Schweitzer }
10785ab1cfc5SPierre Schweitzer
10795ab1cfc5SPierre Schweitzer /* Compute our disks derangements */
10805ab1cfc5SPierre Schweitzer DiskCount -= Increment;
10815ab1cfc5SPierre Schweitzer if (RealDiskCount > DiskCount)
10825ab1cfc5SPierre Schweitzer {
10835ab1cfc5SPierre Schweitzer DiskCount = RealDiskCount;
10845ab1cfc5SPierre Schweitzer }
10855ab1cfc5SPierre Schweitzer Devices = IopComputeHarddiskDerangements(DiskCount);
10865ab1cfc5SPierre Schweitzer
10875ab1cfc5SPierre Schweitzer /* Now, start browsing all our disks for assigning drive letters
10885ab1cfc5SPierre Schweitzer * Here, we'll only handle boot partition and primary partitions
1089c2c66affSColin Finck */
10905ab1cfc5SPierre Schweitzer HarddiskCount = 0;
10915ab1cfc5SPierre Schweitzer for (i = 0; i < DiskCount; ++i)
1092c2c66affSColin Finck {
10935ab1cfc5SPierre Schweitzer /* Get device ID according to derangements map */
10945ab1cfc5SPierre Schweitzer if (Devices != NULL)
10955ab1cfc5SPierre Schweitzer {
10965ab1cfc5SPierre Schweitzer HarddiskCount = Devices[i];
1097c2c66affSColin Finck }
1098c2c66affSColin Finck
10995ab1cfc5SPierre Schweitzer /* Query disk layout */
11005ab1cfc5SPierre Schweitzer swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition0", HarddiskCount);
11015ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&StringU1, Buffer);
11025ab1cfc5SPierre Schweitzer if (!NT_SUCCESS(HalpQueryDriveLayout(&StringU1, &LayoutInfo)))
1103c2c66affSColin Finck {
11045ab1cfc5SPierre Schweitzer LayoutInfo = NULL;
1105c2c66affSColin Finck }
1106c2c66affSColin Finck
11075ab1cfc5SPierre Schweitzer /* Assume we didn't find system */
11085ab1cfc5SPierre Schweitzer SystemFound = FALSE;
11095ab1cfc5SPierre Schweitzer swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, 1);
11105ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&StringU1, Buffer);
11115ab1cfc5SPierre Schweitzer /* Query partition info for our disk */
11125ab1cfc5SPierre Schweitzer if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
1113c2c66affSColin Finck {
11145ab1cfc5SPierre Schweitzer /* It failed, retry for all the partitions */
11155ab1cfc5SPierre Schweitzer for (PartitionCount = 1; ; ++PartitionCount)
1116c2c66affSColin Finck {
11175ab1cfc5SPierre Schweitzer swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
11185ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&StringU1, Buffer);
11195ab1cfc5SPierre Schweitzer if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
1120c2c66affSColin Finck {
11215ab1cfc5SPierre Schweitzer break;
1122c2c66affSColin Finck }
11235ab1cfc5SPierre Schweitzer
11245ab1cfc5SPierre Schweitzer /* We found a primary partition, assign a drive letter */
11255ab1cfc5SPierre Schweitzer if (PartitionType == PrimaryPartition)
11265ab1cfc5SPierre Schweitzer {
11275ab1cfc5SPierre Schweitzer HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, 0);
1128c2c66affSColin Finck break;
1129c2c66affSColin Finck }
1130c2c66affSColin Finck }
1131c2c66affSColin Finck }
11325ab1cfc5SPierre Schweitzer else
1133c2c66affSColin Finck {
11345ab1cfc5SPierre Schweitzer /* All right */
11355ab1cfc5SPierre Schweitzer for (PartitionCount = 2; ; ++PartitionCount)
11365ab1cfc5SPierre Schweitzer {
11375ab1cfc5SPierre Schweitzer /* If our partition is bootable (MBR) or data (GPT), that's system partition */
11385ab1cfc5SPierre Schweitzer if (PartitionType == BootablePartition || PartitionType == DataPartition)
11395ab1cfc5SPierre Schweitzer {
11405ab1cfc5SPierre Schweitzer SystemFound = TRUE;
11415ab1cfc5SPierre Schweitzer
11425ab1cfc5SPierre Schweitzer /* Assign a drive letter and stop here if MBR */
11435ab1cfc5SPierre Schweitzer HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, 0);
11445ab1cfc5SPierre Schweitzer if (PartitionType == BootablePartition)
11455ab1cfc5SPierre Schweitzer {
11465ab1cfc5SPierre Schweitzer break;
1147c2c66affSColin Finck }
1148c2c66affSColin Finck }
1149c2c66affSColin Finck
11505ab1cfc5SPierre Schweitzer /* Keep looping on all the partitions */
11515ab1cfc5SPierre Schweitzer swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
11525ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&StringU1, Buffer);
11535ab1cfc5SPierre Schweitzer if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
1154c2c66affSColin Finck {
11555ab1cfc5SPierre Schweitzer /* Mount every primary partition if we didn't find system */
11565ab1cfc5SPierre Schweitzer if (!SystemFound)
1157c2c66affSColin Finck {
11585ab1cfc5SPierre Schweitzer for (PartitionCount = 1; ; ++PartitionCount)
1159c2c66affSColin Finck {
11605ab1cfc5SPierre Schweitzer swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
11615ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&StringU1, Buffer);
11625ab1cfc5SPierre Schweitzer if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
1163c2c66affSColin Finck {
11645ab1cfc5SPierre Schweitzer break;
1165c2c66affSColin Finck }
11665ab1cfc5SPierre Schweitzer
11675ab1cfc5SPierre Schweitzer if (PartitionType == PrimaryPartition)
11685ab1cfc5SPierre Schweitzer {
11695ab1cfc5SPierre Schweitzer HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, 0);
1170c2c66affSColin Finck break;
1171c2c66affSColin Finck }
1172c2c66affSColin Finck }
1173c2c66affSColin Finck }
11745ab1cfc5SPierre Schweitzer
11755ab1cfc5SPierre Schweitzer break;
11765ab1cfc5SPierre Schweitzer }
11775ab1cfc5SPierre Schweitzer }
1178c2c66affSColin Finck }
1179c2c66affSColin Finck
11805ab1cfc5SPierre Schweitzer /* Free layout, we'll reallocate it for next device */
11815ab1cfc5SPierre Schweitzer if (LayoutInfo != NULL)
1182c2c66affSColin Finck {
11835ab1cfc5SPierre Schweitzer ExFreePoolWithTag(LayoutInfo, TAG_FSTUB);
11845ab1cfc5SPierre Schweitzer }
1185c2c66affSColin Finck
11865ab1cfc5SPierre Schweitzer HarddiskCount = i + 1;
11875ab1cfc5SPierre Schweitzer }
11885ab1cfc5SPierre Schweitzer
11895ab1cfc5SPierre Schweitzer /* Now, assign logical partitions */
11905ab1cfc5SPierre Schweitzer for (i = 0; i < DiskCount; ++i)
11915ab1cfc5SPierre Schweitzer {
11925ab1cfc5SPierre Schweitzer /* Get device ID according to derangements map */
11935ab1cfc5SPierre Schweitzer if (Devices != NULL)
11945ab1cfc5SPierre Schweitzer {
11955ab1cfc5SPierre Schweitzer HarddiskCount = Devices[i];
11965ab1cfc5SPierre Schweitzer }
11975ab1cfc5SPierre Schweitzer else
11985ab1cfc5SPierre Schweitzer {
11995ab1cfc5SPierre Schweitzer HarddiskCount = i;
12005ab1cfc5SPierre Schweitzer }
12015ab1cfc5SPierre Schweitzer
12025ab1cfc5SPierre Schweitzer /* Query device layout */
12035ab1cfc5SPierre Schweitzer swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition0", HarddiskCount);
12045ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&StringU1, Buffer);
12055ab1cfc5SPierre Schweitzer if (!NT_SUCCESS(HalpQueryDriveLayout(&StringU1, &LayoutInfo)))
12065ab1cfc5SPierre Schweitzer {
12075ab1cfc5SPierre Schweitzer LayoutInfo = NULL;
12085ab1cfc5SPierre Schweitzer }
12095ab1cfc5SPierre Schweitzer
12105ab1cfc5SPierre Schweitzer /* And assign drive letter to logical partitions */
12115ab1cfc5SPierre Schweitzer for (PartitionCount = 1; ; ++PartitionCount)
12125ab1cfc5SPierre Schweitzer {
12135ab1cfc5SPierre Schweitzer swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
12145ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&StringU1, Buffer);
12155ab1cfc5SPierre Schweitzer if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
12165ab1cfc5SPierre Schweitzer {
12175ab1cfc5SPierre Schweitzer break;
12185ab1cfc5SPierre Schweitzer }
12195ab1cfc5SPierre Schweitzer
12205ab1cfc5SPierre Schweitzer if (PartitionType == LogicalPartition)
12215ab1cfc5SPierre Schweitzer {
12225ab1cfc5SPierre Schweitzer HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, 0);
12235ab1cfc5SPierre Schweitzer }
12245ab1cfc5SPierre Schweitzer }
12255ab1cfc5SPierre Schweitzer
12265ab1cfc5SPierre Schweitzer /* Free layout, we'll reallocate it for next device */
12275ab1cfc5SPierre Schweitzer if (LayoutInfo != NULL)
12285ab1cfc5SPierre Schweitzer {
12295ab1cfc5SPierre Schweitzer ExFreePoolWithTag(LayoutInfo, 0);
12305ab1cfc5SPierre Schweitzer }
12315ab1cfc5SPierre Schweitzer }
12325ab1cfc5SPierre Schweitzer
12335ab1cfc5SPierre Schweitzer /* Now, assign drive letters to everything else */
12345ab1cfc5SPierre Schweitzer for (i = 0; i < DiskCount; ++i)
12355ab1cfc5SPierre Schweitzer {
12365ab1cfc5SPierre Schweitzer /* Get device ID according to derangements map */
12375ab1cfc5SPierre Schweitzer if (Devices != NULL)
12385ab1cfc5SPierre Schweitzer {
12395ab1cfc5SPierre Schweitzer HarddiskCount = Devices[i];
12405ab1cfc5SPierre Schweitzer }
12415ab1cfc5SPierre Schweitzer else
12425ab1cfc5SPierre Schweitzer {
12435ab1cfc5SPierre Schweitzer HarddiskCount = i;
12445ab1cfc5SPierre Schweitzer }
12455ab1cfc5SPierre Schweitzer
12465ab1cfc5SPierre Schweitzer /* Query device layout */
12475ab1cfc5SPierre Schweitzer swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition0", HarddiskCount);
12485ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&StringU1, Buffer);
12495ab1cfc5SPierre Schweitzer if (!NT_SUCCESS(HalpQueryDriveLayout(&StringU1, &LayoutInfo)))
12505ab1cfc5SPierre Schweitzer {
12515ab1cfc5SPierre Schweitzer LayoutInfo = NULL;
12525ab1cfc5SPierre Schweitzer }
12535ab1cfc5SPierre Schweitzer
12545ab1cfc5SPierre Schweitzer /* Save system partition if any */
12555ab1cfc5SPierre Schweitzer SystemPartition = 0;
12565ab1cfc5SPierre Schweitzer for (PartitionCount = 1; ; ++PartitionCount)
12575ab1cfc5SPierre Schweitzer {
12585ab1cfc5SPierre Schweitzer swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
12595ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&StringU1, Buffer);
12605ab1cfc5SPierre Schweitzer if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
12615ab1cfc5SPierre Schweitzer {
12625ab1cfc5SPierre Schweitzer break;
12635ab1cfc5SPierre Schweitzer }
12645ab1cfc5SPierre Schweitzer
12655ab1cfc5SPierre Schweitzer if ((PartitionType == BootablePartition || PartitionType == PrimaryPartition) && (SystemPartition == 0))
12665ab1cfc5SPierre Schweitzer {
12675ab1cfc5SPierre Schweitzer SystemPartition = PartitionCount;
12685ab1cfc5SPierre Schweitzer }
12695ab1cfc5SPierre Schweitzer }
12705ab1cfc5SPierre Schweitzer
12715ab1cfc5SPierre Schweitzer /* And assign drive letter to anything but system partition */
12725ab1cfc5SPierre Schweitzer for (PartitionCount = 1; ; ++PartitionCount)
12735ab1cfc5SPierre Schweitzer {
12745ab1cfc5SPierre Schweitzer if (PartitionCount != SystemPartition)
12755ab1cfc5SPierre Schweitzer {
12765ab1cfc5SPierre Schweitzer swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
12775ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&StringU1, Buffer);
12785ab1cfc5SPierre Schweitzer if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
12795ab1cfc5SPierre Schweitzer {
12805ab1cfc5SPierre Schweitzer if (LayoutInfo != NULL)
12815ab1cfc5SPierre Schweitzer {
12825ab1cfc5SPierre Schweitzer ExFreePoolWithTag(LayoutInfo, 0);
12835ab1cfc5SPierre Schweitzer }
12845ab1cfc5SPierre Schweitzer
12855ab1cfc5SPierre Schweitzer break;
12865ab1cfc5SPierre Schweitzer }
12875ab1cfc5SPierre Schweitzer
12885ab1cfc5SPierre Schweitzer if (PartitionType == PrimaryPartition || PartitionType == FtPartition)
12895ab1cfc5SPierre Schweitzer {
12905ab1cfc5SPierre Schweitzer HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, 0);
1291c2c66affSColin Finck }
1292c2c66affSColin Finck }
1293c2c66affSColin Finck }
1294c2c66affSColin Finck }
1295c2c66affSColin Finck
12965ab1cfc5SPierre Schweitzer /* We're done with disks, if we have a device map, free it */
12975ab1cfc5SPierre Schweitzer if (Devices != NULL)
1298c2c66affSColin Finck {
12995ab1cfc5SPierre Schweitzer ExFreePoolWithTag(Devices, TAG_FSTUB);
13005ab1cfc5SPierre Schweitzer }
1301c2c66affSColin Finck
13025ab1cfc5SPierre Schweitzer /* Now, assign drive letter to floppy drives */
13035ab1cfc5SPierre Schweitzer for (i = 0; i < ConfigInfo->FloppyCount; ++i)
13045ab1cfc5SPierre Schweitzer {
13055ab1cfc5SPierre Schweitzer swprintf(Buffer, L"\\Device\\Floppy%d", i);
13065ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&StringU1, Buffer);
13075ab1cfc5SPierre Schweitzer if (HalpIsOldStyleFloppy(&StringU1))
13085ab1cfc5SPierre Schweitzer {
13095ab1cfc5SPierre Schweitzer HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, TRUE);
1310c2c66affSColin Finck }
1311c2c66affSColin Finck }
1312c2c66affSColin Finck
13135ab1cfc5SPierre Schweitzer /* And CD drives */
13145ab1cfc5SPierre Schweitzer for (i = 0; i < ConfigInfo->CdRomCount; ++i)
1315c2c66affSColin Finck {
13165ab1cfc5SPierre Schweitzer swprintf(Buffer, L"\\Device\\CdRom%d", i);
13175ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&StringU1, Buffer);
13185ab1cfc5SPierre Schweitzer HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, TRUE);
13195ab1cfc5SPierre Schweitzer }
1320c2c66affSColin Finck
13215ab1cfc5SPierre Schweitzer /* If not remote boot, handle NtDeviceName */
13225ab1cfc5SPierre Schweitzer if (!IoRemoteBootClient && NT_SUCCESS(RtlAnsiStringToUnicodeString(&StringU1, NtDeviceName, TRUE)))
13235ab1cfc5SPierre Schweitzer {
13245ab1cfc5SPierre Schweitzer /* Assign it a drive letter */
13255ab1cfc5SPierre Schweitzer DriveLetter = HalpNextDriveLetter(&StringU1, NULL, NULL, TRUE);
13265ab1cfc5SPierre Schweitzer if (DriveLetter != 0)
13275ab1cfc5SPierre Schweitzer {
13285ab1cfc5SPierre Schweitzer if (DriveLetter != 0xFF)
13295ab1cfc5SPierre Schweitzer {
13305ab1cfc5SPierre Schweitzer *NtSystemPath = DriveLetter;
1331c2c66affSColin Finck }
1332c2c66affSColin Finck }
13335ab1cfc5SPierre Schweitzer /* If it fails through mount manager, retry manually */
13345ab1cfc5SPierre Schweitzer else
13355ab1cfc5SPierre Schweitzer {
13365ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&StringU2, L"\\Device\\Floppy");
13375ab1cfc5SPierre Schweitzer RtlInitUnicodeString(&StringU3, L"\\Device\\CdRom");
13385ab1cfc5SPierre Schweitzer
13395ab1cfc5SPierre Schweitzer if (RtlPrefixUnicodeString(&StringU2, &StringU1, TRUE))
13405ab1cfc5SPierre Schweitzer {
13415ab1cfc5SPierre Schweitzer DriveLetter = 'A';
13425ab1cfc5SPierre Schweitzer }
13435ab1cfc5SPierre Schweitzer else if (RtlPrefixUnicodeString(&StringU3, &StringU1, TRUE))
13445ab1cfc5SPierre Schweitzer {
13455ab1cfc5SPierre Schweitzer DriveLetter = 'D';
13465ab1cfc5SPierre Schweitzer }
13475ab1cfc5SPierre Schweitzer else
13485ab1cfc5SPierre Schweitzer {
13495ab1cfc5SPierre Schweitzer DriveLetter = 'C';
13505ab1cfc5SPierre Schweitzer }
13515ab1cfc5SPierre Schweitzer
13525ab1cfc5SPierre Schweitzer /* Try any drive letter */
13535ab1cfc5SPierre Schweitzer while (HalpSetMountLetter(&StringU1, DriveLetter) != STATUS_SUCCESS)
13545ab1cfc5SPierre Schweitzer {
13555ab1cfc5SPierre Schweitzer ++DriveLetter;
13565ab1cfc5SPierre Schweitzer
13575ab1cfc5SPierre Schweitzer if (DriveLetter > 'Z')
13585ab1cfc5SPierre Schweitzer {
13595ab1cfc5SPierre Schweitzer break;
1360c2c66affSColin Finck }
1361c2c66affSColin Finck }
1362c2c66affSColin Finck
13635ab1cfc5SPierre Schweitzer /* If we're beyond Z (ie, no slot left) */
13645ab1cfc5SPierre Schweitzer if (DriveLetter > 'Z')
1365c2c66affSColin Finck {
13665ab1cfc5SPierre Schweitzer /* Delete Z, and reuse it for system */
13675ab1cfc5SPierre Schweitzer HalpDeleteMountLetter('Z');
13685ab1cfc5SPierre Schweitzer HalpSetMountLetter(&StringU1, 'Z');
13695ab1cfc5SPierre Schweitzer *NtSystemPath = 'Z';
13705ab1cfc5SPierre Schweitzer }
13715ab1cfc5SPierre Schweitzer else
1372c2c66affSColin Finck {
13735ab1cfc5SPierre Schweitzer /* Return matching drive letter */
13745ab1cfc5SPierre Schweitzer *NtSystemPath = DriveLetter;
1375c2c66affSColin Finck }
1376c2c66affSColin Finck }
1377c2c66affSColin Finck
13785ab1cfc5SPierre Schweitzer RtlFreeUnicodeString(&StringU1);
1379c2c66affSColin Finck }
1380c2c66affSColin Finck
13815ab1cfc5SPierre Schweitzer /* Enable auto assignement for mountmgr */
13825ab1cfc5SPierre Schweitzer HalpEnableAutomaticDriveLetterAssignment();
1383c2c66affSColin Finck }
1384c2c66affSColin Finck
1385c2c66affSColin Finck /* PRIVATE FUNCTIONS *********************************************************/
1386c2c66affSColin Finck
1387c2c66affSColin Finck NTSTATUS
1388c2c66affSColin Finck NTAPI
HalpGetFullGeometry(IN PDEVICE_OBJECT DeviceObject,OUT PDISK_GEOMETRY_EX Geometry)1389c2c66affSColin Finck HalpGetFullGeometry(IN PDEVICE_OBJECT DeviceObject,
13905201472bSVictor Perevertkin OUT PDISK_GEOMETRY_EX Geometry)
1391c2c66affSColin Finck {
1392c2c66affSColin Finck PIRP Irp;
1393c2c66affSColin Finck IO_STATUS_BLOCK IoStatusBlock;
1394c2c66affSColin Finck PKEVENT Event;
1395c2c66affSColin Finck NTSTATUS Status;
1396e3c35c22SHermès Bélusca-Maïto
1397c2c66affSColin Finck PAGED_CODE();
1398c2c66affSColin Finck
1399c2c66affSColin Finck /* Allocate a non-paged event */
1400c2c66affSColin Finck Event = ExAllocatePoolWithTag(NonPagedPool,
1401c2c66affSColin Finck sizeof(KEVENT),
1402c2c66affSColin Finck TAG_FILE_SYSTEM);
1403c2c66affSColin Finck if (!Event) return STATUS_INSUFFICIENT_RESOURCES;
1404c2c66affSColin Finck
1405c2c66affSColin Finck /* Initialize it */
1406c2c66affSColin Finck KeInitializeEvent(Event, NotificationEvent, FALSE);
1407c2c66affSColin Finck
1408c2c66affSColin Finck /* Build the IRP */
14095201472bSVictor Perevertkin Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
1410c2c66affSColin Finck DeviceObject,
1411c2c66affSColin Finck NULL,
1412c2c66affSColin Finck 0UL,
1413c2c66affSColin Finck Geometry,
14145201472bSVictor Perevertkin sizeof(DISK_GEOMETRY_EX),
1415c2c66affSColin Finck FALSE,
1416c2c66affSColin Finck Event,
1417c2c66affSColin Finck &IoStatusBlock);
1418c2c66affSColin Finck if (!Irp)
1419c2c66affSColin Finck {
1420c2c66affSColin Finck /* Fail, free the event */
1421c2c66affSColin Finck ExFreePoolWithTag(Event, TAG_FILE_SYSTEM);
1422c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES;
1423c2c66affSColin Finck }
1424c2c66affSColin Finck
1425c2c66affSColin Finck /* Call the driver and check if it's pending */
1426c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp);
1427c2c66affSColin Finck if (Status == STATUS_PENDING)
1428c2c66affSColin Finck {
1429c2c66affSColin Finck /* Wait on the driver */
1430c2c66affSColin Finck KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL);
1431c2c66affSColin Finck Status = IoStatusBlock.Status;
1432c2c66affSColin Finck }
1433c2c66affSColin Finck
1434c2c66affSColin Finck /* Free the event and return the Status */
1435c2c66affSColin Finck ExFreePoolWithTag(Event, TAG_FILE_SYSTEM);
1436c2c66affSColin Finck return Status;
1437c2c66affSColin Finck }
1438c2c66affSColin Finck
1439c2c66affSColin Finck BOOLEAN
1440c2c66affSColin Finck NTAPI
HalpIsValidPartitionEntry(IN PPARTITION_DESCRIPTOR Entry,IN ULONGLONG MaxOffset,IN ULONGLONG MaxSector)1441c2c66affSColin Finck HalpIsValidPartitionEntry(IN PPARTITION_DESCRIPTOR Entry,
1442c2c66affSColin Finck IN ULONGLONG MaxOffset,
1443c2c66affSColin Finck IN ULONGLONG MaxSector)
1444c2c66affSColin Finck {
1445c2c66affSColin Finck ULONGLONG EndingSector;
1446c2c66affSColin Finck PAGED_CODE();
1447c2c66affSColin Finck
1448c2c66affSColin Finck /* Unused partitions are considered valid */
1449c2c66affSColin Finck if (Entry->PartitionType == PARTITION_ENTRY_UNUSED) return TRUE;
1450c2c66affSColin Finck
1451c2c66affSColin Finck /* Get the last sector of the partition */
1452c2c66affSColin Finck EndingSector = GET_STARTING_SECTOR(Entry) + GET_PARTITION_LENGTH(Entry);
1453c2c66affSColin Finck
1454c2c66affSColin Finck /* Check if it's more then the maximum sector */
1455c2c66affSColin Finck if (EndingSector > MaxSector)
1456c2c66affSColin Finck {
1457c2c66affSColin Finck /* Invalid partition */
1458c2c66affSColin Finck DPRINT1("FSTUB: entry is invalid\n");
1459c2c66affSColin Finck DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry));
1460c2c66affSColin Finck DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry));
1461c2c66affSColin Finck DPRINT1("FSTUB: end %#I64x\n", EndingSector);
1462c2c66affSColin Finck DPRINT1("FSTUB: max %#I64x\n", MaxSector);
1463c2c66affSColin Finck return FALSE;
1464c2c66affSColin Finck }
1465c2c66affSColin Finck else if (GET_STARTING_SECTOR(Entry) > MaxOffset)
1466c2c66affSColin Finck {
1467c2c66affSColin Finck /* Invalid partition */
1468c2c66affSColin Finck DPRINT1("FSTUB: entry is invalid\n");
1469c2c66affSColin Finck DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry));
1470c2c66affSColin Finck DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry));
1471c2c66affSColin Finck DPRINT1("FSTUB: end %#I64x\n", EndingSector);
1472c2c66affSColin Finck DPRINT1("FSTUB: maxOffset %#I64x\n", MaxOffset);
1473c2c66affSColin Finck return FALSE;
1474c2c66affSColin Finck }
1475c2c66affSColin Finck
1476c2c66affSColin Finck /* It's fine, return success */
1477c2c66affSColin Finck return TRUE;
1478c2c66affSColin Finck }
1479c2c66affSColin Finck
1480c2c66affSColin Finck VOID
1481c2c66affSColin Finck NTAPI
HalpCalculateChsValues(IN PLARGE_INTEGER PartitionOffset,IN PLARGE_INTEGER PartitionLength,IN CCHAR ShiftCount,IN ULONG SectorsPerTrack,IN ULONG NumberOfTracks,IN ULONG ConventionalCylinders,OUT PPARTITION_DESCRIPTOR PartitionDescriptor)1482c2c66affSColin Finck HalpCalculateChsValues(IN PLARGE_INTEGER PartitionOffset,
1483c2c66affSColin Finck IN PLARGE_INTEGER PartitionLength,
1484c2c66affSColin Finck IN CCHAR ShiftCount,
1485c2c66affSColin Finck IN ULONG SectorsPerTrack,
1486c2c66affSColin Finck IN ULONG NumberOfTracks,
1487c2c66affSColin Finck IN ULONG ConventionalCylinders,
1488c2c66affSColin Finck OUT PPARTITION_DESCRIPTOR PartitionDescriptor)
1489c2c66affSColin Finck {
1490c2c66affSColin Finck LARGE_INTEGER FirstSector, SectorCount;
1491c2c66affSColin Finck ULONG LastSector, Remainder, SectorsPerCylinder;
1492c2c66affSColin Finck ULONG StartingCylinder, EndingCylinder;
1493c2c66affSColin Finck ULONG StartingTrack, EndingTrack;
1494c2c66affSColin Finck ULONG StartingSector, EndingSector;
1495c2c66affSColin Finck PAGED_CODE();
1496c2c66affSColin Finck
1497c2c66affSColin Finck /* Calculate the number of sectors for each cylinder */
1498c2c66affSColin Finck SectorsPerCylinder = SectorsPerTrack * NumberOfTracks;
1499c2c66affSColin Finck
1500c2c66affSColin Finck /* Calculate the first sector, and the sector count */
1501c2c66affSColin Finck FirstSector.QuadPart = PartitionOffset->QuadPart >> ShiftCount;
1502c2c66affSColin Finck SectorCount.QuadPart = PartitionLength->QuadPart >> ShiftCount;
1503c2c66affSColin Finck
1504c2c66affSColin Finck /* Now calculate the last sector */
1505c2c66affSColin Finck LastSector = FirstSector.LowPart + SectorCount.LowPart - 1;
1506c2c66affSColin Finck
1507c2c66affSColin Finck /* Calculate the first and last cylinders */
1508c2c66affSColin Finck StartingCylinder = FirstSector.LowPart / SectorsPerCylinder;
1509c2c66affSColin Finck EndingCylinder = LastSector / SectorsPerCylinder;
1510c2c66affSColin Finck
1511c2c66affSColin Finck /* Set the default number of cylinders */
1512c2c66affSColin Finck if (!ConventionalCylinders) ConventionalCylinders = 1024;
1513c2c66affSColin Finck
1514c2c66affSColin Finck /* Normalize the values */
1515c2c66affSColin Finck if (StartingCylinder >= ConventionalCylinders)
1516c2c66affSColin Finck {
1517c2c66affSColin Finck /* Set the maximum to 1023 */
1518c2c66affSColin Finck StartingCylinder = ConventionalCylinders - 1;
1519c2c66affSColin Finck }
1520c2c66affSColin Finck if (EndingCylinder >= ConventionalCylinders)
1521c2c66affSColin Finck {
1522c2c66affSColin Finck /* Set the maximum to 1023 */
1523c2c66affSColin Finck EndingCylinder = ConventionalCylinders - 1;
1524c2c66affSColin Finck }
1525c2c66affSColin Finck
1526c2c66affSColin Finck /* Calculate the starting head and sector that still remain */
1527c2c66affSColin Finck Remainder = FirstSector.LowPart % SectorsPerCylinder;
1528c2c66affSColin Finck StartingTrack = Remainder / SectorsPerTrack;
1529c2c66affSColin Finck StartingSector = Remainder % SectorsPerTrack;
1530c2c66affSColin Finck
1531c2c66affSColin Finck /* Calculate the ending head and sector that still remain */
1532c2c66affSColin Finck Remainder = LastSector % SectorsPerCylinder;
1533c2c66affSColin Finck EndingTrack = Remainder / SectorsPerTrack;
1534c2c66affSColin Finck EndingSector = Remainder % SectorsPerTrack;
1535c2c66affSColin Finck
1536c2c66affSColin Finck /* Set cylinder data for the MSB */
1537c2c66affSColin Finck PartitionDescriptor->StartingCylinderMsb = (UCHAR)StartingCylinder;
1538c2c66affSColin Finck PartitionDescriptor->EndingCylinderMsb = (UCHAR)EndingCylinder;
1539c2c66affSColin Finck
1540c2c66affSColin Finck /* Set the track data */
1541c2c66affSColin Finck PartitionDescriptor->StartingTrack = (UCHAR)StartingTrack;
1542c2c66affSColin Finck PartitionDescriptor->EndingTrack = (UCHAR)EndingTrack;
1543c2c66affSColin Finck
1544c2c66affSColin Finck /* Update cylinder data for the LSB */
1545c2c66affSColin Finck StartingCylinder = ((StartingSector + 1) & 0x3F) |
1546c2c66affSColin Finck ((StartingCylinder >> 2) & 0xC0);
1547c2c66affSColin Finck EndingCylinder = ((EndingSector + 1) & 0x3F) |
1548c2c66affSColin Finck ((EndingCylinder >> 2) & 0xC0);
1549c2c66affSColin Finck
1550c2c66affSColin Finck /* Set the cylinder data for the LSB */
1551c2c66affSColin Finck PartitionDescriptor->StartingCylinderLsb = (UCHAR)StartingCylinder;
1552c2c66affSColin Finck PartitionDescriptor->EndingCylinderLsb = (UCHAR)EndingCylinder;
1553c2c66affSColin Finck }
1554c2c66affSColin Finck
1555c2c66affSColin Finck VOID
1556c2c66affSColin Finck FASTCALL
xHalGetPartialGeometry(IN PDEVICE_OBJECT DeviceObject,IN PULONG ConventionalCylinders,IN PLONGLONG DiskSize)1557c2c66affSColin Finck xHalGetPartialGeometry(IN PDEVICE_OBJECT DeviceObject,
1558c2c66affSColin Finck IN PULONG ConventionalCylinders,
1559c2c66affSColin Finck IN PLONGLONG DiskSize)
1560c2c66affSColin Finck {
1561c2c66affSColin Finck PDISK_GEOMETRY DiskGeometry = NULL;
1562c2c66affSColin Finck PIO_STATUS_BLOCK IoStatusBlock = NULL;
1563c2c66affSColin Finck PKEVENT Event = NULL;
1564c2c66affSColin Finck PIRP Irp;
1565c2c66affSColin Finck NTSTATUS Status;
1566c2c66affSColin Finck
1567c2c66affSColin Finck /* Set defaults */
1568c2c66affSColin Finck *ConventionalCylinders = 0;
1569c2c66affSColin Finck *DiskSize = 0;
1570c2c66affSColin Finck
1571c2c66affSColin Finck /* Allocate the structure in nonpaged pool */
1572c2c66affSColin Finck DiskGeometry = ExAllocatePoolWithTag(NonPagedPool,
1573c2c66affSColin Finck sizeof(DISK_GEOMETRY),
1574c2c66affSColin Finck TAG_FILE_SYSTEM);
1575c2c66affSColin Finck if (!DiskGeometry) goto Cleanup;
1576c2c66affSColin Finck
1577c2c66affSColin Finck /* Allocate the status block in nonpaged pool */
1578c2c66affSColin Finck IoStatusBlock = ExAllocatePoolWithTag(NonPagedPool,
1579c2c66affSColin Finck sizeof(IO_STATUS_BLOCK),
1580c2c66affSColin Finck TAG_FILE_SYSTEM);
1581c2c66affSColin Finck if (!IoStatusBlock) goto Cleanup;
1582c2c66affSColin Finck
1583c2c66affSColin Finck /* Allocate the event in nonpaged pool too */
1584c2c66affSColin Finck Event = ExAllocatePoolWithTag(NonPagedPool,
1585c2c66affSColin Finck sizeof(KEVENT),
1586c2c66affSColin Finck TAG_FILE_SYSTEM);
1587c2c66affSColin Finck if (!Event) goto Cleanup;
1588c2c66affSColin Finck
1589c2c66affSColin Finck /* Initialize the event */
1590c2c66affSColin Finck KeInitializeEvent(Event, NotificationEvent, FALSE);
1591c2c66affSColin Finck
1592c2c66affSColin Finck /* Build the IRP */
1593c2c66affSColin Finck Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY,
1594c2c66affSColin Finck DeviceObject,
1595c2c66affSColin Finck NULL,
1596c2c66affSColin Finck 0,
1597c2c66affSColin Finck DiskGeometry,
1598c2c66affSColin Finck sizeof(DISK_GEOMETRY),
1599c2c66affSColin Finck FALSE,
1600c2c66affSColin Finck Event,
1601c2c66affSColin Finck IoStatusBlock);
1602c2c66affSColin Finck if (!Irp) goto Cleanup;
1603c2c66affSColin Finck
1604c2c66affSColin Finck /* Now call the driver */
1605c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp);
1606c2c66affSColin Finck if (Status == STATUS_PENDING)
1607c2c66affSColin Finck {
1608c2c66affSColin Finck /* Wait for it to complete */
1609c2c66affSColin Finck KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL);
1610c2c66affSColin Finck Status = IoStatusBlock->Status;
1611c2c66affSColin Finck }
1612c2c66affSColin Finck
1613c2c66affSColin Finck /* Check driver status */
1614c2c66affSColin Finck if (NT_SUCCESS(Status))
1615c2c66affSColin Finck {
1616c2c66affSColin Finck /* Return the cylinder count */
1617c2c66affSColin Finck *ConventionalCylinders = DiskGeometry->Cylinders.LowPart;
1618c2c66affSColin Finck
1619c2c66affSColin Finck /* Make sure it's not larger then 1024 */
1620c2c66affSColin Finck if (DiskGeometry->Cylinders.LowPart >= 1024)
1621c2c66affSColin Finck {
1622c2c66affSColin Finck /* Otherwise, normalize the value */
1623c2c66affSColin Finck *ConventionalCylinders = 1024;
1624c2c66affSColin Finck }
1625c2c66affSColin Finck
1626c2c66affSColin Finck /* Calculate the disk size */
1627c2c66affSColin Finck *DiskSize = DiskGeometry->Cylinders.QuadPart *
1628c2c66affSColin Finck DiskGeometry->TracksPerCylinder *
1629c2c66affSColin Finck DiskGeometry->SectorsPerTrack *
1630c2c66affSColin Finck DiskGeometry->BytesPerSector;
1631c2c66affSColin Finck }
1632c2c66affSColin Finck
1633c2c66affSColin Finck Cleanup:
1634c2c66affSColin Finck /* Free all the pointers */
1635c2c66affSColin Finck if (Event) ExFreePoolWithTag(Event, TAG_FILE_SYSTEM);
1636c2c66affSColin Finck if (IoStatusBlock) ExFreePoolWithTag(IoStatusBlock, TAG_FILE_SYSTEM);
1637c2c66affSColin Finck if (DiskGeometry) ExFreePoolWithTag(DiskGeometry, TAG_FILE_SYSTEM);
1638c2c66affSColin Finck return;
1639c2c66affSColin Finck }
1640c2c66affSColin Finck
1641c2c66affSColin Finck VOID
1642c2c66affSColin Finck FASTCALL
xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject,IN ULONG SectorSize,IN ULONG MbrTypeIdentifier,OUT PVOID * MbrBuffer)1643c2c66affSColin Finck xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject,
1644c2c66affSColin Finck IN ULONG SectorSize,
1645c2c66affSColin Finck IN ULONG MbrTypeIdentifier,
1646c2c66affSColin Finck OUT PVOID *MbrBuffer)
1647c2c66affSColin Finck {
1648c2c66affSColin Finck LARGE_INTEGER Offset;
1649c2c66affSColin Finck PUCHAR Buffer;
1650c2c66affSColin Finck ULONG BufferSize;
1651c2c66affSColin Finck KEVENT Event;
1652c2c66affSColin Finck IO_STATUS_BLOCK IoStatusBlock;
1653c2c66affSColin Finck PIRP Irp;
1654c2c66affSColin Finck PPARTITION_DESCRIPTOR PartitionDescriptor;
1655c2c66affSColin Finck NTSTATUS Status;
1656c2c66affSColin Finck PIO_STACK_LOCATION IoStackLocation;
1657e3c35c22SHermès Bélusca-Maïto
1658c2c66affSColin Finck Offset.QuadPart = 0;
1659c2c66affSColin Finck
1660c2c66affSColin Finck /* Assume failure */
1661c2c66affSColin Finck *MbrBuffer = NULL;
1662c2c66affSColin Finck
1663c2c66affSColin Finck /* Normalize the buffer size */
1664e69f845dSHermès Bélusca-Maïto BufferSize = max(512, SectorSize);
1665c2c66affSColin Finck
1666c2c66affSColin Finck /* Allocate the buffer */
1667c2c66affSColin Finck Buffer = ExAllocatePoolWithTag(NonPagedPool,
1668e69f845dSHermès Bélusca-Maïto max(PAGE_SIZE, BufferSize),
1669c2c66affSColin Finck TAG_FILE_SYSTEM);
1670c2c66affSColin Finck if (!Buffer) return;
1671c2c66affSColin Finck
1672c2c66affSColin Finck /* Initialize the Event */
1673c2c66affSColin Finck KeInitializeEvent(&Event, NotificationEvent, FALSE);
1674c2c66affSColin Finck
1675c2c66affSColin Finck /* Build the IRP */
1676c2c66affSColin Finck Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
1677c2c66affSColin Finck DeviceObject,
1678c2c66affSColin Finck Buffer,
1679c2c66affSColin Finck BufferSize,
1680c2c66affSColin Finck &Offset,
1681c2c66affSColin Finck &Event,
1682c2c66affSColin Finck &IoStatusBlock);
1683c2c66affSColin Finck if (!Irp)
1684c2c66affSColin Finck {
1685c2c66affSColin Finck /* Failed */
1686c2c66affSColin Finck ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM);
1687c2c66affSColin Finck return;
1688c2c66affSColin Finck }
1689c2c66affSColin Finck
1690c2c66affSColin Finck /* Make sure to override volume verification */
1691c2c66affSColin Finck IoStackLocation = IoGetNextIrpStackLocation(Irp);
1692c2c66affSColin Finck IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
1693c2c66affSColin Finck
1694c2c66affSColin Finck /* Call the driver */
1695c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp);
1696c2c66affSColin Finck if (Status == STATUS_PENDING)
1697c2c66affSColin Finck {
1698c2c66affSColin Finck /* Wait for completion */
1699c2c66affSColin Finck KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1700c2c66affSColin Finck Status = IoStatusBlock.Status;
1701c2c66affSColin Finck }
1702c2c66affSColin Finck
1703c2c66affSColin Finck /* Check driver Status */
1704c2c66affSColin Finck if (NT_SUCCESS(Status))
1705c2c66affSColin Finck {
1706c2c66affSColin Finck /* Validate the MBR Signature */
1707*29615feeSVictor Perevertkin if (*(PUINT16)&Buffer[BOOT_SIGNATURE_OFFSET] != BOOT_RECORD_SIGNATURE)
1708c2c66affSColin Finck {
1709c2c66affSColin Finck /* Failed */
1710c2c66affSColin Finck ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM);
1711c2c66affSColin Finck return;
1712c2c66affSColin Finck }
1713c2c66affSColin Finck
1714c2c66affSColin Finck /* Get the partition entry */
17158d2fe541SVictor Perevertkin PartitionDescriptor = (PPARTITION_DESCRIPTOR)&Buffer[PARTITION_TABLE_OFFSET];
1716c2c66affSColin Finck
1717c2c66affSColin Finck /* Make sure it's what the caller wanted */
1718c2c66affSColin Finck if (PartitionDescriptor->PartitionType != MbrTypeIdentifier)
1719c2c66affSColin Finck {
1720c2c66affSColin Finck /* It's not, free our buffer */
1721c2c66affSColin Finck ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM);
1722c2c66affSColin Finck }
1723c2c66affSColin Finck else
1724c2c66affSColin Finck {
1725e69f845dSHermès Bélusca-Maïto /* Check for OnTrack Disk Manager 6.0 / EZ-Drive partitions */
1726e69f845dSHermès Bélusca-Maïto
1727e69f845dSHermès Bélusca-Maïto if (PartitionDescriptor->PartitionType == PARTITION_DM)
1728c2c66affSColin Finck {
1729c2c66affSColin Finck /* Return our buffer, but at sector 63 */
1730c2c66affSColin Finck *(PULONG)Buffer = 63;
1731c2c66affSColin Finck *MbrBuffer = Buffer;
1732c2c66affSColin Finck }
1733e69f845dSHermès Bélusca-Maïto else if (PartitionDescriptor->PartitionType == PARTITION_EZDRIVE)
1734c2c66affSColin Finck {
1735e69f845dSHermès Bélusca-Maïto /* EZ-Drive, return the buffer directly */
1736c2c66affSColin Finck *MbrBuffer = Buffer;
1737c2c66affSColin Finck }
1738c2c66affSColin Finck else
1739c2c66affSColin Finck {
1740c2c66affSColin Finck /* Otherwise crash on debug builds */
1741e69f845dSHermès Bélusca-Maïto ASSERT(PartitionDescriptor->PartitionType == PARTITION_EZDRIVE);
1742c2c66affSColin Finck }
1743c2c66affSColin Finck }
1744c2c66affSColin Finck }
1745c2c66affSColin Finck }
1746c2c66affSColin Finck
1747c2c66affSColin Finck VOID
1748c2c66affSColin Finck NTAPI
FstubFixupEfiPartition(IN PPARTITION_DESCRIPTOR PartitionDescriptor,IN ULONGLONG MaxOffset)1749c2c66affSColin Finck FstubFixupEfiPartition(IN PPARTITION_DESCRIPTOR PartitionDescriptor,
1750c2c66affSColin Finck IN ULONGLONG MaxOffset)
1751c2c66affSColin Finck {
1752c2c66affSColin Finck ULONG PartitionMaxOffset, PartitionLength;
1753c2c66affSColin Finck PAGED_CODE();
1754c2c66affSColin Finck
1755c2c66affSColin Finck /* Compute partition length (according to MBR entry) */
1756c2c66affSColin Finck PartitionMaxOffset = GET_STARTING_SECTOR(PartitionDescriptor) + GET_PARTITION_LENGTH(PartitionDescriptor);
1757c2c66affSColin Finck /* In case the partition length goes beyond disk size... */
1758c2c66affSColin Finck if (PartitionMaxOffset > MaxOffset)
1759c2c66affSColin Finck {
1760c2c66affSColin Finck /* Resize partition to its maximum real length */
1761c2c66affSColin Finck PartitionLength = (ULONG)(PartitionMaxOffset - GET_STARTING_SECTOR(PartitionDescriptor));
1762c2c66affSColin Finck SET_PARTITION_LENGTH(PartitionDescriptor, PartitionLength);
1763c2c66affSColin Finck }
1764c2c66affSColin Finck }
1765c2c66affSColin Finck
1766c2c66affSColin Finck NTSTATUS
1767c2c66affSColin Finck FASTCALL
xHalIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject,IN ULONG SectorSize,IN BOOLEAN ReturnRecognizedPartitions,IN OUT PDRIVE_LAYOUT_INFORMATION * PartitionBuffer)1768c2c66affSColin Finck xHalIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject,
1769c2c66affSColin Finck IN ULONG SectorSize,
1770c2c66affSColin Finck IN BOOLEAN ReturnRecognizedPartitions,
1771c2c66affSColin Finck IN OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
1772c2c66affSColin Finck {
1773c2c66affSColin Finck KEVENT Event;
1774c2c66affSColin Finck IO_STATUS_BLOCK IoStatusBlock;
1775c2c66affSColin Finck PIRP Irp;
1776c2c66affSColin Finck PPARTITION_DESCRIPTOR PartitionDescriptor;
1777c2c66affSColin Finck CCHAR Entry;
1778c2c66affSColin Finck NTSTATUS Status;
1779c2c66affSColin Finck PPARTITION_INFORMATION PartitionInfo;
1780c2c66affSColin Finck PUCHAR Buffer = NULL;
1781c2c66affSColin Finck ULONG BufferSize = 2048, InputSize;
1782c2c66affSColin Finck PDRIVE_LAYOUT_INFORMATION DriveLayoutInfo = NULL;
1783c2c66affSColin Finck LONG j = -1, i = -1, k;
17845201472bSVictor Perevertkin DISK_GEOMETRY_EX DiskGeometryEx;
1785c2c66affSColin Finck LONGLONG EndSector, MaxSector, StartOffset;
1786c2c66affSColin Finck LARGE_INTEGER Offset, VolumeOffset;
1787c2c66affSColin Finck BOOLEAN IsPrimary = TRUE, IsEzDrive = FALSE, MbrFound = FALSE;
1788c2c66affSColin Finck BOOLEAN IsValid, IsEmpty = TRUE;
1789c2c66affSColin Finck PVOID MbrBuffer;
1790c2c66affSColin Finck PIO_STACK_LOCATION IoStackLocation;
1791c2c66affSColin Finck UCHAR PartitionType;
1792c2c66affSColin Finck LARGE_INTEGER HiddenSectors64;
1793e3c35c22SHermès Bélusca-Maïto
1794c2c66affSColin Finck PAGED_CODE();
1795c2c66affSColin Finck
1796e3c35c22SHermès Bélusca-Maïto VolumeOffset.QuadPart = Offset.QuadPart = 0;
1797e3c35c22SHermès Bélusca-Maïto
1798c2c66affSColin Finck /* Allocate the buffer */
1799c2c66affSColin Finck *PartitionBuffer = ExAllocatePoolWithTag(NonPagedPool,
1800c2c66affSColin Finck BufferSize,
1801c2c66affSColin Finck TAG_FILE_SYSTEM);
1802c2c66affSColin Finck if (!(*PartitionBuffer)) return STATUS_INSUFFICIENT_RESOURCES;
1803c2c66affSColin Finck
1804c2c66affSColin Finck /* Normalize the buffer size */
1805c2c66affSColin Finck InputSize = max(512, SectorSize);
1806c2c66affSColin Finck
1807e69f845dSHermès Bélusca-Maïto /* Check for EZ-Drive */
1808e69f845dSHermès Bélusca-Maïto HalExamineMBR(DeviceObject, InputSize, PARTITION_EZDRIVE, &MbrBuffer);
1809c2c66affSColin Finck if (MbrBuffer)
1810c2c66affSColin Finck {
1811e69f845dSHermès Bélusca-Maïto /* EZ-Drive found, bias the offset */
1812c2c66affSColin Finck IsEzDrive = TRUE;
1813c2c66affSColin Finck ExFreePoolWithTag(MbrBuffer, TAG_FILE_SYSTEM);
1814c2c66affSColin Finck Offset.QuadPart = 512;
1815c2c66affSColin Finck }
1816c2c66affSColin Finck
1817c2c66affSColin Finck /* Get drive geometry */
18185201472bSVictor Perevertkin Status = HalpGetFullGeometry(DeviceObject, &DiskGeometryEx);
1819c2c66affSColin Finck if (!NT_SUCCESS(Status))
1820c2c66affSColin Finck {
1821c2c66affSColin Finck ExFreePoolWithTag(*PartitionBuffer, TAG_FILE_SYSTEM);
1822c2c66affSColin Finck *PartitionBuffer = NULL;
1823c2c66affSColin Finck return Status;
1824c2c66affSColin Finck }
1825c2c66affSColin Finck
1826c2c66affSColin Finck /* Get the end and maximum sector */
18275201472bSVictor Perevertkin EndSector = DiskGeometryEx.DiskSize.QuadPart / DiskGeometryEx.Geometry.BytesPerSector;
18285201472bSVictor Perevertkin MaxSector = EndSector << 1;
18295201472bSVictor Perevertkin DPRINT("FSTUB: DiskSize = %#I64x, MaxSector = %#I64x\n",
18305201472bSVictor Perevertkin DiskGeometryEx.DiskSize, MaxSector);
1831c2c66affSColin Finck
1832c2c66affSColin Finck /* Allocate our buffer */
18338d2fe541SVictor Perevertkin Buffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned, InputSize, TAG_FILE_SYSTEM);
1834c2c66affSColin Finck if (!Buffer)
1835c2c66affSColin Finck {
1836c2c66affSColin Finck /* Fail, free the input buffer */
1837c2c66affSColin Finck ExFreePoolWithTag(*PartitionBuffer, TAG_FILE_SYSTEM);
1838c2c66affSColin Finck *PartitionBuffer = NULL;
1839c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES;
1840c2c66affSColin Finck }
1841c2c66affSColin Finck
1842c2c66affSColin Finck /* Start partition loop */
1843c2c66affSColin Finck do
1844c2c66affSColin Finck {
1845c2c66affSColin Finck /* Assume the partition is valid */
1846c2c66affSColin Finck IsValid = TRUE;
1847c2c66affSColin Finck
1848c2c66affSColin Finck /* Initialize the event */
1849c2c66affSColin Finck KeInitializeEvent(&Event, NotificationEvent, FALSE);
1850c2c66affSColin Finck
1851c2c66affSColin Finck /* Clear the buffer and build the IRP */
1852c2c66affSColin Finck RtlZeroMemory(Buffer, InputSize);
1853c2c66affSColin Finck Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
1854c2c66affSColin Finck DeviceObject,
1855c2c66affSColin Finck Buffer,
1856c2c66affSColin Finck InputSize,
1857c2c66affSColin Finck &Offset,
1858c2c66affSColin Finck &Event,
1859c2c66affSColin Finck &IoStatusBlock);
1860c2c66affSColin Finck if (!Irp)
1861c2c66affSColin Finck {
1862c2c66affSColin Finck /* Failed */
1863c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES;
1864c2c66affSColin Finck break;
1865c2c66affSColin Finck }
1866c2c66affSColin Finck
1867c2c66affSColin Finck /* Make sure to disable volume verification */
1868c2c66affSColin Finck IoStackLocation = IoGetNextIrpStackLocation(Irp);
1869c2c66affSColin Finck IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
1870c2c66affSColin Finck
1871c2c66affSColin Finck /* Call the driver */
1872c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp);
1873c2c66affSColin Finck if (Status == STATUS_PENDING)
1874c2c66affSColin Finck {
1875c2c66affSColin Finck /* Wait for completion */
1876c2c66affSColin Finck KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1877c2c66affSColin Finck Status = IoStatusBlock.Status;
1878c2c66affSColin Finck }
1879c2c66affSColin Finck
1880c2c66affSColin Finck /* Normalize status code and check for failure */
1881c2c66affSColin Finck if (Status == STATUS_NO_DATA_DETECTED) Status = STATUS_SUCCESS;
1882c2c66affSColin Finck if (!NT_SUCCESS(Status)) break;
1883c2c66affSColin Finck
1884c2c66affSColin Finck /* If we biased for EZ-Drive, unbias now */
1885c2c66affSColin Finck if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
1886c2c66affSColin Finck
1887c2c66affSColin Finck /* Make sure this is a valid MBR */
1888*29615feeSVictor Perevertkin if (*(PUINT16)&Buffer[BOOT_SIGNATURE_OFFSET] != BOOT_RECORD_SIGNATURE)
1889c2c66affSColin Finck {
1890c2c66affSColin Finck /* It's not, fail */
1891c2c66affSColin Finck DPRINT1("FSTUB: (IoReadPartitionTable) No 0xaa55 found in "
1892c2c66affSColin Finck "partition table %d\n", j + 1);
1893c2c66affSColin Finck break;
1894c2c66affSColin Finck }
1895c2c66affSColin Finck
1896c2c66affSColin Finck /* At this point we have a valid MBR */
1897c2c66affSColin Finck MbrFound = TRUE;
1898c2c66affSColin Finck
1899c2c66affSColin Finck /* Check if we weren't given an offset */
1900c2c66affSColin Finck if (!Offset.QuadPart)
1901c2c66affSColin Finck {
1902c2c66affSColin Finck /* Then read the signature off the disk */
19038d2fe541SVictor Perevertkin (*PartitionBuffer)->Signature = *(PUINT32)&Buffer[DISK_SIGNATURE_OFFSET];
1904c2c66affSColin Finck }
1905c2c66affSColin Finck
1906c2c66affSColin Finck /* Get the partition descriptor array */
19078d2fe541SVictor Perevertkin PartitionDescriptor = (PPARTITION_DESCRIPTOR)&Buffer[PARTITION_TABLE_OFFSET];
1908c2c66affSColin Finck
1909c2c66affSColin Finck /* Start looping partitions */
1910c2c66affSColin Finck j++;
1911c2c66affSColin Finck DPRINT("FSTUB: Partition Table %d:\n", j);
1912e69f845dSHermès Bélusca-Maïto for (Entry = 1, k = 0; Entry <= NUM_PARTITION_TABLE_ENTRIES; Entry++, PartitionDescriptor++)
1913c2c66affSColin Finck {
1914c2c66affSColin Finck /* Get the partition type */
1915c2c66affSColin Finck PartitionType = PartitionDescriptor->PartitionType;
1916c2c66affSColin Finck
1917c2c66affSColin Finck /* Print debug messages */
1918c2c66affSColin Finck DPRINT("Partition Entry %d,%d: type %#x %s\n",
1919c2c66affSColin Finck j,
1920c2c66affSColin Finck Entry,
1921c2c66affSColin Finck PartitionType,
1922c2c66affSColin Finck (PartitionDescriptor->ActiveFlag) ? "Active" : "");
1923c2c66affSColin Finck DPRINT("\tOffset %#08lx for %#08lx Sectors\n",
1924c2c66affSColin Finck GET_STARTING_SECTOR(PartitionDescriptor),
1925c2c66affSColin Finck GET_PARTITION_LENGTH(PartitionDescriptor));
1926c2c66affSColin Finck
1927c2c66affSColin Finck /* Check whether we're facing a protective MBR */
1928c2c66affSColin Finck if (PartitionType == EFI_PMBR_OSTYPE_EFI)
1929c2c66affSColin Finck {
1930c2c66affSColin Finck /* Partition length might be bigger than disk size */
19315201472bSVictor Perevertkin FstubFixupEfiPartition(PartitionDescriptor, DiskGeometryEx.DiskSize.QuadPart);
1932c2c66affSColin Finck }
1933c2c66affSColin Finck
1934c2c66affSColin Finck /* Make sure that the partition is valid, unless it's the first */
1935c2c66affSColin Finck if (!(HalpIsValidPartitionEntry(PartitionDescriptor,
19365201472bSVictor Perevertkin DiskGeometryEx.DiskSize.QuadPart,
1937d3a97e22SHermès Bélusca-Maïto MaxSector)) && (j == 0))
1938c2c66affSColin Finck {
1939c2c66affSColin Finck /* It's invalid, so fail */
1940c2c66affSColin Finck IsValid = FALSE;
1941c2c66affSColin Finck break;
1942c2c66affSColin Finck }
1943c2c66affSColin Finck
1944c2c66affSColin Finck /* Check if it's a container */
1945c2c66affSColin Finck if (IsContainerPartition(PartitionType))
1946c2c66affSColin Finck {
1947c2c66affSColin Finck /* Increase the count of containers */
1948c2c66affSColin Finck if (++k != 1)
1949c2c66affSColin Finck {
1950c2c66affSColin Finck /* More then one table is invalid */
1951c2c66affSColin Finck DPRINT1("FSTUB: Multiple container partitions found in "
1952c2c66affSColin Finck "partition table %d\n - table is invalid\n",
1953c2c66affSColin Finck j);
1954c2c66affSColin Finck IsValid = FALSE;
1955c2c66affSColin Finck break;
1956c2c66affSColin Finck }
1957c2c66affSColin Finck }
1958c2c66affSColin Finck
1959c2c66affSColin Finck /* Check if the partition is supposedly empty */
1960c2c66affSColin Finck if (IsEmpty)
1961c2c66affSColin Finck {
1962c2c66affSColin Finck /* But check if it actually has a start and/or length */
1963c2c66affSColin Finck if ((GET_STARTING_SECTOR(PartitionDescriptor)) ||
1964c2c66affSColin Finck (GET_PARTITION_LENGTH(PartitionDescriptor)))
1965c2c66affSColin Finck {
1966c2c66affSColin Finck /* So then it's not really empty */
1967c2c66affSColin Finck IsEmpty = FALSE;
1968c2c66affSColin Finck }
1969c2c66affSColin Finck }
1970c2c66affSColin Finck
1971c2c66affSColin Finck /* Check if the caller wanted only recognized partitions */
1972c2c66affSColin Finck if (ReturnRecognizedPartitions)
1973c2c66affSColin Finck {
1974c2c66affSColin Finck /* Then check if this one is unused, or a container */
1975c2c66affSColin Finck if ((PartitionType == PARTITION_ENTRY_UNUSED) ||
1976c2c66affSColin Finck IsContainerPartition(PartitionType))
1977c2c66affSColin Finck {
1978c2c66affSColin Finck /* Skip it, since the caller doesn't want it */
1979c2c66affSColin Finck continue;
1980c2c66affSColin Finck }
1981c2c66affSColin Finck }
1982c2c66affSColin Finck
1983c2c66affSColin Finck /* Increase the structure count and check if they can fit */
1984c2c66affSColin Finck if ((sizeof(DRIVE_LAYOUT_INFORMATION) +
1985c2c66affSColin Finck (++i * sizeof(PARTITION_INFORMATION))) >
1986c2c66affSColin Finck BufferSize)
1987c2c66affSColin Finck {
1988c2c66affSColin Finck /* Allocate a new buffer that's twice as big */
1989c2c66affSColin Finck DriveLayoutInfo = ExAllocatePoolWithTag(NonPagedPool,
1990c2c66affSColin Finck BufferSize << 1,
1991c2c66affSColin Finck TAG_FILE_SYSTEM);
1992c2c66affSColin Finck if (!DriveLayoutInfo)
1993c2c66affSColin Finck {
1994e69f845dSHermès Bélusca-Maïto /* Out of memory, undo this extra structure */
1995c2c66affSColin Finck --i;
1996c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES;
1997c2c66affSColin Finck break;
1998c2c66affSColin Finck }
1999c2c66affSColin Finck
2000c2c66affSColin Finck /* Copy the contents of the old buffer */
2001c2c66affSColin Finck RtlMoveMemory(DriveLayoutInfo,
2002c2c66affSColin Finck *PartitionBuffer,
2003c2c66affSColin Finck BufferSize);
2004c2c66affSColin Finck
2005c2c66affSColin Finck /* Free the old buffer and set this one as the new one */
2006c2c66affSColin Finck ExFreePoolWithTag(*PartitionBuffer, TAG_FILE_SYSTEM);
2007c2c66affSColin Finck *PartitionBuffer = DriveLayoutInfo;
2008c2c66affSColin Finck
2009c2c66affSColin Finck /* Double the size */
2010c2c66affSColin Finck BufferSize <<= 1;
2011c2c66affSColin Finck }
2012c2c66affSColin Finck
2013c2c66affSColin Finck /* Now get the current structure being filled and initialize it */
2014c2c66affSColin Finck PartitionInfo = &(*PartitionBuffer)->PartitionEntry[i];
2015c2c66affSColin Finck PartitionInfo->PartitionType = PartitionType;
2016c2c66affSColin Finck PartitionInfo->RewritePartition = FALSE;
2017c2c66affSColin Finck
2018c2c66affSColin Finck /* Check if we're dealing with a partition that's in use */
2019c2c66affSColin Finck if (PartitionType != PARTITION_ENTRY_UNUSED)
2020c2c66affSColin Finck {
2021c2c66affSColin Finck /* Check if it's bootable */
2022c2c66affSColin Finck PartitionInfo->BootIndicator = PartitionDescriptor->
2023c2c66affSColin Finck ActiveFlag & 0x80 ?
2024c2c66affSColin Finck TRUE : FALSE;
2025c2c66affSColin Finck
2026c2c66affSColin Finck /* Check if its' a container */
2027c2c66affSColin Finck if (IsContainerPartition(PartitionType))
2028c2c66affSColin Finck {
2029c2c66affSColin Finck /* Then don't recognize it and use the volume offset */
2030c2c66affSColin Finck PartitionInfo->RecognizedPartition = FALSE;
2031c2c66affSColin Finck StartOffset = VolumeOffset.QuadPart;
2032c2c66affSColin Finck }
2033c2c66affSColin Finck else
2034c2c66affSColin Finck {
2035c2c66affSColin Finck /* Then recognize it and use the partition offset */
2036c2c66affSColin Finck PartitionInfo->RecognizedPartition = TRUE;
2037c2c66affSColin Finck StartOffset = Offset.QuadPart;
2038c2c66affSColin Finck }
2039c2c66affSColin Finck
2040c2c66affSColin Finck /* Get the starting offset */
2041c2c66affSColin Finck PartitionInfo->StartingOffset.QuadPart =
2042c2c66affSColin Finck StartOffset +
2043c2c66affSColin Finck UInt32x32To64(GET_STARTING_SECTOR(PartitionDescriptor),
2044c2c66affSColin Finck SectorSize);
2045c2c66affSColin Finck
2046c2c66affSColin Finck /* Calculate the number of hidden sectors */
2047c2c66affSColin Finck HiddenSectors64.QuadPart = (PartitionInfo->
2048c2c66affSColin Finck StartingOffset.QuadPart -
2049c2c66affSColin Finck StartOffset) /
2050c2c66affSColin Finck SectorSize;
2051c2c66affSColin Finck PartitionInfo->HiddenSectors = HiddenSectors64.LowPart;
2052c2c66affSColin Finck
2053c2c66affSColin Finck /* Get the partition length */
2054c2c66affSColin Finck PartitionInfo->PartitionLength.QuadPart =
2055c2c66affSColin Finck UInt32x32To64(GET_PARTITION_LENGTH(PartitionDescriptor),
2056c2c66affSColin Finck SectorSize);
2057c2c66affSColin Finck
2058c2c66affSColin Finck /* Get the partition number */
2059e69f845dSHermès Bélusca-Maïto /* FIXME: REACTOS HACK -- Needed for xHalIoAssignDriveLetters() */
2060c2c66affSColin Finck PartitionInfo->PartitionNumber = (!IsContainerPartition(PartitionType)) ? i + 1 : 0;
2061c2c66affSColin Finck }
2062c2c66affSColin Finck else
2063c2c66affSColin Finck {
2064c2c66affSColin Finck /* Otherwise, clear all the relevant fields */
2065c2c66affSColin Finck PartitionInfo->BootIndicator = FALSE;
2066c2c66affSColin Finck PartitionInfo->RecognizedPartition = FALSE;
2067c2c66affSColin Finck PartitionInfo->StartingOffset.QuadPart = 0;
2068c2c66affSColin Finck PartitionInfo->PartitionLength.QuadPart = 0;
2069c2c66affSColin Finck PartitionInfo->HiddenSectors = 0;
2070c2c66affSColin Finck
2071e69f845dSHermès Bélusca-Maïto /* FIXME: REACTOS HACK -- Needed for xHalIoAssignDriveLetters() */
2072c2c66affSColin Finck PartitionInfo->PartitionNumber = 0;
2073c2c66affSColin Finck }
2074c2c66affSColin Finck }
2075c2c66affSColin Finck
2076c2c66affSColin Finck /* Finish debug log, and check for failure */
2077c2c66affSColin Finck DPRINT("\n");
2078c2c66affSColin Finck if (!NT_SUCCESS(Status)) break;
2079c2c66affSColin Finck
2080c2c66affSColin Finck /* Also check if we hit an invalid entry here */
2081c2c66affSColin Finck if (!IsValid)
2082c2c66affSColin Finck {
2083c2c66affSColin Finck /* We did, so break out of the loop minus one entry */
2084c2c66affSColin Finck j--;
2085c2c66affSColin Finck break;
2086c2c66affSColin Finck }
2087c2c66affSColin Finck
2088c2c66affSColin Finck /* Reset the offset */
2089c2c66affSColin Finck Offset.QuadPart = 0;
2090c2c66affSColin Finck
2091c2c66affSColin Finck /* Go back to the descriptor array and loop it */
20928d2fe541SVictor Perevertkin PartitionDescriptor = (PPARTITION_DESCRIPTOR)&Buffer[PARTITION_TABLE_OFFSET];
2093e69f845dSHermès Bélusca-Maïto for (Entry = 1; Entry <= NUM_PARTITION_TABLE_ENTRIES; Entry++, PartitionDescriptor++)
2094c2c66affSColin Finck {
2095c2c66affSColin Finck /* Check if this is a container partition, since we skipped them */
2096c2c66affSColin Finck if (IsContainerPartition(PartitionDescriptor->PartitionType))
2097c2c66affSColin Finck {
2098c2c66affSColin Finck /* Get its offset */
2099c2c66affSColin Finck Offset.QuadPart = VolumeOffset.QuadPart +
2100c2c66affSColin Finck UInt32x32To64(
2101c2c66affSColin Finck GET_STARTING_SECTOR(PartitionDescriptor),
2102c2c66affSColin Finck SectorSize);
2103c2c66affSColin Finck
2104c2c66affSColin Finck /* If this is a primary partition, this is the volume offset */
2105c2c66affSColin Finck if (IsPrimary) VolumeOffset = Offset;
2106c2c66affSColin Finck
2107c2c66affSColin Finck /* Also update the maximum sector */
2108c2c66affSColin Finck MaxSector = GET_PARTITION_LENGTH(PartitionDescriptor);
2109c2c66affSColin Finck DPRINT1("FSTUB: MaxSector now = %I64d\n", MaxSector);
2110c2c66affSColin Finck break;
2111c2c66affSColin Finck }
2112c2c66affSColin Finck }
2113c2c66affSColin Finck
2114c2c66affSColin Finck /* Loop the next partitions, which are not primary anymore */
2115c2c66affSColin Finck IsPrimary = FALSE;
2116c2c66affSColin Finck } while (Offset.HighPart | Offset.LowPart);
2117c2c66affSColin Finck
2118c2c66affSColin Finck /* Check if this is a removable device that's probably a super-floppy */
21195201472bSVictor Perevertkin if ((DiskGeometryEx.Geometry.MediaType == RemovableMedia) &&
2120d3a97e22SHermès Bélusca-Maïto (j == 0) && (MbrFound) && (IsEmpty))
2121c2c66affSColin Finck {
2122bf6b5e1cSHermès Bélusca-Maïto PBOOT_SECTOR_INFO BootSectorInfo = (PBOOT_SECTOR_INFO)Buffer;
2123bf6b5e1cSHermès Bélusca-Maïto
2124c2c66affSColin Finck /* Read the jump bytes to detect super-floppy */
2125c2c66affSColin Finck if ((BootSectorInfo->JumpByte[0] == 0xeb) ||
2126c2c66affSColin Finck (BootSectorInfo->JumpByte[0] == 0xe9))
2127c2c66affSColin Finck {
2128c2c66affSColin Finck /* Super floppes don't have typical MBRs, so skip them */
2129c2c66affSColin Finck DPRINT1("FSTUB: Jump byte %#x found along with empty partition "
2130c2c66affSColin Finck "table - disk is a super floppy and has no valid MBR\n",
2131c2c66affSColin Finck BootSectorInfo->JumpByte);
2132c2c66affSColin Finck j = -1;
2133c2c66affSColin Finck }
2134c2c66affSColin Finck }
2135c2c66affSColin Finck
2136c2c66affSColin Finck /* Check if we're still at partition -1 */
2137c2c66affSColin Finck if (j == -1)
2138c2c66affSColin Finck {
2139c2c66affSColin Finck /* The likely cause is the super floppy detection above */
21405201472bSVictor Perevertkin if ((MbrFound) || (DiskGeometryEx.Geometry.MediaType == RemovableMedia))
2141c2c66affSColin Finck {
2142c2c66affSColin Finck /* Print out debugging information */
2143c2c66affSColin Finck DPRINT1("FSTUB: Drive %#p has no valid MBR. Make it into a "
2144c2c66affSColin Finck "super-floppy\n",
2145c2c66affSColin Finck DeviceObject);
2146c2c66affSColin Finck DPRINT1("FSTUB: Drive has %I64d sectors and is %#016I64x "
2147c2c66affSColin Finck "bytes large\n",
21485201472bSVictor Perevertkin EndSector, DiskGeometryEx.DiskSize);
2149c2c66affSColin Finck
2150c2c66affSColin Finck /* We should at least have some sectors */
2151c2c66affSColin Finck if (EndSector > 0)
2152c2c66affSColin Finck {
2153c2c66affSColin Finck /* Get the entry we'll use */
2154c2c66affSColin Finck PartitionInfo = &(*PartitionBuffer)->PartitionEntry[0];
2155c2c66affSColin Finck
2156c2c66affSColin Finck /* Fill it out with data for a super-floppy */
2157c2c66affSColin Finck PartitionInfo->RewritePartition = FALSE;
2158c2c66affSColin Finck PartitionInfo->RecognizedPartition = TRUE;
2159c2c66affSColin Finck PartitionInfo->PartitionType = PARTITION_FAT_16;
2160c2c66affSColin Finck PartitionInfo->BootIndicator = FALSE;
2161c2c66affSColin Finck PartitionInfo->HiddenSectors = 0;
2162c2c66affSColin Finck PartitionInfo->StartingOffset.QuadPart = 0;
21635201472bSVictor Perevertkin PartitionInfo->PartitionLength = DiskGeometryEx.DiskSize;
2164c2c66affSColin Finck
2165e69f845dSHermès Bélusca-Maïto /* FIXME: REACTOS HACK -- Needed for xHalIoAssignDriveLetters() */
2166c2c66affSColin Finck PartitionInfo->PartitionNumber = 0;
2167c2c66affSColin Finck
2168c2c66affSColin Finck /* Set the signature and set the count back to 0 */
2169c2c66affSColin Finck (*PartitionBuffer)->Signature = 1;
2170c2c66affSColin Finck i = 0;
2171c2c66affSColin Finck }
2172c2c66affSColin Finck }
2173c2c66affSColin Finck else
2174c2c66affSColin Finck {
2175c2c66affSColin Finck /* Otherwise, this isn't a super floppy, so set an invalid count */
2176c2c66affSColin Finck i = -1;
2177c2c66affSColin Finck }
2178c2c66affSColin Finck }
2179c2c66affSColin Finck
2180c2c66affSColin Finck /* Set the partition count */
2181c2c66affSColin Finck (*PartitionBuffer)->PartitionCount = ++i;
2182c2c66affSColin Finck
2183c2c66affSColin Finck /* If we have no count, delete the signature */
2184c2c66affSColin Finck if (!i) (*PartitionBuffer)->Signature = 0;
2185c2c66affSColin Finck
2186c2c66affSColin Finck /* Free the buffer and check for success */
2187c2c66affSColin Finck if (Buffer) ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM);
2188c2c66affSColin Finck if (!NT_SUCCESS(Status))
2189c2c66affSColin Finck {
2190c2c66affSColin Finck ExFreePoolWithTag(*PartitionBuffer, TAG_FILE_SYSTEM);
2191c2c66affSColin Finck *PartitionBuffer = NULL;
2192c2c66affSColin Finck }
2193c2c66affSColin Finck
2194c2c66affSColin Finck /* Return status */
2195c2c66affSColin Finck return Status;
2196c2c66affSColin Finck }
2197c2c66affSColin Finck
2198c2c66affSColin Finck NTSTATUS
2199c2c66affSColin Finck FASTCALL
xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject,IN ULONG SectorSize,IN ULONG PartitionNumber,IN ULONG PartitionType)2200c2c66affSColin Finck xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject,
2201c2c66affSColin Finck IN ULONG SectorSize,
2202c2c66affSColin Finck IN ULONG PartitionNumber,
2203c2c66affSColin Finck IN ULONG PartitionType)
2204c2c66affSColin Finck {
2205c2c66affSColin Finck PIRP Irp;
2206c2c66affSColin Finck KEVENT Event;
2207c2c66affSColin Finck IO_STATUS_BLOCK IoStatusBlock;
2208c2c66affSColin Finck NTSTATUS Status;
2209c2c66affSColin Finck LARGE_INTEGER Offset, VolumeOffset;
2210c2c66affSColin Finck PUCHAR Buffer = NULL;
2211c2c66affSColin Finck ULONG BufferSize;
2212c2c66affSColin Finck ULONG i = 0;
2213c2c66affSColin Finck ULONG Entry;
2214c2c66affSColin Finck PPARTITION_DESCRIPTOR PartitionDescriptor;
2215c2c66affSColin Finck BOOLEAN IsPrimary = TRUE, IsEzDrive = FALSE;
2216c2c66affSColin Finck PVOID MbrBuffer;
2217c2c66affSColin Finck PIO_STACK_LOCATION IoStackLocation;
2218e3c35c22SHermès Bélusca-Maïto
2219c2c66affSColin Finck PAGED_CODE();
2220c2c66affSColin Finck
2221e3c35c22SHermès Bélusca-Maïto VolumeOffset.QuadPart = Offset.QuadPart = 0;
2222e3c35c22SHermès Bélusca-Maïto
2223c2c66affSColin Finck /* Normalize the buffer size */
2224c2c66affSColin Finck BufferSize = max(512, SectorSize);
2225c2c66affSColin Finck
2226e69f845dSHermès Bélusca-Maïto /* Check for EZ-Drive */
2227e69f845dSHermès Bélusca-Maïto HalExamineMBR(DeviceObject, BufferSize, PARTITION_EZDRIVE, &MbrBuffer);
2228c2c66affSColin Finck if (MbrBuffer)
2229c2c66affSColin Finck {
2230e69f845dSHermès Bélusca-Maïto /* EZ-Drive found, bias the offset */
2231c2c66affSColin Finck IsEzDrive = TRUE;
2232c2c66affSColin Finck ExFreePoolWithTag(MbrBuffer, TAG_FILE_SYSTEM);
2233c2c66affSColin Finck Offset.QuadPart = 512;
2234c2c66affSColin Finck }
2235c2c66affSColin Finck
2236c2c66affSColin Finck /* Allocate our partition buffer */
22378d2fe541SVictor Perevertkin Buffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned, PAGE_SIZE, TAG_FILE_SYSTEM);
2238c2c66affSColin Finck if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES;
2239c2c66affSColin Finck
2240c2c66affSColin Finck /* Initialize the event we'll use and loop partitions */
2241c2c66affSColin Finck KeInitializeEvent(&Event, NotificationEvent, FALSE);
2242c2c66affSColin Finck do
2243c2c66affSColin Finck {
2244c2c66affSColin Finck /* Reset the event since we reuse it */
224575850abcSThomas Faber KeClearEvent(&Event);
2246c2c66affSColin Finck
2247c2c66affSColin Finck /* Build the read IRP */
2248c2c66affSColin Finck Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
2249c2c66affSColin Finck DeviceObject,
2250c2c66affSColin Finck Buffer,
2251c2c66affSColin Finck BufferSize,
2252c2c66affSColin Finck &Offset,
2253c2c66affSColin Finck &Event,
2254c2c66affSColin Finck &IoStatusBlock);
2255c2c66affSColin Finck if (!Irp)
2256c2c66affSColin Finck {
2257c2c66affSColin Finck /* Fail */
2258c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES;
2259c2c66affSColin Finck break;
2260c2c66affSColin Finck }
2261c2c66affSColin Finck
2262c2c66affSColin Finck /* Make sure to disable volume verification */
2263c2c66affSColin Finck IoStackLocation = IoGetNextIrpStackLocation(Irp);
2264c2c66affSColin Finck IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
2265c2c66affSColin Finck
2266c2c66affSColin Finck /* Call the driver */
2267c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp);
2268c2c66affSColin Finck if (Status == STATUS_PENDING)
2269c2c66affSColin Finck {
2270c2c66affSColin Finck /* Wait for completion */
2271c2c66affSColin Finck KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
2272c2c66affSColin Finck Status = IoStatusBlock.Status;
2273c2c66affSColin Finck }
2274c2c66affSColin Finck
2275c2c66affSColin Finck /* Check for failure */
2276c2c66affSColin Finck if (!NT_SUCCESS(Status)) break;
2277c2c66affSColin Finck
2278c2c66affSColin Finck /* If we biased for EZ-Drive, unbias now */
2279c2c66affSColin Finck if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
2280c2c66affSColin Finck
2281c2c66affSColin Finck /* Make sure this is a valid MBR */
2282*29615feeSVictor Perevertkin if (*(PUINT16)&Buffer[BOOT_SIGNATURE_OFFSET] != BOOT_RECORD_SIGNATURE)
2283c2c66affSColin Finck {
2284c2c66affSColin Finck /* It's not, fail */
2285c2c66affSColin Finck Status = STATUS_BAD_MASTER_BOOT_RECORD;
2286c2c66affSColin Finck break;
2287c2c66affSColin Finck }
2288c2c66affSColin Finck
2289c2c66affSColin Finck /* Get the partition descriptors and loop them */
22908d2fe541SVictor Perevertkin PartitionDescriptor = (PPARTITION_DESCRIPTOR)&Buffer[PARTITION_TABLE_OFFSET];
2291e69f845dSHermès Bélusca-Maïto for (Entry = 1; Entry <= NUM_PARTITION_TABLE_ENTRIES; Entry++, PartitionDescriptor++)
2292c2c66affSColin Finck {
2293c2c66affSColin Finck /* Check if it's unused or a container partition */
2294e3c35c22SHermès Bélusca-Maïto if ((PartitionDescriptor->PartitionType == PARTITION_ENTRY_UNUSED) ||
2295c2c66affSColin Finck (IsContainerPartition(PartitionDescriptor->PartitionType)))
2296c2c66affSColin Finck {
2297c2c66affSColin Finck /* Go to the next one */
2298c2c66affSColin Finck continue;
2299c2c66affSColin Finck }
2300c2c66affSColin Finck
2301c2c66affSColin Finck /* It's a valid partition, so increase the partition count */
2302c2c66affSColin Finck if (++i == PartitionNumber)
2303c2c66affSColin Finck {
2304c2c66affSColin Finck /* We found a match, set the type */
2305c2c66affSColin Finck PartitionDescriptor->PartitionType = (UCHAR)PartitionType;
2306c2c66affSColin Finck
2307c2c66affSColin Finck /* Reset the reusable event */
230875850abcSThomas Faber KeClearEvent(&Event);
2309c2c66affSColin Finck
2310c2c66affSColin Finck /* Build the write IRP */
2311c2c66affSColin Finck Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
2312c2c66affSColin Finck DeviceObject,
2313c2c66affSColin Finck Buffer,
2314c2c66affSColin Finck BufferSize,
2315c2c66affSColin Finck &Offset,
2316c2c66affSColin Finck &Event,
2317c2c66affSColin Finck &IoStatusBlock);
2318c2c66affSColin Finck if (!Irp)
2319c2c66affSColin Finck {
2320c2c66affSColin Finck /* Fail */
2321c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES;
2322c2c66affSColin Finck break;
2323c2c66affSColin Finck }
2324c2c66affSColin Finck
2325c2c66affSColin Finck /* Disable volume verification */
2326c2c66affSColin Finck IoStackLocation = IoGetNextIrpStackLocation(Irp);
2327c2c66affSColin Finck IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
2328c2c66affSColin Finck
2329c2c66affSColin Finck /* Call the driver */
2330c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp);
2331c2c66affSColin Finck if (Status == STATUS_PENDING)
2332c2c66affSColin Finck {
2333c2c66affSColin Finck /* Wait for completion */
2334c2c66affSColin Finck KeWaitForSingleObject(&Event,
2335c2c66affSColin Finck Executive,
2336c2c66affSColin Finck KernelMode,
2337c2c66affSColin Finck FALSE,
2338c2c66affSColin Finck NULL);
2339c2c66affSColin Finck Status = IoStatusBlock.Status;
2340c2c66affSColin Finck }
2341c2c66affSColin Finck
2342c2c66affSColin Finck /* We're done, break out of the loop */
2343c2c66affSColin Finck break;
2344c2c66affSColin Finck }
2345c2c66affSColin Finck }
2346c2c66affSColin Finck
2347c2c66affSColin Finck /* If we looped all the partitions, break out */
2348c2c66affSColin Finck if (Entry <= NUM_PARTITION_TABLE_ENTRIES) break;
2349c2c66affSColin Finck
2350c2c66affSColin Finck /* Nothing found yet, get the partition array again */
23518d2fe541SVictor Perevertkin PartitionDescriptor = (PPARTITION_DESCRIPTOR)&Buffer[PARTITION_TABLE_OFFSET];
2352e69f845dSHermès Bélusca-Maïto for (Entry = 1; Entry <= NUM_PARTITION_TABLE_ENTRIES; Entry++, PartitionDescriptor++)
2353c2c66affSColin Finck {
2354c2c66affSColin Finck /* Check if this was a container partition (we skipped these) */
2355c2c66affSColin Finck if (IsContainerPartition(PartitionDescriptor->PartitionType))
2356c2c66affSColin Finck {
2357c2c66affSColin Finck /* Update the partition offset */
2358c2c66affSColin Finck Offset.QuadPart = VolumeOffset.QuadPart +
2359c2c66affSColin Finck GET_STARTING_SECTOR(PartitionDescriptor) *
2360c2c66affSColin Finck SectorSize;
2361c2c66affSColin Finck
2362c2c66affSColin Finck /* If this was the primary partition, update the volume too */
2363c2c66affSColin Finck if (IsPrimary) VolumeOffset = Offset;
2364c2c66affSColin Finck break;
2365c2c66affSColin Finck }
2366c2c66affSColin Finck }
2367c2c66affSColin Finck
2368c2c66affSColin Finck /* Check if we already searched all the partitions */
2369c2c66affSColin Finck if (Entry > NUM_PARTITION_TABLE_ENTRIES)
2370c2c66affSColin Finck {
2371c2c66affSColin Finck /* Then we failed to find a good MBR */
2372c2c66affSColin Finck Status = STATUS_BAD_MASTER_BOOT_RECORD;
2373c2c66affSColin Finck break;
2374c2c66affSColin Finck }
2375c2c66affSColin Finck
2376c2c66affSColin Finck /* Loop the next partitions, which are not primary anymore */
2377c2c66affSColin Finck IsPrimary = FALSE;
2378c2c66affSColin Finck } while (i < PartitionNumber);
2379c2c66affSColin Finck
2380c2c66affSColin Finck /* Everything done, cleanup */
2381c2c66affSColin Finck if (Buffer) ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM);
2382c2c66affSColin Finck return Status;
2383c2c66affSColin Finck }
2384c2c66affSColin Finck
2385c2c66affSColin Finck NTSTATUS
2386c2c66affSColin Finck FASTCALL
xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject,IN ULONG SectorSize,IN ULONG SectorsPerTrack,IN ULONG NumberOfHeads,IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)2387c2c66affSColin Finck xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject,
2388c2c66affSColin Finck IN ULONG SectorSize,
2389c2c66affSColin Finck IN ULONG SectorsPerTrack,
2390c2c66affSColin Finck IN ULONG NumberOfHeads,
2391c2c66affSColin Finck IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
2392c2c66affSColin Finck {
2393c2c66affSColin Finck KEVENT Event;
2394c2c66affSColin Finck IO_STATUS_BLOCK IoStatusBlock;
2395c2c66affSColin Finck PIRP Irp;
2396c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS;
2397c2c66affSColin Finck ULONG BufferSize;
2398*29615feeSVictor Perevertkin PUCHAR Buffer;
2399c2c66affSColin Finck PPTE Entry;
2400c2c66affSColin Finck PPARTITION_TABLE PartitionTable;
2401c2c66affSColin Finck LARGE_INTEGER Offset, NextOffset, ExtendedOffset, SectorOffset;
2402c2c66affSColin Finck LARGE_INTEGER StartOffset, PartitionLength;
2403c2c66affSColin Finck ULONG i, j;
2404c2c66affSColin Finck CCHAR k;
2405c2c66affSColin Finck BOOLEAN IsEzDrive = FALSE, IsSuperFloppy = FALSE, DoRewrite = FALSE, IsMbr;
2406c2c66affSColin Finck ULONG ConventionalCylinders;
2407c2c66affSColin Finck LONGLONG DiskSize;
2408c2c66affSColin Finck PDISK_LAYOUT DiskLayout = (PDISK_LAYOUT)PartitionBuffer;
2409c2c66affSColin Finck PVOID MbrBuffer;
2410c2c66affSColin Finck UCHAR PartitionType;
2411c2c66affSColin Finck PIO_STACK_LOCATION IoStackLocation;
2412c2c66affSColin Finck PPARTITION_INFORMATION PartitionInfo = PartitionBuffer->PartitionEntry;
2413c2c66affSColin Finck PPARTITION_INFORMATION TableEntry;
2414e3c35c22SHermès Bélusca-Maïto
2415c2c66affSColin Finck PAGED_CODE();
2416c2c66affSColin Finck
2417e3c35c22SHermès Bélusca-Maïto ExtendedOffset.QuadPart = NextOffset.QuadPart = Offset.QuadPart = 0;
2418e3c35c22SHermès Bélusca-Maïto
2419c2c66affSColin Finck /* Normalize the buffer size */
2420c2c66affSColin Finck BufferSize = max(512, SectorSize);
2421c2c66affSColin Finck
2422c2c66affSColin Finck /* Get the partial drive geometry */
2423c2c66affSColin Finck xHalGetPartialGeometry(DeviceObject, &ConventionalCylinders, &DiskSize);
2424c2c66affSColin Finck
2425e69f845dSHermès Bélusca-Maïto /* Check for EZ-Drive */
2426e69f845dSHermès Bélusca-Maïto HalExamineMBR(DeviceObject, BufferSize, PARTITION_EZDRIVE, &MbrBuffer);
2427c2c66affSColin Finck if (MbrBuffer)
2428c2c66affSColin Finck {
2429e69f845dSHermès Bélusca-Maïto /* EZ-Drive found, bias the offset */
2430c2c66affSColin Finck IsEzDrive = TRUE;
2431c2c66affSColin Finck ExFreePoolWithTag(MbrBuffer, TAG_FILE_SYSTEM);
2432c2c66affSColin Finck Offset.QuadPart = 512;
2433c2c66affSColin Finck }
2434c2c66affSColin Finck
2435c2c66affSColin Finck /* Get the number of bits to shift to multiply by the sector size */
2436c2c66affSColin Finck for (k = 0; k < 32; k++) if ((SectorSize >> k) == 1) break;
2437c2c66affSColin Finck
2438c2c66affSColin Finck /* Check if there's only one partition */
2439c2c66affSColin Finck if (PartitionBuffer->PartitionCount == 1)
2440c2c66affSColin Finck {
2441c2c66affSColin Finck /* Check if it has no starting offset or hidden sectors */
2442c2c66affSColin Finck if (!(PartitionInfo->StartingOffset.QuadPart) &&
2443c2c66affSColin Finck !(PartitionInfo->HiddenSectors))
2444c2c66affSColin Finck {
2445c2c66affSColin Finck /* Then it's a super floppy */
2446c2c66affSColin Finck IsSuperFloppy = TRUE;
2447c2c66affSColin Finck
2448c2c66affSColin Finck /* Which also means it must be non-bootable FAT-16 */
2449c2c66affSColin Finck if ((PartitionInfo->PartitionNumber) ||
2450c2c66affSColin Finck (PartitionInfo->PartitionType != PARTITION_FAT_16) ||
2451c2c66affSColin Finck (PartitionInfo->BootIndicator))
2452c2c66affSColin Finck {
2453c2c66affSColin Finck /* It's not, so we fail */
2454c2c66affSColin Finck return STATUS_INVALID_PARAMETER;
2455c2c66affSColin Finck }
2456c2c66affSColin Finck
2457e69f845dSHermès Bélusca-Maïto /* Check if it needs a rewrite, and disable EZ-Drive for sure */
2458c2c66affSColin Finck if (PartitionInfo->RewritePartition) DoRewrite = TRUE;
2459c2c66affSColin Finck IsEzDrive = FALSE;
2460c2c66affSColin Finck }
2461c2c66affSColin Finck }
2462c2c66affSColin Finck
2463c2c66affSColin Finck /* Count the number of partition tables */
2464e69f845dSHermès Bélusca-Maïto DiskLayout->TableCount = (PartitionBuffer->PartitionCount + NUM_PARTITION_TABLE_ENTRIES - 1) / NUM_PARTITION_TABLE_ENTRIES;
2465c2c66affSColin Finck
2466c2c66affSColin Finck /* Allocate our partition buffer */
24678d2fe541SVictor Perevertkin Buffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned, PAGE_SIZE, TAG_FILE_SYSTEM);
2468c2c66affSColin Finck if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES;
2469c2c66affSColin Finck
2470c2c66affSColin Finck /* Loop the entries */
2471c2c66affSColin Finck Entry = (PPTE)&Buffer[PARTITION_TABLE_OFFSET];
2472c2c66affSColin Finck for (i = 0; i < DiskLayout->TableCount; i++)
2473c2c66affSColin Finck {
2474c2c66affSColin Finck /* Set if this is the MBR partition */
2475c2c66affSColin Finck IsMbr= (BOOLEAN)!i;
2476c2c66affSColin Finck
2477c2c66affSColin Finck /* Initialize th event */
2478c2c66affSColin Finck KeInitializeEvent(&Event, NotificationEvent, FALSE);
2479c2c66affSColin Finck
2480c2c66affSColin Finck /* Build the read IRP */
2481c2c66affSColin Finck Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
2482c2c66affSColin Finck DeviceObject,
2483c2c66affSColin Finck Buffer,
2484c2c66affSColin Finck BufferSize,
2485c2c66affSColin Finck &Offset,
2486c2c66affSColin Finck &Event,
2487c2c66affSColin Finck &IoStatusBlock);
2488c2c66affSColin Finck if (!Irp)
2489c2c66affSColin Finck {
2490c2c66affSColin Finck /* Fail */
2491c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES;
2492c2c66affSColin Finck break;
2493c2c66affSColin Finck }
2494c2c66affSColin Finck
2495c2c66affSColin Finck /* Make sure to disable volume verification */
2496c2c66affSColin Finck IoStackLocation = IoGetNextIrpStackLocation(Irp);
2497c2c66affSColin Finck IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
2498c2c66affSColin Finck
2499c2c66affSColin Finck /* Call the driver */
2500c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp);
2501c2c66affSColin Finck if (Status == STATUS_PENDING)
2502c2c66affSColin Finck {
2503c2c66affSColin Finck /* Wait for completion */
2504c2c66affSColin Finck KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
2505c2c66affSColin Finck Status = IoStatusBlock.Status;
2506c2c66affSColin Finck }
2507c2c66affSColin Finck
2508c2c66affSColin Finck /* Check for failure */
2509c2c66affSColin Finck if (!NT_SUCCESS(Status)) break;
2510c2c66affSColin Finck
2511c2c66affSColin Finck /* If we biased for EZ-Drive, unbias now */
2512c2c66affSColin Finck if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
2513c2c66affSColin Finck
2514c2c66affSColin Finck /* Check if this is a normal disk */
2515c2c66affSColin Finck if (!IsSuperFloppy)
2516c2c66affSColin Finck {
2517c2c66affSColin Finck /* Set the boot record signature */
2518*29615feeSVictor Perevertkin *(PUINT16)&Buffer[BOOT_SIGNATURE_OFFSET] = BOOT_RECORD_SIGNATURE;
2519c2c66affSColin Finck
2520c2c66affSColin Finck /* By default, don't require a rewrite */
2521c2c66affSColin Finck DoRewrite = FALSE;
2522c2c66affSColin Finck
2523c2c66affSColin Finck /* Check if we don't have an offset */
2524c2c66affSColin Finck if (!Offset.QuadPart)
2525c2c66affSColin Finck {
2526c2c66affSColin Finck /* Check if the signature doesn't match */
2527*29615feeSVictor Perevertkin if (*(PUINT32)&Buffer[DISK_SIGNATURE_OFFSET] != PartitionBuffer->Signature)
2528c2c66affSColin Finck {
2529d3a97e22SHermès Bélusca-Maïto /* Then write the signature and now we need a rewrite */
2530*29615feeSVictor Perevertkin *(PUINT32)&Buffer[DISK_SIGNATURE_OFFSET] = PartitionBuffer->Signature;
2531c2c66affSColin Finck DoRewrite = TRUE;
2532c2c66affSColin Finck }
2533c2c66affSColin Finck }
2534c2c66affSColin Finck
2535c2c66affSColin Finck /* Loop the partition table entries */
2536c2c66affSColin Finck PartitionTable = &DiskLayout->PartitionTable[i];
2537e69f845dSHermès Bélusca-Maïto for (j = 0; j < NUM_PARTITION_TABLE_ENTRIES; j++)
2538c2c66affSColin Finck {
2539c2c66affSColin Finck /* Get the current entry and type */
2540c2c66affSColin Finck TableEntry = &PartitionTable->PartitionEntry[j];
2541c2c66affSColin Finck PartitionType = TableEntry->PartitionType;
2542c2c66affSColin Finck
2543c2c66affSColin Finck /* Check if the entry needs a rewrite */
2544c2c66affSColin Finck if (TableEntry->RewritePartition)
2545c2c66affSColin Finck {
2546c2c66affSColin Finck /* Then we need one too */
2547c2c66affSColin Finck DoRewrite = TRUE;
2548c2c66affSColin Finck
2549c2c66affSColin Finck /* Save the type and if it's a bootable partition */
2550c2c66affSColin Finck Entry[j].PartitionType = TableEntry->PartitionType;
2551c2c66affSColin Finck Entry[j].ActiveFlag = TableEntry->BootIndicator ? 0x80 : 0;
2552c2c66affSColin Finck
2553c2c66affSColin Finck /* Make sure it's used */
2554c2c66affSColin Finck if (PartitionType != PARTITION_ENTRY_UNUSED)
2555c2c66affSColin Finck {
2556c2c66affSColin Finck /* Make sure it's not a container (unless primary) */
2557c2c66affSColin Finck if ((IsMbr) || !(IsContainerPartition(PartitionType)))
2558c2c66affSColin Finck {
2559c2c66affSColin Finck /* Use the partition offset */
2560c2c66affSColin Finck StartOffset.QuadPart = Offset.QuadPart;
2561c2c66affSColin Finck }
2562c2c66affSColin Finck else
2563c2c66affSColin Finck {
2564c2c66affSColin Finck /* Use the extended logical partition offset */
2565c2c66affSColin Finck StartOffset.QuadPart = ExtendedOffset.QuadPart;
2566c2c66affSColin Finck }
2567c2c66affSColin Finck
2568c2c66affSColin Finck /* Set the sector offset */
2569c2c66affSColin Finck SectorOffset.QuadPart = TableEntry->
2570c2c66affSColin Finck StartingOffset.QuadPart -
2571c2c66affSColin Finck StartOffset.QuadPart;
2572c2c66affSColin Finck
2573c2c66affSColin Finck /* Now calculate the starting sector */
2574c2c66affSColin Finck StartOffset.QuadPart = SectorOffset.QuadPart >> k;
2575c2c66affSColin Finck Entry[j].StartingSector = StartOffset.LowPart;
2576c2c66affSColin Finck
2577c2c66affSColin Finck /* As well as the length */
2578c2c66affSColin Finck PartitionLength.QuadPart = TableEntry->PartitionLength.
2579c2c66affSColin Finck QuadPart >> k;
2580c2c66affSColin Finck Entry[j].PartitionLength = PartitionLength.LowPart;
2581c2c66affSColin Finck
2582c2c66affSColin Finck /* Calculate the CHS values */
2583c2c66affSColin Finck HalpCalculateChsValues(&TableEntry->StartingOffset,
2584c2c66affSColin Finck &TableEntry->PartitionLength,
2585c2c66affSColin Finck k,
2586c2c66affSColin Finck SectorsPerTrack,
2587c2c66affSColin Finck NumberOfHeads,
2588c2c66affSColin Finck ConventionalCylinders,
2589c2c66affSColin Finck (PPARTITION_DESCRIPTOR)
2590c2c66affSColin Finck &Entry[j]);
2591c2c66affSColin Finck }
2592c2c66affSColin Finck else
2593c2c66affSColin Finck {
2594c2c66affSColin Finck /* Otherwise set up an empty entry */
2595c2c66affSColin Finck Entry[j].StartingSector = 0;
2596c2c66affSColin Finck Entry[j].PartitionLength = 0;
2597c2c66affSColin Finck Entry[j].StartingTrack = 0;
2598c2c66affSColin Finck Entry[j].EndingTrack = 0;
2599c2c66affSColin Finck Entry[j].StartingCylinder = 0;
2600c2c66affSColin Finck Entry[j].EndingCylinder = 0;
2601c2c66affSColin Finck }
2602c2c66affSColin Finck }
2603c2c66affSColin Finck
2604c2c66affSColin Finck /* Check if this is a container partition */
2605c2c66affSColin Finck if (IsContainerPartition(PartitionType))
2606c2c66affSColin Finck {
2607c2c66affSColin Finck /* Then update the offset to use */
2608c2c66affSColin Finck NextOffset = TableEntry->StartingOffset;
2609c2c66affSColin Finck }
2610c2c66affSColin Finck }
2611c2c66affSColin Finck }
2612c2c66affSColin Finck
2613c2c66affSColin Finck /* Check if we need to write back the buffer */
2614c2c66affSColin Finck if (DoRewrite)
2615c2c66affSColin Finck {
2616c2c66affSColin Finck /* We don't need to do this again */
2617c2c66affSColin Finck DoRewrite = FALSE;
2618c2c66affSColin Finck
2619c2c66affSColin Finck /* Initialize the event */
2620c2c66affSColin Finck KeInitializeEvent(&Event, NotificationEvent, FALSE);
2621c2c66affSColin Finck
2622c2c66affSColin Finck /* If we unbiased for EZ-Drive, rebias now */
2623e3c35c22SHermès Bélusca-Maïto if (IsEzDrive && !Offset.QuadPart) Offset.QuadPart = 512;
2624c2c66affSColin Finck
2625c2c66affSColin Finck /* Build the write IRP */
2626c2c66affSColin Finck Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
2627c2c66affSColin Finck DeviceObject,
2628c2c66affSColin Finck Buffer,
2629c2c66affSColin Finck BufferSize,
2630c2c66affSColin Finck &Offset,
2631c2c66affSColin Finck &Event,
2632c2c66affSColin Finck &IoStatusBlock);
2633c2c66affSColin Finck if (!Irp)
2634c2c66affSColin Finck {
2635c2c66affSColin Finck /* Fail */
2636c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES;
2637c2c66affSColin Finck break;
2638c2c66affSColin Finck }
2639c2c66affSColin Finck
2640c2c66affSColin Finck /* Make sure to disable volume verification */
2641c2c66affSColin Finck IoStackLocation = IoGetNextIrpStackLocation(Irp);
2642c2c66affSColin Finck IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
2643c2c66affSColin Finck
2644c2c66affSColin Finck /* Call the driver */
2645c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp);
2646c2c66affSColin Finck if (Status == STATUS_PENDING)
2647c2c66affSColin Finck {
2648c2c66affSColin Finck /* Wait for completion */
2649c2c66affSColin Finck KeWaitForSingleObject(&Event,
2650c2c66affSColin Finck Executive,
2651c2c66affSColin Finck KernelMode,
2652c2c66affSColin Finck FALSE,
2653c2c66affSColin Finck NULL);
2654c2c66affSColin Finck Status = IoStatusBlock.Status;
2655c2c66affSColin Finck }
2656c2c66affSColin Finck
2657c2c66affSColin Finck /* Check for failure */
2658c2c66affSColin Finck if (!NT_SUCCESS(Status)) break;
2659c2c66affSColin Finck
2660c2c66affSColin Finck /* If we biased for EZ-Drive, unbias now */
2661c2c66affSColin Finck if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
2662c2c66affSColin Finck }
2663c2c66affSColin Finck
2664c2c66affSColin Finck /* Update the partition offset and set the extended offset if needed */
2665c2c66affSColin Finck Offset = NextOffset;
2666c2c66affSColin Finck if (IsMbr) ExtendedOffset = NextOffset;
2667c2c66affSColin Finck }
2668c2c66affSColin Finck
2669c2c66affSColin Finck /* If we had a buffer, free it, then return status */
2670c2c66affSColin Finck if (Buffer) ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM);
2671c2c66affSColin Finck return Status;
2672c2c66affSColin Finck }
2673c2c66affSColin Finck
2674c2c66affSColin Finck /* PUBLIC FUNCTIONS **********************************************************/
2675c2c66affSColin Finck
2676c2c66affSColin Finck /*
2677c2c66affSColin Finck * @implemented
2678c2c66affSColin Finck */
2679c2c66affSColin Finck VOID
2680c2c66affSColin Finck FASTCALL
HalExamineMBR(IN PDEVICE_OBJECT DeviceObject,IN ULONG SectorSize,IN ULONG MbrTypeIdentifier,OUT PVOID * MbrBuffer)2681c2c66affSColin Finck HalExamineMBR(IN PDEVICE_OBJECT DeviceObject,
2682c2c66affSColin Finck IN ULONG SectorSize,
2683c2c66affSColin Finck IN ULONG MbrTypeIdentifier,
2684c2c66affSColin Finck OUT PVOID *MbrBuffer)
2685c2c66affSColin Finck {
2686c2c66affSColin Finck HALDISPATCH->HalExamineMBR(DeviceObject,
2687c2c66affSColin Finck SectorSize,
2688c2c66affSColin Finck MbrTypeIdentifier,
2689c2c66affSColin Finck MbrBuffer);
2690c2c66affSColin Finck }
2691c2c66affSColin Finck
2692c2c66affSColin Finck /*
2693c2c66affSColin Finck * @implemented
2694c2c66affSColin Finck */
2695c2c66affSColin Finck NTSTATUS
2696c2c66affSColin Finck FASTCALL
IoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject,IN ULONG SectorSize,IN BOOLEAN ReturnRecognizedPartitions,IN OUT PDRIVE_LAYOUT_INFORMATION * PartitionBuffer)2697c2c66affSColin Finck IoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject,
2698c2c66affSColin Finck IN ULONG SectorSize,
2699c2c66affSColin Finck IN BOOLEAN ReturnRecognizedPartitions,
2700c2c66affSColin Finck IN OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
2701c2c66affSColin Finck {
2702c2c66affSColin Finck return HALDISPATCH->HalIoReadPartitionTable(DeviceObject,
2703c2c66affSColin Finck SectorSize,
2704c2c66affSColin Finck ReturnRecognizedPartitions,
2705c2c66affSColin Finck PartitionBuffer);
2706c2c66affSColin Finck }
2707c2c66affSColin Finck
2708c2c66affSColin Finck /*
2709c2c66affSColin Finck * @implemented
2710c2c66affSColin Finck */
2711c2c66affSColin Finck NTSTATUS
2712c2c66affSColin Finck FASTCALL
IoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject,IN ULONG SectorSize,IN ULONG PartitionNumber,IN ULONG PartitionType)2713c2c66affSColin Finck IoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject,
2714c2c66affSColin Finck IN ULONG SectorSize,
2715c2c66affSColin Finck IN ULONG PartitionNumber,
2716c2c66affSColin Finck IN ULONG PartitionType)
2717c2c66affSColin Finck {
2718c2c66affSColin Finck return HALDISPATCH->HalIoSetPartitionInformation(DeviceObject,
2719c2c66affSColin Finck SectorSize,
2720c2c66affSColin Finck PartitionNumber,
2721c2c66affSColin Finck PartitionType);
2722c2c66affSColin Finck }
2723c2c66affSColin Finck
2724c2c66affSColin Finck /*
2725c2c66affSColin Finck * @implemented
2726c2c66affSColin Finck */
2727c2c66affSColin Finck NTSTATUS
2728c2c66affSColin Finck FASTCALL
IoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject,IN ULONG SectorSize,IN ULONG SectorsPerTrack,IN ULONG NumberOfHeads,IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)2729c2c66affSColin Finck IoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject,
2730c2c66affSColin Finck IN ULONG SectorSize,
2731c2c66affSColin Finck IN ULONG SectorsPerTrack,
2732c2c66affSColin Finck IN ULONG NumberOfHeads,
2733c2c66affSColin Finck IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
2734c2c66affSColin Finck {
2735c2c66affSColin Finck return HALDISPATCH->HalIoWritePartitionTable(DeviceObject,
2736c2c66affSColin Finck SectorSize,
2737c2c66affSColin Finck SectorsPerTrack,
2738c2c66affSColin Finck NumberOfHeads,
2739c2c66affSColin Finck PartitionBuffer);
2740c2c66affSColin Finck }
2741c2c66affSColin Finck
2742c2c66affSColin Finck /*
2743c2c66affSColin Finck * @implemented
2744c2c66affSColin Finck */
2745c2c66affSColin Finck VOID
2746c2c66affSColin Finck FASTCALL
IoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,IN PSTRING NtDeviceName,OUT PUCHAR NtSystemPath,OUT PSTRING NtSystemPathString)2747c2c66affSColin Finck IoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
2748c2c66affSColin Finck IN PSTRING NtDeviceName,
2749c2c66affSColin Finck OUT PUCHAR NtSystemPath,
2750c2c66affSColin Finck OUT PSTRING NtSystemPathString)
2751c2c66affSColin Finck {
2752c2c66affSColin Finck HALDISPATCH->HalIoAssignDriveLetters(LoaderBlock,
2753c2c66affSColin Finck NtDeviceName,
2754c2c66affSColin Finck NtSystemPath,
2755c2c66affSColin Finck NtSystemPathString);
2756c2c66affSColin Finck }
2757c2c66affSColin Finck
2758c2c66affSColin Finck /* EOF */
2759