xref: /reactos/ntoskrnl/fstub/disksup.c (revision 29615fee)
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